geis-2.2.17+16.04.20160126/0000755000015600001650000000000012651717732015107 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/doc/0000755000015600001650000000000012651717732015654 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/doc/geistest.10000644000015600001650000000223412651717544017567 0ustar pbuserpbgroup00000000000000.TH geistest 1 "August 16, 2010" "" "geistest" .SH NAME geistest \- test operation of the GEIS API .SH SYNOPSIS .B geistest [ .B -w .I windowid .B ] .B [ .B -d .I deviceid .B ] .br .SH DESCRIPTION This manual page explains the .B geistest program. This program is a test driver for verifying the recognition and propagation of gestures through the GEIS API. Hitting any key on the keyboard will exit the program gracefully. .SH OPTIONS .IP -w Specifies the .I windowId of a specific window to associate with gestures. Particularly useful with touchscreens. If this argument is not set, the default action is to read gestures on all windows. The .I windowId can be determined using the program .BR xwininfo . .IP -d Specifies the .I deviceId of a specific input device to be tested for multi-touch gestural input. If this argument is not set, the default action is to listen to multi-touch input on all devices. This argument may be used more than once to specify multiple input devices. The .I deviceId can be determined using the program .BR xinput . .SH ENVIRONMENT .IP GEIS_DEBUG Enables GEIS library diagnostic messages on stderr. .SH "SEE ALSO" gesturetest(1) geis-2.2.17+16.04.20160126/doc/pygeis.10000644000015600001650000000113212651717544017234 0ustar pbuserpbgroup00000000000000.TH pygeis 1 "February 12, 2013" "" "pygeis" .SH NAME pygeis \- test operation of the GEIS API Python bindings .SH SYNOPSIS .B pygeis [ .B \-V .B ] .br .SH DESCRIPTION This manual page explains the .B pygeis program. This program is a test driver for verifying the recognition and propagation of gestures through the GEIS API Python bindings. Hitting any key on the keyboard will exit the program gracefully. .SH OPTIONS .IP \-V Prints the version number of the program and exits. .SH ENVIRONMENT .IP GEIS_DEBUG Enables GEIS library diagnostic messages on stderr. .SH "SEE ALSO" gesturetest(1) geis-2.2.17+16.04.20160126/doc/using_geis_v2.dox0000644000015600001650000000505012651717544021134 0ustar pbuserpbgroup00000000000000/** @page using_geis_v2 Using The Advanced Interface @section using_geis_v2_intro Introduction to the Advanced GEIS Interface The advanced GEIS interface is designed around the idea that you can create filters to limit the kinds of gestures received and combine those filters into subscriptions that interact with the gesture recognizer to deliver gesture events. The normal flow for using the advanced interface is as follows. -# create a Geis object -# create a GeisSubscription object on the Geis object -# create and add one or more GeisFilter to the GeisSubscription -# activate the GeisSubscription -# wait for and process a series of GeisEvent @subsection using_geis_v2_example An example of advanced API usage This is an example of using the advanced (GEIS v2) API. The full source code for this example (including details missing here) is included in the source distribution of geis. Please note that these examples omit all of the error checking for expository purposes only. @dontinclude geis2.c First, a function to create the filters for a subscription. the filters can not be created until the gesture recognition engine initialization is complete, since otherwise the expected types of the gesture attributes on which to filter are not known by the interface. An empty filter is created. An empty filter means all input devices, all gestures, all regions. For the purpose of this example, we want just 2-touch gestures, so we need to add a term to the filter specifying only those gestures with two touches. @skip target_subscription @until } @line } In the main fucntion, the API instance is created. We tell it to report input devices and gesture classes. @skip geis_new @until NULL For the event loop processing, we're going to need the event fd (this is assuming a Unix implementation of GEIS, other platforms may have a different event indicator). @line geis_get_configuration A subscription object is created. We want gesture continuations. @line geis_subscription_new The application's main event loop is run until a read is indicated as available on the event fd, at which point the GEIS event loop is pumped. @skip geis_dispatch_events @until geis_next_event The events are handled and the event loop pumped until it's empty. @until geis_next_event Finally, the API objects are cleaned up. @skip geis_subscription_delete @until geis_delete @subsection using_geis_v2_examining_devices Examining Devices @dontinclude geis2.c @skip dump_device_event @until } @line } @example geis2.c */ geis-2.2.17+16.04.20160126/doc/Makefile.am0000644000015600001650000000302012651717544017704 0ustar pbuserpbgroup00000000000000## ## Makefile for the doc subdirectory of libgeis ## ## Copyright (C) 2010 Canonical Ltd. ## ## Process this file with automake to produce Makefile.in. ## ## This file is part of the libgeis project. This library is free ## software; you can redistribute it and/or modify it under the ## terms of version 3 of the GNU General Public License as published ## by the Free Software Foundation. ## ## 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 General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this library; see the file COPYING3. If not see ## . ## dist_doc_DATA = \ Doxyfile \ geisspec-1.0.asc \ geisspec-docbook.xml dist_man_MANS = geistest.1 pygeis.1 api/html: mkdir -p api/html doc-html: doc-html-doxygen doc-man: doc-man-doxygen doc-pdf: doc-pdf-doxygen doc-pdf-asciidoc doc-html-doxygen: doxygen doc-man-doxygen: doxygen doc-pdf-doxygen: doxygen doc-html-asciidoc: geisspec-1.0.html doc-pdf-asciidoc: geisspec-1.0.pdf geisspec-1.0.html: geisspec-1.0.asc geisspec-docbook.xml a2x -v -f xhtml -a geisspec geisspec-1.0.asc geisspec-1.0.pdf: geisspec-1.0.asc geisspec-docbook.xml a2x -v -a geisspec geisspec-1.0.asc install-data-local: api/html $(INSTALL) -d $(DESTDIR)$(docdir) cp -a api/html $(DESTDIR)$(docdir) clean-local: -rm -rf *.pdf *.html api geis-2.2.17+16.04.20160126/doc/geisspec-docbook.xml0000644000015600001650000000077412651717544021627 0ustar pbuserpbgroup00000000000000 2010 Stephen M. Webb 1.0.0 22 July 2010 SMW First release. 1.0.1 06 August 2010 SMW Added gesture attribute support functions. geis-2.2.17+16.04.20160126/doc/geisspec-1.0.asc0000644000015600001650000004626512651717544020460 0ustar pbuserpbgroup00000000000000Gesture Engine Interface Support ================================ Stephen M. Webb :Author Initials: SMW v1.0, 12 August 2010 Overview -------- This document describes GEIS, an interface between an application and an underlying gesture recognition system. A GEIS implementation provides a mechanism for recognizing user interface gestures on various configurable devices and for propagating those recognized gestures to subscribed applications. Gestures ~~~~~~~~ A _gesture_ is a defined set of particular movements of pointing devices. GEIS provides no interpretation of gestures, only recognition and propagation. Because gestures can be defined to have global meaning as well as local meaning, it makes sense that gesture recognition be provided by the system rather than be included as a library by a particular application or toolkit. This allows, for example, a set of gestures to be defined for the window manager in use on a display to receive gesture events even when another application is in the foreground and receiving the input. GEIS Operation -------------- The purpose of GEIS is intended to provide a consistent and stable application programming interface for gesture recognition and propagation on multiple target platforms (for example, Linux, Unix, and Windows), multiple target input devices (for example mice, touch pads, mutitouch touchscreens, tables, nunchuks), and multiple gesture recognition engines. Different gesture engines may be available on the same platform. A number of basic types are defined for portability between various underlying display, input, and operating systems. GEIS Basic Types ~~~~~~~~~~~~~~~~~ +GeisBoolean+ is an integral type representing a boolean value and should only hold the values +GEIS_TRUE+ (1) and +GEIS_FALSE+ (0). +GeisInt+ is an integral type large enough to hold any integral gesture attribute value which may be represented on the native platform. This may includes bitmasks, enumerants, integers, handles, and so forth. +GeisFloat+ is a floating-point type which can represent floating-point valued gesture attributes, +GeisString+ is a C-style zero-terminated string of characters in some character set. A +GeisString+ is a read-only string and does not have to be freed or disposed of by the caller. GEIS Instances ~~~~~~~~~~~~~~ An application may need to support different sets of gestures from different input devices or associated with different regions of the same device. For this reason, GEIS provides for one or more distinct connections to the underlying gesture engine. The instances are distinguished by a GeisInstance object. All gesture types and gesture instances IDs are in a namespace associated with the GeisInstance and are not guaranteed to be system wide unique. Threading and Concurrency ^^^^^^^^^^^^^^^^^^^^^^^^^ The GEIS API does not specify threading, reentrancy, or concurrency attributes. The implementation must supply detailed documentation on these aspects. Input Devices ^^^^^^^^^^^^^ The API provides a method to enumerate the available gesture-capable input devices (including the dynamic appearance and disappearance of such devices) and a way to specify a subset of these devices for use in a particular gesture detection instance. A client application might typically respond to gestures from any input device, but others, such as a drawing application, may wish to bypass gesture detection on, for example, a drawing tablet while accepting them from a touchscreen for other functions such as zoom and rotate. GEIS uses a set of client-supplied callbacks to report the availability of input devices so that devices that dynamically appear or disappear can be reported through a consistent interface. GEIS Functions and Errors ------------------------- Errors ~~~~~~ NOTE: This section is not complete. GEIS functions usually return a status code indicating success or failure. The status codes that may be returned, and their meanings, are as follows. +GEIS_SUCCESS+:: Normal, successful completion of the function. +GEIS_BAD_ARGUMENT+:: One or more argument values are invalid. Any command taking parameters may generate this error. +GEIS_STATUS_NOT_SUPPORTED+:: An operation or configuration item is not supported by the implementation. +GEIS_UNKNOWN_ERROR+:: A general catchall error: an error occurred that is not covered by any other defined status code. Initialization ~~~~~~~~~~~~~~ NOTE: This section is not complete. A GEIS instance may be initialized by calling [source, C] ----------- GeisStatus geis_init(GeisWinInfo *win_info, GeisInstance *geis_instance); ----------- +GEIS_SUCCESS+ is returned on success and _geis_instance_ is updated with an instance value to be used in subsequent GEIS calls. The definition of the +GeisWinInfo+ fields is entirely dependant on the implementation. For example, an X11-based gesture recognizer may specify the _window_id_ as the _win_info_ argument. Configuration and Control ~~~~~~~~~~~~~~~~~~~~~~~~~ A particular GEIS implementation may support a subset of standard configuarable items and, in addition, zero or more implementation-specific configuration items. The implementation-specific configuration items will be documented by the implementation. To determine of a confiuration item is supported, use the following call. [source, C] ----------- GeisStatus geis_configuration_supported(GeisInstance instance, int configuration_item); ----------- This function will return +GEIS_STATUS_SUCCESS+ if the _configuration_item_ is supported by the implementation, +GEIS_STATUS_NOT_SUPPORTED+ otherwise. The following standard configuration items must be available. .Input Standard Configuration Items [width="60%",cols="<,3d",frame="topbot",options="header"] |=================== |+configuration item+ | description |GEIS_CONFIG_UNIX_FD | A posix descriptor for event loop synchronization is available. |=================== Configuration-specifc values may be set and retrieved using the following calls. [source,C] ---------- GeisStatus geis_configuration_get_value(GeisInstance instance, int configuration_item, void* value); GeisStatus geis_configuration_set_value(GeisInstance instance, int configuration_item, void* value); ---------- The actual type and meaning of the _value_ argument depends on the _configuration_item_. Standard configuration item types are described in the following table. .Input Standard Configuration Item Types [width="60%",cols="<,<,2d",frame="topbot",options="header"] |=================== |+configuration item+ | type | description |GEIS_CONFIG_UNIX_FD | int | A posix file descriptor |=================== Integration with the native event loop is through an implementation-specific mechanism (likely obtained through the configuration calls above, but documented more thoroughly in the implementation documentation) combined with a call to the GEIS dispatch mechanism. [source,C] ---------- GeisStatus geis_event_dispatch(geisInstance instance); ---------- Input Devices ~~~~~~~~~~~~~ Gestures are associated with input devices (a gesture must be input on a device). Client software may subscribe to gestures that occur on all input devices or on only a subset of input devices. For that to be possible, the client needs to enumerate all available input devices. In addition, many input devices have a dynamic lifetime -- they may be added or removed asynchronously. the client software needs to be made aware that new input devices have become available or existing devices have become unavailable. GEIS input device enumeration and availability notification is performed through the following interface. [source, C] ----------- typedef unsigned int GeisInputDeviceId; #define GEIS_ALL_INPUT_DEVICES ((GeisInputDeviceId)0) typedef void (*GeisInputCallback)(void *cookie, GeisInputDeviceId device_id, void *attrs); typedef struct GeisInputFuncs { GeisInputCallback added; /**< Receives new input device notices */ GeisInputCallback changed; /**< Receives modified input device notices */ GeisInputCallback removed; /**< Receives removes input device notices */ } GeisInputFuncs; GeisStatus geis_input_devices(GeisInstance geis_instance, GeisInputFuncs funcs, void *cookie); ----------- The API provides a list of available input devices one at a time through the client-supplied _added_ callback function. The _changed_ callback function or the _removed_ callback function may be invoked at any time after *geis_input_devices* is called and before *geis_finish* is called to tear down the +GeisInstance+ or *geis_input_devices* is called again to replace the callback function. This can occur when input devices are, for example, physically connected to or disconnected from the system. The _cookie_ value passed to *geis_input_devices* is passed unmodified to callback function. Client programs may use this for passing context-specific information into the callback. The suggested behaviour of an implementation is to invoke the _callback_ for each input device known at call time _before_ returning from the *geis_input_devices* call. Subscribing to Gestures ~~~~~~~~~~~~~~~~~~~~~~~ Gestures are specific to a +GeisInstance+ and set of input devices. The +GeisInstance+ must be informed of the set of gestures (and input devices) of interest. [source, C] ----------- typedef unsigned int GeisGestureType; typedef unsigned int GeisGestureId; #define GEIS_ALL_GESTURES ((GeisGestureType)0) #define GEIS_NO_GESTURE_ID ((GeisGestureId)0) typedef void (*GeisGestureCallback)(void *cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr *attrs); typedef struct GeisGestureFuncs { GeisGestureCallback added; GeisGestureCallback removed; GeisGestureCallback start; GeisGestureCallback update; GeisGestureCallback finish; } GeisGestureFuncs; GeisStatus geis_subscribe(GeisInstance geis_instance, GeisInputDeviceId *input_list, const char* *gesture_list, GeisGestureFuncs funcs, void *cookie); GeisStatus geis_unsubscribe(GeisInstance geis_instance, GeisGestureType *gesture_list); ----------- The client supplies a list of input devices (or the constant +GEIS_ALL_INPUT_DEVICES+) and a +NULL+ terminated list of C-style strings naming the gestures to be recognized. The constant +GEIS_ALL_GESTURES+ indicates all available gestures should be detected. GEIS provides a list of gestures available in the desired window and input device(s) one at a time through the client-supplied _added_ callback function with the +GEIS_GESTURE_TYPE_ADDED+ action. This allows the client to build a map of gesture names to +GeisGestureType+. If the recognition engine does not support a named gesture type passed to *geis_subscribe* then no +GeisGestureType+ is passed to the callback function for the named gesture. The _cookie_ value passed to *geis_subscribe* is passed unmodified to _callback_. Client programs may use this for passing context-specific information into the callback. Receiving Gestures ~~~~~~~~~~~~~~~~~~ One of the gesture event callback functions may be invoked at any time after *geis_input_devices* is called and before *geis_finish* is called to tear down the +GeisInstance+ or *geis_input_devices* is called again to replace the _callback_ function. This can occur when input devices are, for example, physically connected to or disconnected from the system. Most gestures will result in a _start_ callback, zero or more _update_ callbacks, and a _finish_ callback. Some gestures such as _tap_ gestures may result in only a single _update_ callback. This behaviour is dependent on the underlying gesture recognition engine Once a gesture is recognized, a +GEIS_GESTURE_STARTED+ action is sent. A set of zero or more attributes will be returned. These attributes are specific to the gesture. Depending on the nature of the gesture, one or more +GEIS_GESTURE_UPDATED+ actions may be sent, and finally a +GEIS_GESTURE_FINISHED+ action will be sent. Each of these may or may not have a set of attributes associated. A gesture or gesture type action is often associated with a set of attributes. These attributes are delivered to the callback function as a read-only array of _GeisGestureAttr_ type, defined below. [source, C] ----------- typedef struct GeisGestureAttr { GeisString name; GeisAttrType type; union { GeisBoolean boolean_val; GeisFloat float_val; GeisInteger integer_val; GeisString string_val; }; } GeisGestureAttr; ----------- Recognizer Teardown ~~~~~~~~~~~~~~~~~~~ Teardown of the gesture recognition session is accomplished by the *geis_finish* function. [source, C] ----------- GeisStatus geis_finish(GeisInstance *geis_instance); ---------- This function frees any allocated resources associated with _geis_instance_. It does not affect other instances. All resources are expected to be freed automatically on process termination. The *geis_finish* function is not expected to return any status value other than +GEIS_SUCCESS+. Standard Gestures ----------------- A limited number of fundamental gestures are expected to be supplied with the API. All implementations are expected to support at least this set of predefined gestures. Additional predefined gestures and user- or application-defined gestures are beyond the scope of this specification but are expected to be made available by the implementation. .Predefined Gestures [width="60%",cols="<,2d,2d",frame="topbot",options="header"] |======================================================== |gesture name |symbolic name |description | Drag | GEIS_GESTURE_DRAG | | Pinch | GEIS_GESTURE_PINCH | | Rotate | GEIS_GESTURE_ROTATE | | Tap | GEIS_GESTURE_TAP | |========================================================= Common Attributes ~~~~~~~~~~~~~~~~~~~ All standard gestures provide a common set of attributes. .Common Gesture Attributes [width="60%",cols="3<,m,d",frame="topbot",options="header"] |========================================================= |name |type |description | GEIS_GESTURE_ATTRIBUTE_DEVICE_ID | GeisInteger | | GEIS_GESTURE_ATTRIBUTE_TIMESTAMP | GeisInteger | | GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID | GeisInteger | | GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID | GeisInteger | | GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID | GeisInteger | | GEIS_GESTURE_ATTRIBUTE_FOCUS_X | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_FOCUS_Y | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME | GeisString | | GEIS_GESTURE_ATTRIBUTE_FINGERS | GeisInteger | |========================================================= Drag ~~~~ NOTE: This section is not complete. .Pan Gesture Attributes [width="60%",cols="3<,m,d",frame="topbot",options="header"] |========================================================= |name |type |description | GEIS_GESTURE_ATTRIBUTE_DELTA_X | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_DELTA_Y | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_VELOCITY_X | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_POSITION_X | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_POSITION_Y | GeisFloat | |========================================================= Pinch ~~~~~ NOTE: This section is not complete. . Pinch Gesture Attributes [width="60%",cols="3<,m,d",frame="topbot",options="header"] |========================================================= |name |type |description | GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_RADIUS | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1 | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1 | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2 | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2 | GeisFloat | |========================================================= Rotate ~~~~~~ NOTE: This section is not complete. . Swipe Gesture Attributes [width="60%",cols="3<,m,d",frame="topbot",options="header"] |========================================================= |name |type |description | GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_ANGLE | GeisFloat | |========================================================= Tap ~~~ NOTE: This section is not complete. .Tap Gesture Attributes [width="60%",cols="3<,m,d",frame="topbot",options="header"] |========================================================= |name |type |description | GEIS_GESTURE_ATTRIBUTE_POSITION_X | GeisFloat | | GEIS_GESTURE_ATTRIBUTE_POSITION_Y | GeisFloat | |========================================================= GEIS Versioning, Header Files, and Constants -------------------------------------------- Each published version of GEIS supports the specified client API of that version and all prior versions of those APIs (backwards compatibility). Header Files ~~~~~~~~~~~~ The GEIS specification defines an ISO C language binding. The GEIS header file ++ provides prototypes for all GEIS entry points and C preprocessors for all GEIS tokens, for use both by client code and implementers. Languages other than C and C++ will define GEIS interfaces using other methods outside the scope of this specification. Compile-time Version Detection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To allow code to be written portably against future GEIS versions, the compile-time environment must make it possible to determine which GEIS version interface are available. For C and C++ code the ++ header defined C preprocessor symbols corresponding to all versions of GEIS supported by the implementation. [source, C] ----------- #define GEIS_VERSION_1_0 1 ----------- Future versions of GEIS will define additional preprocessor symbols corresponding to the major and minor numbers of those versions. Constants and Implementation-Supplied Values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Constants and enumerator values for GEIS tokens defined in this specification are required to be common across all implementations. A reference version of the +geis.h+ header file can be downloaded from *to be determined*. All implementation-specific types, values, and macros used in +geis.h+ are partitioned into an implementation header, +geisimpl.h+, which is automatically6 included by +geis.h+. Implementers should need only modify +geisimpl.h+, never +geis.h+. Conformance Testing for Implementers ------------------------------------ NOTE: This section is not complete. geis-2.2.17+16.04.20160126/doc/Doxyfile0000644000015600001650000022150512651717544017370 0ustar pbuserpbgroup00000000000000# Doxyfile 1.7.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = GEIS # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Gesture Engine Interface Support" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = ../data/logo_x64.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = api # 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: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # 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 # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. 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 = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # 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 = YES # 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. FULL_PATH_NAMES = YES # 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 # only done if one of the specified strings matches the left-hand part of # 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 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. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # 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 regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # 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. MULTILINE_CPP_IS_BRIEF = 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 the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = 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 = YES # 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 OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = 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 # 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 # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # 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 this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = 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 # 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 # and Mac users are advised to set this option to NO. CASE_SENSE_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 = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # 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 FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # 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. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # 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. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # 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. 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 macro 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 macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 0 # 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. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. 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_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # 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 # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../include \ ../doc # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # 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 the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl \ *.dox # 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. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix file system 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. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # 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 = ../examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_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. 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). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # 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 or if # non of the patterns match the file name, INPUT_FILTER is applied. 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 (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # 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 # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = 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 = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # 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. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is adviced to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # 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. 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 = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = NO # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. 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). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. 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. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value 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, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # 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. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. 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. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. 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 # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = 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 optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # 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 = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man 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 `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # 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 #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # 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. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = GEIS_API= # 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 that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # 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 = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. 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'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # 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 also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # 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 # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called Helvetica to the output # directory and reference it in all dot files that doxygen generates. # When you want a differently looking font you can specify the font name # using DOT_FONTNAME. You need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = 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 # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options 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 CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller 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 caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, 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 in 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 MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # 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 the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # 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. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES geis-2.2.17+16.04.20160126/doc/api.dox0000644000015600001650000000134112651717544017141 0ustar pbuserpbgroup00000000000000/** * @mainpage The GEIS API * * @section sec_intro Introduction * * The GEIS API provides a defined, stable, portable interface for receiving * gestural input. * * GEIS actually provides two APIs: * the @ref using_geis_v1 "simplified interface" * and the @ref using_geis_v2 "advanced interface". * * @page using_geis_v1 Using The Simplified Interface * * @section using_geis_v1_intro Introduction to the Simplified GEIS Interface * * The goal of the simplified GEIS interface is to minimize the work required to * receive gestures from the gesture recognition engine. It is designed around * the idea of creating a set of callback functions and installing them to * receive gesture events on a selected window. */ geis-2.2.17+16.04.20160126/autogen.sh0000755000015600001650000000032412651717544017110 0ustar pbuserpbgroup00000000000000#!/bin/sh srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir autoreconf --force --verbose --install || exit 1 cd $ORIGDIR || exit $? test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" geis-2.2.17+16.04.20160126/include/0000755000015600001650000000000012651717732016532 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/include/Makefile.am0000644000015600001650000000164712651717544020577 0ustar pbuserpbgroup00000000000000# # @file include/Makefile.am # @brief automake recipe for the geis (public) includes directory # # Copyright 2010 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # nobase_include_HEADERS = geis/geis.h geis-2.2.17+16.04.20160126/include/geis/0000755000015600001650000000000012651717732017461 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/include/geis/geis.h0000644000015600001650000022561112651717544020571 0ustar pbuserpbgroup00000000000000/** * @file geis/geis.h * This is the public interface for the GEIS gesture API. * * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 US */ #ifndef GEIS_GEIS_H_ #define GEIS_GEIS_H_ #ifdef __cplusplus extern "C" { #endif /** * @defgroup geis_common Common Types and Definitions * * These types and values are common to both the simplified and advanced GEIS * interfaces. */ /** * @defgroup geis_v1 The Simplified GEIS Interface * * The simplified GEIS interface is the original (GEIS v1) API. It provides a * way to specify a list of gesture names and input devices for which gestures * will be recognized on a given window. * * See @ref using_geis_v1. */ /** * @defgroup geis_v2 The Advanced GEIS Interface * * The advanced GEIS interface (GEIS v2) was developed to give a more nuanced * control over the types of gestures and input devices for which gestures will * be recognized. * * See @ref using_geis_v2. */ /** * GEIS version macros * * These macros can be tested at compile time to query for support of various * features. */ #define GEIS_VERSION_1_0 1 #define GEIS_VERSION_2_0 20101122 #include /** * Errors returned from calls. * @ingroup geis_common * * Most GEIS API calls return a status code indicating success or, in the event * of a lack of success, the reson for failure. */ typedef enum GeisStatus { GEIS_STATUS_SUCCESS = 0, /**< normal successful completion */ GEIS_STATUS_CONTINUE = 20, /**< normal successful completion with data still remaining */ GEIS_STATUS_EMPTY = 21, /**< normal successful completion with no data retrieved */ GEIS_STATUS_NOT_SUPPORTED = 10, /**< a requested feature is not supported */ GEIS_BAD_ARGUMENT = 1000, /**< a bad argument value was passed */ GEIS_UNKNOWN_ERROR = 9999, /**< any other error condition */ GEIS_STATUS_BAD_ARGUMENT = -100, /**< a bad argument value was passed */ GEIS_STATUS_UNKNOWN_ERROR = -999 /**< any other error condition */ } GeisStatus; /** * Attribute data types. * @ingroup geis_common */ typedef enum GeisAttrType { GEIS_ATTR_TYPE_UNKNOWN, /**< Attr is an unknown type. */ GEIS_ATTR_TYPE_BOOLEAN, /**< Attr is truth-valued . */ GEIS_ATTR_TYPE_FLOAT, /**< Attr is real-valued. */ GEIS_ATTR_TYPE_INTEGER, /**< Attr is a counting number. */ GEIS_ATTR_TYPE_POINTER, /**< Attr is a pointer to a data structure. */ GEIS_ATTR_TYPE_STRING /**< Attr is a null-terminated UTF-8 string. */ } GeisAttrType; #define GEIS_FALSE 0 #define GEIS_TRUE 1 /* Standard fundamental gestures */ #define GEIS_GESTURE_DRAG "Drag" #define GEIS_GESTURE_PINCH "Pinch" #define GEIS_GESTURE_ROTATE "Rotate" #define GEIS_GESTURE_TAP "Tap" #define GEIS_GESTURE_TOUCH "Touch" /* Extra higher-level gestures. */ #define GEIS_GESTURE_FLICK "Flick" /** * @defgroup geis_v1_gesture_types Gesture Types * @ingroup geis_v1 * * The names of gesture types. These names can be passed to * geis_subscribe() in a NULL-terminated list to specify only a subset of * available gestures. */ /** * @defgroup geis_v1_gesture_primitives Gesture Primitives * @ingroup geis_v1_gesture_types * * These are the prime gesture primitive that describes the general action of * the touchpoints at an instant in time. * * These are the values passed as the @p gesture_type parameter to the * GeisGestureCallback. * * @{ * * @def GEIS_GESTURE_PRIMITIVE_DRAG * A translate gesture: dragging, swiping, flicking, moving in a generally * linear fashion. * * @def GEIS_GESTURE_PRIMITIVE_PINCH * A pinch or expand gesture: two or more touch points generally moving toward * or away from a common point. * * @def GEIS_GESTURE_PRIMITIVE_ROTATE * A rotation gesture. Two or more points moving relatively along an arc with a * commonish centre. * * @def GEIS_GESTURE_PRIMITIVE_TAP * A tap. Touch down, touch up, one or more touches. * * @def GEIS_GESTURE_PRIMITIVE_TOUCH * A parenthetical gesture event. Touch down (start) and up (finish). */ #define GEIS_GESTURE_PRIMITIVE_DRAG 0 #define GEIS_GESTURE_PRIMITIVE_PINCH 1 #define GEIS_GESTURE_PRIMITIVE_ROTATE 2 #define GEIS_GESTURE_PRIMITIVE_TAP 15 #define GEIS_GESTURE_PRIMITIVE_TOUCH 32 /* @} */ #define GEIS_GESTURE_ID_FLICK 128 /** * @defgroup geis_v1_standar_gesture_types Standard Gesture Types * @ingroup geis_v1_gesture_types * * These gesture types should be available on all GEIS implementations. * * @{ */ /* Gesture names for the Simplified Interface */ #define GEIS_GESTURE_TYPE_DRAG1 "Drag,touch=1" #define GEIS_GESTURE_TYPE_DRAG2 "Drag,touch=2" #define GEIS_GESTURE_TYPE_DRAG3 "Drag,touch=3" #define GEIS_GESTURE_TYPE_DRAG4 "Drag,touch=4" #define GEIS_GESTURE_TYPE_DRAG5 "Drag,touch=5" #define GEIS_GESTURE_TYPE_PINCH1 "Pinch,touch=1" #define GEIS_GESTURE_TYPE_PINCH2 "Pinch,touch=2" #define GEIS_GESTURE_TYPE_PINCH3 "Pinch,touch=3" #define GEIS_GESTURE_TYPE_PINCH4 "Pinch,touch=4" #define GEIS_GESTURE_TYPE_PINCH5 "Pinch,touch=5" #define GEIS_GESTURE_TYPE_ROTATE1 "Rotate,touch=1" #define GEIS_GESTURE_TYPE_ROTATE2 "Rotate,touch=2" #define GEIS_GESTURE_TYPE_ROTATE3 "Rotate,touch=3" #define GEIS_GESTURE_TYPE_ROTATE4 "Rotate,touch=4" #define GEIS_GESTURE_TYPE_ROTATE5 "Rotate,touch=5" #define GEIS_GESTURE_TYPE_TAP1 "Tap,touch=1" #define GEIS_GESTURE_TYPE_TAP2 "Tap,touch=2" #define GEIS_GESTURE_TYPE_TAP3 "Tap,touch=3" #define GEIS_GESTURE_TYPE_TAP4 "Tap,touch=4" #define GEIS_GESTURE_TYPE_TAP5 "Tap,touch=5" #define GEIS_GESTURE_TYPE_TOUCH1 "Touch,touch=1" #define GEIS_GESTURE_TYPE_TOUCH2 "Touch,touch=2" #define GEIS_GESTURE_TYPE_TOUCH3 "Touch,touch=3" #define GEIS_GESTURE_TYPE_TOUCH4 "Touch,touch=4" #define GEIS_GESTURE_TYPE_TOUCH5 "Touch,touch=5" /* @} */ /** * @defgroup geis_v1_vendor_extensions Vendor Extension Gesture Types * @ingroup geis_v1_gesture_types * * Vendor-specific extensions to the GEIS v1 API. * * @{ */ /** * A special gesture type than enabled system-wide gesture priority. */ #define GEIS_GESTURE_TYPE_SYSTEM "Sysflags" #define GEIS_GESTURE_TYPE_FLICK1 "Flick,touch=1" #define GEIS_GESTURE_TYPE_FLICK2 "Flick,touch=2" #define GEIS_GESTURE_TYPE_FLICK3 "Flick,touch=3" #define GEIS_GESTURE_TYPE_FLICK4 "Flick,touch=4" #define GEIS_GESTURE_TYPE_FLICK5 "Flick,touch=5" /* @} */ /** * @name Standard fundamental gesture attributes * * @{ * * @def GEIS_GESTURE_ATTRIBUTE_ANGLE * Angle covered by a gesture since it has started, in radians, counterclockwise. * Its value ranges from -pi to pi. * * @def GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA * Angle covered by a gesture since its last update, in radians, * counterclockwise. * * @def GEIS_GESTURE_ATTRIBUTE_CENTROID_X * This attribute provides the X coordinate of the centroid of the * non-self-intersecting closed polygon defined by the touch points of the * gesture, in device coordinates. * * @def GEIS_GESTURE_ATTRIBUTE_CENTROID_Y * This attribute provides the Y coordinate of the centroid of the * non-self-intersecting closed polygon defined by the touch points of the * gesture, in device coordinates. * * @def GEIS_GESTURE_ATTRIBUTE_FOCUS_X * This attribute provides the X coordinate of the focus point of a gesture, * in screen coordinates. * For direct devices (GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH is GEIS_TRUE) it's * the centroid point. For indirect devices it's the pointer/cursor position. * * @def GEIS_GESTURE_ATTRIBUTE_FOCUS_Y * This attribute provides the Y coordinate of the focus point of a gesture, * in screen coordinates. * For direct devices (GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH is GEIS_TRUE) it's * the centroid point. For indirect devices it's the pointer/cursor position. * * @def GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME * Name of the gesture. * This attribute is filled only when using GEIS v1 API (the simplified * interface). On GEIS v2 this attribute has been replaced by the concept of * gesture classes. Use geis_frame_is_class() instead. * * @def GEIS_GESTURE_ATTRIBUTE_POSITION_X * This attribute provides the X coordinate of the position of a gesture, in * device coordinates. It's the same as the centroid of a gesture. See * GEIS_GESTURE_ATTRIBUTE_CENTROID_X. * * @def GEIS_GESTURE_ATTRIBUTE_POSITION_Y * This attribute provides the Y coordinate of the position of a gesture, in * device coordinates. It's the same as the centroid of a gesture. See * GEIS_GESTURE_ATTRIBUTE_CENTROID_Y. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID * This attribute provides the ID of the touch at index0. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X * This attribute provides the X coordinate of the touch at index0. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y * This attribute provides the Y coordinate of the touch at index0. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID * This attribute provides the ID of the touch at index1. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X * This attribute provides the X coordinate of the touch at index1. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y * This attribute provides the Y coordinate of the touch at index1. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID * This attribute provides the ID of the touch at index2. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X * This attribute provides the X coordinate of the touch at index2. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y * This attribute provides the Y coordinate of the touch at index2. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID * This attribute provides the ID of the touch at index3. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X * This attribute provides the X coordinate of the touch at index3. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y * This attribute provides the Y coordinate of the touch at index3. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID * This attribute provides the ID of the touch at index4. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X * This attribute provides the X coordinate of the touch at index4. * Only used by GEIS v1 API. * * @def GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y * This attribute provides the Y coordinate of the touch at index4. * Only used by GEIS v1 API. */ #define GEIS_GESTURE_ATTRIBUTE_ANGLE "angle" #define GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA "angle delta" #define GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY "angular velocity" #define GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1 "boundingbox x1" #define GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1 "boundingbox y1" #define GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2 "boundingbox x2" #define GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2 "boundingbox y2" #define GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID "child window id" #define GEIS_GESTURE_ATTRIBUTE_CENTROID_X "centroid x" #define GEIS_GESTURE_ATTRIBUTE_CENTROID_Y "centroid y" #define GEIS_GESTURE_ATTRIBUTE_DELTA_X "delta x" #define GEIS_GESTURE_ATTRIBUTE_DELTA_Y "delta y" #define GEIS_GESTURE_ATTRIBUTE_DEVICE_ID "device id" #define GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID "event window id" #define GEIS_GESTURE_ATTRIBUTE_FOCUS_X "focus x" #define GEIS_GESTURE_ATTRIBUTE_FOCUS_Y "focus y" #define GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME "gesture name" #define GEIS_GESTURE_ATTRIBUTE_POSITION_X "position x" #define GEIS_GESTURE_ATTRIBUTE_POSITION_Y "position y" #define GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY "radial velocity" #define GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA "radius delta" #define GEIS_GESTURE_ATTRIBUTE_RADIUS "radius" #define GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID "root window id" #define GEIS_GESTURE_ATTRIBUTE_TAP_TIME "tap time" #define GEIS_GESTURE_ATTRIBUTE_TIMESTAMP "timestamp" #define GEIS_GESTURE_ATTRIBUTE_TOUCHES "touches" #define GEIS_GESTURE_ATTRIBUTE_VELOCITY_X "velocity x" #define GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y "velocity y" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID "touch 0 id" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X "touch 0 x" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y "touch 0 y" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID "touch 1 id" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X "touch 1 x" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y "touch 1 y" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID "touch 2 id" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X "touch 2 x" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y "touch 2 y" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID "touch 3 id" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X "touch 3 x" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y "touch 3 y" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID "touch 4 id" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X "touch 4 x" #define GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y "touch 4 y" /* @} */ /** * @defgroup geis_meta Initialization and Cleanup * @ingroup geis_v1 * * Each instance of a gesture subscription must be created using the geis_init() * call and destroyed using the geis_finish() call. * * A particular subscription instance is associated with a display region. The * nature of the display region depends on the underlying display technology. * For example, an X11 window or even a subregion of an X11 window could be an * associated display region when geis is layered over X11 technology. * * The nature of the display desciption information depends on the actual * underlyinggeis implementation and is documented separately. The * implementation-specific description must be passed to geis_init using a * GeisWinInfo structure. * * @{ */ /** * @class GeisInstance * A geis gesture subscription instance. */ /** @cond typedef */ typedef struct _GeisInstance *GeisInstance; /** @endcond */ /** * @class GeisWinInfo * Generic display region description block */ typedef struct GeisWinInfo { uint32_t win_type; /**< Selects the implementation-specific window type. */ void *win_info; /**< Additional info dependent on the window type. */ } GeisWinInfo; /** * Initializes a geis subscription instance for a display region. * @memberof GeisInstance * * @param[in] win_info a display region description block * -- see geis implementtaion documentation * @param[out] geis_instance an opaque pointer to a geis gesture subscription * instance * * @retval GEIS_BAD_ARGUMENT an invalid GeisWinInfo was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_init(GeisWinInfo *win_info, GeisInstance *geis_instance); /** * Cleans up a geis subscription instance for a display region. * @memberof GeisInstance * * @param[in] geis_instance an opaque pointer to a geis gesture subscription * instance * * @retval GEIS_BAD_ARGUMENT an invalid GeisInstance was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_finish(GeisInstance geis_instance); /* @} */ /** * @defgroup geis_v1_config Configuration and Control * @ingroup geis_v1 * @{ */ /** * Gets the Unix file descriptor for GEIS events. * * Applications or toolkits can use this file descriptor to intgerate geis event * handling into their main event dispatch loop. When a GEIS event is available * for processing, the fd will have a read-available state indicated in * select(), poll(), epoll(), etc. */ #define GEIS_CONFIG_UNIX_FD 10001 /** * Indicates if a particular feaure is supported. * * @param[in] geis_instance An opaque pointer to a geis gesture subscription * instance. * @param[in] configuration_item Indicates which configuration item will be * checked for support. * * @retval GEIS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_configuration_supported(GeisInstance geis_instance, int configuration_item); /** * Gets a feature configuration value. * * @param[in] geis_instance An opaque pointer to a geis gesture subscription * instance. * @param[in] configuration_item Indicates which configuration item will be * get. * @param[in] value A pointer to where the retrieved value will be * stored. * * @retval GEIS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_configuration_get_value(GeisInstance geis_instance, int configuration_item, void *value); /** * Sets a feature configuration value. * * @param[in] geis_instance An opaque pointer to a geis gesture subscription * instance. * @param[in] configuration_item Indicates which configuration item will be * set. * @param[in] value A pointer to where the value to be set will be * read. * * @retval GEIS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_configuration_set_value(GeisInstance geis_instance, int configuration_item, void *value); /** * Dispatches geis events until there are no further events available. * * @param[in] geis_instance an opaque pointer to a geis gesture subscription * instance * * This function is used to integrate geis even dispatch into the main event * loop of an application or toolkit. * * @retval GEIS_BAD_ARGUMENT an invalid GeisInstance was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_event_dispatch(GeisInstance geis_instance); /* @} */ /** * @defgroup geis_v2_geis The Geis API Object * @ingroup geis_v2 * * @{ */ /** * @class Geis * Represents an instance of the gesture recognition engine */ /** @cond typedef */ typedef struct _Geis *Geis; /** @endcond */ /** * @name Standard Initialization Arguments * * @par * These initialization arguments are defined by the GEIS v2 specification. * * @{ * * @def GEIS_INIT_SERVICE_PROVIDER * Enables GEIS to provide a networked service. * This initialization argument takes no parameters. * * @def GEIS_INIT_TRACK_DEVICES * Tells GEIS to send input device events. * This initialization argument takes no parameters. * * @def GEIS_INIT_TRACK_GESTURE_CLASSES * Tells GEIS to send gesture class events. * This initialization argument takes no parameters. * * @def GEIS_INIT_SYNCHRONOUS_START * Performs all setup synchronously: geis_new() will block until all setup has * completed successfully or unsuccessfully. */ #define GEIS_INIT_SERVICE_PROVIDER "org.libgeis.init.server" #define GEIS_INIT_TRACK_DEVICES "org.libgeis.init.track-devices" #define GEIS_INIT_TRACK_GESTURE_CLASSES "org.libgeis.init.track-gesture-classes" #define GEIS_INIT_SYNCHRONOUS_START "org.libgeis.init.synchronous-start" /* @} */ /** * @name Vendor-defined Initialization Arguments * * @par * These initialization arguments are not a part of the GEIS specification and * may change. * * @{ * * @def GEIS_INIT_DBUS_BACKEND * Uses the DBus back end (default). * * @def GEIS_INIT_GRAIL_BACKEND * Uses the native grail back end (fallback). * * @def GEIS_INIT_XCB_BACKEND * Uses the grail-embedded-in-X11 back end. * * @def GEIS_INIT_NO_ATOMIC_GESTURES * Disables the use of (GEIS v1-style) atomic gestures: only a single gesture * is recognized at a time. * * @def GEIS_INIT_SEND_TENTATIVE_EVENTS * Causes tentative events to be sent. Tentative events indicate gestures may * possibly be detected soon and allow early rejection if the events occur * outside any area of interest. * * @def GEIS_INIT_SEND_SYNCHRONOS_EVENTS * Causes all gesture events to be sent, even if there is zero apparent time * difference between the events. Normally all but the first consecutive event * are discarded, since velocity values can not be calculated and multiple * events between frame redraws are unlikely do have any value beyong consuming * CPU. Setting this init value will give the events to you if you really want * them. */ #define GEIS_INIT_DBUS_BACKEND "com.canonical.oif.backend.dbus" #define GEIS_INIT_GRAIL_BACKEND "com.canonical.oif.backend.grail" #define GEIS_INIT_XCB_BACKEND "com.canonical.oif.backend.xcb" #define GEIS_INIT_NO_ATOMIC_GESTURES "com.canonical.oif.no-atomic.gestures" #define GEIS_INIT_SEND_TENTATIVE_EVENTS "com.canonical.oif.events.tentative" #define GEIS_INIT_SEND_SYNCHRONOS_EVENTS "com.canonical.oif.events.synchronous" /* @} */ /** * Initializes an instance of the GEIS v2.0 API. * @ingroup geis_v2_geis * @memberof Geis * * @param[in] init_arg_name The name of an initializaer argument. * @param[in] ... The remaining initializaer arguments. * * A NULL-terminated list of zero or more initialization arguments is passed to * this function to create and initialize a connection to a gesture recognition * engine. * * If no initialization arguments are passed, the parameter list consists of a * single NULL argument. */ GEIS_API GEIS_VARARG Geis geis_new(GeisString init_arg_name, ...); /** * Cleans up an instance of the GEIS v2.0 API. * @ingroup geis_v2_geis * @memberof Geis * * @param[in] geis An instance of the GEIS v2.0 API. * * Tears down the instance of the API and releases any resources associated with * that instance. */ GEIS_API GeisStatus geis_delete(Geis geis); /* @} */ /** * @defgroup geis_v2_error Error Reporting * @ingroup geis_v2 * @{ */ /** * Gets the number of status codes in the error stack. * * @param[in] geis A GEIS API instance or NULL for the global stack * * This function is used primarily to determine the failure details of a GEIS * function that does not explicitly return a GeisStatus value. This is * required for _new() fucntions that return NULL to indicate failure. If the * call to geis_new() itself fails and returns a NULL, the global error stack * must be used, otherwise the API instance error stack must be used. * * The error stack is reset on each GEIS API call, so failure reasons should be * determined immmediately after a GEIS API call. */ GEIS_API GeisSize geis_error_count(Geis geis); /** * Gets the indicated status code from the error stack. * * @param[in] geis A GEIS API instance or NULL for the global stack * @param[in] index Indicates the status value to retrieve. Valid status values * are between 0 and less than the value returned from * geis_error_count() otherwise GEIS_STATUS_BAD_ARGUMENT will * be returned. */ GEIS_API GeisStatus geis_error_code(Geis geis, GeisSize index); /** * Gets the localized error message, if any, associated with the indicated * error. * * @param[in] geis A GEIS API instance or NULL for the global stack * @param[in] index Indicates the status value to retrieve. Valid status values * are between 0 and less than the value returned from * geis_error_count() otherwise GEIS_STATUS_BAD_ARGUMENT will * be returned. */ GEIS_API GeisString geis_error_message(Geis geis, GeisSize index); /* @} */ /** * @defgroup geis_v2_config Configuration * @ingroup geis_v2 * @{ */ /** * @name Required Configuration Items * * @par * These configuration items are defined by the GEIS specification. * * @{ * * @def GEIS_CONFIGURATION_FD * Gets a Unix file descriptor that will signal the availablility of GEIS events * for processing. */ #define GEIS_CONFIGURATION_FD "org.libgeis.configuration.fd" /* @} */ /** * @name Vendor-defined Configuration Items * * @par * These configuration items are not a part of the GEIS specification and may * change. * * @{ * * @def GEIS_CONFIG_MAX_EVENTS */ #define GEIS_CONFIG_MAX_EVENTS "com.canonical.oif.max_events" /** * @def GEIS_CONFIG_ATOMIC_GESTURES * Indicates if atomic gestures are in use. Value type GeisBoolean. */ #define GEIS_CONFIG_ATOMIC_GESTURES "com.canonical.use.atomic.gestures" /** * @def GEIS_CONFIG_SEND_TENTATIVE_EVENTS * See GEIS_INIT_SEND_TENTATIVE_EVENTS */ #define GEIS_CONFIG_SEND_TENTATIVE_EVENTS "com.canonical.oif.events.tentative" /** * @def GEIS_CONFIG_SEND_SYNCHRONOS_EVENTS * See GEIS_INIT_SEND_SYNCHRONOS_EVENTS */ #define GEIS_CONFIG_SEND_SYNCHRONOS_EVENTS "com.canonical.oif.events.synchronous" /** * @def GEIS_CONFIG_DRAG_THRESHOLD * Movement threshold for recognizing a DRAG gesture (in meters). Value type * GeisFloat. */ #define GEIS_CONFIG_DRAG_THRESHOLD "com.canonical.oif.drag.threshold" /** * @def GEIS_CONFIG_DRAG_TIMEOUT * Timeout for recognizing a DRAG gesture (in milliseconds). Value type * GeisInteger. */ #define GEIS_CONFIG_DRAG_TIMEOUT "com.canonical.oif.drag.timeout" /** * @def GEIS_CONFIG_PINCH_THRESHOLD * Movement threshold for recognizing a PINCH gesture (in meters). Value type * GeisFloat. */ #define GEIS_CONFIG_PINCH_THRESHOLD "com.canonical.oif.pinch.threshold" /** * @def GEIS_CONFIG_PINCH_TIMEOUT * Timeout for recognizing a PINCH gesture (in milliseconds). Value type * GeisInteger. */ #define GEIS_CONFIG_PINCH_TIMEOUT "com.canonical.oif.pinch.timeout" /** * @def GEIS_CONFIG_ROTATE_THRESHOLD * Movement threshold for recognizing a ROTATE gesture (in meters). Value type * GeisFloat. */ #define GEIS_CONFIG_ROTATE_THRESHOLD "com.canonical.oif.rotate.threshold" /** * @def GEIS_CONFIG_ROTATE_TIMEOUT * Timeout for recognizing a ROTATE gesture (in milliseconds). Value type * GeisInteger. */ #define GEIS_CONFIG_ROTATE_TIMEOUT "com.canonical.oif.rotate.timeout" /** * @def GEIS_CONFIG_TAP_THRESHOLD * Movement threshold for recognizing a TAP gesture (in meters). Value type * GeisFloat. */ #define GEIS_CONFIG_TAP_THRESHOLD "com.canonical.oif.tap.threshold" /** * @def GEIS_CONFIG_TAP_TIMEOUT * Timeout for recognizing a TAP gesture (in milliseconds). Value type * GeisInteger. */ #define GEIS_CONFIG_TAP_TIMEOUT "com.canonical.oif.tap.timeout" /** * @def GEIS_CONFIG_NUM_ACTIVE_SUBSCRIPTIONS * The number of subscriptions currently active in the back end. * This config is query-only and intended for unit test validations. */ #define GEIS_CONFIG_NUM_ACTIVE_SUBSCRIPTIONS "com.canonical.oif.debug.active_subs" /* @} */ /** * Gets a feature configuration value. * * @param[in] geis An opaque GEIS API object. * @param[in] configuration_item_name Selects the configuration value to return. * @param[out] configuration_item_value Points to a buffer to contain the output * value. The actual type of this buffer * depends on the * @p configuration_value_name. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_get_configuration(Geis geis, GeisString configuration_item_name, void *configuration_item_value); /** * Sets a feature configuration value. * * @param[in] geis An opaque GEIS API object. * @param[in] configuration_item_name Selects the configuration value to return. * @param[in] configuration_item_value Points to a buffer to contain the output * configuration value. The actual type of * this buffer depends on the * @p configuration_value_name. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_set_configuration(Geis geis, GeisString configuration_item_name, void *configuration_item_value); /* @} */ /** * @defgroup geis_v1_input Input Devices * @ingroup geis_v1 * @{ */ typedef unsigned int GeisInputDeviceId; #define GEIS_ALL_INPUT_DEVICES ((GeisInputDeviceId*)0) /** * Prototype for input device callback functions. */ typedef void (*GeisInputCallback)(void *cookie, GeisInputDeviceId device_id, void *attrs); /** * Callback functions used to handle changes in the available input devices. */ typedef struct GeisInputFuncs { GeisInputCallback added; /**< Receives new input device notices */ GeisInputCallback changed; /**< Receives modified input device notices */ GeisInputCallback removed; /**< Receives removes input device notices */ } GeisInputFuncs; /** * Registers a callback to receive information on input devices. * * @param[in] geis_instance points to a geis gesture subscription * instance * @param[in] func points to a GeisInputFuncs table * @param[in] cookie an application specific value to be passed to * the callback * * The callback is called for each gesture-capable input device available for * the display region associated with the geis subscription instance. Over * time, as gesture-capable input devices appear and disappear or change their * abilities or configuration, the callback may be called again. * * @retval GEIS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_input_devices(GeisInstance geis_instance, GeisInputFuncs *func, void *cookie); /* @} */ /** * @defgroup geis_v1_subscription Gesture Subscription * @ingroup geis_v1 * @{ */ typedef unsigned int GeisGestureType; typedef unsigned int GeisGestureId; /** Selects ALL input devices. */ #define GEIS_ALL_GESTURES ((GeisGestureType)0) #define GEIS_NO_GESTURE_ID ((GeisGestureId)0) /** * An individual gesture attribute. * * Gesture events are associated with a list of attributes, each of which is a * (name, type, value) tuple. These attribute reveal a little piece of * information about a gesture. */ typedef struct GeisGestureAttr { /** The name of the gesture attribute. */ GeisString name; /** The data type of the gesture attribute. */ GeisAttrType type; /** The value of the attributes. */ __extension__ union { GeisBoolean boolean_val; GeisFloat float_val; GeisInteger integer_val; GeisString string_val; }; } GeisGestureAttr; /** * A callback used for different gesture events. * * @param[in] cookie an application-specific value to be passed to the * callback. * @param[in] gesture_type a gesture type * @param[in] gesture_id a unique gesture identifier * @param[in] attrs parameters */ typedef void (*GeisGestureCallback)(void *cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr *attrs); /** * The set of callback functions invoked for various gesture-related events. * * An application must define callback functions to handle the various gesture * events. These callbacks are provided in a table passed to geis_subscribe for * each window on which gesture events may occur. */ typedef struct GeisGestureFuncs { /** Invoked when a new gesture type has been defined. */ GeisGestureCallback added; /** Invoked when a defined gesture type is no longer available. */ GeisGestureCallback removed; /** Invoked when a new gesture starts. */ GeisGestureCallback start; /** Invoked when a gesture has changed values. */ GeisGestureCallback update; /** Invoked when a gesture finishes. */ GeisGestureCallback finish; } GeisGestureFuncs; /** * Registers a callback to receive gesture events. * * @param[in] geis_instance an opaque pointer to a geis gesture subscription * instance * @param[in] input_list a null-terminated list of input device IDs * @param[in] gesture_list a null-terminated list of C-style strings naming * gestures for subscription * @param[in] funcs a pointer to a GeisGestureFuncs structure * @param[in] cookie an application specific value to be passed to * the callback * * @retval GEIS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_subscribe(GeisInstance geis_instance, GeisInputDeviceId *input_list, const char* *gesture_list, GeisGestureFuncs *funcs, void *cookie); /** * Unsubscribes to one or more gestures. * * @param[in] geis_instance an opaque pointer to a geis gesture subscription * instance * @param[in] gesture_list a null-terminated list of gesture types */ GEIS_API GeisStatus geis_unsubscribe(GeisInstance geis_instance, GeisGestureType *gesture_list); /* @} */ /** * @defgroup geis_v2_attrs Attributes * @ingroup geis_v2 * * Attributes are named values associated with various GEIS entities, including * input devices, gesture types, and gesture events. * * @{ */ /** * An opaque type that encapsulates a GEIS attribute. * * GeisAttr objects may not be created or destroyed by the application, they may * only have their data examined or extracted. */ /** @cond typedef */ typedef struct _GeisAttr *GeisAttr; /** @endcond */ /** * Gets the name of an attribute. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisString geis_attr_name(GeisAttr attr); /** * Gets the type of an attribute value. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisAttrType geis_attr_type(GeisAttr attr); /** * Gets the value of an attribute as a GeisBoolean. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisBoolean geis_attr_value_to_boolean(GeisAttr attr); /** * Gets the value of an attribute as a GeisFloat. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisFloat geis_attr_value_to_float(GeisAttr attr); /** * Gets the value of an attribute as a GeisInteger. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisInteger geis_attr_value_to_integer(GeisAttr attr); /** * Gets the value of an attribute as a GeisPointer. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisPointer geis_attr_value_to_pointer(GeisAttr attr); /** * Gets the value of an attribute as a GeisString. * * @param[in] attr Identifies the attribute. */ GEIS_API GeisString geis_attr_value_to_string(GeisAttr attr); /* @} */ /** * @defgroup geis_v2_event_control Event Control * @ingroup geis_v2 * * These functions are used to dispatch events generated from the various other * GEIS components. * * Applications must invoke geis_dispatch_events() from time to time to generate * input device, gesture type, and gesture events. The GEIS events are then * retrieved either from the internal event queue using the geis_next_event() * call or through an application-supplied callback set through the * geis_register_event_callback() call. * * @{ */ typedef enum _GeisEventType { GEIS_EVENT_DEVICE_AVAILABLE = 1000, GEIS_EVENT_DEVICE_UNAVAILABLE = 1010, GEIS_EVENT_CLASS_AVAILABLE = 2000, GEIS_EVENT_CLASS_CHANGED = 2005, GEIS_EVENT_CLASS_UNAVAILABLE = 2010, GEIS_EVENT_GESTURE_BEGIN = 3000, GEIS_EVENT_GESTURE_UPDATE = 3010, GEIS_EVENT_GESTURE_END = 3020, GEIS_EVENT_TENTATIVE_BEGIN = 3500, GEIS_EVENT_TENTATIVE_UPDATE = 3510, GEIS_EVENT_TENTATIVE_END = 3520, GEIS_EVENT_INIT_COMPLETE = 4000, GEIS_EVENT_USER_DEFINED = 6000, GEIS_EVENT_ERROR = 7000 } GeisEventType; /** * @class GeisEvent * A generic GEIS event. * * Applications must determine the type of the actual event and convert the * opaque pointer to a concrete event pointer, if required. * * Events are created by the GEIS API but must be destroyed by the application. */ /** @cond typedef */ typedef struct _GeisEvent *GeisEvent; /** @endcond */ /** * Destroys a GeisEvent. * @memberof GeisEvent * * @param[in] event The GeisEvent to destroy. */ GEIS_API void geis_event_delete(GeisEvent event); /** * Gets the type of the event. * @memberof GeisEvent * * @param[in] event The GeisEvent to destroy. */ GEIS_API GeisEventType geis_event_type(GeisEvent event); /** * Gets the number of attributes in the event. * @memberof GeisEvent * * @param[in] event The GeisEvent. */ GEIS_API GeisSize geis_event_attr_count(GeisEvent event); /** * Gets an indicated attribute from the event. * @memberof GeisEvent * * @param[in] event The GeisEvent. * @param[in] index Indicates the attribute to retrieve. */ GEIS_API GeisAttr geis_event_attr(GeisEvent event, GeisSize index); /** * Gets a named attribute from the event. * @memberof GeisEvent * * @param[in] event The GeisEvent. * @param[in] attr_name The name of the attribute to retrieve. */ GEIS_API GeisAttr geis_event_attr_by_name(GeisEvent event, GeisString attr_name); /** * The application callback type for the event dispatcher. * * @param[in] geis the GEIS API instance * @param[in] event the opaque event pointer * @param[in] context the application-supplied context value */ typedef void (*GeisEventCallback)(Geis geis, GeisEvent event, void *context); /** * A special constant indicating the use of the default event callback. */ #define GEIS_DEFAULT_EVENT_CALLBACK ((GeisEventCallback)0) /** * Registers an event-handler callback. * * @param[in] geis the GEIS API instance * @param[in] event_callback the callback to register * @param[in] context the caller context * * This function registers the callback to be executed whenever a new GeisEvent * is generated. The default function pushes the GeisEvent onto an internal * queue to be picked up by a call to geis_next_event(). * * Calling geis_register_event_callback() with a callback of * GEIS_DEFAULT_EVENT_CALLBACK replaces any registered function wit hthe default * function. * * The callback is executed in the same thread context as the one * geis_dispatch_events() is called from. */ GEIS_API void geis_register_event_callback(Geis geis, GeisEventCallback event_callback, void *context); /** * Pumps the GEIS event loop. * * @param[in] geis The GEIS API instance. * * Processes input events until there are no more input events to process and * generates zero or more gesture events, reporting them via the user-supplied * callback or pushing them on the internal event queue for retrieval via the * geis_next_event() call. * * @retval GEIS_STATUS_SUCCESS The event loop was successfully pumped and * no further events remain to be processed at * this time. * * @retval GEIS_STATUS_CONTINUE The event loop was successfully pumped but * the system detected there are events * still remaining to be processed. * * @retval GEIS_STATUS_UNKNOWN_ERROR Some error occurred */ GEIS_API GeisStatus geis_dispatch_events(Geis geis); /** * Retrieves the next queued GEIS event. * * @param[in] geis The GEIS API instance. * @param[out] event The GeisEvent retrieved, if any. * * Pulls the next available GeisEvent from the internal event queue, if any, and * indicates whether there are more events left. * * @retval GEIS_STATUS_SUCCESS An event was successfully pulled from the * queue and the queue is now empty. * * @retval GEIS_STATUS_CONTINUE An event was successfully pulled from the * queue and one or more events remain in the * queue. * * @retval GEIS_STATUS_EMPTY No event was pulled from the queue because * it is empty. The value of *event remains * unchanged. * * @retval GEIS_STATUS_UNKNOWN_ERROR Some error occurred */ GEIS_API GeisStatus geis_next_event(Geis geis, GeisEvent *event); /* @} */ /** * @defgroup geis_v2_device Input Devices * @ingroup geis_v2 * @{ */ /** * @name Device Event Attributes * @{ * * @def GEIS_EVENT_ATTRIBUTE_DEVICE * The event attribute containing a pointer to a GeisDevice. * * The GEIS_EVENT_DEVICE_AVAILABLE and GEIS_EVENT_DEVICE_UNAVAILABLE events * should have a GEIS_ATTR_TYPE_POINTER attribute with this name. It * should contain a pointer to a GeisDevice describing the device made available * or unavailable. */ #define GEIS_EVENT_ATTRIBUTE_DEVICE "device" /* @} */ /** * @name Device Attributes * @{ * * @def GEIS_DEVICE_ATTRIBUTE_NAME * The name of the input device. Not guaranteed unique. * * The attribute value is of type GeisString. * * @def GEIS_DEVICE_ATTRIBUTE_ID * The unique integer ID of the device. Guaranteed unique within a Geis * instance. * * The attribute values is of type GeisInteger. * * @def GEIS_DEVICE_ATTRIBUTE_TOUCHES * The maximum number of touches a device is capable of reporting. * This integer is the number if simultaneous touches the device claims to be * able to detect if it is a multi-touch device. A value of zero indicates the * maximum number of touches can not be determined. * * The attribute value is of type GeisInteger. * * @def GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH * Indicates the device is a direct touch device. * The present of this boolean attribute with a value of GEIS_TRUE indicates the * device is a direct touch multi-touch device (for example, a touchscreen), * otherwise it is an indirect touch device (such as a touchpad) or not a touch * device at all. * * The attribute value is of type GeisBoolean. * * @def GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH * Indicates the device is an independent touch device. * The presence of this boolean attribute with a value of GEIS_TRUE indicates * the device is an independent touch device (for example, an Apple MagicMouse). * Other multi-touch devices should report GEIS_FALSE. * * The attribute value is of type GeisBoolean. * * @def GEIS_DEVICE_ATTRIBUTE_MIN_X * The lower bound of the X-axis (nominally horizontal) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. * * @def GEIS_DEVICE_ATTRIBUTE_MAX_X * The upper bound of the X-axis (nominally horizontal) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. * * @def GEIS_DEVICE_ATTRIBUTE_RES_X * The resolution of the X-axis (nominally horizontal) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. * * @def GEIS_DEVICE_ATTRIBUTE_MIN_Y * The lower bound of the Y-axis (nominally vertical) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. * * @def GEIS_DEVICE_ATTRIBUTE_MAX_Y * The upper bound of the Y-axis (nominally vertical) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. * * @def GEIS_DEVICE_ATTRIBUTE_RES_Y * The resolution of the Y-axis (nominally vertical) coordinate values * reported by the device. * * The attribute values is of type GeisFloat. */ #define GEIS_DEVICE_ATTRIBUTE_NAME "device name" #define GEIS_DEVICE_ATTRIBUTE_ID "device id" #define GEIS_DEVICE_ATTRIBUTE_TOUCHES "device touches" #define GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH "direct touch" #define GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH "independent touch" #define GEIS_DEVICE_ATTRIBUTE_MIN_X "device X minimum" #define GEIS_DEVICE_ATTRIBUTE_MAX_X "device X maximum" #define GEIS_DEVICE_ATTRIBUTE_RES_X "device X resolution" #define GEIS_DEVICE_ATTRIBUTE_MIN_Y "device Y minimum" #define GEIS_DEVICE_ATTRIBUTE_MAX_Y "device Y maximum" #define GEIS_DEVICE_ATTRIBUTE_RES_Y "device Y resolution" /* @} */ /** * @class GeisDevice * A gesture-capable input device. * * GeisDevice objects are created by the GEIS API and are reference counted. */ /** @cond typedef */ typedef struct _GeisDevice *GeisDevice; /** @endcond */ GEIS_API void geis_register_device_callback(Geis geis, GeisEventCallback event_callback, void *context); /** * Gets a cached device description for an identified device. * * @param[in] geis The GEIS API instance. * @param[in] device_id Identifies the device. * * The GEIS instance caches a list of gesture-capable input devices that have * been reported. The GeisDevice description for an identified device may be * retrieved from that cache with this call. * * @returns a valid GeisDevice for the identified device, or NULL if no such * device is in the cache. */ GEIS_API GeisDevice geis_get_device(Geis geis, GeisInteger device_id); /** * Adds a reference count to a device. * @memberof GeisDevice * * @param[in] device The device. * * An application that wishes to guarantee the device object remains valid * should add a reference using this call, and unref when the object is no * longer needed. * * @returns @p device for syntactic convenience. */ GEIS_API GeisDevice geis_device_ref(GeisDevice device); /** * Removes a reference count from a device. * @memberof GeisDevice * * @param[in] device The device. * * This function decrements the number of references to the device and, if the * number of references hits zero, deletes the device. */ GEIS_API void geis_device_unref(GeisDevice device); /** * Gets the name of the input device. * @memberof GeisDevice * * @param[in] device The device. */ GEIS_API GeisString geis_device_name(GeisDevice device); /** * Gets the system identifier of the iput device. * @memberof GeisDevice * * @param[in] device The device. * * The system-defined device identifier is system- and possibly * device-dependent. */ GEIS_API GeisInteger geis_device_id(GeisDevice device); /** * Gets the number of attributes of the device. * @memberof GeisDevice * * @param[in] device The device. */ GEIS_API GeisSize geis_device_attr_count(GeisDevice device); /** * Gets the indicated attribute of the device. * @memberof GeisDevice * * @param[in] device The device. * @param[in] index Indicates which attr to retrieve. */ GEIS_API GeisAttr geis_device_attr(GeisDevice device, GeisSize index); /** * Gets a named attribute from the device. * @memberof GeisDevice * * @param[in] device The device. * @param[in] attr_name The name of the attribute to retrieve. */ GEIS_API GeisAttr geis_device_attr_by_name(GeisDevice device, GeisString attr_name); /* @} */ /** * @defgroup geis_v2_class Gesture Classes * @ingroup geis_v2 * @{ */ /** * @class GeisGestureClass * A defined gesture classifier. * * GeisGestureClass objects are created by the GEIS API and are reference * counted. An application needs to increment and decrement the reference * count of a gesture class object to control its persistence. */ /** @cond typedef */ typedef struct _GeisGestureClass *GeisGestureClass; /** @endcond */ /** * @name Gesture Class Event Attributes * @{ * * @def GEIS_EVENT_ATTRIBUTE_CLASS * The event attribute containing a pointer to a GeisGestureClass. * * The GEIS_EVENT_CLASS_AVAILABLE and GEIS_EVENT_CLASS_UNAVAILABLE events * should have a GEIS_ATTR_TYPE_POINTER attribute with this name. It * should contain a pointer to a GeisGestureClass describing the gesture class * made available or unavailable. */ #define GEIS_EVENT_ATTRIBUTE_CLASS "gesture class" /* @} */ /** * @name Gesture Class Attributes * @{ * * @def GEIS_CLASS_ATTRIBUTE_NAME * The name of the gesture class. * * @def GEIS_CLASS_ATTRIBUTE_ID * The unique integer ID of the gesture class. */ #define GEIS_CLASS_ATTRIBUTE_NAME "class name" #define GEIS_CLASS_ATTRIBUTE_ID "class id" /* @} */ /** * Registers a callback to receive gesture class change notifications. * * @param[in] geis The API instance. * @param[in] event_callback The callback function. * @param[in] context Contextual data to be passed through to the * callback. * * This function is used to register a function to be executed when a change to * the available gesture class definitions has occurred. If no function is * registered, the default action is to deliver gesture class events through the * main event mechanism. * * Passing a value of GEIS_DEFAULT_EVENT_CALLBACK as the @p event-callback will * reset the callback function to the default action. * * The @p event_callback function will be executed in the same thread context as * geis_dispatch_events(). */ GEIS_API void geis_register_class_callback(Geis geis, GeisEventCallback event_callback, void *context); /** * Increments the reference count of a gesture class object. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. */ GEIS_API void geis_gesture_class_ref(GeisGestureClass gesture_class); /** * Decrements the reference count of a gesture class object. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. * * The reference count of the object is decremented and, if it reaches zero, the * object is destroyed. */ GEIS_API void geis_gesture_class_unref(GeisGestureClass gesture_class); /** * Gets the name of the gesture class. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. */ GEIS_API GeisString geis_gesture_class_name(GeisGestureClass gesture_class); /** * Gets the numeric identifier of the gesture class. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. */ GEIS_API GeisInteger geis_gesture_class_id(GeisGestureClass gesture_class); /** * Gets the number of attributes of the gesture class. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. */ GEIS_API GeisSize geis_gesture_class_attr_count(GeisGestureClass gesture_class); /** * Gets the indicated attribute of the gesture class. * @memberof GeisGestureClass * * @param[in] gesture_class The gesture class object. * @param[in] index The index of the attribute to retrieve. */ GEIS_API GeisAttr geis_gesture_class_attr(GeisGestureClass gesture_class, int index); /* @} */ /** * @defgroup geis_v2_region Gesture Regions * @ingroup geis_v2 * @{ */ /** * @class GeisRegion * Defines a region over which gestures may take place. */ /** @cond typedef */ typedef struct _GeisRegion *GeisRegion; /** @endcond */ /** * @name Region Attributes * * @par * These attributes can be used to construct filter terms to restrict a * gesture subscription to a particular region. * * @{ * * @def GEIS_REGION_ATTRIBUTE_WINDOWID * The X11 windowid in which a gesture occurred. Used for filter matching. */ #define GEIS_REGION_ATTRIBUTE_WINDOWID "windowid" /* @} */ /** * @name Region Initialization Arguments * * @par * Gesture regions are created to describe a particular display/feedback region. * The type of the region can not be changed after creation (just create a new * region for that). The types of regions are platform specific and each type * may require addition arguments. * * @par * The following region initialization argument names are required by the * GEIS v2.0 specification. * * @{ * * @def GEIS_REGION_X11_ROOT * Selects the X11 root window as a region. * * @def GEIS_REGION_X11_WINDOWID * Selects an X11 window as a region. * Requires the window_id as an argument. */ #define GEIS_REGION_X11_ROOT "org.libgeis.region.x11.root" #define GEIS_REGION_X11_WINDOWID "org.libgeis.region.x11.windowid" /* @} */ /** * Creates a new GEIS v2.0 region. * @memberof GeisRegion * * @param[in] geis The GEIS API instance. * @param[in] name A name. Used for diagnostics. * @param[in] init_arg_name The name of the first initialization argument. * * The initialization argument list must be terminated by a NULL. * * @returns a newly created region, or NULL on failure. */ GEIS_API GEIS_VARARG GeisRegion geis_region_new(Geis geis, GeisString name, GeisString init_arg_name, ...); /** * Destroys a GEIS v2.0 region. * @memberof GeisRegion * * @param[in] region The region. */ GEIS_API GeisStatus geis_region_delete(GeisRegion region); /** * Gets the name of a GEIS v2.0 region. * @memberof GeisRegion * * @param[in] region The region. * * Returns the @p name value used when creating the region. */ GEIS_API GeisString geis_region_name(GeisRegion region); /* @} */ /** * @defgroup geis_v2_filter Gesture Filter * @ingroup geis_v2 * @{ */ /** * @class GeisFilter * Selects a subset of possible gestures in a subscription. * * A GeisFilter is a collection of filter terms, each of which defines a * criterion for selection of gestures returned on a subscription. * * All filter terms are effectively ANDed together in a filter. **/ /** @cond typedef */ typedef struct _GeisFilter *GeisFilter; /** @endcond */ /** * Indicates the type of filter. */ typedef enum _GeisFilterFacility { GEIS_FILTER_DEVICE = 1000, /**< Filters on device attributes. */ GEIS_FILTER_CLASS = 2000, /**< Filters on gesture class and gesture attributes. */ GEIS_FILTER_REGION = 3000, /**< Filters on region attributes. */ GEIS_FILTER_SPECIAL = 5000 /**< Filters on special attributes. */ } GeisFilterFacility; /** * Indicates the type of filter operation. */ typedef enum _GeisFilterOperation { GEIS_FILTER_OP_EQ, /**< Compares for equality. */ GEIS_FILTER_OP_NE, /**< Compares for inequality */ GEIS_FILTER_OP_GT, /**< Compares for greater-than. */ GEIS_FILTER_OP_GE, /**< Compares for greater-than-or-equal. */ GEIS_FILTER_OP_LT, /**< Compares for less-than. */ GEIS_FILTER_OP_LE /**< Compares for less-tha-or-equal. */ } GeisFilterOperation; /** * Creates a new, empty filter. * @memberof GeisFilter * * @param[in] geis The GEIS API instance. * @param[in] name A name. * * @returns a GeisFilter object or NULL on failure. */ GEIS_API GeisFilter geis_filter_new(Geis geis, GeisString name); /** * Creates a new filter by copying an existing filter. * @memberof GeisFilter * * @param[in] original An existing geisFilter instance. * @param[in] name A name. * * The original filter remains unchanged. * * @returns a GeisFilter object or NULL on failure. */ GEIS_API GeisFilter geis_filter_clone(GeisFilter original, GeisString name); /** * Destroys a GeisFilter. * @memberof GeisFilter * * @param[in] filter The filter. */ GEIS_API GeisStatus geis_filter_delete(GeisFilter filter); /** * Gets the name given to the filter when it was created. * @memberof GeisFilter * * @param[in] filter The filter. */ GEIS_API GeisString geis_filter_name(GeisFilter filter); /** * Adds a term to a filter. * @memberof GeisFilter * * @param[in] filter The filter. * @param[in] facility The term facility. * @param[in] ... A list of zero or more term descriptions. * * A term description is generally a (attr-name, filter-op, value) triple in * which the meaning of the filter-op and value depend on the type of the attr. * * The term description list must be terminated by a NULL. * * In the following example we add terms to filter drag gestures made with three * touch points: * @code * geis_filter_add_term(filter, * GEIS_FILTER_CLASS, * GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG, * GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 3, * NULL); * @endcode * * Term descriptions are usually ANDed together, so that specifying a class name * and a number of touches will filter only for gestures that have both * characteristics. But if you specify several class names (e.g. drag and pinch), * those classes are ORed together instead. So you can receive events from a * gesture that belongs to either drag, drag&pinch or only pinch classes. * */ GEIS_API GEIS_VARARG GeisStatus geis_filter_add_term(GeisFilter filter, GeisFilterFacility facility, ...); /* @} */ /** * @defgroup geis_v2_subscription Gesture Subscription * @ingroup geis_v2 * @{ */ /** * @class GeisSubscription * A gesture recognition subscription. */ /** @cond typedef */ typedef struct _GeisSubscription *GeisSubscription; /** @endcond */ /** * @enum GeisSubscriptionFlags * * These flags are used when creating a new subscription and affect the nature * of the gestures recognized by the subscription. They may ORed together. * * @var GeisSubscriptionFlags::GEIS_SUBSCRIPTION_NONE * No special subscription processing: this is the default. * * @var GeisSubscriptionFlags::GEIS_SUBSCRIPTION_GRAB * The subscription will "grab" all filtered gestures from subwindows. * * @var GeisSubscriptionFlags::GEIS_SUBSCRIPTION_CONT * The gesture engine will return gesture continuations, in which the * class of a recognized gestire may change over the lifetime of the gesture. * If this flag is not set, a new gesture will be identified for each change in * gesture class. */ enum { GEIS_SUBSCRIPTION_NONE = 0x0000, GEIS_SUBSCRIPTION_GRAB = 0x0001, GEIS_SUBSCRIPTION_CONT = 0x0002 }; typedef int GeisSubscriptionFlags; /** * Creates a new subscription. * @memberof GeisSubscription * * @param[in] geis The GEIS API instance. * @param[in] name A name. * @param[in] flags Some flags. * * @returns a GeisSubscription object or NULL on failure. * * A gesture subscription is required for any gesture events to be delivered * from the GEIS API. */ GEIS_API GeisSubscription geis_subscription_new(Geis geis, GeisString name, GeisSubscriptionFlags flags); /** * Destroys a GEIS v2.0 subscription object. * @memberof GeisSubscription * * @param[in] subscription The subscription. */ GEIS_API GeisStatus geis_subscription_delete(GeisSubscription subscription); /** * Activates a subscription. * @memberof GeisSubscription * * @param[in] subscription The subscription. * * Puts the subscription into the active state. Gesture events will be * delivered for this subscription. */ GEIS_API GeisStatus geis_subscription_activate(GeisSubscription subscription); /** * Deactivates a subscription. * @memberof GeisSubscription * * @param[in] subscription The subscription. * * Puts the subscription into the inactive state. Gesture events will not be * delivered for this subscription. */ GEIS_API GeisStatus geis_subscription_deactivate(GeisSubscription subscription); /** * Gets the name given to a subscription when it was created. * @memberof GeisSubscription * * @param[in] subscription The subscription. */ GEIS_API GeisString geis_subscription_name(GeisSubscription subscription); /** * Gets the ID assigned to a subscription when it was created. * @memberof GeisSubscription * * @param[in] subscription The subscription. */ GEIS_API GeisInteger geis_subscription_id(GeisSubscription subscription); /** * Adds a filter to a subscription. * @memberof GeisSubscription * * @param[in] subscription The subscription. * @param[in] filter The filter to be added to the subscription. * * The effect of filters are ORed together so that, for example, a * subscription that has a filter for 3-finger drag gestures and another for * 2-finger pinch gestures will produce events for both 3-finger drag gestures * and 2-finger pinch gestures. * * The default is no filters: that is, all possible gesture events will be * reported. * * The subscription will take ownership of the filter. */ GEIS_API GeisStatus geis_subscription_add_filter(GeisSubscription subscription, GeisFilter filter); /** * Gets an named filter from a subscription. * @memberof GeisSubscription * * @param[in] sub The subscription. * @param[in] name Names the filter to retrieve. * * Returns the first filter with the given name or NULL if no such named filter * is found. */ GEIS_API GeisFilter geis_subscription_filter_by_name(GeisSubscription sub, GeisString name); /** * Removes a filter from a subscription. * @memberof GeisSubscription * * @param[in] subscription The subscription. * @param[in] filter The filter to be removed from the subscription. * * Ownership of the filter is passed to the caller. */ GEIS_API GeisStatus geis_subscription_remove_filter(GeisSubscription subscription, GeisFilter filter); /** * Gets a subscription-level configuration item. * * @param[in] subscription The subscription from which the configuration * item will be retrieved. * @param[in] config_item_name The name of the configuration item. * @param[out] config_item_value A pointer to an appropriate variable to hold * the retrieved config item value. * * Not all back ends support all configuration items. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_subscription_get_configuration(GeisSubscription subscription, GeisString config_item_name, GeisPointer config_item_value); /** * Sets a subscription-level configuration item. * * @param[in] subscription The subscription from which the configuration * item will be retrieved. * @param[in] config_item_name The name of the configuration item. * @param[in] config_item_value A pointer to an appropriate variable holding * the config item value. * * Not all back ends support all configuration items. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GEIS_API GeisStatus geis_subscription_set_configuration(GeisSubscription subscription, GeisString config_item_name, GeisPointer config_item_value); /* @} */ /** * @defgroup geis_v2_gesture Gesture Frames * @ingroup geis_v2 * Gesture state information. * * Gesture frames, and their associated groups and touches, convey information * about the current state of recognized gestures. * * @{ */ /** * @class GeisGroup * A collection of gesture frames. * * @class GeisGroupSet * A collection of GeisGroups. * * @class GeisTouch * An instance of a touch. * * @class GeisTouchId * Relates a touch in a frame to a touch object in a set. * * @class GeisTouchSet * A collection of GeisTouch * * @class GeisFrame * A collection of information describing the state of a gesture. */ /** @cond typedef */ typedef struct _GeisGroup *GeisGroup; typedef struct _GeisGroupSet *GeisGroupSet; typedef GeisSize GeisTouchId; typedef struct _GeisTouch *GeisTouch; typedef struct _GeisTouchSet *GeisTouchSet; typedef struct _GeisFrame *GeisFrame; /** @endcond */ /** * @name Gesture Frame Event Attributes * * @par * A gesture event (GEIS_EVENT_GESTURE_BEGIN, GEIS_EVENT_GESTURE_UPDATE, * GEIS_EVENT_GESTURE_END) should have two GEIS_ATTR_TYPE_POINTER attributes, * one containing a GeisGroupSet and one containing a GeisTouchSet. * * For example: If four fingers are being simultaneously moved over a touchpad * or touchscreen surface, Geis could start generating gesture events * containing two groups: One group having a single frame from a four-fingers * gesture of some class and a second group having two frames, each from a * different two-fingers gesture (like one from a Rotate and the other from a * Pinch gesture). * This means that geis could interpret the movements of those four touch points as * both a single four-fingers gesture and as two separate two-fingers gestures. * * There can be only a single frame per gesture in a gesture event. I.e. no two * frames will return the same GeisGestureId in the same gesture event. * * @{ * * @def GEIS_EVENT_ATTRIBUTE_GROUPSET * The event attribute containing a pointer to a GeisGroupSet. * * @def GEIS_EVENT_ATTRIBUTE_TOUCHSET * The event attribute containing a pointer to a GeisTouchSet. * * @def GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED * Event attribute containing a boolean. * This property allows the client to determine if all the possible gestures * from the set of touches in this event have already been presented. When * this value is true, the client will have received all the information needed * to make a gesture accept and reject decision based on potentially * overlapping gestures. An example is when both one and two touch gestures are * subscribed on the same window with the same gesture classes and thresholds. * When this property is true for one touch gesture events, the client can be * sure there are no other touches unless a two touch gesture event has already * been sent. * Another example is when you subscribe for three touches Touch and four * touches Drag. As soon as a third finger is detected a three touches Touch * gesture will begin, but you cannot be sure a fourth finger isn't coming * right after (that can eventually cause a four touches Drag) until this * property is true. */ #define GEIS_EVENT_ATTRIBUTE_GROUPSET "group set" #define GEIS_EVENT_ATTRIBUTE_TOUCHSET "touch set" #define GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED "construction finished" /* @} */ /** * @name Touch Attributes * * @par * Each touch has zero or more attributes associated with it. Differing hardware * is capable of reporting differing sets of touch attributes, so there is no * guarantee that any or all of the defined touch attributes will bre present. * * If the touch comes from a direct device (see * GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH) its position (x and y attributes) will * be in window coordinates, otherwise it will be in the input device's own * coordinate system. * * @{ * * @def GEIS_TOUCH_ATTRIBUTE_ID * Identifies the touch. * * @def GEIS_TOUCH_ATTRIBUTE_X * The X coordinate of the touch. * * @def GEIS_TOUCH_ATTRIBUTE_Y * The Y coordinate of the touch. */ #define GEIS_TOUCH_ATTRIBUTE_ID "touch id" #define GEIS_TOUCH_ATTRIBUTE_X "touch x" #define GEIS_TOUCH_ATTRIBUTE_Y "touch y" /* @} */ /** * Gets the number of gesture groups in a groupset. * @memberof GeisGroupSet * * @param[in] groupset The groupset. */ GEIS_API GeisSize geis_groupset_group_count(GeisGroupSet groupset); /** * Gets an indicated gesture group from a groupset. * @memberof GeisGroupSet * * @param[in] groupset The groupset. * @param[in] index Indicates which gesture group to retrieve. */ GEIS_API GeisGroup geis_groupset_group(GeisGroupSet groupset, GeisSize index); /** * Gets the identifier of a gesture group. * @memberof GeisGroup * * @param[in] group The gesture group. */ GEIS_API GeisInteger geis_group_id(GeisGroup group); /** * Gets the number of gesture frames in a gesture group. * @memberof GeisGroup * * @param[in] group The gesture group. */ GEIS_API GeisSize geis_group_frame_count(GeisGroup group); /** * Gets an indicated gesture frame from a gesture group. * @memberof GeisGroup * * @param[in] group The gesture group. * @param[in] index Indicates which gesture frame to retrieve. */ GEIS_API GeisFrame geis_group_frame(GeisGroup group, GeisSize index); /** * Marks a gesture group as rejected. * @memberof GeisGroup * * @param[in] group The gesture group to reject. */ GEIS_API void geis_group_reject(GeisGroup group); /** * Gets the number of touches in a touchset. * @memberof GeisTouchSet * * @param[in] touchset The touchset, */ GEIS_API GeisSize geis_touchset_touch_count(GeisTouchSet touchset); /** * Gets an indicated touch from a touchset. * @memberof GeisTouchSet * * @param[in] touchset The touchset. * @param[in] index Indicates which touch to retrieve. */ GEIS_API GeisTouch geis_touchset_touch(GeisTouchSet touchset, GeisSize index); /** * Gets an identified touch from a touchset. * @memberof GeisTouchSet * * @param[in] touchset The touchset. * @param[in] touchid Identifies a touch. * * Returns the identified touch, or NULL if the touchid is not in the touchset. */ GEIS_API GeisTouch geis_touchset_touch_by_id(GeisTouchSet touchset, GeisTouchId touchid); /** * Gets the identifier of a touch. * @memberof GeisTouch * * @param[in] touch The touch. */ GEIS_API GeisTouchId geis_touch_id(GeisTouch touch); /** * Gets the number of attrs associated with a touch. * @memberof GeisTouch * * @param[in] touch The touch. */ GEIS_API GeisSize geis_touch_attr_count(GeisTouch touch); /** * Gets an indicated attr from a touch. * @memberof GeisTouch * * @param[in] touch The touch. * @param[in] index Indicates which attr to retrieve. */ GEIS_API GeisAttr geis_touch_attr(GeisTouch touch, GeisSize index); /** * Gets a named attr from a touch. * @memberof GeisTouch * * @param[in] touch The touch. * @param[in] name Names the attr to retrieve. * * @returns the named attr if it is present, NULL otherwise. */ GEIS_API GeisAttr geis_touch_attr_by_name(GeisTouch touch, GeisString name); /** * Gets the identifier of a gesture frame. * @memberof GeisFrame * * @param[in] frame the gesture frame. * * @returns the identifier of the gesture to which the given frame belongs. */ GEIS_API GeisGestureId geis_frame_id(GeisFrame frame); /** * Indicates if a gesture frame belongs to a gesture class. * @memberof GeisFrame * * @param[in] frame The gesture frame. * @param[in] gesture_class The gesture class. * * @returns true if the gesture can currently be classified by the @p * gesture_class, false otherwise. */ GEIS_API GeisBoolean geis_frame_is_class(GeisFrame frame, GeisGestureClass gesture_class); /** * Gets the number of attrs associated with a gesture frame. * @memberof GeisFrame * * @param[in] frame The gesture frame. */ GEIS_API GeisSize geis_frame_attr_count(GeisFrame frame); /** * Gets an indicated attr from a gesture frame. * @memberof GeisFrame * * @param[in] frame The gesture frame. * @param[in] index Indicates which attr to retrieve. */ GEIS_API GeisAttr geis_frame_attr(GeisFrame frame, GeisSize index); /** * Gets a named attr from a gesture frame. * @memberof GeisFrame * * @param[in] frame The gesture frame. * @param[in] name Names the attr to retrieve, such as one of the * GEIS_GESTURE_ATTRIBUTE_* constants. * @returns the named attr if it is present, NULL otherwise. * * Usage example: * @code * GeisAttr angle = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_ANGLE); * @endcode */ GEIS_API GeisAttr geis_frame_attr_by_name(GeisFrame frame, GeisString name); /** * Gets the current transform matrix of a gesture. * @memberof GeisFrame * * @param[in] frame The gesture frame. */ GEIS_API GeisFloat *geis_frame_matrix(GeisFrame frame); /** * Gets the number of touches making up a gesture for the frame. * @memberof GeisFrame * * @param[in] frame The gesture frame. */ GEIS_API GeisSize geis_frame_touchid_count(GeisFrame frame); /** * Gets the ID of the indicated touch within the gesture frame. * @memberof GeisFrame * * @param[in] frame The gesture frame. * @param[in] index Indicates which touch ID to retrieve. */ GEIS_API GeisTouchId geis_frame_touchid(GeisFrame frame, GeisSize index); /** * Marks a gesture as accepted. * * @param[in] geis The GEIS instance. * @param[in] group The gesture group containing the accepted gesture. * @param[in] gesture_id Identifies the gesture. * * @sa geis_frame_id */ GEIS_API GeisStatus geis_gesture_accept(Geis geis, GeisGroup group, GeisGestureId gesture_id); /** * Marks a gesture as rejected. * * @param[in] geis The GEIS instance. * @param[in] group The gesture group containing the rejected gesture. * @param[in] gesture_id Identifies the gesture. * * After you reject a gesture you no longer get its frames. * * @sa geis_frame_id */ GEIS_API GeisStatus geis_gesture_reject(Geis geis, GeisGroup group, GeisGestureId gesture_id); /* @} */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* GEIS_GEIS_H_ */ geis-2.2.17+16.04.20160126/libs/0000755000015600001650000000000012651717732016040 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libs/geis-dbus/0000755000015600001650000000000012651717732017722 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_region.h0000644000015600001650000000251112651717544023402 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_region.h * @brief Interface for the GEIS DBus region transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_REGION_H_ #define GEIS_DBUS_REGION_H_ #include #include "geis/geis.h" #include "geis_filterable.h" /** * Creates a Dbus "region available" message from a GEIS region. * * @param[in] fa A GEIS region filterable attribute. */ DBusMessage * geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa); /** * Creates GEIS region filterable attribute from a DBus "region available" * message. * * @param[in] message A DBus message. */ GeisFilterableAttribute geis_dbus_region_from_region_available_message(DBusMessage *message); #endif /* GEIS_DBUS_REGION_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_gesture_event.c0000644000015600001650000004574712651717544025013 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_gesture_event.c * @brief Implementation of the GEIS DBus gesture event transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_gesture_event.h" #include "geis_attr.h" #include "geis_dbus.h" #include "geis_dbus_attr.h" #include "geis_event.h" #include "geis_group.h" #include "geis_logging.h" #include "geis_private.h" #include "geis_touch.h" /** * A frame is marshalled as a dict entry of * {id: [array of attrs, array of classes, array of touch ids]}, which is * {i(a(sv)aiai))} in DBus terminaology. */ #define GEIS_DBUS_TYPE_SIGNATURE_FRAME \ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \ DBUS_TYPE_INT32_AS_STRING \ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ DBUS_TYPE_ARRAY_AS_STRING \ GEIS_DBUS_TYPE_SIGNATURE_ATTR \ DBUS_TYPE_ARRAY_AS_STRING \ DBUS_TYPE_INT32_AS_STRING \ DBUS_TYPE_ARRAY_AS_STRING \ DBUS_TYPE_INT32_AS_STRING \ DBUS_STRUCT_END_CHAR_AS_STRING \ DBUS_DICT_ENTRY_END_CHAR_AS_STRING \ #define GEIS_DBUS_TYPE_SIGNATURE_FRAMESET \ DBUS_TYPE_ARRAY_AS_STRING \ GEIS_DBUS_TYPE_SIGNATURE_FRAME static void _marshall_touchset(GeisTouchSet touchset, DBusMessageIter *iter) { DBusMessageIter touchset_iter; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_ARRAY_AS_STRING GEIS_DBUS_TYPE_SIGNATURE_ATTR DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &touchset_iter); for (GeisSize t = 0; t < geis_touchset_touch_count(touchset); ++t) { DBusMessageIter touch_iter; dbus_message_iter_open_container(&touchset_iter, DBUS_TYPE_DICT_ENTRY, NULL, &touch_iter); GeisTouch touch = geis_touchset_touch(touchset, t); dbus_int32_t touch_id = geis_touch_id(touch); dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id); DBusMessageIter attr_iter; dbus_message_iter_open_container(&touch_iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_ATTR, &attr_iter); for (GeisSize a = 0; a < geis_touch_attr_count(touch); ++a) { geis_dbus_attr_marshall(geis_touch_attr(touch, a), &attr_iter); } dbus_message_iter_close_container(&touch_iter, &attr_iter); dbus_message_iter_close_container(&touchset_iter, &touch_iter); } dbus_message_iter_close_container(iter, &touchset_iter); } static void _unmarshall_touchset(DBusMessageIter *iter, GeisTouchSet touchset) { int dtype = dbus_message_iter_get_arg_type(iter); if (dtype != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent touchset"); } DBusMessageIter touch_iter; dbus_message_iter_recurse(iter, &touch_iter); for (dtype = dbus_message_iter_get_arg_type(&touch_iter); dtype != DBUS_TYPE_INVALID; dbus_message_iter_next(&touch_iter), dtype = dbus_message_iter_get_arg_type(&touch_iter)) { DBusMessageIter dict_iter; dbus_message_iter_recurse(&touch_iter, &dict_iter); int type = dbus_message_iter_get_arg_type(&dict_iter); if (type != DBUS_TYPE_INT32) { geis_error("malformed GeisEvent touchset"); continue; } dbus_int32_t touch_id; dbus_message_iter_get_basic(&dict_iter, &touch_id); dbus_message_iter_next(&dict_iter); GeisTouch touch = geis_touch_new(touch_id); type = dbus_message_iter_get_arg_type(&dict_iter); if (type != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent touchset"); continue; } DBusMessageIter attr_iter; dbus_message_iter_recurse(&dict_iter, &attr_iter); for (int type = dbus_message_iter_get_arg_type(&attr_iter); type != DBUS_TYPE_INVALID; dbus_message_iter_next(&attr_iter), type = dbus_message_iter_get_arg_type(&attr_iter)) { GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter); geis_touch_add_attr(touch, attr); } geis_touchset_insert(touchset, touch); } } /** * Marshalls a GEIS frame to a DBus message via a message iterator. * @param[in] frame The GEIS frame to marshall. * @param[in] iter The DBus message iterator. * * @todo The class set and matrix need to be added. */ static void _marshall_frame(GeisFrame frame, DBusMessageIter *frame_iter) { DBusMessageIter dict_iter; dbus_message_iter_open_container(frame_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter); dbus_int32_t frame_id = geis_frame_id(frame); dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_INT32, &frame_id); { DBusMessageIter struct_iter; dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter); { DBusMessageIter attr_iter; dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_ATTR, &attr_iter); for (GeisSize a = 0; a < geis_frame_attr_count(frame); ++a) { geis_dbus_attr_marshall(geis_frame_attr(frame, a), &attr_iter); } dbus_message_iter_close_container(&struct_iter, &attr_iter); } { DBusMessageIter class_iter; dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32_AS_STRING, &class_iter); for (GeisSize t = 0; t < geis_frame_class_count(frame); ++t) { GeisGestureClass frame_class = geis_frame_class(frame, t); dbus_int32_t class_id = geis_gesture_class_id(frame_class); dbus_message_iter_append_basic(&class_iter, DBUS_TYPE_INT32, &class_id); } dbus_message_iter_close_container(&struct_iter, &class_iter); } { DBusMessageIter touch_iter; dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32_AS_STRING, &touch_iter); for (GeisSize t = 0; t < geis_frame_touchid_count(frame); ++t) { dbus_int32_t touch_id = geis_frame_touchid(frame, t); dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id); } dbus_message_iter_close_container(&struct_iter, &touch_iter); } dbus_message_iter_close_container(&dict_iter, &struct_iter); } dbus_message_iter_close_container(frame_iter, &dict_iter); } /** * Unmarshalls a GEIS frame from a DBus message via a message iterator. * @param[in] frame_iter The DBus message iterator. * @param[in] group The group the unmarshalled frame will belong to. */ static void _unmarshall_frame(Geis geis, DBusMessageIter *frame_iter, GeisGroup group) { int type = dbus_message_iter_get_arg_type(frame_iter); if (type != DBUS_TYPE_DICT_ENTRY) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_DICT_ENTRY, type); goto final_exit; } DBusMessageIter dict_iter; dbus_message_iter_recurse(frame_iter, &dict_iter); type = dbus_message_iter_get_arg_type(&dict_iter); if (type != DBUS_TYPE_INT32) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_INT32, type); goto final_exit; } dbus_int32_t frame_id; dbus_message_iter_get_basic(&dict_iter, &frame_id); GeisFrame frame = geis_frame_new(frame_id); geis_group_insert_frame(group, frame); dbus_message_iter_next(&dict_iter); type = dbus_message_iter_get_arg_type(&dict_iter); if (type != DBUS_TYPE_STRUCT) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_STRUCT, type); } else { DBusMessageIter struct_iter; dbus_message_iter_recurse(&dict_iter, &struct_iter); type = dbus_message_iter_get_arg_type(&struct_iter); if (type != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_ARRAY, type); } else { DBusMessageIter attr_iter; dbus_message_iter_recurse(&struct_iter, &attr_iter); for (int type = dbus_message_iter_get_arg_type(&attr_iter); type != DBUS_TYPE_INVALID; dbus_message_iter_next(&attr_iter), type = dbus_message_iter_get_arg_type(&attr_iter)) { GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter); geis_frame_add_attr(frame, attr); } } dbus_message_iter_next(&struct_iter), type = dbus_message_iter_get_arg_type(&struct_iter); if (type != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_ARRAY, type); } else { DBusMessageIter class_iter; dbus_message_iter_recurse(&struct_iter, &class_iter); for (int type = dbus_message_iter_get_arg_type(&class_iter); type != DBUS_TYPE_INVALID; dbus_message_iter_next(&class_iter), type = dbus_message_iter_get_arg_type(&class_iter)) { type = dbus_message_iter_get_arg_type(&class_iter); if (type != DBUS_TYPE_INT32) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_INT32, type); break; } dbus_int32_t class_id; dbus_message_iter_get_basic(&class_iter, &class_id); GeisGestureClassBag bag = geis_gesture_classes(geis); for (GeisSize i = 0; i < geis_gesture_class_bag_count(bag); ++i) { GeisGestureClass gesture_class; gesture_class = geis_gesture_class_bag_gesture_class(bag, i); if (geis_gesture_class_id(gesture_class) == class_id) { geis_frame_set_is_class(frame, gesture_class); break; } } } } dbus_message_iter_next(&struct_iter), type = dbus_message_iter_get_arg_type(&struct_iter); if (type != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_ARRAY, type); } else { DBusMessageIter touch_iter; dbus_message_iter_recurse(&struct_iter, &touch_iter); for (int type = dbus_message_iter_get_arg_type(&touch_iter); type != DBUS_TYPE_INVALID; dbus_message_iter_next(&touch_iter), type = dbus_message_iter_get_arg_type(&touch_iter)) { type = dbus_message_iter_get_arg_type(&touch_iter); if (type != DBUS_TYPE_INT32) { geis_error("malformed GeisEvent frame: expected %c, received %c", DBUS_TYPE_INT32, type); break; } dbus_int32_t touch_id; dbus_message_iter_get_basic(&touch_iter, &touch_id); geis_frame_add_touchid(frame, touch_id); } } } final_exit: return; } /** * Marshalls a GEIS groupset to a DBus message via a message iterator. * @param[in] groupset The GEIS groupset. * @param[in] iter A DBus message iterator. */ static void _marshall_groupset(GeisGroupSet groupset, DBusMessageIter *iter) { DBusMessageIter groupset_iter; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING GEIS_DBUS_TYPE_SIGNATURE_FRAMESET DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &groupset_iter); for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); if (!group) { geis_warning("can not extract group %zu from groupset", i); goto final_exit; } DBusMessageIter group_iter; dbus_message_iter_open_container(&groupset_iter, DBUS_TYPE_DICT_ENTRY, NULL, &group_iter); dbus_int32_t group_id = geis_group_id(group); dbus_message_iter_append_basic(&group_iter, DBUS_TYPE_INT32, &group_id); DBusMessageIter frameset_iter; dbus_message_iter_open_container(&group_iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_FRAME, &frameset_iter); for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); if (!frame) { geis_warning("can not extract frame %zu from group", j); goto final_exit; } _marshall_frame(frame, &frameset_iter); } dbus_message_iter_close_container(&group_iter, &frameset_iter); dbus_message_iter_close_container(&groupset_iter, &group_iter); } dbus_message_iter_close_container(iter, &groupset_iter); final_exit: return; } static void _unmarshall_groupset(Geis geis, DBusMessageIter *iter, GeisGroupSet groupset) { int dtype = dbus_message_iter_get_arg_type(iter); if (dtype != DBUS_TYPE_ARRAY) { geis_error("malformed GeisEvent groupset"); } DBusMessageIter groupset_iter; dbus_message_iter_recurse(iter, &groupset_iter); for (dtype = dbus_message_iter_get_arg_type(&groupset_iter); dtype != DBUS_TYPE_INVALID; dbus_message_iter_next(&groupset_iter), dtype = dbus_message_iter_get_arg_type(&groupset_iter)) { DBusMessageIter group_iter; dbus_message_iter_recurse(&groupset_iter, &group_iter); int type = dbus_message_iter_get_arg_type(&group_iter); if (type != DBUS_TYPE_INT32) { geis_error("malformed GeisEvent group"); continue; } dbus_int32_t group_id; dbus_message_iter_get_basic(&group_iter, &group_id); GeisGroup group = geis_group_new(group_id); geis_groupset_insert(groupset, group); dbus_message_iter_next(&group_iter); DBusMessageIter frameset_iter; dbus_message_iter_recurse(&group_iter, &frameset_iter); for (int ftype = dbus_message_iter_get_arg_type(&frameset_iter); ftype != DBUS_TYPE_INVALID; dbus_message_iter_next(&frameset_iter), ftype = dbus_message_iter_get_arg_type(&frameset_iter)) { _unmarshall_frame(geis, &frameset_iter, group); } } } /* * Creates a Dbus "gesture event" message from a GEIS gesture event. * * A gesture event has the following structure. * - a numeric event type (begin/update/end) * - a set of one or more touches, where each touch has * - a touch ID * - a set of one or more attrs * - a set of one or more gesture groups, where is group has * - a group ID * - a set of one or more gesture frames, where each frame has * - a set of one or more gesture classes * - a set of one or more gesture attrs * - a zet of one or more touch indexes * * @todo add the gesture classes */ DBusMessage * geis_dbus_gesture_event_message_from_geis_event(GeisEvent event) { DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_GESTURE_EVENT); DBusMessageIter iter; dbus_message_iter_init_append(message, &iter); dbus_uint32_t event_type = geis_event_type(event); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &event_type); GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); if (!attr) { geis_error("no touchset for gesture event"); goto final_exit; } GeisTouchSet touchset = geis_attr_value_to_pointer(attr); if (!touchset) { geis_warning("can not convert attr to touchset"); goto final_exit; } _marshall_touchset(touchset, &iter); attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("no groupset for gesture event"); goto final_exit; } GeisGroupSet groupset = geis_attr_value_to_pointer(attr); if (!groupset) { geis_warning("can not convert attr to groupset"); goto final_exit; } _marshall_groupset(groupset, &iter); final_exit: return message; } /* * Indicates if a DBus message is a "gesture event" message. */ GeisBoolean geis_dbus_message_is_gesture_event(DBusMessage *message) { GeisBoolean is_gesture_event_message = GEIS_FALSE; if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_GESTURE_EVENT)) { is_gesture_event_message = GEIS_TRUE; } return is_gesture_event_message; } /* * Creates GEIS event from a DBus "gesture_event" message. */ GeisEvent geis_dbus_gesture_event_from_message(Geis geis, DBusMessage *message) { DBusMessageIter iter; dbus_message_iter_init(message, &iter); dbus_uint32_t event_type; dbus_message_iter_get_basic(&iter, &event_type); GeisEvent event = geis_event_new(event_type); dbus_message_iter_next(&iter); GeisTouchSet touchset = geis_touchset_new(); _unmarshall_touchset(&iter, touchset); GeisAttr touch_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_TOUCHSET, GEIS_ATTR_TYPE_POINTER, touchset); geis_attr_set_destructor(touch_attr, (GeisAttrDestructor)geis_touchset_delete); geis_event_add_attr(event, touch_attr); dbus_message_iter_next(&iter); GeisGroupSet groupset = geis_groupset_new(); _unmarshall_groupset(geis, &iter, groupset); GeisAttr group_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_GROUPSET, GEIS_ATTR_TYPE_POINTER, groupset); geis_attr_set_destructor(group_attr, (GeisAttrDestructor)geis_groupset_delete); geis_event_add_attr(event, group_attr); return event; } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_device.h0000644000015600001650000000317312651717544023363 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_device.h * @brief Interface for the GEIS DBus device transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_DEVICE_H_ #define GEIS_DBUS_DEVICE_H_ #include #include "geis/geis.h" /** * Creates a Dbus "device available" message from a GEIS device. * * @param[in] device A GEIS device. */ DBusMessage * geis_dbus_device_available_message_from_device(GeisDevice device); /** * Creates GEIS device from a DBus "device available" message. * * @param[in] message A DBus message. */ GeisDevice geis_dbus_device_device_from_available_message(DBusMessage *message); /** * Creates a Dbus "device unavailable" message from a GEIS device. * * @param[in] device A GEIS device. */ DBusMessage * geis_dbus_device_unavailable_message_from_device(GeisDevice device); /** * Creates GEIS device from a DBus "device unavailable" message. * * @param[in] message A DBus message. */ GeisDevice geis_dbus_device_device_from_unavailable_message(DBusMessage *message); #endif /* GEIS_DBUS_DEVICE_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/Makefile.am0000644000015600001650000000275112651717544021764 0ustar pbuserpbgroup00000000000000# # @file libs/geis-dbus/Makefile.am # @brief automake recipe for the GEIS v2.0 DBus helper library # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # noinst_LTLIBRARIES = libgeis-dbus.la dist_libgeis_dbus_la_SOURCES = \ geis_dbus.h \ geis_dbus_attr.h geis_dbus_attr.c \ geis_dbus_class.h geis_dbus_class.c \ geis_dbus_device.h geis_dbus_device.c \ geis_dbus_dispatcher.h geis_dbus_dispatcher.c \ geis_dbus_gesture_event.h geis_dbus_gesture_event.c \ geis_dbus_region.h geis_dbus_region.c \ geis_dbus_subscription.h geis_dbus_subscription.c libgeis_dbus_la_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/libs/geis-util \ $(DBUS_CFLAGS) libgeis_dbus_la_LIBADD = \ $(DBUS_LIBS) geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_attr.h0000644000015600001650000000312412651717544023072 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_attr.h * @brief Interface for the GEIS DBus attr transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_ATTR_H_ #define GEIS_DBUS_ATTR_H_ #include #include "geis/geis.h" /** * The DBus type signature for a GEIS attrlist entry. */ #define GEIS_DBUS_TYPE_SIGNATURE_ATTR \ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ DBUS_TYPE_STRING_AS_STRING \ DBUS_TYPE_VARIANT_AS_STRING \ DBUS_STRUCT_END_CHAR_AS_STRING /** * Marshalls a single GEIS attr to an open DBus message container iterator. * * @param[in] attr The GEIS attr. * @param[in] iter The DBus message iterator. */ void geis_dbus_attr_marshall(GeisAttr attr, DBusMessageIter *iter); /** * Unmarshalls a single GEIS attr from a DBus message iterator. * * @param[in] iter The DBus message iterator. * * @returns a GEIS attribute or NULL on error. */ GeisAttr geis_dbus_attr_unmarshall(DBusMessageIter *iter); #endif /* GEIS_DBUS_ATTR_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus.h0000644000015600001650000000344512651717544022046 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus.h * @brief Common definitions for the GEIS DBus module(s). */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_H_ #define GEIS_DBUS_H_ #define GEIS_DBUS_SERVICE_PATH "/com/canonical/oif/Geis" #define GEIS_DBUS_SERVICE_INTERFACE "com.canonical.oif.Geis" #define GEIS_DBUS_GET_SERVER_ADDRESS "GetServerAddress" #define GEIS_DBUS_INIT_COMPLETE "InitComplete" #define GEIS_DBUS_DEVICE_AVAILABLE "DeviceAvailable" #define GEIS_DBUS_DEVICE_UNAVAILABLE "DeviceUnavailable" #define GEIS_DBUS_CLASS_AVAILABLE "ClassAvailable" #define GEIS_DBUS_CLASS_UNAVAILABLE "ClassUnavailable" #define GEIS_DBUS_REGION_AVAILABLE "RegionAvailable" #define GEIS_DBUS_REGION_UNAVAILABLE "RegionUnavailable" #define GEIS_DBUS_SUBSCRIPTION_CREATE "SubscriptionCreate" #define GEIS_DBUS_SUBSCRIPTION_ACTIVATE "SubscriptionActivate" #define GEIS_DBUS_SUBSCRIPTION_DEACTIVATE "SubscriptionDeactivate" #define GEIS_DBUS_SUBSCRIPTION_DESTROY "SubscriptionDestroy" #define GEIS_DBUS_GESTURE_EVENT "GestureEvent" #define GEIS_DBUS_ERROR_SUBSCRIPTION_FAIL GEIS_DBUS_SERVICE_INTERFACE \ ".SubscriptionFail" #endif /* GEIS_DBUS_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_subscription.h0000644000015600001650000001450212651717544024646 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_subscription.h * @brief Interface for the GEIS DBus subscription transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_SUBSCRIPTION_H_ #define GEIS_DBUS_SUBSCRIPTION_H_ #include #include "geis/geis.h" /** * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call. * * @param[in] message A DBus message. * * This function is used on the server side to identify if a received message is * a GEIS_DBUS_SUBSCRIPTION_CREATE method call. * * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_CREATE, * GEIS_FALSE otherwise. */ GeisBoolean geis_dbus_message_is_subscription_create_call(DBusMessage *message); /** * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message. * * @param[in] subscription A GEIS subscription. * * This function is used on the client side to create a * GEIS_DBUS_SUBSCRIPTION_CREATE method call message from a local * %GeisSubscription object. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_create_call_message(GeisSubscription subscription); /** * Creates a %GeisSubscription from a GEIS_DBUS_SUBSCRIPTION_CREATE method call * message. * * @param[in] geis A %Geis instance. * @param[in] message A DBus message. * * This function is used on the server side to create a subscription object to * proxy the client-side subscription object. * * @returns a %GeisSubscription or NULL on failure. */ GeisSubscription geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message); /** * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message. * * @param[in] message The DBUs method_call message to reply to. * @param[in] subscription A GEIS subscription. * * This function is used on the server side to create a response to a received * GEIS_DBUS_SUBSCRIPTION_CREATE method call message. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_create_return_message(DBusMessage *message, GeisSubscription subscription); /** * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message. * * @param[in] message A DBus message. * * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_ACTIVATE, * GEIS_FALSE otherwise. */ GeisBoolean geis_dbus_message_is_subscription_activate_call(DBusMessage *message); /** * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. * * @param[in] subscription A GEIS subscription. * * This function is used on the client side to create a * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message from a local * %GeisSubscription object. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_activate_call_message(GeisSubscription subscription); /** * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message. * * @param[in] message The DBUs method_call message to reply to. * @param[in] subscription A GEIS subscription. * * This function is used on the server side to create a response to a received * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_activate_return_message(DBusMessage *message, GeisSubscription subscription); /** * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message. * * @param[in] message A DBus message. * * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DEACTIVATE, * GEIS_FALSE otherwise. */ GeisBoolean geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message); /** * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method return message. * * @param[in] message The DBUs method_call message to reply to. * @param[in] subscription A GEIS subscription. * * This function is used on the server side to create a response to a received * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_deactivate_return_message(DBusMessage *message, GeisSubscription subscription); /** * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. * * @param[in] subscription A GEIS subscription. * * This function is used on the client side to create a * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message from a local * %GeisSubscription object. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription); /** * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message. * * @param[in] message A DBus message. * * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DESTROY, * GEIS_FALSE otherwise. */ GeisBoolean geis_dbus_message_is_subscription_destroy_call(DBusMessage *message); /** * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. * * @param[in] subscription A GEIS subscription. * * This function is used on the client side to create a * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message from a local * %GeisSubscription object. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_destroy_call_message(GeisSubscription subscription); /** * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message. * * @param[in] message The DBUs method_call message to reply to. * * This function is used on the server side to create a response to a received * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. * * @returns A DBus message object. */ DBusMessage * geis_dbus_subscription_destroy_return_message(DBusMessage *message); #endif /* GEIS_DBUS_SUBSCRIPTION_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_class.h0000644000015600001650000000243112651717544023225 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_class.h * @brief Interface for the GEIS DBus gesture class transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_GESTURE_CLASS_H_ #define GEIS_DBUS_GESTURE_CLASS_H_ #include #include "geis/geis.h" /** * Creates a Dbus "class available" message from a GEIS class. * * @param[in] class A GEIS gesture class. */ DBusMessage * geis_dbus_class_available_message_from_class(GeisGestureClass gesture_class); /** * Creates GEIS class from a DBus "class available" message. * * @param[in] message A DBus message. */ GeisGestureClass geis_dbus_class_class_from_available_message(DBusMessage *message); #endif /* GEIS_DBUS_GESTURE_CLASS_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_attr.c0000644000015600001650000001246112651717544023071 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_attr.c * @brief Implementation of the GEIS DBus attr transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_attr.h" #include "geis_attr.h" #include "geis_logging.h" /* * Marshalls a single GEIS attr to an open DBus message container iterator. */ void geis_dbus_attr_marshall(GeisAttr attr, DBusMessageIter *iter) { DBusMessageIter dict_iter; GeisString attr_name = geis_attr_name(attr); dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &dict_iter); dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name); switch (geis_attr_type(attr)) { case GEIS_ATTR_TYPE_BOOLEAN: { DBusMessageIter variant_iter; dbus_bool_t val = geis_attr_value_to_boolean(attr); dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &variant_iter); dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_BOOLEAN, &val); dbus_message_iter_close_container(&dict_iter, &variant_iter); break; } case GEIS_ATTR_TYPE_FLOAT: { DBusMessageIter variant_iter; double val = geis_attr_value_to_float(attr); dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &variant_iter); dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_DOUBLE, &val); dbus_message_iter_close_container(&dict_iter, &variant_iter); break; } case GEIS_ATTR_TYPE_INTEGER: { DBusMessageIter variant_iter; dbus_int32_t val = geis_attr_value_to_integer(attr); dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant_iter); dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_INT32, &val); dbus_message_iter_close_container(&dict_iter, &variant_iter); break; } case GEIS_ATTR_TYPE_STRING: { DBusMessageIter variant_iter; GeisString val = geis_attr_value_to_string(attr); dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant_iter); dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &val); dbus_message_iter_close_container(&dict_iter, &variant_iter); break; } default: geis_error("invalid attribute type for DBus"); } dbus_message_iter_close_container(iter, &dict_iter); } /* * Unmarshalls a single GEIS attr from a DBus message iterator. */ GeisAttr geis_dbus_attr_unmarshall(DBusMessageIter *iter) { GeisAttr attr = NULL; DBusMessageIter dict_iter; dbus_message_iter_recurse(iter, &dict_iter); int dtype = dbus_message_iter_get_arg_type(&dict_iter); if (dtype != DBUS_TYPE_STRING) { geis_error("error getting attr name from DBus message"); goto final_exit; } char *attr_name; dbus_message_iter_get_basic(&dict_iter, &attr_name); dbus_message_iter_next(&dict_iter); dtype = dbus_message_iter_get_arg_type(&dict_iter); if (dtype != DBUS_TYPE_VARIANT) { geis_error("error getting attr variant from DBus message"); goto final_exit; } DBusMessageIter variant_iter; dbus_message_iter_recurse(&dict_iter, &variant_iter); int vtype = dbus_message_iter_get_arg_type(&variant_iter); switch (vtype) { case DBUS_TYPE_BOOLEAN: { dbus_bool_t val; dbus_message_iter_get_basic(&variant_iter, &val); attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_BOOLEAN, &val); break; } case DBUS_TYPE_DOUBLE: { double dval; dbus_message_iter_get_basic(&variant_iter, &dval); float fval = dval; attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_FLOAT, &fval); break; } case DBUS_TYPE_INT32: { dbus_int32_t val; dbus_message_iter_get_basic(&variant_iter, &val); attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_INTEGER, &val); break; } case DBUS_TYPE_STRING: { GeisString val; dbus_message_iter_get_basic(&variant_iter, &val); attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_STRING, (void *)val); break; } default: geis_error("unexpected attr data type from DBus"); break; } final_exit: return attr; } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_dispatcher.c0000644000015600001650000003122012651717544024237 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_dispatcher.c * @brief Implementation of the GEIS DBus dispatcher. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_dispatcher.h" #include "geis_logging.h" #include "geis_private.h" #include #include typedef struct GeisDBusWatch *GeisDBusWatch; typedef struct GeisDBusWatchBag *GeisDBusWatchBag; /* * Connects a DBusWatch back to a DBusConnection. * * This is an intrusive linked list node. See GeisDBusWatchBag. */ struct GeisDBusWatch { DBusConnection *connection; DBusWatch *watch; GeisDBusWatch next; }; /* * Maps file descriptors to watches and connections. * * A DBusWatch is assciated with a single file descriptor, but each file * descriptor may be associated with more than one DBusWatch. * * Each DBusConnection has one or more DBusWatch. The DBusWatches are passed * around without reference to the connection itself, but we often need the * connection when all we have is the watch. * * To make things more complex, the DBusServer does not have a connection * associated with its watches. * * This is a linked list with a free pool. */ struct GeisDBusWatchBag { GeisDBusWatch front; GeisDBusWatch back; GeisDBusWatch pool; }; static const int _geis_dbus_watch_bag_initial_size = 4; struct GeisDBusDispatcher { Geis geis; GeisDBusWatchBag watches; }; /* * Creates a new empty collection of watches. * * The pool is primed with a few empty watches to save time later, on the * assumption that if you're creating a bag you're going to use it. */ static GeisDBusWatchBag _geis_dbus_watch_bag_new() { GeisDBusWatchBag bag = calloc(1, sizeof(struct GeisDBusWatchBag)); if (!bag) { geis_error("error allocating GeisDBusWatchBag"); goto final_exit; } /* Prime the free pool. */ for (int i = 0; i < _geis_dbus_watch_bag_initial_size; ++i) { GeisDBusWatch gdbw = calloc(1, sizeof(struct GeisDBusWatch)); if (!gdbw) { geis_error("error allocating GeisDBusWatchBag"); goto unwind_pool; } gdbw->next = bag->pool; bag->pool = gdbw; } goto final_exit; unwind_pool: final_exit: return bag; } /* * Destroys a collection of watches. * * @param[in] bag A collection of %GeisDBusWatches. * * There should be no need to unref any of the contents of the bag, they can * just be freed without consequence. */ static void _geis_dbus_watch_bag_delete(GeisDBusWatchBag bag) { /* Free the pool. */ GeisDBusWatch gdbw = bag->pool; while (gdbw) { GeisDBusWatch next = gdbw->next; free(gdbw); gdbw = next; } /* Free the in-use watches. */ gdbw = bag->front; while (gdbw) { GeisDBusWatch next = gdbw->next; free(gdbw); gdbw = next; } free(bag); } /* * Gets an allocated watch from the bag. * * @param[in] bag A collection of %GeisDBusWatches. * @param[in] connection A DBusConnection. * @param[in] watch A DBusWatch. * * A factory function to create a new watch in the collection and return a * pointer to it. */ static GeisDBusWatch _geis_dbus_watch_bag_alloc_watch(GeisDBusWatchBag bag, DBusConnection *connection, DBusWatch *watch) { GeisDBusWatch gdbw = NULL; /* Either pull a free watch off the pool or allocate a new one. */ if (bag->pool) { gdbw = bag->pool; bag->pool = bag->pool->next; } else { gdbw = calloc(1, sizeof(struct GeisDBusWatch)); if (!gdbw) { geis_error("error allocating GeisDBusWatchBag"); goto final_exit; } } /* Fill in the data bits. */ gdbw->connection = connection; gdbw->watch = watch; gdbw->next = NULL; /* Add it to the in-use list. */ if (!bag->front) { bag->front = gdbw; } if (bag->back) { bag->back->next = gdbw; } bag->back = gdbw; final_exit: return gdbw; } /* * Removes a watch from a collection of such beasts. * * @param[in] bag A collection of %GeisDBusWatches. * @param[in] watch The watch to remove. */ static void _geis_dbus_watch_bag_remove_watch(GeisDBusWatchBag bag, DBusWatch *watch) { for (GeisDBusWatch gdbw = bag->front, prev = NULL; gdbw; gdbw = gdbw->next) { if (gdbw->watch == watch) { if (gdbw == bag->front) { bag->front = gdbw->next; } else { prev->next = gdbw->next; } if (gdbw == bag->back) { bag->back = prev; } gdbw->next = bag->pool; bag->pool = gdbw; break; } prev = gdbw; } } /* * Indicates if a file descriptor is already held in the watch bag. * * @param[in] bag A collection of %GeisDBusWatches. * @param[in] fd A file descriptor. * @param[out] flags The DBus watch flags for any enabled watches found. * * @returns zero if the file descriptor is not in the bag, non-zero otherwise. */ static int _geis_dbus_watch_bag_has_fd(GeisDBusWatchBag bag, int fd, unsigned int *flags) { int has_fd = 0; for (GeisDBusWatch gdbw = bag->front; gdbw; gdbw = gdbw->next) { if (dbus_watch_get_unix_fd(gdbw->watch) == fd) { has_fd |= ~0; if (dbus_watch_get_enabled(gdbw->watch)) { *flags |= dbus_watch_get_flags(gdbw->watch); } } } return has_fd; } /* * Finds a DBusWatch in the bag that matches the fd and current activity. * * @param[in] bag A collection of %GeisDBusWatches. * @param[in] fd The file descriptor on which an activity has been detected. * @param[in] activity The bitmask of currently detected activity on the fd. * * A DBusWatch will match if it has the same file descriptor and is watching for * (one of) the activity(ies) that has just occurred. * * Note that writers are implicitly looking for hangups or errors but the DBus * library goes into an infinite loop when a hangup has occurred no a write * watch, so defer that to a read watch. * * @returns a GeisDBusWatch or NULL if no matching watch was found. */ static GeisDBusWatch _geis_dbus_watch_bag_find_fd_activity(GeisDBusWatchBag bag, int fd, GeisBackendMultiplexorActivity activity) { GeisDBusWatch gdbw = NULL; for (gdbw = bag->front; gdbw; gdbw = gdbw->next) { if (dbus_watch_get_unix_fd(gdbw->watch) == fd) { unsigned int flags = dbus_watch_get_flags(gdbw->watch); if ((activity & GEIS_BE_MX_READ_AVAILABLE && flags & DBUS_WATCH_READABLE) || (activity & GEIS_BE_MX_WRITE_AVAILABLE && flags & DBUS_WATCH_WRITABLE) || (activity & GEIS_BE_MX_HANGUP_DETECTED && flags & DBUS_WATCH_READABLE) || (activity & GEIS_BE_MX_ERROR_DETECTED)) { break; } } } return gdbw; } /* * A callback function passed to the Geis multiplexor. * * @param[in] fd The file descriptor on which an activity has been detected. * @param[in] activity The bitmask of currently detected activity on the fd. * @param[in] context The %GeisDBusDispatcher passed through the multiplexor. * * This callback gets invoked whenever a requested activity is detected on a * regostered DBusWatch file descriptor. It translates the GEIS Multiplexor * activity to DBus activity. */ static void _geis_dbus_dispatcher_callback(int fd, GeisBackendMultiplexorActivity activity, void *context) { GeisDBusDispatcher dispatcher = (GeisDBusDispatcher)context; GeisDBusWatch gdb = _geis_dbus_watch_bag_find_fd_activity(dispatcher->watches, fd, activity); if (gdb) { /* Translate GEIS multiplexor activity to DBus watch flags. */ unsigned int flags = 0; if (activity & GEIS_BE_MX_READ_AVAILABLE) flags |= DBUS_WATCH_READABLE; if (activity & GEIS_BE_MX_WRITE_AVAILABLE) flags |= DBUS_WATCH_WRITABLE; if (activity & GEIS_BE_MX_HANGUP_DETECTED) flags |= DBUS_WATCH_HANGUP; if (activity & GEIS_BE_MX_ERROR_DETECTED) flags |= DBUS_WATCH_ERROR; dbus_watch_handle(gdb->watch, flags); if (gdb->connection) { if (activity & GEIS_BE_MX_HANGUP_DETECTED) { dbus_connection_close(gdb->connection); } else { DBusDispatchStatus s; s = dbus_connection_get_dispatch_status(gdb->connection); while (DBUS_DISPATCH_DATA_REMAINS == s) { s = dbus_connection_dispatch(gdb->connection); } } } } } /* * Creates a new GEIS DBus dispatcher. */ GeisDBusDispatcher geis_dbus_dispatcher_new(Geis geis) { GeisDBusDispatcher dispatcher = calloc(1, sizeof(struct GeisDBusDispatcher)); if (!dispatcher) { geis_error("error allocating GEIS DBus dispatcher."); goto final_exit; } dispatcher->geis = geis; dispatcher->watches = _geis_dbus_watch_bag_new(); if (!dispatcher->watches) { geis_error("error creating GEIS DBus dispatcher watches."); goto unwind_dispatcher; } goto final_exit; unwind_dispatcher: free(dispatcher); final_exit: return dispatcher; } /* * Destroys an existing %GeisDBusDispatcher object. */ void geis_dbus_dispatcher_delete(GeisDBusDispatcher dispatcher) { for (GeisDBusWatch gdbw = dispatcher->watches->front; gdbw; gdbw = gdbw->next) { geis_dbus_dispatcher_unregister(dispatcher, gdbw->watch); } _geis_dbus_watch_bag_delete(dispatcher->watches); free(dispatcher); } /* * Registers a new DBusWatch with a %GeisDBusDispatcher object. */ void geis_dbus_dispatcher_register(GeisDBusDispatcher dispatcher, DBusConnection *connection, DBusWatch *watch) { int watch_fd = dbus_watch_get_unix_fd(watch); /* Calculate all the enabled flags on the fd for all watches. */ unsigned int flags = 0; int has_fd = _geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags); _geis_dbus_watch_bag_alloc_watch(dispatcher->watches, connection, watch); if (dbus_watch_get_enabled(watch)) { flags |= dbus_watch_get_flags(watch); } /* Convert the watch flags to multiplexor activities. */ GeisBackendMultiplexorActivity activity = 0; if (flags & DBUS_WATCH_READABLE) activity |= GEIS_BE_MX_READ_AVAILABLE; if (flags & DBUS_WATCH_WRITABLE) activity |= GEIS_BE_MX_WRITE_AVAILABLE; /* Set or adjust the multiplexor seubscription. */ if (has_fd) { geis_remultiplex_fd(dispatcher->geis, watch_fd, activity); } else { geis_multiplex_fd(dispatcher->geis, watch_fd, activity, _geis_dbus_dispatcher_callback, dispatcher); } } /* * Unregisters a DBusWatch for events. */ void geis_dbus_dispatcher_unregister(GeisDBusDispatcher dispatcher, DBusWatch *watch) { int watch_fd = dbus_watch_get_unix_fd(watch); unsigned int flags = 0; _geis_dbus_watch_bag_remove_watch(dispatcher->watches, watch); if (!_geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags)) { geis_demultiplex_fd(dispatcher->geis, watch_fd); } } /* * Marks a DBusWatch as active, maybe. */ void geis_dbus_dispatcher_toggle_watch(GeisDBusDispatcher dispatcher, DBusWatch *watch) { int watch_fd = dbus_watch_get_unix_fd(watch); /* Calculate all the enabled flags on the fd for all watches. */ unsigned int flags = 0; _geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags); if (dbus_watch_get_enabled(watch)) { flags |= dbus_watch_get_flags(watch); } else { flags &= ~dbus_watch_get_flags(watch); } /* Convert the watch flags to multiplexor activities. */ GeisBackendMultiplexorActivity activity = 0; if (flags & DBUS_WATCH_READABLE) activity |= GEIS_BE_MX_READ_AVAILABLE; if (flags & DBUS_WATCH_WRITABLE) activity |= GEIS_BE_MX_WRITE_AVAILABLE; /* Set or adjust the multiplexor seubscription. */ geis_remultiplex_fd(dispatcher->geis, watch_fd, activity); } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_gesture_event.h0000644000015600001650000000270512651717544025003 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_gesture_event.h * @brief Interface for the GEIS DBus gesture event transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_GESTURE_EVENT_H_ #define GEIS_DBUS_GESTURE_EVENT_H_ #include #include "geis/geis.h" /** * Creates a Dbus "gesture event" message from a GEIS gesture event. * * @param[in] event A GEIS event. */ DBusMessage * geis_dbus_gesture_event_message_from_geis_event(GeisEvent event); /** * Indicates if a DBus message is a "gesture event" message. * * @param[in] message A DBus message. */ GeisBoolean geis_dbus_message_is_gesture_event(DBusMessage *message); /** * Creates GEIS event from a DBus "gesture_event" message. * * @param[in] message A DBus message. */ GeisEvent geis_dbus_gesture_event_from_message(Geis geis, DBusMessage *message); #endif /* GEIS_DBUS_GESTURE_EVENT_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_region.c0000644000015600001650000000472612651717544023407 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_region.c * @brief Implementations of the GEIS DBus region transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program. If not, see . */ #include "geis_config.h" #include "geis_dbus_region.h" #include "geis_dbus.h" #include "geis_logging.h" /* * Creates a Dbus "region available" message from a GEIS region. */ DBusMessage * geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa) { DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_REGION_AVAILABLE); DBusMessageIter iter; dbus_message_iter_init_append(message, &iter); const char *attr_name = fa->name; dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &attr_name); dbus_int32_t attr_type = fa->type; dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &attr_type); return message; } /* * Creates GEIS region filterable attribute from a DBus "region available" * message. */ GeisFilterableAttribute geis_dbus_region_from_region_available_message(DBusMessage *message) { geis_debug("begins"); static struct GeisFilterableAttribute attr; DBusMessageIter iter; dbus_message_iter_init(message, &iter); int type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_STRING) { geis_error("error getting attr name name from DBus message."); goto final_exit; } char *attr_name; dbus_message_iter_get_basic(&iter, &attr_name); dbus_message_iter_next(&iter); type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_INT32) { geis_error("error getting attr type from DBus message."); goto final_exit; } dbus_int32_t attr_type; dbus_message_iter_get_basic(&iter, &attr_type); attr.name = attr_name; attr.type = attr_type; final_exit: geis_debug("ends"); return &attr; } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_device.c0000644000015600001650000001030312651717544023347 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_device.c * @brief Implementations of the GEIS DBus device transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program. If not, see . */ #include "geis_config.h" #include "geis_dbus_device.h" #include "geis_dbus.h" #include "geis_dbus_attr.h" #include "geis_device.h" #include "geis_logging.h" /* * Creates a Dbus "device available" message from a GEIS device. * * The Wire protocol for this message is device_id and device_name followed by * the list of device attributes. */ DBusMessage * geis_dbus_device_available_message_from_device(GeisDevice device) { DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_DEVICE_AVAILABLE); DBusMessageIter iter; dbus_message_iter_init_append(message, &iter); dbus_int32_t device_id = geis_device_id(device); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &device_id); const char *device_name = geis_device_name(device); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device_name); DBusMessageIter array_iter; dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_ATTR, &array_iter); GeisSize attr_count = geis_device_attr_count(device); for (GeisSize i = 0; i < attr_count; ++i) { geis_dbus_attr_marshall(geis_device_attr(device, i), &array_iter); } dbus_message_iter_close_container(&iter, &array_iter); return message; } /* * Creates GEIS device from a DBus "device available" message. */ GeisDevice geis_dbus_device_device_from_available_message(DBusMessage *message) { geis_debug("begins"); GeisDevice device = NULL; DBusMessageIter iter; dbus_message_iter_init(message, &iter); int type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_INT32) { geis_error("error getting device ID from DBus message."); goto final_exit; } dbus_int32_t device_id; dbus_message_iter_get_basic(&iter, &device_id); dbus_message_iter_next(&iter); type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_STRING) { geis_error("error getting device name from DBus message."); goto final_exit; } char *device_name; dbus_message_iter_get_basic(&iter, &device_name); device = geis_device_new(device_name, device_id); dbus_message_iter_next(&iter); type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_ARRAY) { geis_error("error getting device attr list from DBus message."); goto final_exit; } DBusMessageIter array_iter; dbus_message_iter_recurse(&iter, &array_iter); int atype = dbus_message_iter_get_arg_type(&array_iter); while (atype == DBUS_TYPE_DICT_ENTRY) { GeisAttr attr = geis_dbus_attr_unmarshall(&array_iter); if (attr) { geis_device_add_attr(device, attr); } dbus_message_iter_next(&array_iter); atype = dbus_message_iter_get_arg_type(&array_iter); } final_exit: geis_debug("ends"); return device; } /* * Creates a Dbus "device unavailable" message from a GEIS device. */ DBusMessage * geis_dbus_device_unavailable_message_from_device(GeisDevice device GEIS_UNUSED) { geis_debug("begins"); DBusMessage *message = NULL; geis_debug("ends"); return message; } /* * Creates GEIS device from a DBus "device unavailable" message. */ GeisDevice geis_dbus_device_device_from_unavailable_message(DBusMessage *message GEIS_UNUSED) { geis_debug("begins"); GeisDevice device = NULL; geis_debug("ends"); return device; } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_class.c0000644000015600001650000000762412651717544023231 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_gesture_class.c * @brief Implementations of the GEIS DBus gesture_class transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program. If not, see . */ #include "geis_config.h" #include "geis_dbus_class.h" #include "geis_dbus.h" #include "geis_dbus_attr.h" #include "geis_class.h" #include "geis_logging.h" /* * Creates a Dbus "gesture_class available" message from a GEIS gesture_class. * * The Wire protocol for this message is class_id and class_name followed by * the list of class attributes. */ DBusMessage * geis_dbus_class_available_message_from_class(GeisGestureClass gesture_class) { DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_CLASS_AVAILABLE); DBusMessageIter iter; dbus_message_iter_init_append(message, &iter); dbus_int32_t gesture_class_id = geis_gesture_class_id(gesture_class); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &gesture_class_id); const char *gesture_class_name = geis_gesture_class_name(gesture_class); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &gesture_class_name); DBusMessageIter array_iter; dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_ATTR, &array_iter); GeisSize attr_count = geis_gesture_class_attr_count(gesture_class); for (GeisSize i = 0; i < attr_count; ++i) { geis_dbus_attr_marshall(geis_gesture_class_attr(gesture_class, i), &array_iter); } dbus_message_iter_close_container(&iter, &array_iter); return message; } /* * Creates GEIS gesture_class from a DBus "gesture_class available" message. */ GeisGestureClass geis_dbus_class_class_from_available_message(DBusMessage *message) { GeisGestureClass gesture_class = NULL; DBusMessageIter iter; dbus_message_iter_init(message, &iter); int type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_INT32) { geis_error("error getting gesture_class ID from DBus message."); goto final_exit; } dbus_int32_t gesture_class_id; dbus_message_iter_get_basic(&iter, &gesture_class_id); dbus_message_iter_next(&iter); type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_STRING) { geis_error("error getting gesture_class name from DBus message."); goto final_exit; } char *gesture_class_name; dbus_message_iter_get_basic(&iter, &gesture_class_name); gesture_class = geis_gesture_class_new(gesture_class_name, gesture_class_id); dbus_message_iter_next(&iter); type = dbus_message_iter_get_arg_type(&iter); if (type != DBUS_TYPE_ARRAY) { geis_error("error getting gesture_class attr list from DBus message."); goto final_exit; } DBusMessageIter array_iter; dbus_message_iter_recurse(&iter, &array_iter); int atype = dbus_message_iter_get_arg_type(&array_iter); while (atype == DBUS_TYPE_DICT_ENTRY) { GeisAttr attr = geis_dbus_attr_unmarshall(&array_iter); if (attr) { geis_gesture_class_add_attr(gesture_class, attr); } dbus_message_iter_next(&array_iter); atype = dbus_message_iter_get_arg_type(&array_iter); } final_exit: return gesture_class; } geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_dispatcher.h0000644000015600001650000000710212651717544024246 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_dispatcher.h * @brief Interface for the GEIS DBus dispatcher. * * The GEIS DBus dispatcher provides a central dispatch point for all DBus * events used internally by GEIS. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_DISPATCHER_H_ #define GEIS_DBUS_DISPATCHER_H_ #include #include "geis/geis.h" /** * The %GeisDBusDispatcher centralizes all dispatch for all DBus events used * internally by the GEIS client-server mechanism. * * Geis implements single-threaded ansynchronous dispatch for DBus events, in * case a single-threaded client is making use of GEIS. This also simplifies a * lot of the internal design of the GEIS DBus service, since no locking or * other forms of synchronization are required. */ typedef struct GeisDBusDispatcher *GeisDBusDispatcher; /** * A callback type for the handler function dispatched on DBus events. * * @todo the parameters of the GeisDispatchCallback must be defined. */ typedef void (*GeisDispatchCallback)(void *context); /** * Creates a new GEIS DBus dispatcher. * * @param[in] geis A GEIS instance. * * Creates a new %GeisDBusDispatcher and registers it with the GEIS API instance * so it will be multiplexed and receive event notification. * * @returns a new %GeisDBusDispatcher object or NULL on failure. */ GeisDBusDispatcher geis_dbus_dispatcher_new(Geis geis); /** * Destroys an existing %GeisDBusDispatcher object. * * @param[in] dispatcher A %GeisDBusDispatcher object. */ void geis_dbus_dispatcher_delete(GeisDBusDispatcher dispatcher); /** * Registers a new DBusWatch with a %GeisDBusDispatcher object. * * @param[in] dispatcher A %GeisDBusDispatcher object. * @param[in] connection A DBus connection. * @param[in] watch A DBusWatch om the connection. * * The @p watch will be registered with the @p dispatcher for future DBus * events. The @p watch may or may not be activated, depending on its @a * enabled state at the time of registration. */ void geis_dbus_dispatcher_register(GeisDBusDispatcher dispatcher, DBusConnection *connection, DBusWatch *watch); /** * Unregisters a DBusWatch for events. * * @param[in] dispatcher A %GeisDBusDispatcher object. * @param[in] watch A DBusWatch. */ void geis_dbus_dispatcher_unregister(GeisDBusDispatcher dispatcher, DBusWatch *watch); /** * Marks a DBusWatch as active or not, depending on its state. * * @param[in] dispatcher A %GeisDBusDispatcher object. * @param[in] watch A pointer to a DBusWatch object. * * The @p dispatcher will listen for events on the @p watch if its @a is_enabled * state is true or not. */ void geis_dbus_dispatcher_toggle_watch(GeisDBusDispatcher dispatcher, DBusWatch *watch); #endif /* GEIS_DBUS_DISPATCHER_H_ */ geis-2.2.17+16.04.20160126/libs/geis-dbus/geis_dbus_subscription.c0000644000015600001650000003762012651717544024647 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_subscription.c * @brief Implementation of the GEIS DBus subscription transport. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_subscription.h" #include "geis_dbus.h" #include "geis_dbus_attr.h" #include "geis_filter_term.h" #include "geis_logging.h" #include "geis_subscription.h" #include /* * A filter term is marshalled as a (facility, operation, value) tuple. * That would be a (ii(sv)) in DBusspeak. */ #define GEIS_DBUS_TYPE_SIGNATURE_TERM \ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ DBUS_TYPE_INT32_AS_STRING \ DBUS_TYPE_INT32_AS_STRING \ GEIS_DBUS_TYPE_SIGNATURE_ATTR \ DBUS_STRUCT_END_CHAR_AS_STRING /* * A term list is an array of terms, as in a(ii(sv)). */ #define GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \ DBUS_TYPE_ARRAY_AS_STRING \ GEIS_DBUS_TYPE_SIGNATURE_TERM /* * A filter is a named array of filter terms. * That's a {sa(ii(sv))} in the DBus tongue. */ #define GEIS_DBUS_TYPE_SIGNATURE_FILTER \ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \ DBUS_TYPE_STRING_AS_STRING \ GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \ DBUS_DICT_ENTRY_END_CHAR_AS_STRING /** * Adds filter terms to a DBus message. * * @param[in] filter The filter for which terms will be marshalled. * @param[in] filter_iter A DBus message output iterator. */ static void _geis_dbus_marshall_subscription_filter_terms(GeisFilter filter, DBusMessageIter *filter_iter) { DBusMessageIter term_list_iter; dbus_message_iter_open_container(filter_iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_TERM, &term_list_iter); for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i) { GeisFilterTerm term = geis_filter_term(filter, i); dbus_int32_t facility = geis_filter_term_facility(term); dbus_int32_t operation = geis_filter_term_operation(term); GeisAttr attr = geis_filter_term_attr(term); DBusMessageIter term_iter; dbus_message_iter_open_container(&term_list_iter, DBUS_TYPE_STRUCT, NULL, &term_iter); dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &facility); dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &operation); geis_dbus_attr_marshall(attr, &term_iter); dbus_message_iter_close_container(&term_list_iter, &term_iter); } dbus_message_iter_close_container(filter_iter, &term_list_iter); } /** * Squeezes the filters on a subscription into the DBus wire protocol. * * @param[in] sub A %GeisSubscription * @param[in] msg_iter The open output iterator for a DBus message. * * The filters are marshalled as an array of DBus dict entries. */ static void _geis_dbus_marshall_subscription_filters(GeisSubscription subscription, DBusMessageIter *msg_iter) { DBusMessageIter filter_list_iter; dbus_message_iter_open_container(msg_iter, DBUS_TYPE_ARRAY, GEIS_DBUS_TYPE_SIGNATURE_FILTER, &filter_list_iter); for (GeisFilterIterator it = geis_subscription_filter_begin(subscription); it != geis_subscription_filter_end(subscription); it = geis_subscription_filter_next(subscription, it)) { const char *filter_name = geis_filter_name(*it); DBusMessageIter filter_iter; dbus_message_iter_open_container(&filter_list_iter, DBUS_TYPE_DICT_ENTRY, NULL, &filter_iter); dbus_message_iter_append_basic(&filter_iter, DBUS_TYPE_STRING, &filter_name); _geis_dbus_marshall_subscription_filter_terms(*it, &filter_iter); dbus_message_iter_close_container(&filter_list_iter, &filter_iter); } dbus_message_iter_close_container(msg_iter, &filter_list_iter); } static void _geis_dbus_unmarshall_filter_terms(GeisFilter filter, DBusMessageIter *filter_iter) { DBusMessageIter term_list_iter; dbus_message_iter_recurse(filter_iter, &term_list_iter); for (int dtype = dbus_message_iter_get_arg_type(&term_list_iter); dtype != DBUS_TYPE_INVALID; dbus_message_iter_next(&term_list_iter), dtype = dbus_message_iter_get_arg_type(&term_list_iter)) { int ttype = dbus_message_iter_get_arg_type(&term_list_iter); if (ttype != DBUS_TYPE_STRUCT) { geis_error("malformed GeisSubscription term"); goto final_exit; } DBusMessageIter term_iter; dbus_message_iter_recurse(&term_list_iter, &term_iter); dbus_int32_t facility; dbus_message_iter_get_basic(&term_iter, &facility); dbus_message_iter_next(&term_iter); dbus_int32_t operation; dbus_message_iter_get_basic(&term_iter, &operation); dbus_message_iter_next(&term_iter); GeisAttr attr = geis_dbus_attr_unmarshall(&term_iter); GeisFilterTerm term = geis_filter_term_new(facility, operation, attr); geis_filter_add_term_internal(filter, term); } final_exit: return; } /** * Unmarshalls a filter from a DBus message. * * @param[in] geis A GEIS instance. * @param[in] filter_iter A DBus message iterator pointing to the filter. */ static GeisFilter _geis_dbus_unmarshall_filter(Geis geis, DBusMessageIter *filter_iter) { GeisFilter filter = NULL; int ftype = dbus_message_iter_get_arg_type(filter_iter); if (ftype != DBUS_TYPE_DICT_ENTRY) { geis_error("malformed GeisSubscription filter"); goto final_exit; } DBusMessageIter dict_iter; dbus_message_iter_recurse(filter_iter, &dict_iter); ftype = dbus_message_iter_get_arg_type(&dict_iter); if (ftype != DBUS_TYPE_STRING) { geis_error("malformed GeisSubscription filter"); goto final_exit; } GeisString filter_name; dbus_message_iter_get_basic(&dict_iter, &filter_name); dbus_message_iter_next(&dict_iter); filter = geis_filter_new(geis, filter_name); ftype = dbus_message_iter_get_arg_type(&dict_iter); if (ftype != DBUS_TYPE_ARRAY) { geis_error("malformed GeisSubscription filter"); goto final_exit; } _geis_dbus_unmarshall_filter_terms(filter, &dict_iter); final_exit: return filter; } /** * Unmarshalls a list of filters from a DBus message. * * @param[in] geis A GEIS instance. * @param[in] subscription_iter A DBus message iterator for the subscription. * @param[in] subscription A GEIS subsccription. * * This function unmarshalls filters from a GEIS DBus subscription message and * adds them to a existing GEIS subscription. */ static void _geis_dbus_unmarshall_subscription_filters(Geis geis, DBusMessageIter *subscription_iter, GeisSubscription subscription) { DBusMessageIter filter_list_iter; dbus_message_iter_recurse(subscription_iter, &filter_list_iter); for (int dtype = dbus_message_iter_get_arg_type(&filter_list_iter); dtype != DBUS_TYPE_INVALID; dbus_message_iter_next(&filter_list_iter), dtype = dbus_message_iter_get_arg_type(&filter_list_iter)) { GeisFilter filter = _geis_dbus_unmarshall_filter(geis, &filter_list_iter); if (filter) { geis_subscription_add_filter(subscription, filter); } } } /* * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call. */ GeisBoolean geis_dbus_message_is_subscription_create_call(DBusMessage *message) { return dbus_message_is_method_call(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_CREATE); } /* * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message. */ DBusMessage * geis_dbus_subscription_create_call_message(GeisSubscription subscription) { DBusMessage *message = NULL; GeisString sub_name = "dummy"; dbus_int32_t sub_id = -1; dbus_uint32_t sub_flags = 0; DBusMessageIter iter; message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_CREATE); if (subscription) { sub_name = geis_subscription_name(subscription); sub_id = geis_subscription_id(subscription); sub_flags = geis_subscription_flags(subscription); } dbus_message_iter_init_append(message, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &sub_name); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_id); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_flags); _geis_dbus_marshall_subscription_filters(subscription, &iter); return message; } /* * Creates a %GeisSubscription from a method call message. */ GeisSubscription geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message) { DBusMessageIter message_iter; dbus_message_iter_init(message, &message_iter); GeisString client_sub_name; dbus_message_iter_get_basic(&message_iter, &client_sub_name); dbus_message_iter_next(&message_iter); dbus_int32_t client_sub_id; dbus_message_iter_get_basic(&message_iter, &client_sub_id); dbus_message_iter_next(&message_iter); dbus_uint32_t client_sub_flags; dbus_message_iter_get_basic(&message_iter, &client_sub_flags); dbus_message_iter_next(&message_iter); GeisSubscription subscription = NULL; subscription = geis_subscription_new(geis, client_sub_name, client_sub_flags); if (!subscription) { geis_error("error creating proxy subscription"); goto final_exit; } intptr_t fudge = client_sub_id; geis_subscription_set_pdata(subscription, (GeisPointer)fudge); int dtype = dbus_message_iter_get_arg_type(&message_iter); if (dtype != DBUS_TYPE_ARRAY) { geis_error("malformed GeisSubscription message" " (expected type %c, received type %c)", DBUS_TYPE_ARRAY, dtype); goto final_exit; } _geis_dbus_unmarshall_subscription_filters(geis, &message_iter, subscription); final_exit: return subscription; } /* * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message. */ DBusMessage * geis_dbus_subscription_create_return_message(DBusMessage *message, GeisSubscription subscription) { DBusMessage *reply = dbus_message_new_method_return(message); intptr_t fudge = (intptr_t)geis_subscription_pdata(subscription); dbus_int32_t client_sub_id = fudge; dbus_int32_t server_sub_id = geis_subscription_id(subscription); dbus_message_append_args(reply, DBUS_TYPE_INT32, &client_sub_id, DBUS_TYPE_INT32, &server_sub_id, DBUS_TYPE_INVALID); return reply; } /* * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message. */ GeisBoolean geis_dbus_message_is_subscription_activate_call(DBusMessage *message) { return dbus_message_is_method_call(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_ACTIVATE); } /* * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. */ DBusMessage * geis_dbus_subscription_activate_call_message(GeisSubscription subscription) { DBusMessage *message = NULL; DBusMessageIter iter; message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_ACTIVATE); dbus_message_iter_init_append(message, &iter); dbus_int32_t subscription_id = geis_subscription_id(subscription); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &subscription_id); _geis_dbus_marshall_subscription_filters(subscription, &iter); return message; } /* * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message. */ DBusMessage * geis_dbus_subscription_activate_return_message(DBusMessage *message, GeisSubscription subscription) { DBusMessage *reply = NULL; reply = dbus_message_new_method_return(message); dbus_int32_t subscription_id = -1; if (subscription) { subscription_id = geis_subscription_id(subscription); } dbus_message_append_args(reply, DBUS_TYPE_INT32, &subscription_id, DBUS_TYPE_INVALID); return reply; } /* * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message. */ GeisBoolean geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message) { return dbus_message_is_method_call(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_DEACTIVATE); } /* * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. */ DBusMessage * geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription GEIS_UNUSED) { DBusMessage *message = NULL; message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_DEACTIVATE); return message; } /** */ DBusMessage * geis_dbus_subscription_deactivate_return_message(DBusMessage *message, GeisSubscription subscription) { DBusMessage *reply = NULL; reply = dbus_message_new_method_return(message); dbus_int32_t subscription_id = geis_subscription_id(subscription); dbus_message_append_args(reply, DBUS_TYPE_INT32, &subscription_id, DBUS_TYPE_INVALID); return reply; } /* * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message. */ GeisBoolean geis_dbus_message_is_subscription_destroy_call(DBusMessage *message) { return dbus_message_is_method_call(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_DESTROY); } /* * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. */ DBusMessage * geis_dbus_subscription_destroy_call_message(GeisSubscription subscription) { DBusMessage *message = NULL; message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SUBSCRIPTION_DESTROY); dbus_int32_t server_sub_id = (intptr_t)geis_subscription_pdata(subscription); dbus_message_append_args(message, DBUS_TYPE_INT32, &server_sub_id, DBUS_TYPE_INVALID); return message; } /* * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message. */ DBusMessage * geis_dbus_subscription_destroy_return_message(DBusMessage *message) { return dbus_message_new_method_return(message); } geis-2.2.17+16.04.20160126/libs/Makefile.am0000644000015600001650000000163512651717544020102 0ustar pbuserpbgroup00000000000000# # @file libs/Makefile.am # @brief automake recipe for the geis helper libraries subproject # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # SUBDIRS = geis-util geis-dbus geis-2.2.17+16.04.20160126/libs/geis-util/0000755000015600001650000000000012651717732017742 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libs/geis-util/geis_bag.h0000644000015600001650000001040612651717551021653 0ustar pbuserpbgroup00000000000000/** * @file geis_bag.h * @brief generic bag container interface */ /* * Copyright 2011 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef GEIS_UTIL_BAG_H #define GEIS_UTIL_BAG_H #include "geis/geis.h" /** * @struct GeisBag * @brief A handle for a generic value-storage bag. * @ingroup geis_util * * A bag is a container that holds zero or more copies of a data structure of * homogeneous type. It is implemented as a contiguous store of data that grows * when needed using a predetermined growth factor to give amortized constant * insertion and removal rates. * * Uses of this structure should be wrapped by more type-specific functions. * * @typedef GeisBag * @brief opaque pointer to a GeisBag object. */ typedef struct GeisBag *GeisBag; struct GeisBag { GeisSize store_size; /**< The size of data_store in datum_size * units. */ GeisFloat store_growth_factor; /**< The storage growth factor. */ GeisSize datum_size; /**< The number of bytes in each datum. */ GeisSize data_count; /**< The number of data in data_store. */ void *data_store; /**< The the data store. */ }; #define geis_bag_default_init_alloc 2 #define geis_bag_default_growth_factor 1.5f /** * Creates a new, empty bag. * @memberof GeisBag * * @param[in] data_size The size (in bytes) of the stored datum. * @param[in] init_alloc The initial number of data to allocate space for. * @param[in] growth_factor The growth factor for extending the bag. * * Constructs a generic homogenous container that is designed to hold data with * a size of @p data_size (in bytes). Space for @p init_alloc data is initially * allocated, and subsequent expansions will be done by a factor of * @p growth_factor (taking the ceiling of the current allocation times the @p * growth_factor). * * @returns a new, empty GeisBag on success or a NULL on failure. */ GeisBag geis_bag_new(GeisSize data_size, GeisSize init_alloc, GeisFloat growth_factor); /** * Destroys a bag. * @memberof GeisBag * * @param[in] bag The bag to destroy. * * Frees all resources used by the bag itself: does not destroy any store data. */ void geis_bag_delete(GeisBag bag); /** * Gets the number of data contained in the bag. * @memberof GeisBag * * @param[in] bag The bag. * * @returns the count of the data contained in the bag. */ GeisSize geis_bag_count(GeisBag bag); /** * Appends a new datam to the store. * @memberof GeisBag * * @param[in] bag The bag to append to. * @param[in] datum The datum to append. * * @returns GEIS_STATUS_UNKNOWN_ERROR if @p datum failed to be appended (for * example, memory allocation failure during bag expansion), GEIS_STATUS_SUCCESS * otherwise. */ GeisStatus geis_bag_append(GeisBag bag, void *datum); /** * Gets a pointer to a datum by index. * @memberof GeisBag * * @param[in] bag The bag. * @param[in] index Indicates the datum to retrieve. * * @returns NULL if @p index is out of range, a pointer to the indictaed datum * otherwise. */ void* geis_bag_at(GeisBag bag, GeisSize index); /** * Removes an indicated datum from the bag. * @memberof GeisBag * * @param[in] bag The bag. * @param[in] index Indicates the datum to remove. * * This function removes the datum and if necessary fills in the 'hole' in the * store by moving other data around. It will invalidate any pointers into the * bag: avoid using 'em. Does not call any deleter functions, so plan * accordingly. * * @returns GEIS_STATUS_BAD_ARGUMENT if @p index is out of range, * GEIS_STATUS_SUCCESS otherwise. */ GeisStatus geis_bag_remove(GeisBag bag, GeisSize index); #endif /* GEIS_UTIL_BAG_H */ geis-2.2.17+16.04.20160126/libs/geis-util/geis_bag.c0000644000015600001650000000701612651717544021653 0ustar pbuserpbgroup00000000000000/** * @file geis_bag.c * @brief generic bag container */ /* * Copyright 2011 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "geis_config.h" #include "geis_bag.h" #include #include "geis_logging.h" #include #include #include /** * Allocates data storage for a GeisBag. */ static void * _bag_store_allocate(GeisSize store_size, GeisSize data_size) { void *store = calloc(store_size, data_size); if (!store) geis_error("failed to allocate bag store"); return store; } /* * Creates a new, empty bag. */ GeisBag geis_bag_new(GeisSize datum_size, GeisSize init_alloc, GeisFloat growth_factor) { GeisBag bag = calloc(1, sizeof(struct GeisBag)); if (!bag) { geis_error("failed to allocate bag"); goto final_exit; } bag->store_size = init_alloc; bag->store_growth_factor = growth_factor; bag->datum_size = datum_size; bag->data_count = 0; bag->data_store = _bag_store_allocate(bag->store_size, bag->datum_size); if (!bag->data_store) { free(bag); bag = NULL; } final_exit: return bag; } /* * Destroys a bag. */ void geis_bag_delete(GeisBag bag) { free(bag->data_store); free(bag); } /* * Gets the number of data contained in the bag. */ GeisSize geis_bag_count(GeisBag bag) { return bag->data_count; } /* * Appends a new datam to the store. */ GeisStatus geis_bag_append(GeisBag bag, void *datum) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->data_count >= bag->store_size) { GeisSize new_store_size = ceilf(bag->store_size * bag->store_growth_factor); void *new_data_store = _bag_store_allocate(new_store_size, bag->datum_size); if (!new_data_store) { goto final_exit; } memcpy(new_data_store, bag->data_store, bag->data_count * bag->datum_size); free(bag->data_store); bag->data_store = new_data_store; bag->store_size = new_store_size; } memcpy((char *)bag->data_store + bag->data_count * bag->datum_size, datum, bag->datum_size); ++bag->data_count; status = GEIS_STATUS_SUCCESS; final_exit: return status; } /* * Gets a pointer to a datum by index. */ void * geis_bag_at(GeisBag bag, GeisSize index) { void *datum = NULL; if (index >= bag->data_count) { assert(index < bag->data_count); goto final_exit; } datum = (char *)bag->data_store + bag->datum_size * index; final_exit: return datum; } /* * Removes an indicated datum from the bag. */ GeisStatus geis_bag_remove(GeisBag bag, GeisSize index) { GeisStatus status = GEIS_STATUS_BAD_ARGUMENT; if (index >= bag->data_count) { assert(index < bag->data_count); goto final_exit; } size_t size = (bag->data_count - index - 1) * bag->datum_size; if (size) { char *dst = (char *)bag->data_store + bag->datum_size * index; char *src = dst + bag->datum_size; memmove(dst, src, size); } --bag->data_count; status = GEIS_STATUS_SUCCESS; final_exit: return status; } geis-2.2.17+16.04.20160126/libs/geis-util/Makefile.am0000644000015600001650000000172612651717544022005 0ustar pbuserpbgroup00000000000000# # @file libs/geis-util/Makefile.am # @brief automake recipe for the GEIS utilities convenience library # # Copyright 2011 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # noinst_LTLIBRARIES = libgeis-util.la dist_libgeis_util_la_SOURCES = \ geis_bag.h geis_bag.c \ geis_logging.h geis_logging.c libgeis_util_la_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis geis-2.2.17+16.04.20160126/libs/geis-util/geis_util.dox0000644000015600001650000000027612651717544022450 0ustar pbuserpbgroup00000000000000/** * @defgroup geis_util GEIS internal utility library * * This is a collection of various utilities used throughout the GEIS * implementation. It is not a part of the public API. */ geis-2.2.17+16.04.20160126/libs/geis-util/geis_logging.h0000644000015600001650000000463312651717544022557 0ustar pbuserpbgroup00000000000000/** * @file geis_logging.h * @brief internal GEIS debug/logging facilities * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_LOGGING_H_ #define GEIS_LOGGING_H_ /** * @defgroup geis_logging GEIS Logging Facilities * @ingroup geis_util * * This facility allows the run-time delivery of debugging and error emssages * from the library. By default, no debug or error diagnostics are emitted by * the library. However, if the environment variable GEIS_DEBUG is set to an * appropriate value, these diagnostic messages will be emitted to stderr. * * The following GEIS_DEBUG values are supported. * * GEIS_DEBUG=1 error messages only are emitted * GEIS_DEBUG=2 error and warning messages are emitted * GEIS_DEBUG=3 error, warning, and debug messages are emitted * * @{ */ #define _GEIS_LOG_LEVEL_ERROR 1 #define _GEIS_LOG_LEVEL_WARNING 2 #define _GEIS_LOG_LEVEL_DEBUG 3 /** * Emits a message at the DEBUG logging level. * @param[in] fmt printf-style format string */ #define geis_debug(...) _geis_message(_GEIS_LOG_LEVEL_DEBUG, \ __extension__ __FUNCTION__, __LINE__, \ __VA_ARGS__) #define geis_warning(...) _geis_message(_GEIS_LOG_LEVEL_WARNING, \ __extension__ __FUNCTION__, __LINE__, \ __VA_ARGS__) #define geis_error(...) _geis_message(_GEIS_LOG_LEVEL_ERROR, \ __extension__ __FUNCTION__, __LINE__, \ __VA_ARGS__) int _geis_message(int level, const char *function, int line, const char *format, ...) __attribute__((format(printf, 4, 5))); /* @} */ #endif /* GEIS_LOGGING_H_ */ geis-2.2.17+16.04.20160126/libs/geis-util/geis_logging.c0000644000015600001650000000361312651717544022547 0ustar pbuserpbgroup00000000000000/** * @file geis_logging.h * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_logging.h" #include #include #include #include static const char *prefix_format = "GEIS(%s)-%s:%d "; static const char *debug_marker = "debug"; static const char *warning_marker = "warning"; static const char *error_marker = "error"; static int reporting_level() { char *level = getenv("GEIS_DEBUG"); if (level) { return atoi(level); } return 0; } static int level_is_enabled(int desired_level) { static int level = -1; if (level < 0) level = reporting_level(); return level >= desired_level; } int _geis_message(int level, const char* function, int line, const char *format, ...) { int count = 0; if (level_is_enabled(level)) { const char *marker = NULL; switch (level) { case _GEIS_LOG_LEVEL_DEBUG: marker = debug_marker; break; case _GEIS_LOG_LEVEL_WARNING: marker = warning_marker; break; default: marker = error_marker; break; } fprintf(stderr, prefix_format, marker, function, line); va_list ap; va_start(ap, format); count = vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); } return count; } geis-2.2.17+16.04.20160126/README0000644000015600001650000000126612651717544015775 0ustar pbuserpbgroup00000000000000This is the source for the GEIS (Gesture Engine Implementation Support) library built on top of the XCB bindings to the GRAIL gesture recognition and instantiation library. Please see the file INSTALL for instructoins on building and installing this software. Better yet, pull the binaries from your operating system distribution. To prepare the sources for building on a fresh VCS checkout, you will need to run the shell script autogen.sh. This requires that the following packages be installed first so that autoconf macros are available. In addition, the full autotools suite (autoconf, automake, libtool, etc) must be available. libxorg-gtest-dev 0.2.0 pkg-config 0.26 geis-2.2.17+16.04.20160126/Makefile.am0000644000015600001650000000235512651717544017151 0ustar pbuserpbgroup00000000000000# # @file Makefile.am # @brief top-level makefile for the libgeis project # # Copyright 2010, 2011, 2012 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ACLOCAL_AMFLAGS = -I m4 --install AM_MAKEFLAGS = --no-print-directory AM_DISTCHECK_CONFIGURE_FLAGS = --disable-integration-tests SUBDIRS = include libs libgeis testsuite python tools examples doc data doc-%: $(MAKE) -C doc $@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libgeis.pc EXTRA_DIST = \ AUTHORS \ COPYING \ COPYING.GPL \ INSTALL \ NEWS \ README geis-2.2.17+16.04.20160126/tools/0000755000015600001650000000000012651717732016247 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/tools/geis-server/0000755000015600001650000000000012651717732020502 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/tools/geis-server/geis-server.c0000644000015600001650000000376112651717544023111 0ustar pbuserpbgroup00000000000000/** * geis-server.c Test driver for the GEIS server. * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU General Public License as published by the * Free Software Foundation. * * 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see #include #include #include #include int main() { GeisStatus status; Geis geis = geis_new(GEIS_INIT_SERVICE_PROVIDER, GEIS_INIT_XCB_BACKEND, NULL); if (!geis) { fprintf(stderr, "error creating geis instance.\n"); goto final_exit; } int geis_fd = -1; status = geis_get_configuration(geis, GEIS_CONFIGURATION_FD, &geis_fd); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error obtaining geis fd.\n"); goto unwind_geis; } while (1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(0, &read_fds); FD_SET(geis_fd, &read_fds); int sstat = select(geis_fd + 1, &read_fds, NULL, NULL, NULL); if (sstat < 0) { fprintf(stderr, "error %d in select(): %s\n", errno, strerror(errno)); break; } if (FD_ISSET(geis_fd, &read_fds)) { status = geis_dispatch_events(geis); GeisEvent event_out; status = geis_next_event(geis, &event_out); while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { geis_event_delete(event_out); status = geis_next_event(geis, &event_out); } } if (FD_ISSET(0, &read_fds)) { break; } } unwind_geis: geis_delete(geis); final_exit: return 0; } geis-2.2.17+16.04.20160126/tools/geis-server/Makefile.am0000644000015600001650000000201412651717544022534 0ustar pbuserpbgroup00000000000000# # @file tools/geis-server # @brief automake recipe for the GEIS v2.0 test server # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 General Public License # along with this program. If not, see . # SUBDIRS = geisview geis-server geis-2.2.17+16.04.20160126/tools/geisview/0000755000015600001650000000000012651717732020071 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/tools/geisview/__init__.py0000644000015600001650000000150212651717544022201 0ustar pbuserpbgroup00000000000000#!/usr/bin/python # # @file geisview/__init__.py # @brief Module __init__ for geisview # # This program is a handy diagnostic tool for viewing the raw data produced # through the GEIS multi-touch and gesture interface. # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # geis-2.2.17+16.04.20160126/tools/geisview/Makefile.am0000644000015600001650000000270312651717544022130 0ustar pbuserpbgroup00000000000000# # @file tools/geisview/Makefile.am # @brief automake recipe for the geisview tool # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA geisviewdir = $(pythondir)/geisview shareddir = $(datadir)/geisview xdgdir = $(datadir)/applications dist_bin_SCRIPTS = geisview dist_shared_DATA = \ geisview.ui \ filter_definition.ui \ filter_list.ui geisview_PYTHON = \ __init__.py \ classview.py \ defaults.py \ deviceview.py \ filter_definition.py \ filter_list.py defaults.py: defaults.py.in Makefile $(AM_V_GEN)$(SED) \ -e 's,[@]shareddir[@],$(shareddir),g' \ $< >$@ dist_xdg_DATA = geisview.desktop dist_man_MANS = geisview.1 BUILT_SOURCES = defaults.py EXTRA_DIST = defaults.py.in CLEANFILES = $(BUILT_SOURCES) geis-2.2.17+16.04.20160126/tools/geisview/filter_list.py0000644000015600001650000000363012651717544022766 0ustar pbuserpbgroup00000000000000# # @file geisview/filter_list.py # @brief A geisview filter list dialog # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import geisview.defaults import geisview.filter_definition import os from gi.repository import Gtk class FilterList(object): def __init__(self): self._builder = Gtk.Builder() self._builder.add_from_file(os.path.join(geisview.defaults.ui_dir, "filter_list.ui")) self._builder.connect_signals(self) self._dialog = self._builder.get_object("filter_list"); self._name_entry = self._builder.get_object("name_entry"); self._facility_combo = self._builder.get_object("facility_combo"); self._filter_list_store = self._builder.get_object("filter_list_store") self._dialog.show_all() def run(self): print("FilterList.run() begins") response = self._dialog.run() self._dialog.destroy() print("FilterList.run() ends, response=%s" % response) def on_add_filter(self, widget, data=None): print("FilterList.on_add_filter()") dlg = geisview.filter_definition.FilterDefinition() dlg.run() def on_edit_filter(self, widget, data=None): print("FilterList.on_edit_filter()") def on_remove_filter(self, widget, data=None): print("FilterList.on_remove_filter()") geis-2.2.17+16.04.20160126/tools/geisview/geisview.desktop0000644000015600001650000000024512651717544023310 0ustar pbuserpbgroup00000000000000[Desktop Entry] Type=Application Name=geisview Comment=GEIS gesture event viewer Exec=geisview Icon=geisview32x32 Categories=Utility; Keywords=multi-touch;gestures; geis-2.2.17+16.04.20160126/tools/geisview/defaults.py.in0000644000015600001650000000436312651717544022666 0ustar pbuserpbgroup00000000000000# # @file geisview/defaults.py # @brief Default values for geisview. # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import os import gettext root_dir = os.path.dirname(__file__) if os.path.exists(os.path.join(root_dir, "Makefile.am")): # running in source directory data_dir = root_dir locale_dir = os.path.join(data_dir, "locale") ui_dir = data_dir else: # running from installed data_dir = os.path.join("@shareddir@") locale_dir = os.path.join(data_dir, "locale") ui_dir = data_dir i18n_domain = "geisview" gettext.bindtextdomain(i18n_domain, locale_dir) gettext.textdomain(i18n_domain) from gettext import gettext as _ version = "1.0" appname = _("GEIS Viewer") appname_short = _("geisview") copyright = 'Copyright 2011 Canonical, Ltd.' description = _("A GEIS data viewer.\n\nGEIS Viewer is a part of " "the Canonical gesture recognition stack.") authors = ["Stephen M. Webb <stephen.webb@canonical.com>"] translator_credit = u'' license = "{} {} {}".format(_(u"%s is free software; you can redistribute " "it and/or modify it under the terms of version 3 of the GNU General " "Public License " "as published by the Free Software Foundation.\n\n").replace("%s", appname), _("%s 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 General Public License for more details.\n\n").replace("%s", appname), _("You should have received a copy of the GNU General Public License " "along with this program. If not, see .")) geis-2.2.17+16.04.20160126/tools/geisview/geisview.10000644000015600001650000000230112651717544021772 0ustar pbuserpbgroup00000000000000.TH geisview 1 "February 12, 2013" "" "geisview" .SH NAME geisview \- view operation of the GEIS API .SH SYNOPSIS .B geisview [ .B \-V .B ] .B [ .B \-w .I windowid .B ] .B [ .B \-b .I backend .B ] .br .SH DESCRIPTION This manual page explains the .B geisview program. This program is a test driver for verifying the recognition and propagation of gestures through the GEIS API. .SH OPTIONS .IP \-V Prints the version number of the program and exits. .IP \-w Specifies the .I windowId of a specific window to associate with gestures. Particularly useful with touchscreens. If this argument is not set, the default action is to read gestures on the root window. The .I windowId can be determined using the program .BR xwininfo . .IP \-b Specifies the recognizer .I back end to use. The following are valid back end selections. .RS .sp .TP 7 dbus Uses the DBus back end to connect to a running GEIS server (default). .TP grail Uses the dynamically loaded grail back end (default fallback). .TP mock Uses a mock back end for testing. .TP xcb Uses the pre-XI2 back end (may not be available). .RE .SH ENVIRONMENT .IP GEIS_DEBUG Enables GEIS library diagnostic messages on stderr. .SH "SEE ALSO" geistest(1) geis-2.2.17+16.04.20160126/tools/geisview/classview.py0000644000015600001650000000332712651717544022451 0ustar pbuserpbgroup00000000000000# # @file geisview/gesture_classview.py # @brief GestureClass viewer for geisview. # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from gi.repository import Gtk class GestureClassView(Gtk.Window): def __init__(self, gesture_classes): Gtk.Window.__init__(self) self.set_title("GEIS GestureClasss") self.set_size_request(200, 200) self._tree_store = Gtk.TreeStore(str, str) for (class_id, gclass) in gesture_classes.items(): it = self._tree_store.append(None, ["%s" % gclass.id(), "%s" % gclass.name()]) self._tree_view = Gtk.TreeView(self._tree_store) # self._tree_view.set_mode(Gtk.SELECTION_SINGLE) cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn('ID') col.pack_start(cell, True) col.add_attribute(cell, 'text', 0) self._tree_view.append_column(col) cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn('Name') col.pack_start(cell, True) col.add_attribute(cell, 'text', 1) self._tree_view.append_column(col) self.add(self._tree_view) self.show_all() geis-2.2.17+16.04.20160126/tools/geisview/filter_definition.ui0000644000015600001650000003640012651717544024131 0ustar pbuserpbgroup00000000000000 False 5 True center-on-parent 320 260 True dialog True False 2 True False end gtk-cancel True True True False True False False 0 gtk-ok True False True True True True False True False False 1 False True end 0 True False 2 2 True False 0 Filter _Name: True GTK_FILL 6 True False 0 Filter _Facility: True 1 2 GTK_FILL 6 True True 1 2 True True facility_store 0 0 1 2 1 2 False False 1 True False True False 0 Filter _Terms: True False True 6 0 True False True True automatic automatic etched-in True True term_list_store Attribute True True 0 Operator True True 1 1 Value True True 2 True True 0 True False start gtk-add True True True False True False False 0 gtk-edit True True True False True False False 1 gtk-remove True True True False True False False 2 False True 6 1 True True 1 True True 6 2 cancel ok_button geis-2.2.17+16.04.20160126/tools/geisview/filter_list.ui0000644000015600001650000001750212651717544022756 0ustar pbuserpbgroup00000000000000 False 5 GEIS Filters True center-on-parent True dialog True False True False end gtk-cancel True True True False True False False 0 gtk-ok True True True True True False True False False 1 False True end 0 True False 3 True True automatic automatic etched-in True True False False True True 0 True False 3 start gtk-add True True True False True False False 0 gtk-edit True True True False True False False 1 gtk-remove True True True False True False False 2 False True 6 1 True True 1 cancel ok geis-2.2.17+16.04.20160126/tools/geisview/geisview0000755000015600001650000002730012651717544021644 0ustar pbuserpbgroup00000000000000#!/usr/bin/python3 # # @file geisview # @brief A viewer for raw GEIS data. # # This program is a handy diagnostic tool for viewing the raw data produced # through the GEIS multi-touch and gesture interface. # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import argparse import geis import geisview.defaults import geisview.classview import geisview.deviceview import geisview.filter_list from gettext import gettext as _ import os import sys from gi.repository import Gtk, GLib _geis_backends = { 'dbus': geis.GEIS_INIT_DBUS_BACKEND, 'grail': geis.GEIS_INIT_GRAIL_BACKEND, 'mock': geis.GEIS_INIT_MOCK_BACKEND, 'xcb': geis.GEIS_INIT_XCB_BACKEND, } class GeisViewer(object): """Provides a GUI client to display raw GEIS data. """ def __init__(self, args): self._builder = Gtk.Builder() self._builder.add_from_file(os.path.join(geisview.defaults.ui_dir, "geisview.ui")) self._builder.connect_signals(self) self._args = args; self._main_window = self._builder.get_object("main_window") self._filters_dialog = self._builder.get_object("filters_dialog") be = _geis_backends.get(args.backend, None) try: if be: self._geis = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES, geis.GEIS_INIT_TRACK_GESTURE_CLASSES, be) else: self._geis = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES, geis.GEIS_INIT_TRACK_GESTURE_CLASSES) except Exception as ex: box = Gtk.MessageDialog(None, Gtk.DIALOG_MODAL, Gtk.MESSAGE_ERROR, Gtk.BUTTONS_CLOSE, ex.__str__()) box.run() box.destroy() Gtk.main_quit() self._geis_event_store = self._builder.get_object("geis_event_store") geis_fd = self._geis.get_configuration(geis.GEIS_CONFIGURATION_FD) GLib.io_add_watch(geis_fd, GLib.IO_IN, self._dispatch_geis_events) self._classes = {} self._devices = {} self.windowid = int(args.windowid, 0) self._sub = geis.Subscription(self._geis) self._main_window.show() def _subscribe(self): print("creating subscription") filt = geis.Filter(self._geis, "> 1 touch") filt.add_term(geis.GEIS_FILTER_CLASS, (geis.GEIS_GESTURE_ATTRIBUTE_TOUCHES, geis.GEIS_FILTER_OP_GT, 1)) if self.windowid: filt.add_term(geis.GEIS_FILTER_REGION, (geis.GEIS_REGION_ATTRIBUTE_WINDOWID, geis.GEIS_FILTER_OP_EQ, self.windowid)) self._sub.add_filter(filt) def gtk_main_quit(self, widget, data=None): Gtk.main_quit() def on_menu_item_save(self, widget, data=None): print("on_menu_item_save") def on_menu_item_save_as(self, widget, data=None): print("on_menu_item_save_as") def on_edit_clear_events_menu_item(self, widget, data=None): self._geis_event_store.clear() def on_edit_filters_menu_item_activate(self, widget, data=None): print("on_edit_filters_menu_item_activate") filter_list_dialog = geisview.filter_list.FilterList() filter_list_dialog.run() def on_view_classes_menu_item_activate(self, widget, data=None): class_view = geisview.classview.GestureClassView(self._classes) def on_view_device_menu_item_activate(self, widget, data=None): device_view = geisview.deviceview.DeviceView(self._devices) def on_menu_item_about(self, widget, data=None): about = Gtk.AboutDialog() about.set_transient_for(self._main_window) about.set_name(geisview.defaults.appname) about.set_version(geisview.defaults.version) about.set_copyright(geisview.defaults.copyright) about.set_license(geisview.defaults.license) about.set_wrap_license(True) about.set_comments(geisview.defaults.description) about.set_authors(geisview.defaults.authors) about.set_logo_icon_name("geisview") about.set_translator_credits(geisview.defaults.translator_credit) about.connect("response", lambda d, r: d.destroy()) about.show() def _detail_touches(self, event_row, touchset): count_label = _("touches: %i") % len(touchset) slot_label = _("touch slot %i") touch_row = self._geis_event_store.append(event_row) self._geis_event_store.set(touch_row, 0, count_label) for touch in touchset: slot_row = self._geis_event_store.append(touch_row) self._geis_event_store.set(slot_row, 0, slot_label % touch.id()) for (k, v) in touch.attrs().items(): attr_row = self._geis_event_store.append(slot_row) self._geis_event_store.set(attr_row, 0, "%s: %s" % (k, v)) def _detail_frame(self, group_row, frame): """Extracts and display the details of a gesture frame. """ frame_label = _("frame: %i") % frame.id() touch_label = _("touch indexes %s") % frame.touches() class_label = _("classes: %s") % [gc.name() for gc in filter(frame.is_class, iter(self._classes.values()))] dev = None frame_row = self._geis_event_store.append(group_row) self._geis_event_store.set(frame_row, 0, frame_label) self._geis_event_store.append(frame_row, [class_label, None, None]) for (k, v) in frame.attrs().items(): row = self._geis_event_store.append(frame_row) self._geis_event_store.set(row, 0, "%s: %s" % (k, v)) if k == geis.GEIS_GESTURE_ATTRIBUTE_DEVICE_ID and v in self._devices: dev = self._devices[v] self._geis_event_store.append(frame_row, [touch_label, None, None]) if dev: print("device %s extents %s" % (dev.id(), dev.extents())) def _detail_gesture(self, event_row, attrs): touchset = attrs[geis.GEIS_EVENT_ATTRIBUTE_TOUCHSET] groupset = attrs[geis.GEIS_EVENT_ATTRIBUTE_GROUPSET] self._detail_touches(event_row, touchset) count_label = _("groups: %i") % len(groupset) group_label = _("group %i") it = self._geis_event_store.append(event_row, [count_label, None, None]) for group in groupset: group_row = self._geis_event_store.append(it, [group_label % group.id(), None, None]) for frame in group: self._detail_frame(group_row, frame) def _detail_gesture_class(self, event_row, gesture_class): for (k, v) in gesture_class.attrs().items(): row = self._geis_event_store.append(event_row) self._geis_event_store.set(row, 0, "%s: %s" % (k, v)) def _detail_device(self, event_row, device): for (k, v) in device.attrs().items(): row = self._geis_event_store.append(event_row) self._geis_event_store.set(row, 0, "%s: %s" % (k, v)) def _do_gesture_begin(self, event): it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("Gesture Begin")) self._detail_gesture(it, event.attrs()) def _do_gesture_update(self, event): it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("Gesture Update")) self._detail_gesture(it, event.attrs()) def _do_gesture_end(self, event): it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("Gesture End")) self._detail_gesture(it, event.attrs()) def _do_class_added(self, event): gclass = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_CLASS] it = self._geis_event_store.append(None) self._classes[gclass.id()] = gclass self._geis_event_store.set(it, 0, _("Class %s Added: %s") % (gclass.id(), gclass.name())) self._detail_gesture_class(it, gclass) def _do_device_added(self, event): device = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_DEVICE] self._devices[device.id()] = device it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("Device %s Added: %s") % (device.id(), device.name())) self._detail_device(it, device) def _do_device_removed(self, event): device = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_DEVICE] del self._devices[device.id()] it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("Device %s Removed: %s") % (device.id(), device.name())) def _do_init_complete(self, event): it = self._geis_event_store.append(None) self._geis_event_store.set(it, 0, _("GEIS initialization complete")) self._subscribe() self._sub.activate() def _do_other_event(self, event): event_label = _("Unknown Event") it = self._geis_event_store.append(None, [event_label, None, None]) def _dispatch_geis_events(self, fd, condition): """ Performs GEIS event loop processing. """ _geis_event_action = { geis.GEIS_EVENT_GESTURE_BEGIN: self._do_gesture_begin, geis.GEIS_EVENT_GESTURE_UPDATE: self._do_gesture_update, geis.GEIS_EVENT_GESTURE_END: self._do_gesture_end, geis.GEIS_EVENT_CLASS_AVAILABLE: self._do_class_added, geis.GEIS_EVENT_DEVICE_AVAILABLE: self._do_device_added, geis.GEIS_EVENT_DEVICE_UNAVAILABLE: self._do_device_removed, geis.GEIS_EVENT_INIT_COMPLETE: self._do_init_complete } status = self._geis.dispatch_events() while status == geis.GEIS_STATUS_CONTINUE: status = self._geis.dispatch_events() try: while True: event = self._geis.next_event() _geis_event_action.get(event.type(), self._do_other_event)(event) except geis.NoMoreEvents: pass return True class Options(argparse.ArgumentParser): """Handles the geisviewer command-line arguments. """ def __init__(self): argparse.ArgumentParser.__init__(self, description="monitor gestures") self.add_argument('-V', '--version', action='version', version='1.0') self.add_argument('-w', '--window', action='store', dest='windowid', default = "0", help=_('indicates the X windowid to receive input')) self.add_argument('-b', '--backend', action='store', dest='backend', choices=list(_geis_backends.keys()), default=None, help=_('selects the recognizer back end')) def main(): windowid = None options = Options() try: args = options.parse_args() if args.windowid: windowid = int(args.windowid, 0) except argparse.ArgumentError as ex: print(ex) sys.exit(1) geis_viewer = GeisViewer(args) Gtk.main() if __name__ == '__main__': main() geis-2.2.17+16.04.20160126/tools/geisview/filter_definition.py0000644000015600001650000001152412651717544024144 0ustar pbuserpbgroup00000000000000# # @file geisview/filter_definition.py # @brief A GEIS filter definition dialog # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import geis import geisview.defaults import os from gi.repository import Gtk # A list of filter facilities to choose from geis_filter_facilities = ('GEIS_FILTER_REGION', 'GEIS_FILTER_DEVICE', 'GEIS_FILTER_CLASS') geis_region_terms = ('GEIS_REGION_ATTRIBUTE_WINDOWID') geis_device_terms = ('GEIS_DEVICE_ATTRIBUTE_ID', 'GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH') geis_gesture_terms = ('GEIS_GESTURE_ATTRIBUTE_TOUCHES', 'GEIS_CLASS_ATTRIBUTE_NAME') geis_term_op = {'GEIS_FILTER_OP_EQ': '==', 'GEIS_FILTER_OP_NE': '!=', 'GEIS_FILTER_OP_GT': '>', 'GEIS_FILTER_OP_GE': '>=', 'GEIS_FILTER_OP_LT': '<', 'GEIS_FILTER_OP_LE': '<='} facility_combo_name_col = 0 facility_combo_value_col = 1 def populate_term_op(store): for (name, symbol) in geis_term_op: row = store.append() store.set(row, symbol, geis.__dict__[name]) class FilterDefinition(object): def __init__(self): print("FilterDefinition.__init__() begins") builder = Gtk.Builder() builder.add_from_file(os.path.join(geisview.defaults.ui_dir, "filter_definition.ui")) builder.connect_signals(self) # prime the name field self._dialog = builder.get_object("filter_definition"); self._name_entry = builder.get_object("name_entry"); # prime the facility combo self._facility_store = builder.get_object("facility_store"); for fac in geis_filter_facilities: row = self._facility_store.append() self._facility_store.set(row, facility_combo_name_col, fac, facility_combo_value_col, geis.__dict__[fac]) self._facility_combo = builder.get_object("facility_combo"); self._facility_combo.set_active(0) # prime the filter terms self._term_list_view = builder.get_object("term_list_view"); self._term_list_store = builder.get_object("term_list_store") self._ok_button = builder.get_object("ok_button"); self._dialog.show_all() print("FilterDefinition.__init__() ends") def run(self): print("FilterDefinition.run() begins") response = self._dialog.run() if (response): name = self._name_entry.get_text() print("FilterDefinition.run() name=%s" % name) print("FilterDefinition.run() facility=%s" % self._facility_store[self._facility_combo.get_active()][facility_combo_value_col]) self._dialog.destroy() print("FilterDefinition.run() ends, response=%s" % response) def on_name_changed(self, widget, data=None): name = self._name_entry.get_text() if len(name) > 0: self._ok_button.set_sensitive(True) else: self._ok_button.set_sensitive(False) def on_add_term(self, widget, data=None): print("FilterDefinition.on_add_term()") row = self._term_list_store.append() self._term_list_store.set(row, 0, "", 1, "==", 2, "") def on_edit_term(self, widget, data=None): print("FilterDefinition.on_edit_term()") def on_remove_term(self, widget, data=None): print("FilterDefinition.on_remove_term()") def on_term_attr_editing_started(self, widget, entry, path, data=None): print("FilterDefinition.on_term_attr_editing_started()") choices = Gtk.ListStore(str, str) for c in geis_gesture_terms: choices.append([c, geis.__dict__[c]]) completion = Gtk.EntryCompletion() completion.set_model(choices) completion.set_text_column(0) completion.set_inline_completion(True) completion.set_popup_completion(False) entry.set_completion(completion) entry.set_text("") def on_term_op_edited(self, widget, path, new_text, data=None): print("FilterDefinition.on_term_op_edited(%s, %s, %s)" % (widget, path, new_text)) geis-2.2.17+16.04.20160126/tools/geisview/geisview.ui0000644000015600001650000004315212651717544022260 0ustar pbuserpbgroup00000000000000 True False gtk-missing-image True False gtk-missing-image False 480 420 True False True False True False False _File True True False gtk-new True False False True True gtk-open True False False True True gtk-save True False False True True gtk-save-as True False False True True True False False gtk-quit True False False True True True False False _Edit True True False gtk-cut True False False True True gtk-copy True False False True True gtk-paste True False False True True gtk-delete True False False True True True False False Clear Events True True False False Filters... True True False False _View True True False Show _Devices True False False True image1 False Show _Classes True False False True image2 False True False False _Help True True False gtk-about True False False True True False True 0 True True True True automatic automatic True etched-in True True 1 geis_event_store False False column 0 False True True automatic automatic in True True geis_event_detail True True True True 1 True False 2 False True 2 geis-2.2.17+16.04.20160126/tools/geisview/deviceview.py0000644000015600001650000000264312651717544022603 0ustar pbuserpbgroup00000000000000# # @file geisview/deviceview.py # @brief Device viewer for geisview. # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from gi.repository import Gtk class DeviceView(Gtk.Window): def __init__(self, devices): Gtk.Window.__init__(self) self.set_title("GEIS Devices") self.set_size_request(200, 200) self._devices = devices self._tree_store = Gtk.TreeStore(str) for device in devices: it = self._tree_store.append(None, ["%s" % device]) self._tree_view = Gtk.TreeView(self._tree_store) # self._tree_view.set_mode(Gtk.SELECTION_SINGLE) cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn('Label') col.pack_start(cell, True) col.add_attribute(cell, 'text', 0) self._tree_view.append_column(col) self.add(self._tree_view) self.show_all() geis-2.2.17+16.04.20160126/COPYING0000644000015600001650000001672712651717544016160 0ustar pbuserpbgroup00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. geis-2.2.17+16.04.20160126/gen-version.sh0000755000015600001650000000341512651717544017706 0ustar pbuserpbgroup00000000000000#!/bin/sh # # Tool to automatically generate the package version from the bzr tags. # # This tool generates a package version string based on the tags in the bzr # branch. When an official release is made, the branch should be tagged with a # tag of the form 'vN.N.N'. This script will then give a version string of # 'N.N.N'. If any changes are made to the barcnh after tagging, the version # string will be of the form 'N.N.N+rRRR' where RRR is the bzr revno of the # latest commit. # # This scheme allows snapshot releases to be packaged. # # Copyright 2011 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Default to some unknown version string. version_string="unknown" # Get the cirrent BZR revision number. cur_bzr_rev=$(bzr version-info --custom --template="{revno}") # Extract the release version string and BZR revision number. tag_line=$(bzr tags --sort=time \ | grep -E 'v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+' \ | tail -1) tag_version=$(echo $tag_line | sed -n -e 's/v\([^[:space:]]*\).*/\1/p') tag_rev=$(echo $tag_line | cut -d' ' -f2-) if [ -n "$tag_version" ]; then version_string=$tag_version fi if [ $cur_bzr_rev -gt $tag_rev ]; then version_string="${version_string}+r${cur_bzr_rev}" fi echo $version_string geis-2.2.17+16.04.20160126/AUTHORS0000644000015600001650000000005612651717544016161 0ustar pbuserpbgroup00000000000000Stephen M. Webb geis-2.2.17+16.04.20160126/m4/0000755000015600001650000000000012651717732015427 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/m4/xorg-gtest.m40000644000015600001650000001010112651717544017766 0ustar pbuserpbgroup00000000000000# serial 9 # Copyright (C) 2012 Canonical, Ltd. # # 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 (including the next # paragraph) 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. # CHECK_XORG_GTEST([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Checks whether the xorg-gtest source is available on the system. Allows for # adjusting the include and source path. Sets have_xorg_gtest=yes if the source # is present. Sets XORG_GTEST_CPPFLAGS and XORG_GTEST_SOURCE to the preprocessor # flags and source location respectively. Sets XORG_GTEST_LIBS to all the # libraries needed to link against a built xorg-gtest library. # # Both default actions are no-ops. AC_DEFUN([CHECK_XORG_GTEST], [ AC_ARG_WITH([gtest-include-path], [AS_HELP_STRING([--with-gtest-include-path], [location of the Google test headers])], [GTEST_CPPFLAGS="-I$withval"]) AC_ARG_WITH([gtest-source-path], [AS_HELP_STRING([--with-gtest-source-path], [location of the Google test sources, defaults to /usr/src/gtest])], [GTEST_SOURCE="$withval"], [GTEST_SOURCE="/usr/src/gtest"]) AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc] [$GTEST_SOURCE/src/gtest_main.cc], [have_gtest=yes], [have_gtest=no]) PKG_CHECK_EXISTS([xorg-gtest], [have_xorg_gtest=yes], [have_xorg_gtest=no]) AS_IF([test -z "$GTEST_SOURCE"],[GTEST_SOURCE="$XORG_GTEST_SOURCE/src/gtest"]) GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE -I$XORG_GTEST_SOURCE/src/gtest/include -I$XORG_GTEST_SOURCE/src/gtest" XORG_GTEST_CPPFLAGS=`$PKG_CONFIG --variable=CPPflags --print-errors xorg-gtest` XORG_GTEST_CPPFLAGS="$GTEST_CPPFLAGS $XORG_GTEST_CPPFLAGS" XORG_GTEST_CPPFLAGS="$XORG_GTEST_CPPFLAGS -I$XORG_GTEST_SOURCE" XORG_GTEST_LDFLAGS="-lpthread -lX11 -lXi" PKG_CHECK_MODULES(X11, [x11], [have_x11=yes], [have_x11=no]) # Check if we should include support for evemu AC_ARG_WITH([evemu], [AS_HELP_STRING([--with-evemu], [support Linux input device recording playback (default: enabled if available)])], [], [with_evemu=check]) AS_IF([test "x$with_evemu" = xyes], [PKG_CHECK_MODULES(EVEMU, [evemu], [have_xorg_gtest_evemu=yes])], [test "x$with_evemu" = xcheck], [PKG_CHECK_MODULES(EVEMU, [evemu], [have_xorg_gtest_evemu=yes], [have_xorg_gtest_evemu=no])]) AS_IF([test "x$have_xorg_gtest_evemu" = xyes], [XORG_GTEST_CPPFLAGS="$XORG_GTEST_CPPFLAGS -DHAVE_EVEMU"]) AS_IF([test "x$have_xorg_gtest" = xyes], [AC_SUBST(GTEST_SOURCE)] [AC_SUBST(GTEST_CPPFLAGS)] [AC_SUBST(XORG_GTEST_SOURCE)] [AC_SUBST(XORG_GTEST_CPPFLAGS)] [AC_SUBST(XORG_GTEST_LDFLAGS)] # Get BASE_CXXFLAGS and STRICT_CXXFLAGS [XORG_MACROS_VERSION(1.17)] [AC_LANG_PUSH([C++])] [XORG_STRICT_OPTION] [AC_LANG_POP] [$1], [$2]) ]) # CHECK_XORG_GTEST geis-2.2.17+16.04.20160126/m4/xorg-macros.m40000644000015600001650000020634212651717544020142 0ustar pbuserpbgroup00000000000000dnl xorg-macros.m4. Generated from xorg-macros.m4.in xorgversion.m4 by configure. dnl dnl Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. dnl dnl Permission is hereby granted, free of charge, to any person obtaining a dnl copy of this software and associated documentation files (the "Software"), dnl to deal in the Software without restriction, including without limitation dnl the rights to use, copy, modify, merge, publish, distribute, sublicense, dnl and/or sell copies of the Software, and to permit persons to whom the dnl Software is furnished to do so, subject to the following conditions: dnl dnl The above copyright notice and this permission notice (including the next dnl paragraph) shall be included in all copies or substantial portions of the dnl Software. dnl dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER dnl DEALINGS IN THE SOFTWARE. # XORG_MACROS_VERSION(required-version) # ------------------------------------- # Minimum version: 1.1.0 # # If you're using a macro added in Version 1.1 or newer, include this in # your configure.ac with the minimum required version, such as: # XORG_MACROS_VERSION(1.1) # # To ensure that this macro is defined, also add: # m4_ifndef([XORG_MACROS_VERSION], # [m4_fatal([must install xorg-macros 1.1 or later before running autoconf/autogen])]) # # # See the "minimum version" comment for each macro you use to see what # version you require. m4_defun([XORG_MACROS_VERSION],[ m4_define([vers_have], [1.17]) m4_define([maj_have], m4_substr(vers_have, 0, m4_index(vers_have, [.]))) m4_define([maj_needed], m4_substr([$1], 0, m4_index([$1], [.]))) m4_if(m4_cmp(maj_have, maj_needed), 0,, [m4_fatal([xorg-macros major version ]maj_needed[ is required but ]vers_have[ found])]) m4_if(m4_version_compare(vers_have, [$1]), -1, [m4_fatal([xorg-macros version $1 or higher is required but ]vers_have[ found])]) m4_undefine([vers_have]) m4_undefine([maj_have]) m4_undefine([maj_needed]) ]) # XORG_MACROS_VERSION # XORG_PROG_RAWCPP() # ------------------ # Minimum version: 1.0.0 # # Find cpp program and necessary flags for use in pre-processing text files # such as man pages and config files AC_DEFUN([XORG_PROG_RAWCPP],[ AC_REQUIRE([AC_PROG_CPP]) AC_PATH_PROGS(RAWCPP, [cpp], [${CPP}], [$PATH:/bin:/usr/bin:/usr/lib:/usr/libexec:/usr/ccs/lib:/usr/ccs/lbin:/lib]) # Check for flag to avoid builtin definitions - assumes unix is predefined, # which is not the best choice for supporting other OS'es, but covers most # of the ones we need for now. AC_MSG_CHECKING([if $RAWCPP requires -undef]) AC_LANG_CONFTEST([AC_LANG_SOURCE([[Does cpp redefine unix ?]])]) if test `${RAWCPP} < conftest.$ac_ext | grep -c 'unix'` -eq 1 ; then AC_MSG_RESULT([no]) else if test `${RAWCPP} -undef < conftest.$ac_ext | grep -c 'unix'` -eq 1 ; then RAWCPPFLAGS=-undef AC_MSG_RESULT([yes]) # under Cygwin unix is still defined even with -undef elif test `${RAWCPP} -undef -ansi < conftest.$ac_ext | grep -c 'unix'` -eq 1 ; then RAWCPPFLAGS="-undef -ansi" AC_MSG_RESULT([yes, with -ansi]) else AC_MSG_ERROR([${RAWCPP} defines unix with or without -undef. I don't know what to do.]) fi fi rm -f conftest.$ac_ext AC_MSG_CHECKING([if $RAWCPP requires -traditional]) AC_LANG_CONFTEST([AC_LANG_SOURCE([[Does cpp preserve "whitespace"?]])]) if test `${RAWCPP} < conftest.$ac_ext | grep -c 'preserve \"'` -eq 1 ; then AC_MSG_RESULT([no]) else if test `${RAWCPP} -traditional < conftest.$ac_ext | grep -c 'preserve \"'` -eq 1 ; then RAWCPPFLAGS="${RAWCPPFLAGS} -traditional" AC_MSG_RESULT([yes]) else AC_MSG_ERROR([${RAWCPP} does not preserve whitespace with or without -traditional. I don't know what to do.]) fi fi rm -f conftest.$ac_ext AC_SUBST(RAWCPPFLAGS) ]) # XORG_PROG_RAWCPP # XORG_MANPAGE_SECTIONS() # ----------------------- # Minimum version: 1.0.0 # # Determine which sections man pages go in for the different man page types # on this OS - replaces *ManSuffix settings in old Imake *.cf per-os files. # Not sure if there's any better way than just hardcoding by OS name. # Override default settings by setting environment variables # Added MAN_SUBSTS in version 1.8 # Added AC_PROG_SED in version 1.8 AC_DEFUN([XORG_MANPAGE_SECTIONS],[ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_SED]) if test x$APP_MAN_SUFFIX = x ; then APP_MAN_SUFFIX=1 fi if test x$APP_MAN_DIR = x ; then APP_MAN_DIR='$(mandir)/man$(APP_MAN_SUFFIX)' fi if test x$LIB_MAN_SUFFIX = x ; then LIB_MAN_SUFFIX=3 fi if test x$LIB_MAN_DIR = x ; then LIB_MAN_DIR='$(mandir)/man$(LIB_MAN_SUFFIX)' fi if test x$FILE_MAN_SUFFIX = x ; then case $host_os in solaris*) FILE_MAN_SUFFIX=4 ;; *) FILE_MAN_SUFFIX=5 ;; esac fi if test x$FILE_MAN_DIR = x ; then FILE_MAN_DIR='$(mandir)/man$(FILE_MAN_SUFFIX)' fi if test x$MISC_MAN_SUFFIX = x ; then case $host_os in solaris*) MISC_MAN_SUFFIX=5 ;; *) MISC_MAN_SUFFIX=7 ;; esac fi if test x$MISC_MAN_DIR = x ; then MISC_MAN_DIR='$(mandir)/man$(MISC_MAN_SUFFIX)' fi if test x$DRIVER_MAN_SUFFIX = x ; then case $host_os in solaris*) DRIVER_MAN_SUFFIX=7 ;; *) DRIVER_MAN_SUFFIX=4 ;; esac fi if test x$DRIVER_MAN_DIR = x ; then DRIVER_MAN_DIR='$(mandir)/man$(DRIVER_MAN_SUFFIX)' fi if test x$ADMIN_MAN_SUFFIX = x ; then case $host_os in solaris*) ADMIN_MAN_SUFFIX=1m ;; *) ADMIN_MAN_SUFFIX=8 ;; esac fi if test x$ADMIN_MAN_DIR = x ; then ADMIN_MAN_DIR='$(mandir)/man$(ADMIN_MAN_SUFFIX)' fi AC_SUBST([APP_MAN_SUFFIX]) AC_SUBST([LIB_MAN_SUFFIX]) AC_SUBST([FILE_MAN_SUFFIX]) AC_SUBST([MISC_MAN_SUFFIX]) AC_SUBST([DRIVER_MAN_SUFFIX]) AC_SUBST([ADMIN_MAN_SUFFIX]) AC_SUBST([APP_MAN_DIR]) AC_SUBST([LIB_MAN_DIR]) AC_SUBST([FILE_MAN_DIR]) AC_SUBST([MISC_MAN_DIR]) AC_SUBST([DRIVER_MAN_DIR]) AC_SUBST([ADMIN_MAN_DIR]) XORG_MAN_PAGE="X Version 11" AC_SUBST([XORG_MAN_PAGE]) MAN_SUBSTS="\ -e 's|__vendorversion__|\"\$(PACKAGE_STRING)\" \"\$(XORG_MAN_PAGE)\"|' \ -e 's|__xorgversion__|\"\$(PACKAGE_STRING)\" \"\$(XORG_MAN_PAGE)\"|' \ -e 's|__xservername__|Xorg|g' \ -e 's|__xconfigfile__|xorg.conf|g' \ -e 's|__projectroot__|\$(prefix)|g' \ -e 's|__apploaddir__|\$(appdefaultdir)|g' \ -e 's|__appmansuffix__|\$(APP_MAN_SUFFIX)|g' \ -e 's|__drivermansuffix__|\$(DRIVER_MAN_SUFFIX)|g' \ -e 's|__adminmansuffix__|\$(ADMIN_MAN_SUFFIX)|g' \ -e 's|__libmansuffix__|\$(LIB_MAN_SUFFIX)|g' \ -e 's|__miscmansuffix__|\$(MISC_MAN_SUFFIX)|g' \ -e 's|__filemansuffix__|\$(FILE_MAN_SUFFIX)|g'" AC_SUBST([MAN_SUBSTS]) ]) # XORG_MANPAGE_SECTIONS # XORG_CHECK_SGML_DOCTOOLS([MIN-VERSION]) # ------------------------ # Minimum version: 1.7.0 # # Defines the variable XORG_SGML_PATH containing the location of X11/defs.ent # provided by xorg-sgml-doctools, if installed. AC_DEFUN([XORG_CHECK_SGML_DOCTOOLS],[ AC_MSG_CHECKING([for X.Org SGML entities m4_ifval([$1],[>= $1])]) XORG_SGML_PATH= PKG_CHECK_EXISTS([xorg-sgml-doctools m4_ifval([$1],[>= $1])], [XORG_SGML_PATH=`$PKG_CONFIG --variable=sgmlrootdir xorg-sgml-doctools`], [m4_ifval([$1],[:], [if test x"$cross_compiling" != x"yes" ; then AC_CHECK_FILE([$prefix/share/sgml/X11/defs.ent], [XORG_SGML_PATH=$prefix/share/sgml]) fi]) ]) # Define variables STYLESHEET_SRCDIR and XSL_STYLESHEET containing # the path and the name of the doc stylesheet if test "x$XORG_SGML_PATH" != "x" ; then AC_MSG_RESULT([$XORG_SGML_PATH]) STYLESHEET_SRCDIR=$XORG_SGML_PATH/X11 XSL_STYLESHEET=$STYLESHEET_SRCDIR/xorg.xsl else AC_MSG_RESULT([no]) fi AC_SUBST(XORG_SGML_PATH) AC_SUBST(STYLESHEET_SRCDIR) AC_SUBST(XSL_STYLESHEET) AM_CONDITIONAL([HAVE_STYLESHEETS], [test "x$XSL_STYLESHEET" != "x"]) ]) # XORG_CHECK_SGML_DOCTOOLS # XORG_CHECK_LINUXDOC # ------------------- # Minimum version: 1.0.0 # # Defines the variable MAKE_TEXT if the necessary tools and # files are found. $(MAKE_TEXT) blah.sgml will then produce blah.txt. # Whether or not the necessary tools and files are found can be checked # with the AM_CONDITIONAL "BUILD_LINUXDOC" AC_DEFUN([XORG_CHECK_LINUXDOC],[ AC_REQUIRE([XORG_CHECK_SGML_DOCTOOLS]) AC_REQUIRE([XORG_WITH_PS2PDF]) AC_PATH_PROG(LINUXDOC, linuxdoc) AC_MSG_CHECKING([whether to build documentation]) if test x$XORG_SGML_PATH != x && test x$LINUXDOC != x ; then BUILDDOC=yes else BUILDDOC=no fi AM_CONDITIONAL(BUILD_LINUXDOC, [test x$BUILDDOC = xyes]) AC_MSG_RESULT([$BUILDDOC]) AC_MSG_CHECKING([whether to build pdf documentation]) if test x$have_ps2pdf != xno && test x$BUILD_PDFDOC != xno; then BUILDPDFDOC=yes else BUILDPDFDOC=no fi AM_CONDITIONAL(BUILD_PDFDOC, [test x$BUILDPDFDOC = xyes]) AC_MSG_RESULT([$BUILDPDFDOC]) MAKE_TEXT="SGML_SEARCH_PATH=$XORG_SGML_PATH GROFF_NO_SGR=y $LINUXDOC -B txt -f" MAKE_PS="SGML_SEARCH_PATH=$XORG_SGML_PATH $LINUXDOC -B latex --papersize=letter --output=ps" MAKE_PDF="$PS2PDF" MAKE_HTML="SGML_SEARCH_PATH=$XORG_SGML_PATH $LINUXDOC -B html --split=0" AC_SUBST(MAKE_TEXT) AC_SUBST(MAKE_PS) AC_SUBST(MAKE_PDF) AC_SUBST(MAKE_HTML) ]) # XORG_CHECK_LINUXDOC # XORG_CHECK_DOCBOOK # ------------------- # Minimum version: 1.0.0 # # Checks for the ability to build output formats from SGML DocBook source. # For XXX in {TXT, PDF, PS, HTML}, the AM_CONDITIONAL "BUILD_XXXDOC" # indicates whether the necessary tools and files are found and, if set, # $(MAKE_XXX) blah.sgml will produce blah.xxx. AC_DEFUN([XORG_CHECK_DOCBOOK],[ AC_REQUIRE([XORG_CHECK_SGML_DOCTOOLS]) BUILDTXTDOC=no BUILDPDFDOC=no BUILDPSDOC=no BUILDHTMLDOC=no AC_PATH_PROG(DOCBOOKPS, docbook2ps) AC_PATH_PROG(DOCBOOKPDF, docbook2pdf) AC_PATH_PROG(DOCBOOKHTML, docbook2html) AC_PATH_PROG(DOCBOOKTXT, docbook2txt) AC_MSG_CHECKING([whether to build text documentation]) if test x$XORG_SGML_PATH != x && test x$DOCBOOKTXT != x && test x$BUILD_TXTDOC != xno; then BUILDTXTDOC=yes fi AM_CONDITIONAL(BUILD_TXTDOC, [test x$BUILDTXTDOC = xyes]) AC_MSG_RESULT([$BUILDTXTDOC]) AC_MSG_CHECKING([whether to build PDF documentation]) if test x$XORG_SGML_PATH != x && test x$DOCBOOKPDF != x && test x$BUILD_PDFDOC != xno; then BUILDPDFDOC=yes fi AM_CONDITIONAL(BUILD_PDFDOC, [test x$BUILDPDFDOC = xyes]) AC_MSG_RESULT([$BUILDPDFDOC]) AC_MSG_CHECKING([whether to build PostScript documentation]) if test x$XORG_SGML_PATH != x && test x$DOCBOOKPS != x && test x$BUILD_PSDOC != xno; then BUILDPSDOC=yes fi AM_CONDITIONAL(BUILD_PSDOC, [test x$BUILDPSDOC = xyes]) AC_MSG_RESULT([$BUILDPSDOC]) AC_MSG_CHECKING([whether to build HTML documentation]) if test x$XORG_SGML_PATH != x && test x$DOCBOOKHTML != x && test x$BUILD_HTMLDOC != xno; then BUILDHTMLDOC=yes fi AM_CONDITIONAL(BUILD_HTMLDOC, [test x$BUILDHTMLDOC = xyes]) AC_MSG_RESULT([$BUILDHTMLDOC]) MAKE_TEXT="SGML_SEARCH_PATH=$XORG_SGML_PATH $DOCBOOKTXT" MAKE_PS="SGML_SEARCH_PATH=$XORG_SGML_PATH $DOCBOOKPS" MAKE_PDF="SGML_SEARCH_PATH=$XORG_SGML_PATH $DOCBOOKPDF" MAKE_HTML="SGML_SEARCH_PATH=$XORG_SGML_PATH $DOCBOOKHTML" AC_SUBST(MAKE_TEXT) AC_SUBST(MAKE_PS) AC_SUBST(MAKE_PDF) AC_SUBST(MAKE_HTML) ]) # XORG_CHECK_DOCBOOK # XORG_WITH_XMLTO([MIN-VERSION], [DEFAULT]) # ---------------- # Minimum version: 1.5.0 # Minimum version for optional DEFAULT argument: 1.11.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-xmlto option, it allows maximum flexibilty in making decisions # as whether or not to use the xmlto package. When DEFAULT is not specified, # --with-xmlto assumes 'auto'. # # Interface to module: # HAVE_XMLTO: used in makefiles to conditionally generate documentation # XMLTO: returns the path of the xmlto program found # returns the path set by the user in the environment # --with-xmlto: 'yes' user instructs the module to use xmlto # 'no' user instructs the module not to use xmlto # # Added in version 1.10.0 # HAVE_XMLTO_TEXT: used in makefiles to conditionally generate text documentation # xmlto for text output requires either lynx, links, or w3m browsers # # If the user sets the value of XMLTO, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_XMLTO],[ AC_ARG_VAR([XMLTO], [Path to xmlto command]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(xmlto, AS_HELP_STRING([--with-xmlto], [Use xmlto to regenerate documentation (default: ]_defopt[)]), [use_xmlto=$withval], [use_xmlto=]_defopt) m4_undefine([_defopt]) if test "x$use_xmlto" = x"auto"; then AC_PATH_PROG([XMLTO], [xmlto]) if test "x$XMLTO" = "x"; then AC_MSG_WARN([xmlto not found - documentation targets will be skipped]) have_xmlto=no else have_xmlto=yes fi elif test "x$use_xmlto" = x"yes" ; then AC_PATH_PROG([XMLTO], [xmlto]) if test "x$XMLTO" = "x"; then AC_MSG_ERROR([--with-xmlto=yes specified but xmlto not found in PATH]) fi have_xmlto=yes elif test "x$use_xmlto" = x"no" ; then if test "x$XMLTO" != "x"; then AC_MSG_WARN([ignoring XMLTO environment variable since --with-xmlto=no was specified]) fi have_xmlto=no else AC_MSG_ERROR([--with-xmlto expects 'yes' or 'no']) fi # Test for a minimum version of xmlto, if provided. m4_ifval([$1], [if test "$have_xmlto" = yes; then # scrape the xmlto version AC_MSG_CHECKING([the xmlto version]) xmlto_version=`$XMLTO --version 2>/dev/null | cut -d' ' -f3` AC_MSG_RESULT([$xmlto_version]) AS_VERSION_COMPARE([$xmlto_version], [$1], [if test "x$use_xmlto" = xauto; then AC_MSG_WARN([xmlto version $xmlto_version found, but $1 needed]) have_xmlto=no else AC_MSG_ERROR([xmlto version $xmlto_version found, but $1 needed]) fi]) fi]) # Test for the ability of xmlto to generate a text target have_xmlto_text=no cat > conftest.xml << "EOF" EOF AS_IF([test "$have_xmlto" = yes], [AS_IF([$XMLTO --skip-validation txt conftest.xml >/dev/null 2>&1], [have_xmlto_text=yes], [AC_MSG_WARN([xmlto cannot generate text format, this format skipped])])]) rm -f conftest.xml AM_CONDITIONAL([HAVE_XMLTO_TEXT], [test $have_xmlto_text = yes]) AM_CONDITIONAL([HAVE_XMLTO], [test "$have_xmlto" = yes]) ]) # XORG_WITH_XMLTO # XORG_WITH_XSLTPROC([MIN-VERSION], [DEFAULT]) # -------------------------------------------- # Minimum version: 1.12.0 # Minimum version for optional DEFAULT argument: 1.12.0 # # XSLT (Extensible Stylesheet Language Transformations) is a declarative, # XML-based language used for the transformation of XML documents. # The xsltproc command line tool is for applying XSLT stylesheets to XML documents. # It is used under the cover by xmlto to generate html files from DocBook/XML. # The XSLT processor is often used as a standalone tool for transformations. # It should not be assumed that this tool is used only to work with documnetation. # When DEFAULT is not specified, --with-xsltproc assumes 'auto'. # # Interface to module: # HAVE_XSLTPROC: used in makefiles to conditionally generate documentation # XSLTPROC: returns the path of the xsltproc program found # returns the path set by the user in the environment # --with-xsltproc: 'yes' user instructs the module to use xsltproc # 'no' user instructs the module not to use xsltproc # have_xsltproc: returns yes if xsltproc found in PATH or no # # If the user sets the value of XSLTPROC, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_XSLTPROC],[ AC_ARG_VAR([XSLTPROC], [Path to xsltproc command]) # Preserves the interface, should it be implemented later m4_ifval([$1], [m4_warn([syntax], [Checking for xsltproc MIN-VERSION is not implemented])]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(xsltproc, AS_HELP_STRING([--with-xsltproc], [Use xsltproc for the transformation of XML documents (default: ]_defopt[)]), [use_xsltproc=$withval], [use_xsltproc=]_defopt) m4_undefine([_defopt]) if test "x$use_xsltproc" = x"auto"; then AC_PATH_PROG([XSLTPROC], [xsltproc]) if test "x$XSLTPROC" = "x"; then AC_MSG_WARN([xsltproc not found - cannot transform XML documents]) have_xsltproc=no else have_xsltproc=yes fi elif test "x$use_xsltproc" = x"yes" ; then AC_PATH_PROG([XSLTPROC], [xsltproc]) if test "x$XSLTPROC" = "x"; then AC_MSG_ERROR([--with-xsltproc=yes specified but xsltproc not found in PATH]) fi have_xsltproc=yes elif test "x$use_xsltproc" = x"no" ; then if test "x$XSLTPROC" != "x"; then AC_MSG_WARN([ignoring XSLTPROC environment variable since --with-xsltproc=no was specified]) fi have_xsltproc=no else AC_MSG_ERROR([--with-xsltproc expects 'yes' or 'no']) fi AM_CONDITIONAL([HAVE_XSLTPROC], [test "$have_xsltproc" = yes]) ]) # XORG_WITH_XSLTPROC # XORG_WITH_PERL([MIN-VERSION], [DEFAULT]) # ---------------------------------------- # Minimum version: 1.15.0 # # PERL (Practical Extraction and Report Language) is a language optimized for # scanning arbitrary text files, extracting information from those text files, # and printing reports based on that information. # # When DEFAULT is not specified, --with-perl assumes 'auto'. # # Interface to module: # HAVE_PERL: used in makefiles to conditionally scan text files # PERL: returns the path of the perl program found # returns the path set by the user in the environment # --with-perl: 'yes' user instructs the module to use perl # 'no' user instructs the module not to use perl # have_perl: returns yes if perl found in PATH or no # # If the user sets the value of PERL, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_PERL],[ AC_ARG_VAR([PERL], [Path to perl command]) # Preserves the interface, should it be implemented later m4_ifval([$1], [m4_warn([syntax], [Checking for perl MIN-VERSION is not implemented])]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(perl, AS_HELP_STRING([--with-perl], [Use perl for extracting information from files (default: ]_defopt[)]), [use_perl=$withval], [use_perl=]_defopt) m4_undefine([_defopt]) if test "x$use_perl" = x"auto"; then AC_PATH_PROG([PERL], [perl]) if test "x$PERL" = "x"; then AC_MSG_WARN([perl not found - cannot extract information and report]) have_perl=no else have_perl=yes fi elif test "x$use_perl" = x"yes" ; then AC_PATH_PROG([PERL], [perl]) if test "x$PERL" = "x"; then AC_MSG_ERROR([--with-perl=yes specified but perl not found in PATH]) fi have_perl=yes elif test "x$use_perl" = x"no" ; then if test "x$PERL" != "x"; then AC_MSG_WARN([ignoring PERL environment variable since --with-perl=no was specified]) fi have_perl=no else AC_MSG_ERROR([--with-perl expects 'yes' or 'no']) fi AM_CONDITIONAL([HAVE_PERL], [test "$have_perl" = yes]) ]) # XORG_WITH_PERL # XORG_WITH_ASCIIDOC([MIN-VERSION], [DEFAULT]) # ---------------- # Minimum version: 1.5.0 # Minimum version for optional DEFAULT argument: 1.11.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-asciidoc option, it allows maximum flexibilty in making decisions # as whether or not to use the asciidoc package. When DEFAULT is not specified, # --with-asciidoc assumes 'auto'. # # Interface to module: # HAVE_ASCIIDOC: used in makefiles to conditionally generate documentation # ASCIIDOC: returns the path of the asciidoc program found # returns the path set by the user in the environment # --with-asciidoc: 'yes' user instructs the module to use asciidoc # 'no' user instructs the module not to use asciidoc # # If the user sets the value of ASCIIDOC, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_ASCIIDOC],[ AC_ARG_VAR([ASCIIDOC], [Path to asciidoc command]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(asciidoc, AS_HELP_STRING([--with-asciidoc], [Use asciidoc to regenerate documentation (default: ]_defopt[)]), [use_asciidoc=$withval], [use_asciidoc=]_defopt) m4_undefine([_defopt]) if test "x$use_asciidoc" = x"auto"; then AC_PATH_PROG([ASCIIDOC], [asciidoc]) if test "x$ASCIIDOC" = "x"; then AC_MSG_WARN([asciidoc not found - documentation targets will be skipped]) have_asciidoc=no else have_asciidoc=yes fi elif test "x$use_asciidoc" = x"yes" ; then AC_PATH_PROG([ASCIIDOC], [asciidoc]) if test "x$ASCIIDOC" = "x"; then AC_MSG_ERROR([--with-asciidoc=yes specified but asciidoc not found in PATH]) fi have_asciidoc=yes elif test "x$use_asciidoc" = x"no" ; then if test "x$ASCIIDOC" != "x"; then AC_MSG_WARN([ignoring ASCIIDOC environment variable since --with-asciidoc=no was specified]) fi have_asciidoc=no else AC_MSG_ERROR([--with-asciidoc expects 'yes' or 'no']) fi m4_ifval([$1], [if test "$have_asciidoc" = yes; then # scrape the asciidoc version AC_MSG_CHECKING([the asciidoc version]) asciidoc_version=`$ASCIIDOC --version 2>/dev/null | cut -d' ' -f2` AC_MSG_RESULT([$asciidoc_version]) AS_VERSION_COMPARE([$asciidoc_version], [$1], [if test "x$use_asciidoc" = xauto; then AC_MSG_WARN([asciidoc version $asciidoc_version found, but $1 needed]) have_asciidoc=no else AC_MSG_ERROR([asciidoc version $asciidoc_version found, but $1 needed]) fi]) fi]) AM_CONDITIONAL([HAVE_ASCIIDOC], [test "$have_asciidoc" = yes]) ]) # XORG_WITH_ASCIIDOC # XORG_WITH_DOXYGEN([MIN-VERSION], [DEFAULT]) # -------------------------------- # Minimum version: 1.5.0 # Minimum version for optional DEFAULT argument: 1.11.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-doxygen option, it allows maximum flexibilty in making decisions # as whether or not to use the doxygen package. When DEFAULT is not specified, # --with-doxygen assumes 'auto'. # # Interface to module: # HAVE_DOXYGEN: used in makefiles to conditionally generate documentation # DOXYGEN: returns the path of the doxygen program found # returns the path set by the user in the environment # --with-doxygen: 'yes' user instructs the module to use doxygen # 'no' user instructs the module not to use doxygen # # If the user sets the value of DOXYGEN, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_DOXYGEN],[ AC_ARG_VAR([DOXYGEN], [Path to doxygen command]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(doxygen, AS_HELP_STRING([--with-doxygen], [Use doxygen to regenerate documentation (default: ]_defopt[)]), [use_doxygen=$withval], [use_doxygen=]_defopt) m4_undefine([_defopt]) if test "x$use_doxygen" = x"auto"; then AC_PATH_PROG([DOXYGEN], [doxygen]) if test "x$DOXYGEN" = "x"; then AC_MSG_WARN([doxygen not found - documentation targets will be skipped]) have_doxygen=no else have_doxygen=yes fi elif test "x$use_doxygen" = x"yes" ; then AC_PATH_PROG([DOXYGEN], [doxygen]) if test "x$DOXYGEN" = "x"; then AC_MSG_ERROR([--with-doxygen=yes specified but doxygen not found in PATH]) fi have_doxygen=yes elif test "x$use_doxygen" = x"no" ; then if test "x$DOXYGEN" != "x"; then AC_MSG_WARN([ignoring DOXYGEN environment variable since --with-doxygen=no was specified]) fi have_doxygen=no else AC_MSG_ERROR([--with-doxygen expects 'yes' or 'no']) fi m4_ifval([$1], [if test "$have_doxygen" = yes; then # scrape the doxygen version AC_MSG_CHECKING([the doxygen version]) doxygen_version=`$DOXYGEN --version 2>/dev/null` AC_MSG_RESULT([$doxygen_version]) AS_VERSION_COMPARE([$doxygen_version], [$1], [if test "x$use_doxygen" = xauto; then AC_MSG_WARN([doxygen version $doxygen_version found, but $1 needed]) have_doxygen=no else AC_MSG_ERROR([doxygen version $doxygen_version found, but $1 needed]) fi]) fi]) AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = yes]) ]) # XORG_WITH_DOXYGEN # XORG_WITH_GROFF([DEFAULT]) # ---------------- # Minimum version: 1.6.0 # Minimum version for optional DEFAULT argument: 1.11.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-groff option, it allows maximum flexibilty in making decisions # as whether or not to use the groff package. When DEFAULT is not specified, # --with-groff assumes 'auto'. # # Interface to module: # HAVE_GROFF: used in makefiles to conditionally generate documentation # HAVE_GROFF_MM: the memorandum macros (-mm) package # HAVE_GROFF_MS: the -ms macros package # GROFF: returns the path of the groff program found # returns the path set by the user in the environment # --with-groff: 'yes' user instructs the module to use groff # 'no' user instructs the module not to use groff # # Added in version 1.9.0: # HAVE_GROFF_HTML: groff has dependencies to output HTML format: # pnmcut pnmcrop pnmtopng pnmtops from the netpbm package. # psselect from the psutils package. # the ghostcript package. Refer to the grohtml man pages # # If the user sets the value of GROFF, AC_PATH_PROG skips testing the path. # # OS and distros often splits groff in a basic and full package, the former # having the groff program and the later having devices, fonts and macros # Checking for the groff executable is not enough. # # If macros are missing, we cannot assume that groff is useless, so we don't # unset HAVE_GROFF or GROFF env variables. # HAVE_GROFF_?? can never be true while HAVE_GROFF is false. # AC_DEFUN([XORG_WITH_GROFF],[ AC_ARG_VAR([GROFF], [Path to groff command]) m4_define([_defopt], m4_default([$1], [auto])) AC_ARG_WITH(groff, AS_HELP_STRING([--with-groff], [Use groff to regenerate documentation (default: ]_defopt[)]), [use_groff=$withval], [use_groff=]_defopt) m4_undefine([_defopt]) if test "x$use_groff" = x"auto"; then AC_PATH_PROG([GROFF], [groff]) if test "x$GROFF" = "x"; then AC_MSG_WARN([groff not found - documentation targets will be skipped]) have_groff=no else have_groff=yes fi elif test "x$use_groff" = x"yes" ; then AC_PATH_PROG([GROFF], [groff]) if test "x$GROFF" = "x"; then AC_MSG_ERROR([--with-groff=yes specified but groff not found in PATH]) fi have_groff=yes elif test "x$use_groff" = x"no" ; then if test "x$GROFF" != "x"; then AC_MSG_WARN([ignoring GROFF environment variable since --with-groff=no was specified]) fi have_groff=no else AC_MSG_ERROR([--with-groff expects 'yes' or 'no']) fi # We have groff, test for the presence of the macro packages if test "x$have_groff" = x"yes"; then AC_MSG_CHECKING([for ${GROFF} -ms macros]) if ${GROFF} -ms -I. /dev/null >/dev/null 2>&1 ; then groff_ms_works=yes else groff_ms_works=no fi AC_MSG_RESULT([$groff_ms_works]) AC_MSG_CHECKING([for ${GROFF} -mm macros]) if ${GROFF} -mm -I. /dev/null >/dev/null 2>&1 ; then groff_mm_works=yes else groff_mm_works=no fi AC_MSG_RESULT([$groff_mm_works]) fi # We have groff, test for HTML dependencies, one command per package if test "x$have_groff" = x"yes"; then AC_PATH_PROGS(GS_PATH, [gs gswin32c]) AC_PATH_PROG(PNMTOPNG_PATH, [pnmtopng]) AC_PATH_PROG(PSSELECT_PATH, [psselect]) if test "x$GS_PATH" != "x" -a "x$PNMTOPNG_PATH" != "x" -a "x$PSSELECT_PATH" != "x"; then have_groff_html=yes else have_groff_html=no AC_MSG_WARN([grohtml dependencies not found - HTML Documentation skipped. Refer to grohtml man pages]) fi fi # Set Automake conditionals for Makefiles AM_CONDITIONAL([HAVE_GROFF], [test "$have_groff" = yes]) AM_CONDITIONAL([HAVE_GROFF_MS], [test "$groff_ms_works" = yes]) AM_CONDITIONAL([HAVE_GROFF_MM], [test "$groff_mm_works" = yes]) AM_CONDITIONAL([HAVE_GROFF_HTML], [test "$have_groff_html" = yes]) ]) # XORG_WITH_GROFF # XORG_WITH_FOP([MIN-VERSION], [DEFAULT]) # --------------------------------------- # Minimum version: 1.6.0 # Minimum version for optional DEFAULT argument: 1.11.0 # Minimum version for optional MIN-VERSION argument: 1.15.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-fop option, it allows maximum flexibilty in making decisions # as whether or not to use the fop package. When DEFAULT is not specified, # --with-fop assumes 'auto'. # # Interface to module: # HAVE_FOP: used in makefiles to conditionally generate documentation # FOP: returns the path of the fop program found # returns the path set by the user in the environment # --with-fop: 'yes' user instructs the module to use fop # 'no' user instructs the module not to use fop # # If the user sets the value of FOP, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_FOP],[ AC_ARG_VAR([FOP], [Path to fop command]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(fop, AS_HELP_STRING([--with-fop], [Use fop to regenerate documentation (default: ]_defopt[)]), [use_fop=$withval], [use_fop=]_defopt) m4_undefine([_defopt]) if test "x$use_fop" = x"auto"; then AC_PATH_PROG([FOP], [fop]) if test "x$FOP" = "x"; then AC_MSG_WARN([fop not found - documentation targets will be skipped]) have_fop=no else have_fop=yes fi elif test "x$use_fop" = x"yes" ; then AC_PATH_PROG([FOP], [fop]) if test "x$FOP" = "x"; then AC_MSG_ERROR([--with-fop=yes specified but fop not found in PATH]) fi have_fop=yes elif test "x$use_fop" = x"no" ; then if test "x$FOP" != "x"; then AC_MSG_WARN([ignoring FOP environment variable since --with-fop=no was specified]) fi have_fop=no else AC_MSG_ERROR([--with-fop expects 'yes' or 'no']) fi # Test for a minimum version of fop, if provided. m4_ifval([$1], [if test "$have_fop" = yes; then # scrape the fop version AC_MSG_CHECKING([for fop minimum version]) fop_version=`$FOP -version 2>/dev/null | cut -d' ' -f3` AC_MSG_RESULT([$fop_version]) AS_VERSION_COMPARE([$fop_version], [$1], [if test "x$use_fop" = xauto; then AC_MSG_WARN([fop version $fop_version found, but $1 needed]) have_fop=no else AC_MSG_ERROR([fop version $fop_version found, but $1 needed]) fi]) fi]) AM_CONDITIONAL([HAVE_FOP], [test "$have_fop" = yes]) ]) # XORG_WITH_FOP # XORG_WITH_PS2PDF([DEFAULT]) # ---------------- # Minimum version: 1.6.0 # Minimum version for optional DEFAULT argument: 1.11.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a module to test for the # presence of the tool and obtain it's path in separate variables. Coupled with # the --with-ps2pdf option, it allows maximum flexibilty in making decisions # as whether or not to use the ps2pdf package. When DEFAULT is not specified, # --with-ps2pdf assumes 'auto'. # # Interface to module: # HAVE_PS2PDF: used in makefiles to conditionally generate documentation # PS2PDF: returns the path of the ps2pdf program found # returns the path set by the user in the environment # --with-ps2pdf: 'yes' user instructs the module to use ps2pdf # 'no' user instructs the module not to use ps2pdf # # If the user sets the value of PS2PDF, AC_PATH_PROG skips testing the path. # AC_DEFUN([XORG_WITH_PS2PDF],[ AC_ARG_VAR([PS2PDF], [Path to ps2pdf command]) m4_define([_defopt], m4_default([$1], [auto])) AC_ARG_WITH(ps2pdf, AS_HELP_STRING([--with-ps2pdf], [Use ps2pdf to regenerate documentation (default: ]_defopt[)]), [use_ps2pdf=$withval], [use_ps2pdf=]_defopt) m4_undefine([_defopt]) if test "x$use_ps2pdf" = x"auto"; then AC_PATH_PROG([PS2PDF], [ps2pdf]) if test "x$PS2PDF" = "x"; then AC_MSG_WARN([ps2pdf not found - documentation targets will be skipped]) have_ps2pdf=no else have_ps2pdf=yes fi elif test "x$use_ps2pdf" = x"yes" ; then AC_PATH_PROG([PS2PDF], [ps2pdf]) if test "x$PS2PDF" = "x"; then AC_MSG_ERROR([--with-ps2pdf=yes specified but ps2pdf not found in PATH]) fi have_ps2pdf=yes elif test "x$use_ps2pdf" = x"no" ; then if test "x$PS2PDF" != "x"; then AC_MSG_WARN([ignoring PS2PDF environment variable since --with-ps2pdf=no was specified]) fi have_ps2pdf=no else AC_MSG_ERROR([--with-ps2pdf expects 'yes' or 'no']) fi AM_CONDITIONAL([HAVE_PS2PDF], [test "$have_ps2pdf" = yes]) ]) # XORG_WITH_PS2PDF # XORG_ENABLE_DOCS (enable_docs=yes) # ---------------- # Minimum version: 1.6.0 # # Documentation tools are not always available on all platforms and sometimes # not at the appropriate level. This macro enables a builder to skip all # documentation targets except traditional man pages. # Combined with the specific tool checking macros XORG_WITH_*, it provides # maximum flexibilty in controlling documentation building. # Refer to: # XORG_WITH_XMLTO --with-xmlto # XORG_WITH_ASCIIDOC --with-asciidoc # XORG_WITH_DOXYGEN --with-doxygen # XORG_WITH_FOP --with-fop # XORG_WITH_GROFF --with-groff # XORG_WITH_PS2PDF --with-ps2pdf # # Interface to module: # ENABLE_DOCS: used in makefiles to conditionally generate documentation # --enable-docs: 'yes' user instructs the module to generate docs # 'no' user instructs the module not to generate docs # parm1: specify the default value, yes or no. # AC_DEFUN([XORG_ENABLE_DOCS],[ m4_define([docs_default], m4_default([$1], [yes])) AC_ARG_ENABLE(docs, AS_HELP_STRING([--enable-docs], [Enable building the documentation (default: ]docs_default[)]), [build_docs=$enableval], [build_docs=]docs_default) m4_undefine([docs_default]) AM_CONDITIONAL(ENABLE_DOCS, [test x$build_docs = xyes]) AC_MSG_CHECKING([whether to build documentation]) AC_MSG_RESULT([$build_docs]) ]) # XORG_ENABLE_DOCS # XORG_ENABLE_DEVEL_DOCS (enable_devel_docs=yes) # ---------------- # Minimum version: 1.6.0 # # This macro enables a builder to skip all developer documentation. # Combined with the specific tool checking macros XORG_WITH_*, it provides # maximum flexibilty in controlling documentation building. # Refer to: # XORG_WITH_XMLTO --with-xmlto # XORG_WITH_ASCIIDOC --with-asciidoc # XORG_WITH_DOXYGEN --with-doxygen # XORG_WITH_FOP --with-fop # XORG_WITH_GROFF --with-groff # XORG_WITH_PS2PDF --with-ps2pdf # # Interface to module: # ENABLE_DEVEL_DOCS: used in makefiles to conditionally generate developer docs # --enable-devel-docs: 'yes' user instructs the module to generate developer docs # 'no' user instructs the module not to generate developer docs # parm1: specify the default value, yes or no. # AC_DEFUN([XORG_ENABLE_DEVEL_DOCS],[ m4_define([devel_default], m4_default([$1], [yes])) AC_ARG_ENABLE(devel-docs, AS_HELP_STRING([--enable-devel-docs], [Enable building the developer documentation (default: ]devel_default[)]), [build_devel_docs=$enableval], [build_devel_docs=]devel_default) m4_undefine([devel_default]) AM_CONDITIONAL(ENABLE_DEVEL_DOCS, [test x$build_devel_docs = xyes]) AC_MSG_CHECKING([whether to build developer documentation]) AC_MSG_RESULT([$build_devel_docs]) ]) # XORG_ENABLE_DEVEL_DOCS # XORG_ENABLE_SPECS (enable_specs=yes) # ---------------- # Minimum version: 1.6.0 # # This macro enables a builder to skip all functional specification targets. # Combined with the specific tool checking macros XORG_WITH_*, it provides # maximum flexibilty in controlling documentation building. # Refer to: # XORG_WITH_XMLTO --with-xmlto # XORG_WITH_ASCIIDOC --with-asciidoc # XORG_WITH_DOXYGEN --with-doxygen # XORG_WITH_FOP --with-fop # XORG_WITH_GROFF --with-groff # XORG_WITH_PS2PDF --with-ps2pdf # # Interface to module: # ENABLE_SPECS: used in makefiles to conditionally generate specs # --enable-specs: 'yes' user instructs the module to generate specs # 'no' user instructs the module not to generate specs # parm1: specify the default value, yes or no. # AC_DEFUN([XORG_ENABLE_SPECS],[ m4_define([spec_default], m4_default([$1], [yes])) AC_ARG_ENABLE(specs, AS_HELP_STRING([--enable-specs], [Enable building the specs (default: ]spec_default[)]), [build_specs=$enableval], [build_specs=]spec_default) m4_undefine([spec_default]) AM_CONDITIONAL(ENABLE_SPECS, [test x$build_specs = xyes]) AC_MSG_CHECKING([whether to build functional specifications]) AC_MSG_RESULT([$build_specs]) ]) # XORG_ENABLE_SPECS # XORG_ENABLE_UNIT_TESTS (enable_unit_tests=auto) # ---------------------------------------------- # Minimum version: 1.13.0 # # This macro enables a builder to enable/disable unit testing # It makes no assumption about the test cases implementation # Test cases may or may not use Automake "Support for test suites" # They may or may not use the software utility library GLib # # When used in conjunction with XORG_WITH_GLIB, use both AM_CONDITIONAL # ENABLE_UNIT_TESTS and HAVE_GLIB. Not all unit tests may use glib. # The variable enable_unit_tests is used by other macros in this file. # # Interface to module: # ENABLE_UNIT_TESTS: used in makefiles to conditionally build tests # enable_unit_tests: used in configure.ac for additional configuration # --enable-unit-tests: 'yes' user instructs the module to build tests # 'no' user instructs the module not to build tests # parm1: specify the default value, yes or no. # AC_DEFUN([XORG_ENABLE_UNIT_TESTS],[ AC_BEFORE([$0], [XORG_WITH_GLIB]) AC_BEFORE([$0], [XORG_LD_WRAP]) AC_REQUIRE([XORG_MEMORY_CHECK_FLAGS]) m4_define([_defopt], m4_default([$1], [auto])) AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--enable-unit-tests], [Enable building unit test cases (default: ]_defopt[)]), [enable_unit_tests=$enableval], [enable_unit_tests=]_defopt) m4_undefine([_defopt]) AM_CONDITIONAL(ENABLE_UNIT_TESTS, [test "x$enable_unit_tests" != xno]) AC_MSG_CHECKING([whether to build unit test cases]) AC_MSG_RESULT([$enable_unit_tests]) ]) # XORG_ENABLE_UNIT_TESTS # XORG_ENABLE_INTEGRATION_TESTS (enable_unit_tests=auto) # ------------------------------------------------------ # Minimum version: 1.17.0 # # This macro enables a builder to enable/disable integration testing # It makes no assumption about the test cases' implementation # Test cases may or may not use Automake "Support for test suites" # # Please see XORG_ENABLE_UNIT_TESTS for unit test support. Unit test support # usually requires less dependencies and may be built and run under less # stringent environments than integration tests. # # Interface to module: # ENABLE_INTEGRATION_TESTS: used in makefiles to conditionally build tests # enable_integration_tests: used in configure.ac for additional configuration # --enable-integration-tests: 'yes' user instructs the module to build tests # 'no' user instructs the module not to build tests # parm1: specify the default value, yes or no. # AC_DEFUN([XORG_ENABLE_INTEGRATION_TESTS],[ AC_REQUIRE([XORG_MEMORY_CHECK_FLAGS]) m4_define([_defopt], m4_default([$1], [auto])) AC_ARG_ENABLE(integration-tests, AS_HELP_STRING([--enable-integration-tests], [Enable building integration test cases (default: ]_defopt[)]), [enable_integration_tests=$enableval], [enable_integration_tests=]_defopt) m4_undefine([_defopt]) AM_CONDITIONAL([ENABLE_INTEGRATION_TESTS], [test "x$enable_integration_tests" != xno]) AC_MSG_CHECKING([whether to build unit test cases]) AC_MSG_RESULT([$enable_integration_tests]) ]) # XORG_ENABLE_INTEGRATION_TESTS # XORG_WITH_GLIB([MIN-VERSION], [DEFAULT]) # ---------------------------------------- # Minimum version: 1.13.0 # # GLib is a library which provides advanced data structures and functions. # This macro enables a module to test for the presence of Glib. # # When used with ENABLE_UNIT_TESTS, it is assumed GLib is used for unit testing. # Otherwise the value of $enable_unit_tests is blank. # # Please see XORG_ENABLE_INTEGRATION_TESTS for integration test support. Unit # test support usually requires less dependencies and may be built and run under # less stringent environments than integration tests. # # Interface to module: # HAVE_GLIB: used in makefiles to conditionally build targets # with_glib: used in configure.ac to know if GLib has been found # --with-glib: 'yes' user instructs the module to use glib # 'no' user instructs the module not to use glib # AC_DEFUN([XORG_WITH_GLIB],[ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) m4_define([_defopt], m4_default([$2], [auto])) AC_ARG_WITH(glib, AS_HELP_STRING([--with-glib], [Use GLib library for unit testing (default: ]_defopt[)]), [with_glib=$withval], [with_glib=]_defopt) m4_undefine([_defopt]) have_glib=no # Do not probe GLib if user explicitly disabled unit testing if test "x$enable_unit_tests" != x"no"; then # Do not probe GLib if user explicitly disabled it if test "x$with_glib" != x"no"; then m4_ifval( [$1], [PKG_CHECK_MODULES([GLIB], [glib-2.0 >= $1], [have_glib=yes], [have_glib=no])], [PKG_CHECK_MODULES([GLIB], [glib-2.0], [have_glib=yes], [have_glib=no])] ) fi fi # Not having GLib when unit testing has been explicitly requested is an error if test "x$enable_unit_tests" = x"yes"; then if test "x$have_glib" = x"no"; then AC_MSG_ERROR([--enable-unit-tests=yes specified but glib-2.0 not found]) fi fi # Having unit testing disabled when GLib has been explicitly requested is an error if test "x$enable_unit_tests" = x"no"; then if test "x$with_glib" = x"yes"; then AC_MSG_ERROR([--enable-unit-tests=yes specified but glib-2.0 not found]) fi fi # Not having GLib when it has been explicitly requested is an error if test "x$with_glib" = x"yes"; then if test "x$have_glib" = x"no"; then AC_MSG_ERROR([--with-glib=yes specified but glib-2.0 not found]) fi fi AM_CONDITIONAL([HAVE_GLIB], [test "$have_glib" = yes]) ]) # XORG_WITH_GLIB # XORG_LD_WRAP([required|optional]) # --------------------------------- # Minimum version: 1.13.0 # # Check if linker supports -wrap, passed via compiler flags # # When used with ENABLE_UNIT_TESTS, it is assumed -wrap is used for unit testing. # Otherwise the value of $enable_unit_tests is blank. # # Argument added in 1.16.0 - default is "required", to match existing behavior # of returning an error if enable_unit_tests is yes, and ld -wrap is not # available, an argument of "optional" allows use when some unit tests require # ld -wrap and others do not. # AC_DEFUN([XORG_LD_WRAP],[ XORG_CHECK_LINKER_FLAGS([-Wl,-wrap,exit],[have_ld_wrap=yes],[have_ld_wrap=no], [AC_LANG_PROGRAM([#include void __wrap_exit(int status) { return; }], [exit(0);])]) # Not having ld wrap when unit testing has been explicitly requested is an error if test "x$enable_unit_tests" = x"yes" -a "x$1" != "xoptional"; then if test "x$have_ld_wrap" = x"no"; then AC_MSG_ERROR([--enable-unit-tests=yes specified but ld -wrap support is not available]) fi fi AM_CONDITIONAL([HAVE_LD_WRAP], [test "$have_ld_wrap" = yes]) # ]) # XORG_LD_WRAP # XORG_CHECK_LINKER_FLAGS # ----------------------- # SYNOPSIS # # XORG_CHECK_LINKER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE], [PROGRAM-SOURCE]) # # DESCRIPTION # # Check whether the given linker FLAGS work with the current language's # linker, or whether they give an error. # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # PROGRAM-SOURCE is the program source to link with, if needed # # NOTE: Based on AX_CHECK_COMPILER_FLAGS. # # LICENSE # # Copyright (c) 2009 Mike Frysinger # Copyright (c) 2009 Steven G. Johnson # Copyright (c) 2009 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well.# AC_DEFUN([XORG_CHECK_LINKER_FLAGS], [AC_MSG_CHECKING([whether the linker accepts $1]) dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname: AS_LITERAL_IF([$1], [AC_CACHE_VAL(AS_TR_SH(xorg_cv_linker_flags_[$1]), [ ax_save_FLAGS=$LDFLAGS LDFLAGS="$1" AC_LINK_IFELSE([m4_default([$4],[AC_LANG_PROGRAM()])], AS_TR_SH(xorg_cv_linker_flags_[$1])=yes, AS_TR_SH(xorg_cv_linker_flags_[$1])=no) LDFLAGS=$ax_save_FLAGS])], [ax_save_FLAGS=$LDFLAGS LDFLAGS="$1" AC_LINK_IFELSE([AC_LANG_PROGRAM()], eval AS_TR_SH(xorg_cv_linker_flags_[$1])=yes, eval AS_TR_SH(xorg_cv_linker_flags_[$1])=no) LDFLAGS=$ax_save_FLAGS]) eval xorg_check_linker_flags=$AS_TR_SH(xorg_cv_linker_flags_[$1]) AC_MSG_RESULT($xorg_check_linker_flags) if test "x$xorg_check_linker_flags" = xyes; then m4_default([$2], :) else m4_default([$3], :) fi ]) # XORG_CHECK_LINKER_FLAGS # XORG_MEMORY_CHECK_FLAGS # ----------------------- # Minimum version: 1.16.0 # # This macro attempts to find appropriate memory checking functionality # for various platforms which unit testing code may use to catch various # forms of memory allocation and access errors in testing. # # Interface to module: # XORG_MALLOC_DEBUG_ENV - environment variables to set to enable debugging # Usually added to TESTS_ENVIRONMENT in Makefile.am # # If the user sets the value of XORG_MALLOC_DEBUG_ENV, it is used verbatim. # AC_DEFUN([XORG_MEMORY_CHECK_FLAGS],[ AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_VAR([XORG_MALLOC_DEBUG_ENV], [Environment variables to enable memory checking in tests]) # Check for different types of support on different platforms case $host_os in solaris*) AC_CHECK_LIB([umem], [umem_alloc], [malloc_debug_env='LD_PRELOAD=libumem.so UMEM_DEBUG=default']) ;; *-gnu*) # GNU libc - Value is used as a single byte bit pattern, # both directly and inverted, so should not be 0 or 255. malloc_debug_env='MALLOC_PERTURB_=15' ;; darwin*) malloc_debug_env='MallocPreScribble=1 MallocScribble=1 DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib' ;; *bsd*) malloc_debug_env='MallocPreScribble=1 MallocScribble=1' ;; esac # User supplied flags override default flags if test "x$XORG_MALLOC_DEBUG_ENV" != "x"; then malloc_debug_env="$XORG_MALLOC_DEBUG_ENV" fi AC_SUBST([XORG_MALLOC_DEBUG_ENV],[$malloc_debug_env]) ]) # XORG_WITH_LINT # XORG_CHECK_MALLOC_ZERO # ---------------------- # Minimum version: 1.0.0 # # Defines {MALLOC,XMALLOC,XTMALLOC}_ZERO_CFLAGS appropriately if # malloc(0) returns NULL. Packages should add one of these cflags to # their AM_CFLAGS (or other appropriate *_CFLAGS) to use them. AC_DEFUN([XORG_CHECK_MALLOC_ZERO],[ AC_ARG_ENABLE(malloc0returnsnull, AS_HELP_STRING([--enable-malloc0returnsnull], [malloc(0) returns NULL (default: auto)]), [MALLOC_ZERO_RETURNS_NULL=$enableval], [MALLOC_ZERO_RETURNS_NULL=auto]) AC_MSG_CHECKING([whether malloc(0) returns NULL]) if test "x$MALLOC_ZERO_RETURNS_NULL" = xauto; then AC_RUN_IFELSE([AC_LANG_PROGRAM([ #include ],[ char *m0, *r0, *c0, *p; m0 = malloc(0); p = malloc(10); r0 = realloc(p,0); c0 = calloc(0,10); exit((m0 == 0 || r0 == 0 || c0 == 0) ? 0 : 1); ])], [MALLOC_ZERO_RETURNS_NULL=yes], [MALLOC_ZERO_RETURNS_NULL=no], [MALLOC_ZERO_RETURNS_NULL=yes]) fi AC_MSG_RESULT([$MALLOC_ZERO_RETURNS_NULL]) if test "x$MALLOC_ZERO_RETURNS_NULL" = xyes; then MALLOC_ZERO_CFLAGS="-DMALLOC_0_RETURNS_NULL" XMALLOC_ZERO_CFLAGS=$MALLOC_ZERO_CFLAGS XTMALLOC_ZERO_CFLAGS="$MALLOC_ZERO_CFLAGS -DXTMALLOC_BC" else MALLOC_ZERO_CFLAGS="" XMALLOC_ZERO_CFLAGS="" XTMALLOC_ZERO_CFLAGS="" fi AC_SUBST([MALLOC_ZERO_CFLAGS]) AC_SUBST([XMALLOC_ZERO_CFLAGS]) AC_SUBST([XTMALLOC_ZERO_CFLAGS]) ]) # XORG_CHECK_MALLOC_ZERO # XORG_WITH_LINT() # ---------------- # Minimum version: 1.1.0 # # This macro enables the use of a tool that flags some suspicious and # non-portable constructs (likely to be bugs) in C language source code. # It will attempt to locate the tool and use appropriate options. # There are various lint type tools on different platforms. # # Interface to module: # LINT: returns the path to the tool found on the platform # or the value set to LINT on the configure cmd line # also an Automake conditional # LINT_FLAGS: an Automake variable with appropriate flags # # --with-lint: 'yes' user instructs the module to use lint # 'no' user instructs the module not to use lint (default) # # If the user sets the value of LINT, AC_PATH_PROG skips testing the path. # If the user sets the value of LINT_FLAGS, they are used verbatim. # AC_DEFUN([XORG_WITH_LINT],[ AC_ARG_VAR([LINT], [Path to a lint-style command]) AC_ARG_VAR([LINT_FLAGS], [Flags for the lint-style command]) AC_ARG_WITH(lint, [AS_HELP_STRING([--with-lint], [Use a lint-style source code checker (default: disabled)])], [use_lint=$withval], [use_lint=no]) # Obtain platform specific info like program name and options # The lint program on FreeBSD and NetBSD is different from the one on Solaris case $host_os in *linux* | *openbsd* | kfreebsd*-gnu | darwin* | cygwin*) lint_name=splint lint_options="-badflag" ;; *freebsd* | *netbsd*) lint_name=lint lint_options="-u -b" ;; *solaris*) lint_name=lint lint_options="-u -b -h -erroff=E_INDISTING_FROM_TRUNC2" ;; esac # Test for the presence of the program (either guessed by the code or spelled out by the user) if test "x$use_lint" = x"yes" ; then AC_PATH_PROG([LINT], [$lint_name]) if test "x$LINT" = "x"; then AC_MSG_ERROR([--with-lint=yes specified but lint-style tool not found in PATH]) fi elif test "x$use_lint" = x"no" ; then if test "x$LINT" != "x"; then AC_MSG_WARN([ignoring LINT environment variable since --with-lint=no was specified]) fi else AC_MSG_ERROR([--with-lint expects 'yes' or 'no'. Use LINT variable to specify path.]) fi # User supplied flags override default flags if test "x$LINT_FLAGS" != "x"; then lint_options=$LINT_FLAGS fi AC_SUBST([LINT_FLAGS],[$lint_options]) AM_CONDITIONAL(LINT, [test "x$LINT" != x]) ]) # XORG_WITH_LINT # XORG_LINT_LIBRARY(LIBNAME) # -------------------------- # Minimum version: 1.1.0 # # Sets up flags for building lint libraries for checking programs that call # functions in the library. # # Interface to module: # LINTLIB - Automake variable with the name of lint library file to make # MAKE_LINT_LIB - Automake conditional # # --enable-lint-library: - 'yes' user instructs the module to created a lint library # - 'no' user instructs the module not to create a lint library (default) AC_DEFUN([XORG_LINT_LIBRARY],[ AC_REQUIRE([XORG_WITH_LINT]) AC_ARG_ENABLE(lint-library, [AS_HELP_STRING([--enable-lint-library], [Create lint library (default: disabled)])], [make_lint_lib=$enableval], [make_lint_lib=no]) if test "x$make_lint_lib" = x"yes" ; then LINTLIB=llib-l$1.ln if test "x$LINT" = "x"; then AC_MSG_ERROR([Cannot make lint library without --with-lint]) fi elif test "x$make_lint_lib" != x"no" ; then AC_MSG_ERROR([--enable-lint-library expects 'yes' or 'no'.]) fi AC_SUBST(LINTLIB) AM_CONDITIONAL(MAKE_LINT_LIB, [test x$make_lint_lib != xno]) ]) # XORG_LINT_LIBRARY # XORG_COMPILER_BRAND # ------------------- # Minimum version: 1.14.0 # # Checks for various brands of compilers and sets flags as appropriate: # GNU gcc - relies on AC_PROG_CC (via AC_PROG_CC_C99) to set GCC to "yes" # GNU g++ - relies on AC_PROG_CXX to set GXX to "yes" # clang compiler - sets CLANGCC to "yes" # Intel compiler - sets INTELCC to "yes" # Sun/Oracle Solaris Studio cc - sets SUNCC to "yes" # AC_DEFUN([XORG_COMPILER_BRAND], [ AC_LANG_CASE( [C], [ AC_REQUIRE([AC_PROG_CC_C99]) ], [C++], [ AC_REQUIRE([AC_PROG_CXX]) ] ) AC_CHECK_DECL([__clang__], [CLANGCC="yes"], [CLANGCC="no"]) AC_CHECK_DECL([__INTEL_COMPILER], [INTELCC="yes"], [INTELCC="no"]) AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) ]) # XORG_COMPILER_BRAND # XORG_TESTSET_CFLAG(, , [, ...]) # --------------- # Minimum version: 1.16.0 # # Test if the compiler works when passed the given flag as a command line argument. # If it succeeds, the flag is appeneded to the given variable. If not, it tries the # next flag in the list until there are no more options. # # Note that this does not guarantee that the compiler supports the flag as some # compilers will simply ignore arguments that they do not understand, but we do # attempt to weed out false positives by using -Werror=unknown-warning-option and # -Werror=unused-command-line-argument # AC_DEFUN([XORG_TESTSET_CFLAG], [ m4_if([$#], 0, [m4_fatal([XORG_TESTSET_CFLAG was given with an unsupported number of arguments])]) m4_if([$#], 1, [m4_fatal([XORG_TESTSET_CFLAG was given with an unsupported number of arguments])]) AC_LANG_COMPILER_REQUIRE AC_LANG_CASE( [C], [ AC_REQUIRE([AC_PROG_CC_C99]) define([PREFIX], [C]) define([CACHE_PREFIX], [cc]) define([COMPILER], [$CC]) ], [C++], [ define([PREFIX], [CXX]) define([CACHE_PREFIX], [cxx]) define([COMPILER], [$CXX]) ] ) [xorg_testset_save_]PREFIX[FLAGS]="$PREFIX[FLAGS]" if test "x$[xorg_testset_]CACHE_PREFIX[_unknown_warning_option]" = "x" ; then PREFIX[FLAGS]="$PREFIX[FLAGS] -Werror=unknown-warning-option" AC_CACHE_CHECK([if ]COMPILER[ supports -Werror=unknown-warning-option], [xorg_cv_]CACHE_PREFIX[_flag_unknown_warning_option], AC_COMPILE_IFELSE([AC_LANG_SOURCE([int i;])], [xorg_cv_]CACHE_PREFIX[_flag_unknown_warning_option=yes], [xorg_cv_]CACHE_PREFIX[_flag_unknown_warning_option=no])) [xorg_testset_]CACHE_PREFIX[_unknown_warning_option]=$[xorg_cv_]CACHE_PREFIX[_flag_unknown_warning_option] PREFIX[FLAGS]="$[xorg_testset_save_]PREFIX[FLAGS]" fi if test "x$[xorg_testset_]CACHE_PREFIX[_unused_command_line_argument]" = "x" ; then if test "x$[xorg_testset_]CACHE_PREFIX[_unknown_warning_option]" = "xyes" ; then PREFIX[FLAGS]="$PREFIX[FLAGS] -Werror=unknown-warning-option" fi PREFIX[FLAGS]="$PREFIX[FLAGS] -Werror=unused-command-line-argument" AC_CACHE_CHECK([if ]COMPILER[ supports -Werror=unused-command-line-argument], [xorg_cv_]CACHE_PREFIX[_flag_unused_command_line_argument], AC_COMPILE_IFELSE([AC_LANG_SOURCE([int i;])], [xorg_cv_]CACHE_PREFIX[_flag_unused_command_line_argument=yes], [xorg_cv_]CACHE_PREFIX[_flag_unused_command_line_argument=no])) [xorg_testset_]CACHE_PREFIX[_unused_command_line_argument]=$[xorg_cv_]CACHE_PREFIX[_flag_unused_command_line_argument] PREFIX[FLAGS]="$[xorg_testset_save_]PREFIX[FLAGS]" fi found="no" m4_foreach([flag], m4_cdr($@), [ if test $found = "no" ; then if test "x$xorg_testset_unknown_warning_option" = "xyes" ; then PREFIX[FLAGS]="$PREFIX[FLAGS] -Werror=unknown-warning-option" fi if test "x$xorg_testset_unused_command_line_argument" = "xyes" ; then PREFIX[FLAGS]="$PREFIX[FLAGS] -Werror=unused-command-line-argument" fi PREFIX[FLAGS]="$PREFIX[FLAGS] ]flag[" dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname AC_MSG_CHECKING([if ]COMPILER[ supports]flag[]) cacheid=AS_TR_SH([xorg_cv_]CACHE_PREFIX[_flag_]flag[]) AC_CACHE_VAL($cacheid, [AC_LINK_IFELSE([AC_LANG_PROGRAM([int i;])], [eval $cacheid=yes], [eval $cacheid=no])]) PREFIX[FLAGS]="$[xorg_testset_save_]PREFIX[FLAGS]" eval supported=\$$cacheid AC_MSG_RESULT([$supported]) if test "$supported" = "yes" ; then $1="$$1 ]flag[" found="yes" fi fi ]) ]) # XORG_TESTSET_CFLAG # XORG_COMPILER_FLAGS # --------------- # Minimum version: 1.16.0 # # Defines BASE_CFLAGS or BASE_CXXFLAGS to contain a set of command line # arguments supported by the selected compiler which do NOT alter the generated # code. These arguments will cause the compiler to print various warnings # during compilation AND turn a conservative set of warnings into errors. # # The set of flags supported by BASE_CFLAGS and BASE_CXXFLAGS will grow in # future versions of util-macros as options are added to new compilers. # AC_DEFUN([XORG_COMPILER_FLAGS], [ AC_REQUIRE([XORG_COMPILER_BRAND]) AC_ARG_ENABLE(selective-werror, AS_HELP_STRING([--disable-selective-werror], [Turn off selective compiler errors. (default: enabled)]), [SELECTIVE_WERROR=$enableval], [SELECTIVE_WERROR=yes]) AC_LANG_CASE( [C], [ define([PREFIX], [C]) ], [C++], [ define([PREFIX], [CXX]) ] ) # -v is too short to test reliably with XORG_TESTSET_CFLAG if test "x$SUNCC" = "xyes"; then [BASE_]PREFIX[FLAGS]="-v" else [BASE_]PREFIX[FLAGS]="" fi # This chunk of warnings were those that existed in the legacy CWARNFLAGS XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wall]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wpointer-arith]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmissing-declarations]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wformat=2], [-Wformat]) AC_LANG_CASE( [C], [ XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wstrict-prototypes]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmissing-prototypes]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wnested-externs]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wbad-function-cast]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wold-style-definition]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wdeclaration-after-statement]) ] ) # This chunk adds additional warnings that could catch undesired effects. XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wunused]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wuninitialized]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wshadow]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wcast-qual]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmissing-noreturn]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmissing-format-attribute]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wredundant-decls]) # These are currently disabled because they are noisy. They will be enabled # in the future once the codebase is sufficiently modernized to silence # them. For now, I don't want them to drown out the other warnings. # XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wlogical-op]) # XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wparentheses]) # XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wcast-align]) # Turn some warnings into errors, so we don't accidently get successful builds # when there are problems that should be fixed. if test "x$SELECTIVE_WERROR" = "xyes" ; then XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=implicit], [-errwarn=E_NO_EXPLICIT_TYPE_GIVEN -errwarn=E_NO_IMPLICIT_DECL_ALLOWED]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=nonnull]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=init-self]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=main]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=missing-braces]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=sequence-point]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=return-type], [-errwarn=E_FUNC_HAS_NO_RETURN_STMT]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=trigraphs]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=array-bounds]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=write-strings]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=address]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=int-to-pointer-cast], [-errwarn=E_BAD_PTR_INT_COMBINATION]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Werror=pointer-to-int-cast]) # Also -errwarn=E_BAD_PTR_INT_COMBINATION else AC_MSG_WARN([You have chosen not to turn some select compiler warnings into errors. This should not be necessary. Please report why you needed to do so in a bug report at $PACKAGE_BUGREPORT]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wimplicit]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wnonnull]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Winit-self]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmain]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wmissing-braces]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wsequence-point]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wreturn-type]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wtrigraphs]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Warray-bounds]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wwrite-strings]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Waddress]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wint-to-pointer-cast]) XORG_TESTSET_CFLAG([[BASE_]PREFIX[FLAGS]], [-Wpointer-to-int-cast]) fi AC_SUBST([BASE_]PREFIX[FLAGS]) ]) # XORG_COMPILER_FLAGS # XORG_CWARNFLAGS # --------------- # Minimum version: 1.2.0 # Deprecated since: 1.16.0 (Use XORG_COMPILER_FLAGS instead) # # Defines CWARNFLAGS to enable C compiler warnings. # # This function is deprecated because it defines -fno-strict-aliasing # which alters the code generated by the compiler. If -fno-strict-aliasing # is needed, then it should be added explicitly in the module when # it is updated to use BASE_CFLAGS. # AC_DEFUN([XORG_CWARNFLAGS], [ AC_REQUIRE([XORG_COMPILER_FLAGS]) AC_REQUIRE([XORG_COMPILER_BRAND]) AC_LANG_CASE( [C], [ CWARNFLAGS="$BASE_CFLAGS" if test "x$GCC" = xyes ; then CWARNFLAGS="$CWARNFLAGS -fno-strict-aliasing" fi AC_SUBST(CWARNFLAGS) ] ) ]) # XORG_CWARNFLAGS # XORG_STRICT_OPTION # ----------------------- # Minimum version: 1.3.0 # # Add configure option to enable strict compilation flags, such as treating # warnings as fatal errors. # If --enable-strict-compilation is passed to configure, adds strict flags to # $BASE_CFLAGS or $BASE_CXXFLAGS and the deprecated $CWARNFLAGS. # # Starting in 1.14.0 also exports $STRICT_CFLAGS for use in other tests or # when strict compilation is unconditionally desired. AC_DEFUN([XORG_STRICT_OPTION], [ AC_REQUIRE([XORG_CWARNFLAGS]) AC_REQUIRE([XORG_COMPILER_FLAGS]) AC_ARG_ENABLE(strict-compilation, AS_HELP_STRING([--enable-strict-compilation], [Enable all warnings from compiler and make them errors (default: disabled)]), [STRICT_COMPILE=$enableval], [STRICT_COMPILE=no]) AC_LANG_CASE( [C], [ define([PREFIX], [C]) ], [C++], [ define([PREFIX], [CXX]) ] ) [STRICT_]PREFIX[FLAGS]="" XORG_TESTSET_CFLAG([[STRICT_]PREFIX[FLAGS]], [-pedantic]) XORG_TESTSET_CFLAG([[STRICT_]PREFIX[FLAGS]], [-Werror], [-errwarn]) # Earlier versions of gcc (eg: 4.2) support -Werror=attributes, but do not # activate it with -Werror, so we add it here explicitly. XORG_TESTSET_CFLAG([[STRICT_]PREFIX[FLAGS]], [-Werror=attributes]) if test "x$STRICT_COMPILE" = "xyes"; then [BASE_]PREFIX[FLAGS]="$[BASE_]PREFIX[FLAGS] $[STRICT_]PREFIX[FLAGS]" AC_LANG_CASE([C], [CWARNFLAGS="$CWARNFLAGS $STRICT_CFLAGS"]) fi AC_SUBST([STRICT_]PREFIX[FLAGS]) AC_SUBST([BASE_]PREFIX[FLAGS]) AC_LANG_CASE([C], AC_SUBST([CWARNFLAGS])) ]) # XORG_STRICT_OPTION # XORG_DEFAULT_OPTIONS # -------------------- # Minimum version: 1.3.0 # # Defines default options for X.Org modules. # AC_DEFUN([XORG_DEFAULT_OPTIONS], [ AC_REQUIRE([AC_PROG_INSTALL]) XORG_COMPILER_FLAGS XORG_CWARNFLAGS XORG_STRICT_OPTION XORG_RELEASE_VERSION XORG_CHANGELOG XORG_INSTALL XORG_MANPAGE_SECTIONS m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) ]) # XORG_DEFAULT_OPTIONS # XORG_INSTALL() # ---------------- # Minimum version: 1.4.0 # # Defines the variable INSTALL_CMD as the command to copy # INSTALL from $prefix/share/util-macros. # AC_DEFUN([XORG_INSTALL], [ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) macros_datadir=`$PKG_CONFIG --print-errors --variable=pkgdatadir xorg-macros` INSTALL_CMD="(cp -f "$macros_datadir/INSTALL" \$(top_srcdir)/.INSTALL.tmp && \ mv \$(top_srcdir)/.INSTALL.tmp \$(top_srcdir)/INSTALL) \ || (rm -f \$(top_srcdir)/.INSTALL.tmp; touch \$(top_srcdir)/INSTALL; \ echo 'util-macros \"pkgdatadir\" from xorg-macros.pc not found: installing possibly empty INSTALL.' >&2)" AC_SUBST([INSTALL_CMD]) ]) # XORG_INSTALL dnl Copyright 2005 Red Hat, Inc dnl dnl Permission to use, copy, modify, distribute, and sell this software and its dnl documentation for any purpose is hereby granted without fee, provided that dnl the above copyright notice appear in all copies and that both that dnl copyright notice and this permission notice appear in supporting dnl documentation. dnl dnl The above copyright notice and this permission notice shall be included dnl in all copies or substantial portions of the Software. dnl dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF dnl MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. dnl IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR dnl OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, dnl ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR dnl OTHER DEALINGS IN THE SOFTWARE. dnl dnl Except as contained in this notice, the name of the copyright holders shall dnl not be used in advertising or otherwise to promote the sale, use or dnl other dealings in this Software without prior written authorization dnl from the copyright holders. dnl # XORG_RELEASE_VERSION # -------------------- # Defines PACKAGE_VERSION_{MAJOR,MINOR,PATCHLEVEL} for modules to use. AC_DEFUN([XORG_RELEASE_VERSION],[ AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MAJOR], [`echo $PACKAGE_VERSION | cut -d . -f 1`], [Major version of this package]) PVM=`echo $PACKAGE_VERSION | cut -d . -f 2 | cut -d - -f 1` if test "x$PVM" = "x"; then PVM="0" fi AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MINOR], [$PVM], [Minor version of this package]) PVP=`echo $PACKAGE_VERSION | cut -d . -f 3 | cut -d - -f 1` if test "x$PVP" = "x"; then PVP="0" fi AC_DEFINE_UNQUOTED([PACKAGE_VERSION_PATCHLEVEL], [$PVP], [Patch version of this package]) ]) # XORG_CHANGELOG() # ---------------- # Minimum version: 1.2.0 # # Defines the variable CHANGELOG_CMD as the command to generate # ChangeLog from git. # # AC_DEFUN([XORG_CHANGELOG], [ CHANGELOG_CMD="(GIT_DIR=\$(top_srcdir)/.git git log > \$(top_srcdir)/.changelog.tmp && \ mv \$(top_srcdir)/.changelog.tmp \$(top_srcdir)/ChangeLog) \ || (rm -f \$(top_srcdir)/.changelog.tmp; touch \$(top_srcdir)/ChangeLog; \ echo 'git directory not found: installing possibly empty changelog.' >&2)" AC_SUBST([CHANGELOG_CMD]) ]) # XORG_CHANGELOG geis-2.2.17+16.04.20160126/m4/ax_enable_xi2.m40000644000015600001650000000251712651717544020377 0ustar pbuserpbgroup00000000000000# # @file m4/ac_enable_xi2.m4 # @brief autoconf macro to enable or disable support for XInput 2.2 # # Copyright 2011, 2013 Canonical, Ltd. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # AC_DEFUN([AX_ENABLE_XI2],[ AC_ARG_ENABLE([xi2.1], AS_HELP_STRING([--disable-xi2.1], [Disable XI2.1 features])) AS_IF([test "x$enable_xi2_1" != "xno"],[ AC_MSG_CHECKING([for XI2.1]) ax_have_xi_2_1=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ #include XITouchClassInfo* p = 0; ])], [ax_have_xi_2_1=yes AC_DEFINE([HAVE_XI_2_1],[1],[XInput 2.1 is available])] ) AC_MSG_RESULT([$ax_have_xi_2_1]) PKG_CHECK_MODULES([XORG], [xorg-server >= 1.10.1], , AC_MSG_ERROR([X.Org Server development libraries not found])) ]) ]) geis-2.2.17+16.04.20160126/m4/ltsugar.m40000644000015600001650000001042412651717544017354 0ustar pbuserpbgroup00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) geis-2.2.17+16.04.20160126/python/0000755000015600001650000000000012651717732016430 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/python/Makefile.am0000644000015600001650000000255512651717544020474 0ustar pbuserpbgroup00000000000000# # @file python/Makefile.am # @brief automake recipe for the libgeis python bindings # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA dist_bin_SCRIPTS = pygeis dist_noinst_SCRIPTS = run_pygeis nobase_python_PYTHON = \ geis/__init__.py \ geis/geis_v2.py pyexec_LTLIBRARIES = _geis_bindings.la _geis_bindings_la_SOURCES = \ _geis_bindings/_geis_bindings.c _geis_bindings_la_CFLAGS = \ $(AM_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ $(PYTHON_CFLAGS) _geis_bindings_la_LDFLAGS = \ -module -avoid-version \ -export-symbols-regex PyInit__geis_bindings \ $(top_builddir)/libgeis/libgeis.la \ $(PYTHON_LIBS) geis-2.2.17+16.04.20160126/python/pygeis0000755000015600001650000001012612651717544017657 0ustar pbuserpbgroup00000000000000#!/usr/bin/python3 # # @file pygies # @brief a demo/test program for the GEIS python bindings # # Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import argparse import geis from gi.repository import GLib import sys def _print_gesture(attrs): touchset = attrs[geis.GEIS_EVENT_ATTRIBUTE_TOUCHSET] groupset = attrs[geis.GEIS_EVENT_ATTRIBUTE_GROUPSET] print(" touches (" + str(len(touchset)) + "):") for touch in touchset: print(" ", touch.id(), touch.attrs()) print(" groups:") for group in groupset: print(" ", group.id(), ":") for frame in group: print(" frame ", frame.id(), ":") for (k, v) in frame.attrs().items(): print(" " + k + ":", v) print(" touches: ", frame.touches()) def _do_init_complete(event, sub): print("init complete") sub.activate() def _do_device_available(event, sub): print("device available") def _do_gesture_begin(event, sub): print("gesture begin") _print_gesture(event.attrs()) def _do_gesture_update(event, sub): print("gesture update") _print_gesture(event.attrs()) def _do_gesture_end(event, sub): print("gesture end") _print_gesture(event.attrs()) def _do_other_event(event, sub): print("unknown geis event received") _geis_event_action = { geis.GEIS_EVENT_INIT_COMPLETE: _do_init_complete, geis.GEIS_EVENT_DEVICE_AVAILABLE: _do_device_available, geis.GEIS_EVENT_GESTURE_BEGIN: _do_gesture_begin, geis.GEIS_EVENT_GESTURE_UPDATE: _do_gesture_update, geis.GEIS_EVENT_GESTURE_END: _do_gesture_end } def _dispatch_geis_events(fd, condition, g): """ Performs GEIS event loop processing. """ status = g.dispatch_events() while status == geis.GEIS_STATUS_CONTINUE: status = g.dispatch_events() try: while True: event = g.next_event() _geis_event_action.get(event.type(), _do_other_event)(event, None) except geis.NoMoreEvents: pass return True def _class_callback(g, event, sub): if event.type() == geis.GEIS_EVENT_CLASS_AVAILABLE: gclass = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_CLASS] name = gclass.name() print(".. adding class %s" % name) filt = geis.Filter(g, name) filt.add_term(geis.GEIS_FILTER_CLASS, (geis.GEIS_CLASS_ATTRIBUTE_NAME, geis.GEIS_FILTER_OP_EQ, name), (geis.GEIS_GESTURE_ATTRIBUTE_TOUCHES, geis.GEIS_FILTER_OP_GT, 2)) sub.add_filter(filt) def _event_callback(geis, event, sub): _geis_event_action.get(event.type(), _do_other_event)(event, sub) class Options(argparse.ArgumentParser): def __init__(self): argparse.ArgumentParser.__init__(self, description="monitor gestures") self.add_argument('-V', '--version', action='version', version='1.0') if __name__ == '__main__': options = Options() try: options.parse_args() except argparse.ArgumentError as ex: print(ex) sys.exit(1) g = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES, geis.GEIS_INIT_TRACK_GESTURE_CLASSES, geis.GEIS_INIT_SYNCHRONOUS_START) geis_fd = g.get_configuration(geis.GEIS_CONFIGURATION_FD) sub = geis.Subscription(g) g.register_class_callback(_class_callback, sub) g.register_event_callback(_event_callback, sub) try: ml = GLib.MainLoop() GLib.io_add_watch(geis_fd, GLib.IO_IN, _dispatch_geis_events, g) ml.run() except KeyboardInterrupt: pass geis-2.2.17+16.04.20160126/python/geis/0000755000015600001650000000000012651717732017357 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/python/geis/__init__.py0000644000015600001650000002501512651717544021474 0ustar pbuserpbgroup00000000000000# Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Python bindings for the GEIS gesture recognition interface. """ __all__ = ( 'Geis', 'Event', 'Filter', 'Subscription', 'NoMoreEvents', 'GEIS_STATUS_SUCCESS', 'GEIS_STATUS_CONTINUE', 'GEIS_STATUS_EMPTY', 'GEIS_STATUS_NOT_SUPPORTED', 'GEIS_STATUS_BAD_ARGUMENT', 'GEIS_STATUS_UNKNOWN_ERROR', 'GEIS_ATTR_TYPE_BOOLEAN', 'GEIS_ATTR_TYPE_FLOAT', 'GEIS_ATTR_TYPE_INTEGER', 'GEIS_ATTR_TYPE_POINTER', 'GEIS_ATTR_TYPE_STRING', 'GEIS_INIT_SERVICE_PROVIDER', 'GEIS_INIT_TRACK_DEVICES', 'GEIS_INIT_TRACK_GESTURE_CLASSES', 'GEIS_INIT_SYNCHRONOUS_START', 'GEIS_INIT_MOCK_BACKEND', 'GEIS_INIT_DBUS_BACKEND', 'GEIS_INIT_GRAIL_BACKEND', 'GEIS_INIT_XCB_BACKEND', 'GEIS_CLASS_ATTRIBUTE_ID', 'GEIS_CLASS_ATTRIBUTE_NAME', 'GEIS_CONFIGURATION_FD', 'GEIS_CONFIG_MAX_EVENTS', 'GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH', 'GEIS_DEVICE_ATTRIBUTE_ID', 'GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH', 'GEIS_DEVICE_ATTRIBUTE_NAME', 'GEIS_DEVICE_ATTRIBUTE_TOUCHES', 'GEIS_EVENT_ATTRIBUTE_CLASS', 'GEIS_EVENT_ATTRIBUTE_DEVICE', 'GEIS_EVENT_ATTRIBUTE_GROUPSET', 'GEIS_EVENT_ATTRIBUTE_GROUPSET', 'GEIS_EVENT_ATTRIBUTE_TOUCHSET', 'GEIS_EVENT_ATTRIBUTE_TOUCHSET', 'GEIS_EVENT_CLASS_AVAILABLE', 'GEIS_EVENT_CLASS_CHANGED', 'GEIS_EVENT_CLASS_UNAVAILABLE', 'GEIS_EVENT_DEVICE_AVAILABLE', 'GEIS_EVENT_DEVICE_UNAVAILABLE', 'GEIS_EVENT_ERROR', 'GEIS_EVENT_GESTURE_BEGIN', 'GEIS_EVENT_GESTURE_END', 'GEIS_EVENT_GESTURE_UPDATE', 'GEIS_EVENT_INIT_COMPLETE', 'GEIS_EVENT_USER_DEFINED', 'GEIS_GESTURE_ATTRIBUTE_ANGLE', 'GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA', 'GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY', 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1', 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2', 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1', 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2', 'GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID', 'GEIS_GESTURE_ATTRIBUTE_DELTA_X', 'GEIS_GESTURE_ATTRIBUTE_DELTA_Y', 'GEIS_GESTURE_ATTRIBUTE_DEVICE_ID', 'GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID', 'GEIS_GESTURE_ATTRIBUTE_FOCUS_X', 'GEIS_GESTURE_ATTRIBUTE_FOCUS_Y', 'GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME', 'GEIS_GESTURE_ATTRIBUTE_POSITION_X', 'GEIS_GESTURE_ATTRIBUTE_POSITION_Y', 'GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY', 'GEIS_GESTURE_ATTRIBUTE_RADIUS', 'GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA', 'GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID', 'GEIS_GESTURE_ATTRIBUTE_TAP_TIME', 'GEIS_GESTURE_ATTRIBUTE_TIMESTAMP', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X', 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y', 'GEIS_GESTURE_ATTRIBUTE_TOUCHES', 'GEIS_GESTURE_ATTRIBUTE_VELOCITY_X', 'GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y', 'GEIS_REGION_ATTRIBUTE_WINDOWID', 'GEIS_REGION_X11_ROOT', 'GEIS_REGION_X11_WINDOWID', 'GEIS_TOUCH_ATTRIBUTE_ID', 'GEIS_TOUCH_ATTRIBUTE_ID', 'GEIS_TOUCH_ATTRIBUTE_X', 'GEIS_TOUCH_ATTRIBUTE_X', 'GEIS_TOUCH_ATTRIBUTE_Y', 'GEIS_TOUCH_ATTRIBUTE_Y', 'GEIS_FILTER_DEVICE', 'GEIS_FILTER_CLASS', 'GEIS_FILTER_REGION', 'GEIS_FILTER_OP_EQ', 'GEIS_FILTER_OP_NE', 'GEIS_FILTER_OP_GT', 'GEIS_FILTER_OP_GE', 'GEIS_FILTER_OP_LT', 'GEIS_FILTER_OP_LE', ) from _geis_bindings import GEIS_STATUS_SUCCESS, \ GEIS_STATUS_CONTINUE, \ GEIS_STATUS_EMPTY, \ GEIS_STATUS_NOT_SUPPORTED, \ GEIS_STATUS_BAD_ARGUMENT, \ GEIS_STATUS_UNKNOWN_ERROR from _geis_bindings import GEIS_ATTR_TYPE_BOOLEAN, \ GEIS_ATTR_TYPE_FLOAT, \ GEIS_ATTR_TYPE_INTEGER, \ GEIS_ATTR_TYPE_POINTER, \ GEIS_ATTR_TYPE_STRING from _geis_bindings import GEIS_INIT_SERVICE_PROVIDER, \ GEIS_INIT_TRACK_DEVICES, \ GEIS_INIT_TRACK_GESTURE_CLASSES, \ GEIS_INIT_MOCK_BACKEND, \ GEIS_INIT_DBUS_BACKEND, \ GEIS_INIT_GRAIL_BACKEND, \ GEIS_INIT_XCB_BACKEND, \ GEIS_INIT_SYNCHRONOUS_START from _geis_bindings import GEIS_CONFIGURATION_FD, \ GEIS_CONFIG_MAX_EVENTS from _geis_bindings import GEIS_EVENT_ATTRIBUTE_DEVICE, \ GEIS_DEVICE_ATTRIBUTE_NAME, \ GEIS_DEVICE_ATTRIBUTE_ID, \ GEIS_DEVICE_ATTRIBUTE_TOUCHES, \ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, \ GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH from _geis_bindings import GEIS_EVENT_ATTRIBUTE_CLASS, \ GEIS_CLASS_ATTRIBUTE_NAME, \ GEIS_CLASS_ATTRIBUTE_ID from _geis_bindings import GEIS_REGION_ATTRIBUTE_WINDOWID, \ GEIS_REGION_X11_ROOT, \ GEIS_REGION_X11_WINDOWID from _geis_bindings import GEIS_EVENT_ATTRIBUTE_GROUPSET, \ GEIS_EVENT_ATTRIBUTE_TOUCHSET, \ GEIS_TOUCH_ATTRIBUTE_ID, \ GEIS_TOUCH_ATTRIBUTE_X, \ GEIS_TOUCH_ATTRIBUTE_Y from _geis_bindings import GEIS_EVENT_DEVICE_AVAILABLE, \ GEIS_EVENT_DEVICE_UNAVAILABLE, \ GEIS_EVENT_CLASS_AVAILABLE, \ GEIS_EVENT_CLASS_CHANGED, \ GEIS_EVENT_CLASS_UNAVAILABLE, \ GEIS_EVENT_GESTURE_BEGIN, \ GEIS_EVENT_GESTURE_UPDATE, \ GEIS_EVENT_GESTURE_END, \ GEIS_EVENT_INIT_COMPLETE, \ GEIS_EVENT_USER_DEFINED, \ GEIS_EVENT_ERROR from _geis_bindings import GEIS_GESTURE_ATTRIBUTE_ANGLE, \ GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA, \ GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY, \ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1, \ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2, \ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1, \ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2, \ GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID, \ GEIS_GESTURE_ATTRIBUTE_DELTA_X, \ GEIS_GESTURE_ATTRIBUTE_DELTA_Y, \ GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, \ GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID, \ GEIS_GESTURE_ATTRIBUTE_FOCUS_X, \ GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, \ GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME, \ GEIS_GESTURE_ATTRIBUTE_POSITION_X, \ GEIS_GESTURE_ATTRIBUTE_POSITION_Y, \ GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY, \ GEIS_GESTURE_ATTRIBUTE_RADIUS, \ GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA, \ GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID, \ GEIS_GESTURE_ATTRIBUTE_TAP_TIME, \ GEIS_GESTURE_ATTRIBUTE_TIMESTAMP, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X, \ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y, \ GEIS_GESTURE_ATTRIBUTE_TOUCHES, \ GEIS_GESTURE_ATTRIBUTE_VELOCITY_X, \ GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y from _geis_bindings import GEIS_FILTER_DEVICE, \ GEIS_FILTER_CLASS, \ GEIS_FILTER_REGION, \ GEIS_FILTER_OP_EQ, \ GEIS_FILTER_OP_NE, \ GEIS_FILTER_OP_GT, \ GEIS_FILTER_OP_GE, \ GEIS_FILTER_OP_LT, \ GEIS_FILTER_OP_LE from geis.geis_v2 import Geis, Event, Filter, Subscription, NoMoreEvents geis-2.2.17+16.04.20160126/python/geis/geis_v2.py0000644000015600001650000005151512651717544021277 0ustar pbuserpbgroup00000000000000# Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of version 3 of the GNU General Public License as # published by the Free Software Foundation. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Python bindings for the GEIS v2 gesture recognition interface. Do not use this module directly -- the public API is provided by the 'geis' module. """ import ctypes import ctypes.util import _geis_bindings import re import sys class GeisError(Exception): """ A general error has occurred internally in GEIS. """ def __init__(self, reason): Exception.__init__(self, reason) class NoMoreEvents(Exception): """ Raised by the event dispatch mechanism to indicate there are no pending events in the queue. """ def __init__(self): Exception.__init__(self, 'geis event queue is empty') def _check_null(ret, func, args): """ Converts a NULL pointer return value into an Exception. """ if ret == 0: raise GeisError("%s failed" % func.__name__) return ret _EventCallback = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.py_object) _geis_lib = ctypes.CDLL(ctypes.util.find_library("geis")) try: _geis_new = _geis_lib.geis_new _geis_new.restype = ctypes.c_void_p _geis_new.errcheck = _check_null _geis_delete = _geis_lib.geis_delete _geis_get_configuration = _geis_lib.geis_get_configuration _geis_dispatch_events = _geis_lib.geis_dispatch_events _geis_register_class_callback = _geis_lib.geis_register_class_callback _geis_register_device_callback = _geis_lib.geis_register_device_callback _geis_register_event_callback = _geis_lib.geis_register_event_callback _geis_next_event = _geis_lib.geis_next_event _geis_subscription_new = _geis_lib.geis_subscription_new _geis_subscription_new.restype = ctypes.c_void_p _geis_subscription_new.errcheck = _check_null _geis_subscription_delete = _geis_lib.geis_subscription_delete _geis_subscription_activate = _geis_lib.geis_subscription_activate _geis_subscription_deactivate = _geis_lib.geis_subscription_deactivate _geis_subscription_name = _geis_lib.geis_subscription_name _geis_attr_name = _geis_lib.geis_attr_name _geis_attr_name.restype = ctypes.c_char_p _geis_attr_type = _geis_lib.geis_attr_type _geis_attr_value_to_pointer = _geis_lib.geis_attr_value_to_pointer _geis_event_type = _geis_lib.geis_event_type _geis_event_attr_count = _geis_lib.geis_event_attr_count _geis_event_attr = _geis_lib.geis_event_attr _geis_event_attr.restype = ctypes.c_void_p _geis_gesture_class_unref = _geis_lib.geis_gesture_class_unref _geis_gesture_class_name = _geis_lib.geis_gesture_class_name _geis_gesture_class_name.restype = ctypes.c_char_p _geis_gesture_class_id = _geis_lib.geis_gesture_class_id _geis_gesture_class_attr_count = _geis_lib.geis_gesture_class_attr_count _geis_gesture_class_attr = _geis_lib.geis_gesture_class_attr _geis_gesture_class_attr.restype = ctypes.c_void_p _geis_device_ref = _geis_lib.geis_device_ref _geis_device_unref = _geis_lib.geis_device_unref _geis_device_name = _geis_lib.geis_device_name _geis_device_name.restype = ctypes.c_char_p _geis_device_id = _geis_lib.geis_device_id _geis_device_attr_count = _geis_lib.geis_device_attr_count _geis_device_attr = _geis_lib.geis_device_attr _geis_device_attr.restype = ctypes.c_void_p _geis_touchset_touch_count = _geis_lib.geis_touchset_touch_count _geis_touchset_touch = _geis_lib.geis_touchset_touch _geis_touchset_touch.restype = ctypes.c_void_p _geis_touch_attr_count = _geis_lib.geis_touch_attr_count _geis_touch_attr = _geis_lib.geis_touch_attr _geis_touch_attr.restype = ctypes.c_void_p _geis_groupset_group_count = _geis_lib.geis_groupset_group_count _geis_groupset_group = _geis_lib.geis_groupset_group _geis_groupset_group.restype = ctypes.c_void_p _geis_group_frame_count = _geis_lib.geis_group_frame_count _geis_group_frame = _geis_lib.geis_group_frame _geis_group_frame.restype = ctypes.c_void_p _geis_frame_attr_count = _geis_lib.geis_frame_attr_count _geis_frame_attr = _geis_lib.geis_frame_attr _geis_frame_attr.restype = ctypes.c_void_p _geis_frame_is_class = _geis_lib.geis_frame_is_class _geis_frame_touchid_count = _geis_lib.geis_frame_touchid_count _geis_frame_touchid = _geis_lib.geis_frame_touchid except AttributeError as ex: print(ex) sys.exit(1) class GestureClass(object): """Describes a class of gestures. """ def __init__(self, attr): self._class = _geis_attr_value_to_pointer(attr) self._id = _geis_gesture_class_id(self._class) self._name = _geis_gesture_class_name(self._class).decode('utf-8') self._attr_count = _geis_gesture_class_attr_count(self._class) self._attrs = {} for i in range(self._attr_count): attr = _geis_gesture_class_attr(self._class, i) attr_name = _geis_attr_name(attr).decode('utf-8') self._attrs[attr_name] = _attr_types.get(_geis_attr_type(attr), _attr_type_unknown)(attr) @property def _as_parameter_(self): return self._class def id(self): """ Gets the gesture class's system identifier (an integer). """ return self._id def name(self): """ Gets the gesture class's self-identified name. """ return self._name def attrs(self): """ Gets the named attributes associated with the gesture class. """ return self._attrs class Device(object): """Describes a touchable device. """ def __init__(self, attr): self._device = _geis_attr_value_to_pointer(attr) self._id = _geis_device_id(self._device) self._name = _geis_device_name(self._device).decode('utf-8') self._min_x = 0.0 self._min_y = 0.0 self._max_x = 0.0 self._max_y = 0.0 self._attr_count = _geis_device_attr_count(self._device) self._attrs = {} for i in range(self._attr_count): attr = _geis_device_attr(self._device, i) attr_name = _geis_attr_name(attr).decode('utf-8') self._attrs[attr_name] = _attr_types.get(_geis_attr_type(attr), _attr_type_unknown)(attr) if re.search("Abs MT Position X \d+ min", attr_name): self._min_x = self._attrs[attr_name] if re.search("Abs MT Position X \d+ max", attr_name): self._max_x = self._attrs[attr_name] if re.search("Abs MT Position Y \d+ min", attr_name): self._min_y = self._attrs[attr_name] if re.search("Abs MT Position Y \d+ max", attr_name): self._max_y = self._attrs[attr_name] def id(self): """ Gets the device's system identifier (an integer). """ return self._id def name(self): """ Gets the device's self-identified name. """ return self._name def extents(self): """ Gets the device's defined extents (bounding box). Returns: A tuple of (min X, min Y, max X, max Y). """ return (self._min_x, self._min_y, self._max_x, self._max_y) def attrs(self): """ Gets the named attributes associated with the device. """ return self._attrs class Touch(object): """Represents a particular touch.""" def __init__(self, touch): self._touch = touch self._attr_count = _geis_touch_attr_count(self._touch) def id(self): """ Gets the persistent identifier of the touch. """ return _geis_lib.geis_touch_id(self._touch) def attrs(self): """ Gets the attributes of the touch. """ attr_list = {} for i in range(self._attr_count): attr = _geis_touch_attr(self._touch, i) attr_name = _geis_attr_name(attr).decode('utf-8') attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr), _attr_type_unknown)(attr) return attr_list class Touchset(object): """A collection of Touch objects.""" def __init__(self, attr): self._touchset = _geis_attr_value_to_pointer(attr) self._count = _geis_touchset_touch_count(self._touchset) self._index = 0 def __len__(self): return self._count def __iter__(self): return self def __next__(self): """ Gets the next touch in the touchset as an iterable. """ if self._index == self._count: raise StopIteration touch = Touch(_geis_touchset_touch(self._touchset, self._index)) self._index = self._index + 1 return touch class Groupset(object): """A collection of Group objects.""" def __init__(self, attr): self._groupset = _geis_attr_value_to_pointer(attr) self._count = _geis_groupset_group_count(self._groupset) self._index = 0 def __len__(self): return self._count def __iter__(self): return self def __next__(self): """ Gets the next group in the groupset as an iterable. """ if self._index == self._count: raise StopIteration touch = Group(_geis_groupset_group(self._groupset, self._index)) self._index = self._index + 1 return touch class Group(object): """A set of Frame objects made up of a combination of touches.""" def __init__(self, group): self._group = group self._count = _geis_group_frame_count(self._group) self._index = 0 def __len__(self): return self._count def __iter__(self): return self def id(self): return _geis_lib.geis_group_id(self._group) def __next__(self): """ Gets the next frame in the group as an iterable. """ if self._index == self._count: raise StopIteration frame = Frame(_geis_group_frame(self._group, self._index)) self._index = self._index + 1 return frame class Frame(object): """A gesture frame.""" def __init__(self, frame): self._frame = frame def id(self): return _geis_lib.geis_frame_id(self._frame) def attrs(self): attr_list = {} for i in range(_geis_frame_attr_count(self._frame)): attr = _geis_frame_attr(self._frame, i) attr_name = _geis_attr_name(attr).decode('utf-8') attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr), _attr_type_unknown)(attr) return attr_list def is_class(self, gclass): return _geis_frame_is_class(self._frame, gclass) def touches(self): touch_list = [] for i in range(_geis_frame_touchid_count(self._frame)): touch_list.append(_geis_frame_touchid(self._frame, i)) return touch_list def _pointer_type_class(attr): """ Converts a generic attr into a GestureClass object. """ return GestureClass(attr) def _pointer_type_device(attr): """ Converts a generic attr into a Device object. """ return Device(attr) def _pointer_type_groupset(attr): """ Converts a generic attr into a Groupset object. """ return Groupset(attr) def _pointer_type_touchset(attr): """ Converts a generic attr into a Touchset object. """ return Touchset(attr) def _pointer_type_unknown(attr): print("unknown pointer type ") return None _attr_pointer_type = { _geis_bindings.GEIS_EVENT_ATTRIBUTE_CLASS: _pointer_type_class, _geis_bindings.GEIS_EVENT_ATTRIBUTE_DEVICE: _pointer_type_device, _geis_bindings.GEIS_EVENT_ATTRIBUTE_GROUPSET: _pointer_type_groupset, _geis_bindings.GEIS_EVENT_ATTRIBUTE_TOUCHSET: _pointer_type_touchset } def _attr_type_boolean(attr): """ Extracts an attribute value as a boolean. """ return _geis_lib.geis_attr_value_to_boolean(attr) def _attr_type_float(attr): """ Extracts an attribute value as a float. """ geis_attr_value_to_float = _geis_lib.geis_attr_value_to_float geis_attr_value_to_float.restype = ctypes.c_float return geis_attr_value_to_float(attr) def _attr_type_integer(attr): """ Extracts an attribute value as a integer. """ return _geis_lib.geis_attr_value_to_integer(attr) def _attr_type_pointer(attr): """ Extracts an attribute value as an object. """ return _attr_pointer_type.get(_geis_attr_name(attr).decode('utf-8'), _pointer_type_unknown)(attr) def _attr_type_string(attr): """ Extracts an attribute value as a string. """ geis_attr_value_to_string = _geis_lib.geis_attr_value_to_string geis_attr_value_to_string.restype = ctypes.c_char_p return geis_attr_value_to_string(attr) def _attr_type_unknown(attr): print("unknown attr type" + _geis_attr_name(attr).decode('utf-8')) return None _attr_types = { _geis_bindings.GEIS_ATTR_TYPE_BOOLEAN: _attr_type_boolean, _geis_bindings.GEIS_ATTR_TYPE_FLOAT: _attr_type_float, _geis_bindings.GEIS_ATTR_TYPE_INTEGER: _attr_type_integer, _geis_bindings.GEIS_ATTR_TYPE_POINTER: _attr_type_pointer, _geis_bindings.GEIS_ATTR_TYPE_STRING: _attr_type_string } def _cb_wrapper(ignored, eptr, context): """ A currying wrapper for event callbacks. This is a currying function to wrap a Python callback with arbitrary arguments so it can be invoked from a C callback. :param ignored: This argumenet is ignored. :param eptr: A C pointer to the internal GEIS event. :param context: A tuple containing the Geis class instance, the Python callable, and the argument list. """ (geis_instance, cb, args) = context cb(geis_instance, Event(eptr), args[0]) class Geis(object): """A GEIS API instance. """ def __init__(self, *args): """Create a GEIS instance. This constructor takes a variable number of arguments (zero or more) all of he geis.GEIS_INIT_... form. On failure, an Exception is raised. """ terminator = 0, va_args = args + terminator self._instance = _geis_new(*va_args) if self._instance == 0: raise GeisError('can not create GEIS instance') self._cb_wrapper = _EventCallback(_cb_wrapper) self._class_curry = None self._device_curry = None self._event_curry = None def __del__(self): _geis_delete(self._instance) @property def _as_parameter_(self): return self._instance def get_configuration(self, item_name): """ Gets a named configuration value. """ if (item_name == _geis_bindings.GEIS_CONFIGURATION_FD): fd = ctypes.c_long() status = _geis_get_configuration(self._instance, item_name.encode('utf-8'), ctypes.byref(fd)) if status != _geis_bindings.GEIS_STATUS_SUCCESS: raise GeisError('error retrieving GEIS fd') return fd.value raise ValueError('unsupported config item name') def set_configuration(self, name, value): """ Sets a named configuration value. """ raise ValueError('unsupported config item name') def register_class_callback(self, callback, *args): """ Registers a python callback to receive GEIS gesture class events. """ context = self, callback, args self._class_curry = ctypes.py_object(context) _geis_register_class_callback(self._instance, self._cb_wrapper, self._class_curry) def register_device_callback(self, callback, *args): """ Registers a python callback to receive GEIS gesture device events. """ context = self, callback, args self._device_curry = ctypes.py_object(context) _geis_register_device_callback(self._instance, self._cb_wrapper, self._device_curry) def register_event_callback(self, callback, *args): """ Registers a python callback to receive general GEIS events. """ self._event_curry = ctypes.py_object((self, callback, args)) _geis_register_event_callback(self._instance, self._cb_wrapper, self._event_curry) def dispatch_events(self): """ Pumps the geis event loop. """ return _geis_dispatch_events(self._instance) def next_event(self): """ Pulls the next event, if any, off the geis event queue. :return: a geis.Event object :raise: geis.NoMoreEvents """ event = Event() status = _geis_next_event(self._instance, event) if status not in [_geis_bindings.GEIS_STATUS_CONTINUE, _geis_bindings.GEIS_STATUS_SUCCESS]: raise NoMoreEvents() return event class Event(object): """ An event returned from the GEIS API. """ def __init__(self, internal=ctypes.c_void_p()): self._event = internal @property def _as_parameter_(self): return ctypes.byref(self._event) def type(self): """ Gets the type of the event. """ return _geis_event_type(self._event) def attrs(self): """ Gets the attributes associated with the event. """ attr_list = {} for i in range(_geis_event_attr_count(self._event)): attr = _geis_event_attr(self._event, i) attr_name = _geis_attr_name(attr).decode('utf-8') attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr), _attr_type_unknown)(attr) return attr_list class Filter(object): """ A Geis Filter object. """ def __init__(self, geis, name): self._filter = _geis_lib.geis_filter_new(geis, name.encode('utf-8')) def __del__(self): _geis_lib.geis_filter_delete(self._filter) @property def _as_parameter_(self): return self._filter def name(self): """ Gets the name of the filter. """ return _geis_lib.geis_filter_name(self._filter) def add_term(self, facility, *terms): """ Adds a new term to the filter. :param facility: the filter facility to which the terms belong :param terms: a collection of (name, operation, value) tuples """ for term in terms: if len(term) != 3: raise ValueError('invalid filter term') name, op, value = term _geis_lib.geis_filter_add_term(self._filter, facility, name.encode('utf-8'), op, value, 0) class Subscription(object): """ A Geis subscription object. """ def __init__(self, geis): """Constructs a GEIS subscription object. A subscription is a request to the gesture recognizer to receive gesture events. The default subscription is to receive all events from all devices for all regions. The domain of the events received can be restructed through the use of filters. :param geis: The GEIS v2 instance. :raise: Exception """ object.__init__(self) self._sub = _geis_subscription_new(geis, "py".encode('utf-8'), 0) self._filters = [] def __del__(self): _geis_subscription_delete(self._sub) def activate(self): """ Activates the subscription. """ _geis_subscription_activate(self._sub) def deactivate(self): """ Deactivates the subscription. """ _geis_subscription_deactivate(self._sub) def name(self): """ Gets the name of the subscription. """ return _geis_subscription_name(self._sub) def add_filter(self, filt): """Adds a filter to the subscription. :param filter: the filter to add """ # keep a reference to the filter for Python doesn't garbage collect it if filt not in self._filters: self._filters.append(filt) _geis_lib.geis_subscription_add_filter(self._sub, filt) def remove_filter(self, filt): """ Removes a filter from the subscription. :param filter: the filter to remove """ _geis_lib.geis_subscription_remove_filter(self._sub, filt) geis-2.2.17+16.04.20160126/python/run_pygeis0000755000015600001650000000033712651717544020546 0ustar pbuserpbgroup00000000000000#!/bin/sh # # Runs the pygeis program from inside the build tree. # tool_path=$(dirname $0) LD_LIBRARY_PATH=$tool_path/../libgeis/.libs PYTHONPATH=$tool_path/.libs export LD_LIBRARY_PATH PYTHONPATH $tool_path/pygeis "$@" geis-2.2.17+16.04.20160126/python/_geis_bindings/0000755000015600001650000000000012651717732021373 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/python/_geis_bindings/_geis_bindings.c0000644000015600001650000002104512651717544024505 0ustar pbuserpbgroup00000000000000#include #include #include "geis_test_api.h" PyDoc_STRVAR(module_doc, "Low-level python bindings for libgeis.\n" "Do not use this module directly " "-- the public API is provided by the 'geis' module." ); static PyMethodDef exported_functions[] = { {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_geis_bindings", module_doc, sizeof(NULL), exported_functions, NULL, NULL, NULL, NULL }; PyObject * PyInit__geis_bindings(void) { PyObject *this_module; this_module = PyModule_Create(&moduledef); if (this_module == NULL) return NULL; /* Global status values. */ PyModule_AddIntConstant(this_module, "GEIS_STATUS_SUCCESS", GEIS_STATUS_SUCCESS); PyModule_AddIntConstant(this_module, "GEIS_STATUS_CONTINUE", GEIS_STATUS_CONTINUE); PyModule_AddIntConstant(this_module, "GEIS_STATUS_EMPTY", GEIS_STATUS_EMPTY); PyModule_AddIntConstant(this_module, "GEIS_STATUS_NOT_SUPPORTED", GEIS_STATUS_NOT_SUPPORTED); PyModule_AddIntConstant(this_module, "GEIS_STATUS_BAD_ARGUMENT", GEIS_STATUS_BAD_ARGUMENT); PyModule_AddIntConstant(this_module, "GEIS_STATUS_UNKNOWN_ERROR", GEIS_STATUS_UNKNOWN_ERROR); /* Attribute types */ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_BOOLEAN", GEIS_ATTR_TYPE_BOOLEAN); PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_FLOAT", GEIS_ATTR_TYPE_FLOAT); PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_INTEGER", GEIS_ATTR_TYPE_INTEGER); PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_POINTER", GEIS_ATTR_TYPE_POINTER); PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_STRING", GEIS_ATTR_TYPE_STRING); /* Initialization Options */ PyModule_AddStringMacro(this_module, GEIS_INIT_SERVICE_PROVIDER); PyModule_AddStringMacro(this_module, GEIS_INIT_TRACK_DEVICES); PyModule_AddStringMacro(this_module, GEIS_INIT_TRACK_GESTURE_CLASSES); PyModule_AddStringMacro(this_module, GEIS_INIT_SYNCHRONOUS_START); PyModule_AddStringMacro(this_module, GEIS_INIT_MOCK_BACKEND); PyModule_AddStringMacro(this_module, GEIS_INIT_DBUS_BACKEND); PyModule_AddStringMacro(this_module, GEIS_INIT_GRAIL_BACKEND); PyModule_AddStringMacro(this_module, GEIS_INIT_XCB_BACKEND); /* Configuration Items */ PyModule_AddStringMacro(this_module, GEIS_CONFIGURATION_FD); PyModule_AddStringMacro(this_module, GEIS_CONFIG_MAX_EVENTS); /* Device Constants */ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_DEVICE); PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_NAME); PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_ID); PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_TOUCHES); PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH); PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH); /* Gesture Class Constants */ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_CLASS); PyModule_AddStringMacro(this_module, GEIS_CLASS_ATTRIBUTE_NAME); PyModule_AddStringMacro(this_module, GEIS_CLASS_ATTRIBUTE_ID); /* Region Constants */ PyModule_AddStringMacro(this_module, GEIS_REGION_ATTRIBUTE_WINDOWID); PyModule_AddStringMacro(this_module, GEIS_REGION_X11_ROOT); PyModule_AddStringMacro(this_module, GEIS_REGION_X11_WINDOWID); /* Gesture Constants */ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_GROUPSET); PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_TOUCHSET); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGLE); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DELTA_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DELTA_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_FOCUS_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_POSITION_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_POSITION_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIUS); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TAP_TIME); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCHES); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X); PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y); PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_ID); PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_X); PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_Y); /* Event Types */ PyModule_AddIntConstant(this_module, "GEIS_EVENT_DEVICE_AVAILABLE", GEIS_EVENT_DEVICE_AVAILABLE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_DEVICE_UNAVAILABLE", GEIS_EVENT_DEVICE_UNAVAILABLE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_AVAILABLE", GEIS_EVENT_CLASS_AVAILABLE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_CHANGED", GEIS_EVENT_CLASS_CHANGED); PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_UNAVAILABLE", GEIS_EVENT_CLASS_UNAVAILABLE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_BEGIN", GEIS_EVENT_GESTURE_BEGIN); PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_UPDATE", GEIS_EVENT_GESTURE_UPDATE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_END", GEIS_EVENT_GESTURE_END); PyModule_AddIntConstant(this_module, "GEIS_EVENT_INIT_COMPLETE", GEIS_EVENT_INIT_COMPLETE); PyModule_AddIntConstant(this_module, "GEIS_EVENT_USER_DEFINED", GEIS_EVENT_USER_DEFINED); PyModule_AddIntConstant(this_module, "GEIS_EVENT_ERROR", GEIS_EVENT_ERROR); /* Filtery Bits */ PyModule_AddIntConstant(this_module, "GEIS_FILTER_DEVICE", GEIS_FILTER_DEVICE); PyModule_AddIntConstant(this_module, "GEIS_FILTER_CLASS", GEIS_FILTER_CLASS); PyModule_AddIntConstant(this_module, "GEIS_FILTER_REGION", GEIS_FILTER_REGION); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_EQ", GEIS_FILTER_OP_EQ); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_NE", GEIS_FILTER_OP_NE); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_GT", GEIS_FILTER_OP_GT); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_GE", GEIS_FILTER_OP_GE); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_LT", GEIS_FILTER_OP_LT); PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_LE", GEIS_FILTER_OP_LE); return this_module; } geis-2.2.17+16.04.20160126/COPYING.GPL0000644000015600001650000010437412651717544016575 0ustar pbuserpbgroup00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . geis-2.2.17+16.04.20160126/data/0000755000015600001650000000000012651717732016020 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/data/Makefile.am0000644000015600001650000000156612651717544020065 0ustar pbuserpbgroup00000000000000# # @file data/Makefile.am # @brief automake recipe for GEIS assets and other data # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 General Public License # along with this program. If not, see . # pixmapdir = ${datarootdir}/pixmaps dist_pixmap_DATA = geisview32x32.xpm geis-2.2.17+16.04.20160126/data/geisview32x32.xpm0000644000015600001650000003233512651717544021101 0ustar pbuserpbgroup00000000000000/* XPM */ static char * geisview32x32_xpm[] = { "32 32 706 2", " c None", ". c #C6C6CC", "+ c #BCBCBF", "@ c #B7B7BD", "# c #E1E1E3", "$ c #ACACB2", "% c #BAB9C1", "& c #E3E2EB", "* c #E5E5E8", "= c #DBDBD9", "- c #9D9DA5", "; c #111016", "> c #8B8B8A", ", c #DBDBDA", "' c #A6A5AF", ") c #FAFAFB", "! c #D2D2D2", "~ c #E7E7E7", "{ c #6D6069", "] c #96989F", "^ c #C4C7CF", "/ c #B3B5BE", "( c #2B2B34", "_ c #CCCCCC", ": c #D0D0DC", "< c #93929E", "[ c #DEDEE8", "} c #74747B", "| c #B9B9BD", "1 c #DFE0EF", "2 c #9B8387", "3 c #F3C1C0", "4 c #C89595", "5 c #8D6C6C", "6 c #9D7F84", "7 c #878796", "8 c #88878C", "9 c #B0B1BD", "0 c #86858A", "a c #B1B1B3", "b c #E5E3F6", "c c #75747C", "d c #A9A9B6", "e c #D3D4DE", "f c #BD908F", "g c #BE9190", "h c #906A6B", "i c #DEACA9", "j c #AA989E", "k c #DCDFE2", "l c #DCDBE0", "m c #ABACA9", "n c #FFFFFF", "o c #BBBBC5", "p c #8A8995", "q c #89888F", "r c #696875", "s c #686975", "t c #C0C1D5", "u c #83727D", "v c #A29A9F", "w c #DCDFE7", "x c #E5E8EF", "y c #393741", "z c #FAFBFD", "A c #F9F9FD", "B c #AFAFBC", "C c #8F8F98", "D c #8B8B98", "E c #7A7989", "F c #3F3F43", "G c #7E7D8D", "H c #E2E2E7", "I c #FBFCFD", "J c #F7F7FA", "K c #434146", "L c #70646B", "M c #41434B", "N c #000000", "O c #020003", "P c #454546", "Q c #C2C1C4", "R c #62626A", "S c #B5B4C0", "T c #FEFDFD", "U c #E2E5ED", "V c #8B8C98", "W c #4F4B50", "X c #AC8383", "Y c #C59E9D", "Z c #BD9493", "` c #8B6B6C", " . c #B88F8E", ".. c #645A58", "+. c #5F5E5E", "@. c #B8B8B9", "#. c #9B9A9F", "$. c #96979E", "%. c #434441", "&. c #1C1C1F", "*. c #343338", "=. c #2F323D", "-. c #82696B", ";. c #705455", ">. c #5E4B4A", ",. c #9B7B7C", "'. c #917B79", "). c #BF9997", "!. c #81676B", "~. c #DBACAC", "{. c #544443", "]. c #9C9D9C", "^. c #8F8F90", "/. c #D5D5D6", "(. c #777679", "_. c #8A8A8A", ":. c #747474", "<. c #595A5B", "[. c #987474", "}. c #9B7C7C", "|. c #4C3F3F", "1. c #CD9B9B", "2. c #E6B4B4", "3. c #453436", "4. c #E3C2C2", "5. c #FDC3C1", "6. c #FFD6D8", "7. c #544D51", "8. c #6D6F71", "9. c #DADBDF", "0. c #828286", "a. c #C2C2C5", "b. c #444543", "c. c #AAAAAB", "d. c #CECFCF", "e. c #7D7A79", "f. c #322424", "g. c #9C7678", "h. c #FFC4C5", "i. c #FFC9CA", "j. c #B68C8E", "k. c #886666", "l. c #FFDDDD", "m. c #A88282", "n. c #E8C2C1", "o. c #0C090B", "p. c #636366", "q. c #C2C2CB", "r. c #C9C8D3", "s. c #91919A", "t. c #AAAAAE", "u. c #0F0F0F", "v. c #A2A1AB", "w. c #656367", "x. c #A68D8C", "y. c #FFDFDF", "z. c #FBD4D4", "A. c #D1A8A8", "B. c #A28483", "C. c #FFD2D4", "D. c #FAD1D1", "E. c #FFE2E0", "F. c #876E70", "G. c #5B4F54", "H. c #50525D", "I. c #868697", "J. c #F8F8FF", "K. c #767685", "L. c #ABACAF", "M. c #DADADB", "N. c #DDDDDD", "O. c #B2B2B3", "P. c #7F7F82", "Q. c #515150", "R. c #9999A6", "S. c #51535C", "T. c #675352", "U. c #836B6D", "V. c #FFEBEC", "W. c #301F1F", "X. c #EFC7C7", "Y. c #FFDCDC", "Z. c #FFE5E6", "`. c #978886", " + c #E4E6EA", ".+ c #EEEDF0", "++ c #C0BFCF", "@+ c #757785", "#+ c #A7A5B8", "$+ c #9D9AA2", "%+ c #D4D2D5", "&+ c #E9E5E6", "*+ c #DFDDE0", "=+ c #BFB9C7", "-+ c #CBCACC", ";+ c #97959C", ">+ c #99989E", ",+ c #D1D1D2", "'+ c #999999", ")+ c #717185", "!+ c #CFD0DD", "~+ c #5E5E6E", "{+ c #332626", "]+ c #DEACAA", "^+ c #90848C", "/+ c #B8B7BF", "(+ c #2B2B30", "_+ c #464041", ":+ c #534241", "<+ c #4A4B50", "[+ c #FDFEFD", "}+ c #FCFBFC", "|+ c #E3E3E8", "1+ c #A8A5AF", "2+ c #B0B0AF", "3+ c #FFFFFA", "4+ c #FAF5E3", "5+ c #F9F3DC", "6+ c #F9F3DA", "7+ c #F2F1EE", "8+ c #504F55", "9+ c #A8A6A9", "0+ c #D5D5D4", "a+ c #85868F", "b+ c #9D9DA1", "c+ c #ECECF0", "d+ c #FFFEFE", "e+ c #57585D", "f+ c #666677", "g+ c #C1C0D3", "h+ c #545768", "i+ c #E4ABA7", "j+ c #A5A8B3", "k+ c #FCFDFA", "l+ c #2D2C2D", "m+ c #71717D", "n+ c #787A8B", "o+ c #D6D5DC", "p+ c #9F9CA9", "q+ c #BBBCBB", "r+ c #D9D9DA", "s+ c #FEFEFA", "t+ c #FCFAF2", "u+ c #F8F2DB", "v+ c #F7EFD1", "w+ c #FFFDE3", "x+ c #48474B", "y+ c #5C5A61", "z+ c #D5D5D5", "A+ c #707074", "B+ c #D4D4D5", "C+ c #C0C1CD", "D+ c #E3E3FB", "E+ c #D8D8DD", "F+ c #170D31", "G+ c #545361", "H+ c #C2C2DA", "I+ c #5A5A6B", "J+ c #C0A6B2", "K+ c #FDFFFF", "L+ c #FBFAFB", "M+ c #E0E1ED", "N+ c #BDBAC2", "O+ c #9B7A79", "P+ c #FFCACC", "Q+ c #EAB2B0", "R+ c #C39897", "S+ c #E9E5EE", "T+ c #CDCECD", "U+ c #FCFBF6", "V+ c #FDFAF2", "W+ c #FAF7ED", "X+ c #FBF7E6", "Y+ c #ADACB2", "Z+ c #75717A", "`+ c #98979D", " @ c #AEAEAE", ".@ c #ACADAD", "+@ c #E3E4FC", "@@ c #F3F5FF", "#@ c #8570B9", "$@ c #7A5FBC", "%@ c #5C5871", "&@ c #B7B6CC", "*@ c #55535D", "=@ c #A8A7BB", "-@ c #E5E5EC", ";@ c #836E6F", ">@ c #F0C4C2", ",@ c #CA9E9D", "'@ c #291E1F", ")@ c #21242C", "!@ c #3B3C47", "~@ c #838390", "{@ c #F9F7F8", "]@ c #FFFCEE", "^@ c #FBF9EE", "/@ c #FAF8EC", "(@ c #FBF8EE", "_@ c #FAF8ED", ":@ c #FEFCF4", "<@ c #CBC7D4", "[@ c #5E5254", "}@ c #4C4A50", "|@ c #BEBEBE", "1@ c #B3B3B2", "2@ c #9999AC", "3@ c #BABCC8", "4@ c #856BC4", "5@ c #926FE2", "6@ c #8E9098", "7@ c #9190A1", "8@ c #848492", "9@ c #B4B5B9", "0@ c #858592", "a@ c #C1C6C8", "b@ c #EAB0B0", "c@ c #E5B2B2", "d@ c #EEC0BF", "e@ c #C09695", "f@ c #B8918F", "g@ c #999BA4", "h@ c #BFBEC6", "i@ c #F9F3F7", "j@ c #F9F3DD", "k@ c #F8F3DA", "l@ c #FAF7EB", "m@ c #D3D0D6", "n@ c #302826", "o@ c #807272", "p@ c #6B6B6B", "q@ c #E3E3E2", "r@ c #A8A7B0", "s@ c #727381", "t@ c #C4AD3F", "u@ c #7D6A79", "v@ c #775DB4", "w@ c #C2C3D7", "x@ c #7A7A89", "y@ c #5B5B65", "z@ c #B1AFC5", "A@ c #373B42", "B@ c #E0BABB", "C@ c #FCBCBB", "D@ c #E8B1B1", "E@ c #C8A4A1", "F@ c #ECCCCD", "G@ c #51494D", "H@ c #C0C1C5", "I@ c #D3D2D9", "J@ c #9B97A4", "K@ c #FEFCF3", "L@ c #F8F1D0", "M@ c #F8EFCF", "N@ c #F8F2DA", "O@ c #FAF8EF", "P@ c #FAF9F3", "Q@ c #F0EDFA", "R@ c #665A5B", "S@ c #7B6C6C", "T@ c #101111", "U@ c #807F8A", "V@ c #B2B2B6", "W@ c #444544", "X@ c #8A758C", "Y@ c #6A589B", "Z@ c #A180F2", "`@ c #545165", " # c #ABACBE", ".# c #060607", "+# c #7E8288", "@# c #645356", "## c #FFC6C7", "$# c #FBBEBD", "%# c #B0898B", "&# c #E5B5B6", "*# c #816B6B", "=# c #5A585D", "-# c #EFEDEE", ";# c #FEFDFF", "># c #96939F", ",# c #1A1B1E", "'# c #B9B5BD", ")# c #FFFDF3", "!# c #FFFEEC", "~# c #FFFFF5", "{# c #E2D3DE", "]# c #908891", "^# c #978688", "/# c #3C3334", "(# c #5E5D5D", "_# c #76767D", ":# c #EBEAE9", "<# c #715EA0", "[# c #9277C7", "}# c #534766", "|# c #67557F", "1# c #858791", "2# c #332653", "3# c #181229", "4# c #A087E2", "5# c #F3BAB5", "6# c #E0AEAD", "7# c #8B6F70", "8# c #BD9797", "9# c #886968", "0# c #000002", "a# c #FCFDFF", "b# c #FAFAFA", "c# c #FEFEFD", "d# c #484953", "e# c #B1ADB7", "f# c #1F1E20", "g# c #46444D", "h# c #A4A2AE", "i# c #C0ACB2", "j# c #312B2D", "k# c #867778", "l# c #7C7F7E", "m# c #FEFEFE", "n# c #545458", "o# c #1A1032", "p# c #292440", "q# c #685955", "r# c #604C8D", "s# c #828493", "t# c #382761", "u# c #7659BD", "v# c #836591", "w# c #FFCBCA", "x# c #664F51", "y# c #231E21", "z# c #0C0E11", "A# c #838491", "B# c #E9EAFE", "C# c #FDFCFD", "D# c #FFFFFE", "E# c #D4D4D4", "F# c #64636C", "G# c #99939D", "H# c #B1ABB6", "I# c #A8A4B0", "J# c #9E959D", "K# c #D9B9B9", "L# c #110E14", "M# c #010003", "N# c #3F3F3F", "O# c #FDFDFD", "P# c #E1E1E0", "Q# c #C4C5C1", "R# c #664EA3", "S# c #7260A6", "T# c #8F78C6", "U# c #A586F0", "V# c #544189", "W# c #664DA6", "X# c #8D6ADA", "Y# c #7054B4", "Z# c #7B5F83", "`# c #FFD1D0", " $ c #1D1312", ".$ c #2C2C31", "+$ c #B8B6C6", "@$ c #FEFEFB", "#$ c #EBEAEA", "$$ c #909195", "%$ c #50505B", "&$ c #010000", "*$ c #CAADA6", "=$ c #E6CAC7", "-$ c #B6999A", ";$ c #120F14", ">$ c #7557BA", ",$ c #000100", "'$ c #4C4C4C", ")$ c #B1AEB7", "!$ c #3D315A", "~$ c #705E9A", "{$ c #795DBC", "]$ c #644AA1", "^$ c #B390FF", "/$ c #8A69DA", "($ c #4B3A79", "_$ c #694FA5", ":$ c #7E6196", "<$ c #4D3A41", "[$ c #B0B0BD", "}$ c #ECECEE", "|$ c #CAC9CC", "1$ c #CBCBCB", "2$ c #EBECEB", "3$ c #BBB9C7", "4$ c #575171", "5$ c #7959B1", "6$ c #2A2127", "7$ c #926DE3", "8$ c #6951AF", "9$ c #3E3064", "0$ c #1C1431", "a$ c #020009", "b$ c #A3A3A3", "c$ c #43346E", "d$ c #4E436E", "e$ c #5D488B", "f$ c #503B83", "g$ c #B293FF", "h$ c #A585F9", "i$ c #AA88FF", "j$ c #463574", "k$ c #533E82", "l$ c #6D52A7", "m$ c #68529A", "n$ c #757882", "o$ c #FAFAFD", "p$ c #CECED1", "q$ c #78797A", "r$ c #DCDCDB", "s$ c #FDFDFE", "t$ c #E4E5F6", "u$ c #6A648B", "v$ c #AA7CFF", "w$ c #1F1833", "x$ c #513E82", "y$ c #946FF9", "z$ c #7758BF", "A$ c #594391", "B$ c #402E68", "C$ c #362958", "D$ c #848584", "E$ c #7C6F98", "F$ c #AD8CF3", "G$ c #261F38", "H$ c #8463C5", "I$ c #917872", "J$ c #9B85B6", "K$ c #A181FA", "L$ c #B08FFF", "M$ c #4E3982", "N$ c #3C2E61", "O$ c #9878E4", "P$ c #4B3977", "Q$ c #644A9B", "R$ c #71688D", "S$ c #6A6B70", "T$ c #E5E4EA", "U$ c #8D8C92", "V$ c #B9B9BA", "W$ c #EBEBF1", "X$ c #C5C6E0", "Y$ c #62508D", "Z$ c #9473E0", "`$ c #523C82", " % c #7A638D", ".% c #9D885B", "+% c #7A5CC0", "@% c #7558B2", "#% c #553F88", "$% c #7659B9", "%% c #363733", "&% c #7D6EA2", "*% c #423463", "=% c #926EE6", "-% c #8A71BA", ";% c #D7BC16", ">% c #8E7A7F", ",% c #B193FE", "'% c #AC8AFF", ")% c #9C7BE9", "!% c #312551", "~% c #B690FF", "{% c #06050B", "]% c #08070F", "^% c #9C75FC", "/% c #9069EE", "(% c #737283", "_% c #AAAAB1", ":% c #92929B", "<% c #B0B1B6", "[% c #FCFBFD", "}% c #CBCBDB", "|% c #828193", "1% c #A17FF5", "2% c #9772F5", "3% c #6A50AE", "4% c #8D70CB", "5% c #846AC2", "6% c #8065C0", "7% c #9979E8", "8% c #8562EC", "9% c #9A7CE5", "0% c #4A484E", "a% c #847D97", "b% c #A17FF8", "c% c #8A6DDE", "d% c #9F85DE", "e% c #9B80EA", "f% c #A286E0", "g% c #8772A6", "h% c #8C7591", "i% c #AD91FD", "j% c #A47FFF", "k% c #AE90FE", "l% c #513D89", "m% c #6E52AD", "n% c #9E74FF", "o% c #767097", "p% c #9394A4", "q% c #BFBFC6", "r% c #A8A9B2", "s% c #D6D6DE", "t% c #636079", "u% c #9872F6", "v% c #A888FC", "w% c #A483FF", "x% c #8966E2", "y% c #B092FF", "z% c #AC8FFB", "A% c #9E79FF", "B% c #9881E9", "C% c #D5B800", "D% c #9B8096", "E% c #4E3C7C", "F% c #938C9F", "G% c #826872", "H% c #AD9D2F", "I% c #A88AF8", "J% c #AD91FF", "K% c #B695FF", "L% c #857183", "M% c #8E799C", "N% c #B093FF", "O% c #AF92FF", "P% c #AD90FD", "Q% c #AC8BFF", "R% c #9A74F2", "S% c #523F88", "T% c #A47AFF", "U% c #7A6D9E", "V% c #9A99A4", "W% c #908F99", "X% c #A9A9B5", "Y% c #867AA5", "Z% c #534577", "`% c #A078FF", " & c #AF91FF", ".& c #B093FE", "+& c #A180FD", "@& c #AE92FD", "#& c #AE90FD", "$& c #AA8CFC", "%& c #A085E6", "&& c #88757C", "*& c #9D84D9", "=& c #A684FF", "-& c #F2F5EB", ";& c #594198", ">& c #9178D8", ",& c #AC90F7", "'& c #AF92FE", ")& c #AD92FC", "!& c #B497FF", "~& c #B193FF", "{& c #AE93FE", "]& c #B092FD", "^& c #AF92FC", "/& c #AF93FB", "(& c #A280FA", "_& c #9770FB", ":& c #8C69E6", "<& c #ACABBF", "[& c #9A9BA5", "}& c #9B99A9", "|& c #C0C4CE", "1& c #7353BC", "2& c #9F7CFF", "3& c #B094FE", "4& c #AF93FE", "5& c #AD92FD", "6& c #AE91FD", "7& c #AD91FC", "8& c #A685FD", "9& c #AD8CFF", "0& c #9C77FE", "a& c #9B76FC", "b& c #9B76FD", "c& c #9A75FC", "d& c #9A75FD", "e& c #9A74FC", "f& c #9B75FD", "g& c #9974FD", "h& c #9873FE", "i& c #9A73FD", "j& c #956DFB", "k& c #AF9EE8", "l& c #C0C0DA", "m& c #ADA3D4", "n& c #9A73FE", "o& c #9A74FD", "p& c #9974FC", "q& c #9973FC", "r& c #9973FD", "s& c #9872FE", "t& c #9872FD", "u& c #9872FC", "v& c #9871FD", "w& c #9871FC", " ", " . + @ # ", " $ % & * = - ; > ", " , ' ) ! ~ { ] ^ / ( _ : ", " < [ } | 1 2 3 4 5 6 7 8 9 0 ", " a b c d e f g h i j k l m n o p ", " q r s t u v w x y z n A B C D ", " E F G H I n n J K L M N O P N ", " Q R S n n T U V W X Y Z ` ...+.@. ", " #.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^. ", " /.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0. ", " a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s. ", " t.u.v.n w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N. ", " O.P.Q.R.n S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+ ", " ;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+9+ ", " 0+a+b+c+d+e+f+g+h+i+j+n k+n l+N m+n+o+p+q+r+s+t+u+v+w+x+y+z+ ", " A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+N S+T+n U+V+W+4+X+Y+Z+`+ ", " @.@+@@@#@$@%@&@*@=@-@J.;@>@,@'@)@!@~@{@]@^@/@(@_@W+:@<@[@}@|@", " 1@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@u+k@l@(@W+m@n@o@N p@", " q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@n ", " U@V@W@X@Y@Z@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#n ", " _#:#<#[#}#|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#e#f#0#g#h#i#j#k#l#n m#", " n#n o#p#q#r#s#t#u#v#w#x#y#z#A#B#C#D#E#F#N G#H#I#J#K#L#M#N#n O#", "P#Q#R#S#T#U#V#W#X#Y#Z#`# $.$+$n @$m#c##$$$%$&$*$=$-$;$>$,$N '$n ", "n )$!$~${$]$^$/$($_$:$<$[$}$|$m#n 1$m#n 2$3$4$5$6$N 7$8$9$0$a$b$", "n c$d$e$f$g$h$i$j$k$l$N m$n$) o$p$q$r$m#s$t$u$v$w$x$y$z$A$B$C$D$", "E$F$G$H$I$J$K$L$M$N$O$N P$Q$R$S$T$U$V$n W$X$Y$Z$`$ %.%+%@%#%$%%%", "&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%", "a%b%c%d%e%f%g%h%i%j%k%l%N m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%", "F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&", "-&;&>&,&'&)&!&~&@&{&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&@&6&6&P%y%7&8&", "D#9&0&a&b&b&b&c&d&e&d&f&c&g&h&i&j&k&l&m&f&n&o&p&q&r&s&t&u&v&w&o&"}; geis-2.2.17+16.04.20160126/data/logo_x64.png0000644000015600001650000003055412651717544020177 0ustar pbuserpbgroup00000000000000PNG  IHDR@@iq MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGD pHYs..*' tIME "$0 IDATxyT?眚zz陦dV02hLCD^L&F0^cL(QQQPAAfn陞:5/ロ&{֪zߞ~{IKg> W,I(2f8KHtiҲetІʒDzi5 wܽE2 A4]01} ue@Vl !pȀ$`[~.^|UrⓏښAz{{{_d/v@8Q%VX#O^ĊW^YyIf }aVڶ}Xh9^o瑖+ ,??z}}$^X;QUs/>_!\BHa?󮨈)77@LƪjtzVUGBŀͦ#wTF=N]C5?0"$³=Hi8ğU!IHcHiS?n _+IRe߾nMss;cǎ0Oʄg_ KF2GO\B"&zzز3y5&>x$Ia`Lii?K _g].cXZx=IW.(;+jw½W"2%| ^-\QR؉ӈJ,} 騩n#== UλCS $ B7W=)^]I>^{mCA<2^738[uՑhDh[mx?OQninlC')7edJV^zw<,Ӫ?[6VGeJ$s01«|]g;wIAdE ,&1t 18$ $OWKNb⨪:LJ`ލ9Ν;(/?f#Kfe:fVLwgLG*T>#2m[?g8xODF:(-÷~*ڎR RlQNAMM-]m$G27=2"!4@F 3 o~ 0$ 6n 'k$.3r5l(Ng7BB-%E2y d22̾Z qir(whBbxx`|ff%3tzA?GvfRBKynq!U*֭[>$N{$V~S]݈Ūԓ/3kv @E!=SBIFC3ggٸ펅p~qL&#w`tn6c4Xmg?m8󓛗KBBǏWxb ?Mr!;Ⱥw<_u4v Ŏ|R\0Ws7ubKKs)Ʀ0{\/_'rü|22˝z~M΢ f޼kx|c+=7sv׀ĄO055[pKGGykΤIO`do[ѯC#޽בdttQ&NǑ_RQ}SSs~<`!&O~ r|-͌/ddÎ?\wߋ- ݎxӧƍݻW!IJeH 9eZQQӞ?eTn >.gϱSԶ63!oM̂S@L--ol8t:#8$LEz(w`22e:_|$."BkП$-_Šm6>BBB"1QI||,{#:, P5fKA|T=̟2_y'+(5 5 &&΄&)_ϐo΋4pKXmΜi K.iRW꿡)zC|ӧ`p8c̙$H`M yoa嚷~d_rJ(B ڻzNc߽#U͛[e\N'{ubqDwoGFB~$fSҊ @oA`dz٢9YYKj̊'X(͇`IW;1MTfi^DEEiG|M;D#T EFoY_Q2*MX4M 4 Ig?"cEFA""l:Go}n߁&dmBA@,Z$)KN `͚l6;?~KNk͎<؏J(f#Xl9%q:݌(ʧY98uTr1t:j&^11ȰD f`0Õ#צS6dhiqǎ/0R^~I¢|b0dZ\Ȗ{/tUc@H:ImsNWPaGd4>ܸ߯XDDDv3qL43gN|EbccOD fu%Z}*aFqYDsa=f9*v#imk",‚ ظqs7]Q}pV7MΆgb?Ğ_e!4G"yz햛[ ;9Sy_2!y^Gmd2w7;H׋P}$)z7N;W~Y3f܃?He/[`IֽB)^|>2fۼkj`/38ƏmDuͧdtn ub [| cHHv%%E+zxKQn!|BE ъke)$'[n9#?zDz:h˖=Mg$<^'&}8w:D8LA</af HJoƻ~ L*0yR 7o_VIin飷^emml@Vhz%BE~!h^~CDEE3C7B 1Qp% K܈^F#'%]mX\1Պh2cg#x=pDTBIvve᧗>~zn/I,}BKӭ;v,i"i*tT#I#ee%|u3Sƞ/3nK#8!_s_裨0‚9S :2'NWpgEdY^znb3+Ah`PPOWS_Su's//_yh x%f_3¬\foyy`4P} (f1֝\{WL2̘>` $ ``x-Rd$I Ȓ b#yO74nl_VNrr<py@ 2Rb 6璒`C(2x܃tu`-)X8 YOW5 f61lp/(:o} փyBMSNFDDD8 v@A| OM>e4DȦ@Rd$Yk!ּE}իwqځV]]=8iHCrJIՂ? 䍸ÍQuNMd"II=ǸqHJM k^F)ma7 pKM&=N"FP0f2ukX{aZlA x B#4|$ P@ K;DLI u;/Hӧ TU|} &-Gb /m<QpI0[EgW3Z:wQ~032e`hBWMMɻf׫XoKӹHϢ /4"B @AG Ph<\qr`! :"U $Kz$$izp8]^}&lq䦍icrL8QQAkk=$rL5[ijkClgԙh>z5љS$v:܇:Z^[/(3 z$# BDhChA !ԯ<ƖfRsa4HKlv{1!Ng&>!ӕػ{?7NAbfZ:hAz/O$ 22k$> 0ZS{ LJNèC5KmN ;gqxtfz. @@ZH7q$9D@`24$Ɩs4y9ڵkILLG=v(6nΕgo gt'xmGDe*DTdgr̹t\`zj"!c6[d Mf472uudWRkg1jT^h19v{{1e7 [XEP`zdوcMBlBo 7#}&N]I[w}d6EBWw tubd߼1@~t&(ɜ/o2eL~?/;bc#$/]ݜ>˵ǑJ N[D$M"Eo\i*+Os| BJB,<JffW]3e0ڲ1uPܣ*"23ͪ$Q1Ke?2oCCb4 Z -utu،+8|j3'ꥡl**򇗟#cD28+o57ԬC``ID"Vj=#_RTO/{>̷o9s\Vr.W?3gb~ (AP/|MNo$$95ooq]*{ ~F&C0jO?54D[EVg[Mݷ|dcO(@WMWO//#F{_LbB e3clJKK""JLRr]=N6oZOqN&kjpx!u7[bmŘPeB!QS]C`h >۱y7^8TqDžNQP TZi;UsftOrÇqi CE6 6!YViq>ZV>Gn_őx) fN`q${hl;BC&`ֹ+aU6_q-M̚ygNx], Gb0!C >':&C4}ߚ393Ϗ?0E'0H*##[Y뜪 s Auu5 ,`֭ddd\eٲ'dYdrW0}L*c fNALrKnΖ>, w7y#+CnJzGy-tӷ7v>0LLPq8EMgw')T$5%FտGk[=&1k$b,~rƍ7L~#UkȲLww7nft˖- +wnUhGvrY 5>- <'1`ft6x`6Q}]@"/{9Jr~rSkcӍCK`(TY{Q[88yy ]&L.5 Fkpo>t˖fHBGjޠ=k'Ead X:ZwlX7،vv@>E4j~4΢/c⌙z~FQy*rBB3{\hlEɳ)7_",އoiE,ZC^d̝#>$Q\uٳzkע:5DI}w8y}8t;[7ɾg\xWDgg)hg 7Glg(%!2ױX9n2(((a̙3ň#" e\Btnݻ8e2s\\<0;nRF?s?ƙƣ|'Y+ oaԠܔ|a`9Եs:::Bip471ce:x]^{ʲ`hB# }D ɇ_1Tj +=ʞ݇(**j~JO?ӧ+db`Ib`A~ZW,@p?`D1ΎIg 'ʞETX E}5{w_=a6{ 4} 61Eq JP3PP#2<`MH#_Ѕ:b==I<(JLL55_$K zx|zmF>/ѶlU9vn#ҜXL&εVl 08;r1(ʘN6r!߇p?|E||c gfDN=EYwyZtLM@ j  x1 -m"5"}hW6kV|K~~N/II4^hϧ=]nikǢ G)ɸQ3(q F-ubF3(aGH#5A$3wW+nʒ(ͼGNzoxQ̫taLQ&`ӎ 5;Sټ#!y"i;kbSDDFroArR:Ca0A FGG+M tID $'e*bofƴwx+6S6V!71㑀(G"ax&(̹?]ZZ S3RIDATy6EKX01E1BC,V3V$$DPab-DDzhY[cpw"4)˺)%WgS9r KKÁߧa0h(22=}C:D'"1Eo&>28PE&nO;[($OBS8c6k}'|t;#oY`uE9|x{̡(7hBF JeL$*DK{;6S8%W"vsh${!)yLih?5B0tRXOsS#hjѓ q$}w{^-B08 cEnGhn!و}Ύ> s' !0`ɣrpH >b b&:*s>g.6 8{>LW\;\](  nLp} hBE(HDf7$7YCMN(BKXN c15#T|*9ILՅ!.n3T? yWn:#1$P [q$9BB\ 11(F 1JsJR|NNP 34$lLTU$AOIw!Iz$Y2Zm֝97pF*n-gמψ": MR0GA$0c1b$ UaWOX N>'K%}ȀO܆ק_%)soaM &EVQdJd$ґQC$@4 ^#"FOqet aT„Q fn#{x ]mnQ!i:@`#ˡg 1%4P *a6 BD<5Er >+ߝ4]mm~Y4{;Iq=M3KBL s(Jtws{$S::EB $l7Axx\gP׺Ԅ2NSXRDks#11l߾17b6iFa~1əq|Wƣ%J2bK9Bf4-$5e)q$ M0?2^DGF?ra Ip|p-=?cI ˳WdA/ bdF\!&[o_Bg0N\61nx4ix?^J $Uw/CZPHB+!i: Im '鰄bЄ@_$ Ӱ.?o,H}$`P_-" Z7*gE~~1fϷ@n)8L֐dP;/ ab?kx_{50[dNhtKdEA4?5t}3\A  aZ,'>U'FZ֟NAlXT4IBU%*@X8dD(.jI.%4PU)j IENDB`geis-2.2.17+16.04.20160126/INSTALL0000644000015600001650000003660512651717544016153 0ustar pbuserpbgroup00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. geis-2.2.17+16.04.20160126/configure.ac0000644000015600001650000001162712651717544017405 0ustar pbuserpbgroup00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # # # Copyright 2010, 2011, 2012, 2013 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # AC_PREREQ(2.65) AC_INIT([geis], [2.2.17], [stephen.webb@canonical.com],, [https://launchpad.net/geis]) AC_CONFIG_HEADERS([geis_config.h]) AC_CONFIG_AUX_DIR([config.aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.11 gnu -Wall color-tests dist-xz]) AM_SILENT_RULES([yes]) # Checks for programs. AM_PROG_CC_C_O AC_PROG_CXX AM_PROG_AR AM_PATH_PYTHON([3.2]) LT_PREREQ([2.2.6b]) LT_INIT # Checks for libraries. PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16], , AC_MSG_ERROR([D-Bus development libraries not found])) PKG_CHECK_MODULES([GRAIL], [grail >= 3.0.8 frame >= 2.2], , AC_MSG_ERROR([Grail development libraries not found])) PKG_CHECK_MODULES([XCB], [xcb >= 1.6], , AC_MSG_ERROR([XCB development libraries not found])) PKG_CHECK_MODULES([XI2], [x11 xext xi >= 1.3], , AC_MSG_ERROR([XI2 development libraries not found])) PKG_CHECK_MODULES([PYTHON], [python3 >= 3.2]) AX_ENABLE_XI2 # Check toolchain features AC_MSG_CHECKING([whether hidden visibility is supported]) geis_hidden=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ void __attribute__((visibility ("hidden"))) bar (void) {}])], [geis_hidden=yes]) AC_MSG_RESULT($geis_hidden) if test x$geis_hidden = xyes; then AC_DEFINE([GEIS_DSO_PRIVATE],[1],[symbol visibility is supported]) fi AC_DEFINE([GEIS_UNUSED],[__attribute__((unused))],[symbol is unused]) AC_SUBST(AM_CFLAGS, "-Wall -Wextra -Werror -pedantic -std=iso9899:1999 -D_GNU_SOURCE=1") # Check for TDD tools PKG_CHECK_MODULES([CHECK], [check >= 0.9.8], [have_check=yes], AC_MSG_WARN([package 'check' not found: related unit testing disabled])) AM_CONDITIONAL([HAVE_CHECK],[test "x$have_check" = xyes]) # Optionally build the integration test suite. AC_ARG_ENABLE([integration-tests], [AS_HELP_STRING([--enable-integration-tests], [Enable building integration test cases (default: auto)])], [enable_integration_tests=$enableval], [enable_integration_tests=auto]) # Check for Google C++ Testing Framework have_xorg_gtest=no AS_IF([test "x$enable_integration_tests" != xno], [CHECK_XORG_GTEST( [AC_SUBST(XORG_GTEST_LIBS, [-pthread])], [AS_IF([test "x$enable_integration_tests" = xyes], [AC_MSG_ERROR( [xorg-gtest is not available])], [AC_MSG_WARN( [xorg-gtest is not available, tests will not be built])])])]) AM_CONDITIONAL([HAVE_GTEST], [test "x$have_gtest" = xyes]) AM_CONDITIONAL([ENABLE_INTEGRATION_TESTS], [test "x$have_xorg_gtest" = xyes]) AC_CONFIG_FILES([Makefile libgeis.pc doc/Makefile include/Makefile libs/Makefile libs/geis-util/Makefile libs/geis-dbus/Makefile libgeis/Makefile libgeis/backend/Makefile libgeis/backend/test_fixture/Makefile libgeis/backend/dbus/Makefile libgeis/backend/grail/Makefile libgeis/server/Makefile testsuite/Makefile testsuite/gtest/Makefile testsuite/geis-util/Makefile testsuite/libgeis/Makefile testsuite/geis2/Makefile testsuite/geis1/Makefile testsuite/geistest/Makefile testsuite/x11_mocks/Makefile examples/Makefile python/Makefile tools/Makefile tools/geisview/Makefile tools/geis-server/Makefile data/Makefile]) AC_OUTPUT bold_green=$(tput bold)$(tput setf 2) bold_white=$(tput bold)$(tput setf 7) reset=$(tput sgr0) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ ${bold_green}geis $VERSION${reset}]) AC_MSG_NOTICE([ ===============================]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ prefix : ${bold_white}${prefix}${reset}]) AC_MSG_NOTICE([ integration tests : ${bold_white}${have_xorg_gtest}${reset}]) AC_MSG_NOTICE([]) geis-2.2.17+16.04.20160126/NEWS0000644000015600001650000000331312651717544015607 0ustar pbuserpbgroup00000000000000geis NEWS -- a history of user-visible changes Copyright 2010, 2011 Canonical Ltd. * Changes in v2.0.0 ** Introduction of the GEIS v2.0 API 2012-03-14 Stephen M. Webb Fix FTBFS in the daily PPA due to a bug in libdbus. 2012-03-13 Stephen M. Webb Added working gesture reject and accept (lp: #934207). 2012-03-07 Stephen M. Webb Propagate window grab errors up the stack (lp: #937021). 2012-03-06 Stephen M. Webb fixed FTBFS dues to missing CPPFLAGS in testsuite 2012-03-06 Jussi Pakkanen Merged compile+link tests. 2012-03-05 Stephen M. Webb Added gtest infrastructure and test. 2012-02-28 Daniel d'Andrada Some small documentation improvements. 2012-02-24 Daniel d'Andrada grail_backend: Properly activate a subscription that has no filters. It should get all gesture events. 2012-02-23 Stephen M. Webb Adds blocking mode for geis_new() (lp: #921633). - Added GEIS_INIT_SYNCHRONOUS_START initializer - modified geistest and pygeis tools to use it 2012-02-22 Daniel d'Andrada Some small improvements to geis.h documentation here and there. 2012-02-22 Stephen M. Webb Restore previous search path for API documentation (lp: #934160). 2012-02-21 Stephen M. Webb Restore previous search path for API documentation (lp: #934160). 2012-02-16 Stephen M. Webb bumped version to 2.2.5 geis-2.2.17+16.04.20160126/libgeis/0000755000015600001650000000000012651717732016525 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/geis_event.h0000644000015600001650000000256312651717544021035 0ustar pbuserpbgroup00000000000000/** * @file geis_event.c * @brief Internal interface of the GeisEvent module * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_EVENT_H_ #define GEIS_EVENT_H_ #include "geis/geis.h" /** * Creates a new, empty event of type @p type. * * @param[in] type The type of the event. */ GeisEvent geis_event_new(GeisEventType type); /** * Overrides the type of the event. * * @param[in] event The event. * @param[in] type The type of the event. */ void geis_event_override_type(GeisEvent event, GeisEventType type); /** * Adds an attr to an event. * * @param[in] event The event. * @param[in] attr The attr. */ GeisStatus geis_event_add_attr(GeisEvent event, GeisAttr attr); #endif /* GEIS_EVENT_H_ */ geis-2.2.17+16.04.20160126/libgeis/server/0000755000015600001650000000000012651717732020033 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_server.h0000644000015600001650000000413112651717544023536 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_server.h * @brief Interface for the GEIS DBus server. * * The GEIS DBus server offers remote GEIS functionality over a set of managed * DBus connections. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_SERVER_H_ #define GEIS_DBUS_SERVER_H_ #include "geis/geis.h" #include "geis_dbus_dispatcher.h" typedef struct GeisDBusServer *GeisDBusServer; typedef struct GeisDBusClientProxy *GeisDBusClientProxy; /** * Creates a new %GeisDBusServer object. */ GeisDBusServer geis_dbus_server_new(Geis geis); /** * Destroys a %GeisDBusServer. * * @param[in] server A GeisDBusServer. */ void geis_dbus_server_delete(GeisDBusServer server); /** * Gets the address of a %GeisDBusServer. * * @param[in] server A GeisDBusServer. */ char * geis_dbus_server_address(GeisDBusServer server); /** * Gets the server dispatcher. * * @param[in] server A GeisDBusServer. */ GeisDBusDispatcher geis_dbus_server_dispatcher(GeisDBusServer server); /** * Gets the server geis instance. * * @param[in] server A %GeisDBusServer. */ Geis geis_dbus_server_geis(GeisDBusServer server); /** * Shuts down and disconnects a client. * * @param[in] server A %GeisDBusServer. * @param[in] proxy A %GeisDBusClientProxy. */ void geis_dbus_server_client_disconnect(GeisDBusServer server, GeisDBusClientProxy proxy); #endif /* GEIS_DBUS_SERVER_H_ */ geis-2.2.17+16.04.20160126/libgeis/server/Makefile.am0000644000015600001650000000261212651717544022071 0ustar pbuserpbgroup00000000000000# # @file libgeis/server/Makefile.am # @brief automake recipe for the GEIS v2.0 DBus Server # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # noinst_LTLIBRARIES = libgeis-dbus-server.la libgeis_dbus_server_la_SOURCES = \ geis_dbus_announcer.h geis_dbus_announcer.c \ geis_dbus_client_proxy.h geis_dbus_client_proxy.c \ geis_dbus_proxy_box.h geis_dbus_proxy_box.c \ geis_dbus_server.h geis_dbus_server.c libgeis_dbus_server_la_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libs/geis-dbus \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/libs/geis-util \ $(DBUS_CFLAGS) libgeis_dbus_server_la_LIBADD = \ $(DBUS_LIBS) geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_client_proxy.h0000644000015600001650000000327712651717544024761 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_client_proxy.h * @brief Interface for the GEIS DBus client proxy. * * The GEIS DBus client proxy provides client_proxy-side handling of client * requests. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_CLIENT_PROXY_H_ #define GEIS_DBUS_CLIENT_PROXY_H_ #include "geis/geis.h" #include "geis_dbus_dispatcher.h" #include "geis_dbus_server.h" /** * Creates a new %GeisDBusClientProxy object. */ GeisDBusClientProxy geis_dbus_client_proxy_new(GeisDBusServer server, DBusConnection *connection); /** * Destroys a %GeisDBusClientProxy. * * @param[in] client_proxy A %GeisDBusClientProxy. */ void geis_dbus_client_proxy_delete(GeisDBusClientProxy client_proxy); /** * Handles a GEIS event. * * @param[in] client_proxy A %GeisDBusClientProxy. * @param[in] event A %GeisEvent. */ void geis_dbus_client_proxy_handle_geis_event(GeisDBusClientProxy client_proxy, GeisEvent event); #endif /* GEIS_DBUS_CLIENT_PROXY_H_ */ geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_proxy_box.c0000644000015600001650000000760412651717544024264 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_proxy_box.c * @brief Implementation of a storage facility for GEIS DBus server client * proxies. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_proxy_box.h" #include #include "geis_logging.h" typedef struct GeisDBusProxyBoxNode *GeisDBusProxyBoxNode; struct GeisDBusProxyBoxNode { GeisDBusClientProxy proxy; GeisDBusProxyBoxNode next; }; /** * The box is represented using a circular linked list with a free pool. */ struct GeisDBusProxyBox { GeisDBusProxyBoxNode head; GeisDBusProxyBoxNode avail; }; /* * Constructs a %GeisDBusProxyBox. */ GeisDBusProxyBox geis_dbus_proxy_box_new() { GeisDBusProxyBox box = calloc(1, sizeof(struct GeisDBusProxyBox)); if (!box) { geis_error("error allocating GeisDBusProxyBox"); } return box; } /* * Destroys a %GeisDBusProxyBox. * * Assumes all contained client proxies have already been freed, otherwise there * will be resource leaks because this container does not know how to free them. */ void geis_dbus_proxy_box_delete(GeisDBusProxyBox box) { GeisDBusProxyBoxNode p = box->avail; while (p) { box->avail = p->next; free(p); p = box->avail; } free(box); } /* * Inserts a %GeisDBusClientProxy in to a %GeisDBusProxyBox. */ void geis_dbus_proxy_box_insert(GeisDBusProxyBox box, GeisDBusClientProxy proxy) { if (box->avail == NULL) { box->avail = calloc(1, sizeof(struct GeisDBusProxyBoxNode)); if (!box->avail) { geis_error("error allocating proxy box node"); return; } } GeisDBusProxyBoxNode p = box->avail; p->proxy = proxy; box->avail = p->next; if (box->head == NULL) { box->head = p; } else { p->next = box->head->next; } box->head->next = p; } /* * Removes a %GeisDBusClientProxy from a %GeisDBusProxyBox. */ void geis_dbus_proxy_box_remove(GeisDBusProxyBox box, GeisDBusClientProxy proxy) { assert(box->head != NULL); GeisDBusProxyBoxNode ptr = box->head; GeisDBusProxyBoxNode p = box->head->next; do { if (p->proxy == proxy) { if (ptr == p) { box->head = NULL; } else { ptr->next = p->next; if (box->head == p) box->head = ptr; } p->next = box->avail; box->avail = p; break; } ptr = ptr->next; p = p->next; } while (ptr != box->head); } /* * Gets an iterator initialized to the first client proxy in a box. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_begin(GeisDBusProxyBox box) { if (box->head) return box->head->next; return box->head; } /* * Gets an iterator initialized to one-past-the-end of a client proxy box. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_end(GeisDBusProxyBox box GEIS_UNUSED) { return NULL; } /* * Gets the current client proxy from a client proxy box iterator. */ GeisDBusClientProxy geis_dbus_proxy_box_iter_value(GeisDBusProxyBoxIterator iter) { return iter->proxy; } /* * Advances a client proxy box iterator. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_iter_next(GeisDBusProxyBox box, GeisDBusProxyBoxIterator iter) { if (iter == box->head) return geis_dbus_proxy_box_end(box); else return iter->next; } geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_announcer.h0000644000015600001650000000272612651717544024230 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_announcer.h * @brief Interface for the GEIS DBus announcer. * * The GEIS DBus announcer makes the location of the GEIS DBus server available * over the DBus session bus. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_ANNOUNCER_H_ #define GEIS_DBUS_ANNOUNCER_H_ #include "geis/geis.h" #include "geis_dbus_server.h" typedef struct GeisDBusAnnouncer *GeisDBusAnnouncer; /** * Creates a new GeisDBusAnouncer object. * * @param[in] server The GEIS DBus server to announce. */ GeisDBusAnnouncer geis_dbus_announcer_new(GeisDBusServer server); /** * Destroys a %GeisDBusAnnouncer object. * * @param[in] announcer A GeisDBusAnnouncer. */ void geis_dbus_announcer_delete(GeisDBusAnnouncer announcer); #endif /* GEIS_DBUS_ANNOUNCER_H_ */ geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_client_proxy.c0000644000015600001650000003432212651717544024747 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_client_proxy.c * @brief Implementation of the GEIS DBus client proxy. * */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_client_proxy.h" #include "geis_dbus.h" #include "geis_dbus_class.h" #include "geis_dbus_device.h" #include "geis_dbus_gesture_event.h" #include "geis_dbus_region.h" #include "geis_dbus_subscription.h" #include "geis_device.h" #include "geis_filter.h" #include "geis_logging.h" #include "geis_private.h" #include struct GeisDBusClientProxy { GeisDBusServer server; DBusConnection *connection; GeisSubBag subscriptions; }; /** * Allocates a client proxy from a memory pool. * * This is a customization point for future refinement of object allocation. * * @returns an allocated GeisDBusClientProxy object or NULL on allocation * failure. */ GeisDBusClientProxy _client_proxy_allocate() { GeisDBusClientProxy proxy = calloc(1, sizeof(struct GeisDBusClientProxy)); return proxy; } /** * Deallocates a client proxy object, returning its memory to a pool. * * @param[in] proxy The %GeisDBusClientProxy to deallocate. * * This is a customization point for future refinement of object allocation. */ void _client_proxy_deallocate(GeisDBusClientProxy proxy) { free(proxy); } /** * Handles subscription creation requests. * * @param[in] proxy A %GeisDBusClientProxy. * @param[in] message The DBus message from the proxied client. */ static DBusMessage * _client_proxy_subscribe(GeisDBusClientProxy proxy, DBusMessage *message) { Geis geis = geis_dbus_server_geis(proxy->server); GeisSubscription sub; DBusMessage *reply; sub = geis_dbus_subscription_from_create_call_message(geis, message); if (!sub) { reply = dbus_message_new_error(message, GEIS_DBUS_ERROR_SUBSCRIPTION_FAIL, "error creating proxy from DBus message"); goto final_exit; } geis_subscription_bag_insert(proxy->subscriptions, sub); if (GEIS_STATUS_SUCCESS != geis_subscription_activate(sub)) { reply = dbus_message_new_error(message, GEIS_DBUS_ERROR_SUBSCRIPTION_FAIL, "error activating proxy subscription"); goto final_exit; } reply = geis_dbus_subscription_create_return_message(message, sub); final_exit: return reply; } /** * Handles subscription activation requests. * * @param[in] proxy A %GeisDBusClientProxy. * @param[in] message The DBus message from the proxied client. * * @returns a DBus reply message to send. * * @todo Implement subscription retrieval. */ static DBusMessage * _client_proxy_activate(GeisDBusClientProxy proxy GEIS_UNUSED, DBusMessage *message) { GeisSubscription sub = NULL; DBusMessage *reply; reply = geis_dbus_subscription_activate_return_message(message, sub); return reply; } /** * Handles subscription deactivation requests. * * @param[in] proxy A %GeisDBusClientProxy. * @param[in] message The DBus message from the proxied client. * * @returns a DBus reply message to send. * * @todo Implement subscription retrieval. */ static DBusMessage * _client_proxy_deactivate(GeisDBusClientProxy proxy GEIS_UNUSED, DBusMessage *message) { GeisSubscription sub = NULL; DBusMessage *reply; reply = geis_dbus_subscription_deactivate_return_message(message, sub); return reply; } /** * Handles subscription destroy requests. * * @param[in] proxy A %GeisDBusClientProxy. * @param[in] message The DBus message from the proxied client. * * @returns a DBus reply message to send. * * @todo Implement this function. */ static DBusMessage * _client_proxy_unsubscribe(GeisDBusClientProxy proxy GEIS_UNUSED, DBusMessage *message) { dbus_int32_t server_sub_id; dbus_message_get_args(message, NULL, DBUS_TYPE_INT32 , &server_sub_id, DBUS_TYPE_INVALID); GeisSubscription sub = geis_subscription_bag_find(proxy->subscriptions, server_sub_id); geis_subscription_deactivate(sub); geis_subscription_bag_remove(proxy->subscriptions, sub); geis_subscription_delete(sub); DBusMessage *reply = geis_dbus_subscription_destroy_return_message(message); return reply; } /** * The DBus message dispatch function for the client proxy. * * @param[in] connection The %GeisDBusClientProxy DBus connection. * @param[in] message The DBus message received. * @param[in] user_data The %GeisDBusClientProxy. */ static DBusHandlerResult _client_proxy_message_handler(DBusConnection *connection, DBusMessage *message, void *user_data) { DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; GeisDBusClientProxy proxy = (GeisDBusClientProxy)user_data; if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) { geis_dbus_server_client_disconnect(proxy->server, proxy); result = DBUS_HANDLER_RESULT_HANDLED; } else if (geis_dbus_message_is_subscription_create_call(message)) { DBusMessage *reply = _client_proxy_subscribe(proxy, message); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); result = DBUS_HANDLER_RESULT_HANDLED; } else if (geis_dbus_message_is_subscription_activate_call(message)) { DBusMessage *reply = _client_proxy_activate(proxy, message); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); result = DBUS_HANDLER_RESULT_HANDLED; } else if (geis_dbus_message_is_subscription_deactivate_call(message)) { DBusMessage *reply = _client_proxy_deactivate(proxy, message); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); result = DBUS_HANDLER_RESULT_HANDLED; } else if (geis_dbus_message_is_subscription_destroy_call(message)) { DBusMessage *reply = _client_proxy_unsubscribe(proxy, message); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); result = DBUS_HANDLER_RESULT_HANDLED; } else if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(message)) { const char *s = NULL; dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); geis_error("error %s: %s", dbus_message_get_error_name(message), s); } else { geis_warning("unhandled DBus %s received:", dbus_message_type_to_string(dbus_message_get_type(message))); geis_warning(" signature=\"%s\"", dbus_message_get_signature(message)); geis_warning(" sender=\"%s\"", dbus_message_get_sender(message)); geis_warning(" path=\"%s\"", dbus_message_get_path(message) ? dbus_message_get_path(message) : "(no path)"); geis_warning(" interface=\"%s\"", dbus_message_get_interface(message) ? dbus_message_get_interface(message) : "(no interface)"); geis_warning(" member=\"%s\"", dbus_message_get_member(message) ? dbus_message_get_member(message) : "(no member)"); } return result; } /** * Reports all currently-known gesture-capable input devices to the proxied * client. * * @param[in] proxy A %GeisDBusClientProxy. */ static void _client_proxy_report_devices(GeisDBusClientProxy proxy) { GeisDeviceBag devices = geis_devices(geis_dbus_server_geis(proxy->server)); for (GeisSize i = 0; i < geis_device_bag_count(devices); ++i) { GeisDevice device = geis_device_bag_device(devices, i); DBusMessage *message = geis_dbus_device_available_message_from_device(device); dbus_connection_send(proxy->connection, message, NULL); dbus_message_unref(message); } } /** * Reports all currently-known gesture classes to the proxied client. * * @param[in] proxy A %GeisDBusClientProxy. */ static void _client_proxy_report_classes(GeisDBusClientProxy proxy) { GeisGestureClassBag classes; classes = geis_gesture_classes(geis_dbus_server_geis(proxy->server)); for (GeisSize i = 0; i < geis_gesture_class_bag_count(classes); ++i) { GeisGestureClass gesture_class; DBusMessage *message; gesture_class = geis_gesture_class_bag_gesture_class(classes, i); message = geis_dbus_class_available_message_from_class(gesture_class); dbus_connection_send(proxy->connection, message, NULL); dbus_message_unref(message); } } /** * Reports all currently-known regions to the proxied client. * * @param[in] proxy A %GeisDBusClientProxy. * * OK, in reality, this just sends the valid and available filterable region * attributes. Go wild. */ static void _client_proxy_report_regions(GeisDBusClientProxy proxy GEIS_UNUSED) { Geis geis = geis_dbus_server_geis(proxy->server); GeisFilterableAttributeBagIter it = geis_region_filter_attrs_begin(geis); while (it != geis_region_filter_attrs_end(geis)) { DBusMessage *message = geis_dbus_region_available_message_from_region(&*it); dbus_connection_send(proxy->connection, message, NULL); dbus_message_unref(message); it = geis_region_filter_attrs_next(geis, it); } } /** * Adds the client proxy watches to the dispatcher watch list. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static dbus_bool_t _client_proxy_add_watch(DBusWatch *watch, void *data) { dbus_bool_t status = TRUE; GeisDBusClientProxy proxy = (GeisDBusClientProxy)data; geis_dbus_dispatcher_register(geis_dbus_server_dispatcher(proxy->server), proxy->connection, watch); return status; } /** * Toggles the enabled/disabled status of the client proxy watches. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static void _client_proxy_toggle_watch(DBusWatch *watch, void *data) { GeisDBusClientProxy proxy = (GeisDBusClientProxy)data; geis_dbus_dispatcher_toggle_watch(geis_dbus_server_dispatcher(proxy->server), watch); } /** * Removes the client proxy watches from the dispatcher watch list. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static void _client_proxy_remove_watch(DBusWatch *watch, void *data) { GeisDBusClientProxy proxy = (GeisDBusClientProxy)data; geis_dbus_dispatcher_unregister(geis_dbus_server_dispatcher(proxy->server), watch); } /* * Creates a new %GeisDBusClientProxy object. */ GeisDBusClientProxy geis_dbus_client_proxy_new(GeisDBusServer server, DBusConnection *connection) { GeisDBusClientProxy proxy = _client_proxy_allocate(); if (!proxy) { geis_error("error allocating client proxy"); goto final_exit; } proxy->server = server; proxy->connection = dbus_connection_ref(connection); proxy->subscriptions = geis_subscription_bag_new(2); if (!proxy->subscriptions) { dbus_connection_unref(proxy->connection); goto final_exit; } /* Don't shut down the app on disconnect, that would be unmutual. */ dbus_connection_set_exit_on_disconnect(proxy->connection, FALSE); /* Integrate with the app event loop via the GEIS multiplexor. */ dbus_connection_set_watch_functions(proxy->connection, _client_proxy_add_watch, _client_proxy_remove_watch, _client_proxy_toggle_watch, proxy, 0); /* Install a handler for any and all messages. */ dbus_connection_add_filter(proxy->connection, _client_proxy_message_handler, proxy, 0); /* Kick off reporting devices and classes. */ _client_proxy_report_devices(proxy); _client_proxy_report_classes(proxy); _client_proxy_report_regions(proxy); /* Tell the remote end it's a go. */ DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_INIT_COMPLETE); dbus_connection_send(proxy->connection, message, NULL); dbus_message_unref(message); final_exit: return proxy; } /* * Destroys a %GeisDBusClientProxy. */ void geis_dbus_client_proxy_delete(GeisDBusClientProxy proxy) { geis_subscription_bag_delete(proxy->subscriptions); dbus_connection_unref(proxy->connection); _client_proxy_deallocate(proxy); } /* * Handles a GEIS event. * * GEIS events are generally gesture events. Don;t be fooled, though, there may * be others and this function is incomplete. * * @todo Refine this function to handle non-gesture events. */ void geis_dbus_client_proxy_handle_geis_event(GeisDBusClientProxy proxy, GeisEvent event) { for (GeisSubBagIterator sit = geis_subscription_bag_begin(proxy->subscriptions); sit != geis_subscription_bag_end(proxy->subscriptions); sit = geis_subscription_bag_iterator_next(proxy->subscriptions, sit)) { for (GeisFilterIterator fit = geis_subscription_filter_begin(*sit); fit != geis_subscription_filter_end(*sit); fit = geis_subscription_filter_next(*sit, fit)) { if (geis_filter_pass_event(*fit, event)) { DBusMessage *message; message = geis_dbus_gesture_event_message_from_geis_event(event); dbus_connection_send(proxy->connection, message, NULL); dbus_message_unref(message); } } } } geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_server.c0000644000015600001650000001627112651717544023541 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_server.h * @brief Interface for the GEIS DBus server. * * The GEIS DBus server offers remote GEIS functionality over a set of managed * DBus connections. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_server.h" #include "geis_dbus_announcer.h" #include "geis_dbus_client_proxy.h" #include "geis_dbus_dispatcher.h" #include "geis_dbus_proxy_box.h" #include "geis_logging.h" #include struct GeisDBusServer { Geis geis; DBusServer *dbus_server; GeisDBusDispatcher dispatcher; GeisDBusAnnouncer announcer; GeisDBusProxyBox proxy_box; }; static void _new_geis_dbus_client_connection(DBusServer *server GEIS_UNUSED, DBusConnection *new_connection, void *data) { GeisDBusServer geis_server = (GeisDBusServer)data; GeisDBusClientProxy proxy = geis_dbus_client_proxy_new(geis_server, new_connection); if (proxy) { geis_dbus_proxy_box_insert(geis_server->proxy_box, proxy); } } /* * Shuts down and disconnects a client. */ void geis_dbus_server_client_disconnect(GeisDBusServer geis_server, GeisDBusClientProxy proxy) { geis_dbus_proxy_box_remove(geis_server->proxy_box, proxy); geis_dbus_client_proxy_delete(proxy); } /* * Processes GEIS events. */ static void _geis_event_callback(Geis geis GEIS_UNUSED, GeisEvent event, GeisPointer context) { GeisDBusServer server = (GeisDBusServer)context; for (GeisDBusProxyBoxIterator it = geis_dbus_proxy_box_begin(server->proxy_box); it != geis_dbus_proxy_box_end(server->proxy_box); it = geis_dbus_proxy_box_iter_next(server->proxy_box, it)) { GeisDBusClientProxy proxy = geis_dbus_proxy_box_iter_value(it); geis_dbus_client_proxy_handle_geis_event(proxy, event); } geis_event_delete(event); } /* * Adds the announcer watches to the dispatcher watch list. */ static dbus_bool_t _server_add_watch(DBusWatch *watch, void *data) { dbus_bool_t status = TRUE; dbus_bool_t is_enabled = dbus_watch_get_enabled(watch); GeisDBusServer server = (GeisDBusServer)data; if (is_enabled) /* fixme: ?? */ { geis_dbus_dispatcher_register(server->dispatcher, NULL, watch); } return status; } /* * Toggles the enabled/disabled status of the server watches. */ static void _server_toggle_watch(DBusWatch *watch, void *data) { GeisDBusServer server = (GeisDBusServer)data; geis_dbus_dispatcher_toggle_watch(server->dispatcher, watch); } /* * Removes the server watches from the dispatcher watch list. */ static void _server_remove_watch(DBusWatch *watch, void *data) { GeisDBusServer server = (GeisDBusServer)data; geis_dbus_dispatcher_unregister(server->dispatcher, watch); } /* * Adds a server timeout. */ static dbus_bool_t _server_add_timeout(DBusTimeout *timeout GEIS_UNUSED, void *data GEIS_UNUSED) { dbus_bool_t status = TRUE; return status; } /* * Removes a server timeout. */ static void _server_remove_timeout(DBusTimeout *timeout GEIS_UNUSED, void *data GEIS_UNUSED) { } /* * Adds a server timeout. */ static void _server_toggle_timeout(DBusTimeout *timeout GEIS_UNUSED, void *data GEIS_UNUSED) { } /* * Creates a new GeisDBusServer. */ GeisDBusServer geis_dbus_server_new(Geis geis) { GeisDBusServer server = NULL; DBusError error; server = calloc(1, sizeof(struct GeisDBusServer)); if (!server) { goto final_exit; } server->geis = geis; dbus_error_init(&error); server->dbus_server = dbus_server_listen("unix:abstract=geis", &error); if (!server->dbus_server || dbus_error_is_set(&error)) { char msg[128]; snprintf(msg, sizeof(msg), "error %s creating DBus server: %s", error.name, error.message); geis_error("%s", msg); dbus_error_free(&error); goto unwind_alloc; } server->dispatcher = geis_dbus_dispatcher_new(server->geis); if (!server->dispatcher) { geis_error("error creating server dispatcher."); goto unwind_server; } server->announcer = geis_dbus_announcer_new(server); if (!server->announcer) { geis_error("error creating server announcer."); goto unwind_dispatcher; } server->proxy_box = geis_dbus_proxy_box_new(); if (!server->proxy_box) { geis_error("error creating server proxy box."); goto unwind_announcer; } dbus_server_set_watch_functions(server->dbus_server, _server_add_watch, _server_remove_watch, _server_toggle_watch, server, NULL); dbus_server_set_timeout_functions(server->dbus_server, _server_add_timeout, _server_remove_timeout, _server_toggle_timeout, server, NULL); dbus_server_set_new_connection_function(server->dbus_server, _new_geis_dbus_client_connection, server, NULL); geis_register_event_callback(server->geis, _geis_event_callback, server); goto final_exit; unwind_announcer: geis_dbus_announcer_delete(server->announcer); unwind_dispatcher: geis_dbus_dispatcher_delete(server->dispatcher); unwind_server: dbus_server_disconnect(server->dbus_server); dbus_server_unref(server->dbus_server); unwind_alloc: free(server); server= NULL; final_exit: return server; } /* * Destroys a GeisDBusServer. */ void geis_dbus_server_delete(GeisDBusServer server) { if (server) { geis_dbus_proxy_box_delete(server->proxy_box); geis_dbus_announcer_delete(server->announcer); dbus_server_disconnect(server->dbus_server); dbus_server_unref(server->dbus_server); geis_dbus_dispatcher_delete(server->dispatcher); free(server); } } /* * Gets the address of a GeisDBusServer. */ char * geis_dbus_server_address(GeisDBusServer server) { return dbus_server_get_address(server->dbus_server); } /* * Gets the server dispatcher. */ GeisDBusDispatcher geis_dbus_server_dispatcher(GeisDBusServer server) { return server->dispatcher; } /* * Gets the server geis instance. */ Geis geis_dbus_server_geis(GeisDBusServer server) { return server->geis; } geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_proxy_box.h0000644000015600001650000000603412651717544024265 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_proxy_box.h * @brief Interface for a storage facility for GEIS DBus server client proxies. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_CLIENT_BOX_H_ #define GEIS_DBUS_CLIENT_BOX_H_ #include "geis_dbus_client_proxy.h" /** * A Container for GeisDBusProxy objects. */ typedef struct GeisDBusProxyBox *GeisDBusProxyBox; /** * An iterator for traversing and accessing client proxies contained in a box. * * Client proxy box iterators are not threadsafe and should be conidered * invalidated if the box is updated during a traversal. */ typedef struct GeisDBusProxyBoxNode *GeisDBusProxyBoxIterator; /** * Constructs a %GeisDBusProxyBox. * * @returns a valid %GeisDBusProxyBox or NULL on failure. */ GeisDBusProxyBox geis_dbus_proxy_box_new(); /** * Destroys a %GeisDBusProxyBox. * * @param[in] box A %GeisDBusProxyBox. */ void geis_dbus_proxy_box_delete(GeisDBusProxyBox box); /** * Inserts a %GeisDBusClientProxy in to a %GeisDBusProxyBox. * * @param[in] box A %GeisDBusProxyBox. * @param[in] proxy The %GeisDBusClientProxy to insert. */ void geis_dbus_proxy_box_insert(GeisDBusProxyBox box, GeisDBusClientProxy proxy); /** * Removes a %GeisDBusClientProxy from a %GeisDBusProxyBox. * * @param[in] box A %GeisDBusProxyBox. * @param[in] proxy The %GeisDBusClientProxy to remove. */ void geis_dbus_proxy_box_remove(GeisDBusProxyBox box, GeisDBusClientProxy proxy); /** * Gets an iterator initialized to the first client proxy in a box. * * @param[in] box A %GeisDBusProxyBox. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_begin(GeisDBusProxyBox box); /** * Gets an iterator initialized to one-past-the-end of a client proxy box. * * @param[in] box A %GeisDBusProxyBox. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_end(GeisDBusProxyBox box); /** * Gets the current client proxy from a client proxy box iterator. * * @param[in] iter The iterator. */ GeisDBusClientProxy geis_dbus_proxy_box_iter_value(GeisDBusProxyBoxIterator iter); /** * Advances a client proxy box iterator. * * @param[in] box A %GeisDBusProxyBox. * @param[in] iter The iterator. * * @returns the next iterator in sequence. */ GeisDBusProxyBoxIterator geis_dbus_proxy_box_iter_next(GeisDBusProxyBox box, GeisDBusProxyBoxIterator iter); #endif /* GEIS_DBUS_CLIENT_BOX_H_ */ geis-2.2.17+16.04.20160126/libgeis/server/geis_dbus_announcer.c0000644000015600001650000001376112651717544024224 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_announcer.c * @brief Implementation of the GEIS DBus announcer. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_announcer.h" #include #include "geis_dbus.h" #include "geis_logging.h" #include #include struct GeisDBusAnnouncer { GeisDBusServer server; DBusConnection *session_bus; }; static void _unregister_messages(DBusConnection *connection GEIS_UNUSED, void *user_data GEIS_UNUSED) { /* dummy */ } /* * Processes DBus metamessages. */ static DBusHandlerResult _announcer_dbus_messages(DBusConnection *connection GEIS_UNUSED, DBusMessage *message, void *user_data GEIS_UNUSED) { DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; if (dbus_message_is_signal(message, DBUS_SERVICE_DBUS, "NameAcquired")) { result = DBUS_HANDLER_RESULT_HANDLED; } return result; } /* * Processes GEIS messages. */ static DBusHandlerResult _announcer_geis_messages(DBusConnection *connection, DBusMessage *message, void *user_data) { DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; GeisDBusAnnouncer announcer = (GeisDBusAnnouncer)user_data; if (dbus_message_is_method_call(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_GET_SERVER_ADDRESS)) { char *server_addr = geis_dbus_server_address(announcer->server); DBusMessage *reply = dbus_message_new_method_return(message); dbus_message_append_args(reply, DBUS_TYPE_STRING, &server_addr, DBUS_TYPE_INVALID); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); dbus_free(server_addr); result = DBUS_HANDLER_RESULT_HANDLED; } return result; } /* * Virtual dispatch table for handling DBus messages. */ static struct DBusObjectPathVTable _dbus_message_vtbl = { _unregister_messages, _announcer_dbus_messages, 0, 0, 0, 0 }; /* * Virtual dispatch table for handling Geis messages. */ static struct DBusObjectPathVTable _geis_message_vtbl = { _unregister_messages, _announcer_geis_messages, 0, 0, 0, 0 }; /* * Adds the announcer watches to the dispatcher watch list. */ static dbus_bool_t _announcer_add_watch(DBusWatch *watch, void *data) { dbus_bool_t status = TRUE; GeisDBusAnnouncer announcer = (GeisDBusAnnouncer)data; GeisDBusDispatcher dispatcher = geis_dbus_server_dispatcher(announcer->server); geis_dbus_dispatcher_register(dispatcher, announcer->session_bus, watch); return status; } /* * Toggles the enabled/disabled status of the announcer watches. */ static void _announcer_toggle_watch(DBusWatch *watch, void *data) { GeisDBusAnnouncer announcer = (GeisDBusAnnouncer)data; GeisDBusDispatcher dispatcher = geis_dbus_server_dispatcher(announcer->server); geis_dbus_dispatcher_toggle_watch(dispatcher, watch); } /* * Removes the announcer watches from the dispatcher watch list. */ static void _announcer_remove_watch(DBusWatch *watch, void *data) { GeisDBusAnnouncer announcer = (GeisDBusAnnouncer)data; GeisDBusDispatcher dispatcher = geis_dbus_server_dispatcher(announcer->server); geis_dbus_dispatcher_unregister(dispatcher, watch); } /* * Creates a new GeisDBusAnouncer object. */ GeisDBusAnnouncer geis_dbus_announcer_new(GeisDBusServer server) { DBusError error; GeisDBusAnnouncer announcer = NULL; announcer = calloc(1, sizeof(struct GeisDBusAnnouncer)); if (!announcer) goto final_exit; announcer->server = server; dbus_error_init(&error); announcer->session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error); if (!announcer->session_bus || dbus_error_is_set(&error)) { char msg[128]; sprintf(msg, "error %s connecting to session bus: %s", error.name, error.message); geis_error("%s", msg); goto unwind_error; } dbus_connection_set_watch_functions(announcer->session_bus, _announcer_add_watch, _announcer_remove_watch, _announcer_toggle_watch, announcer, 0); dbus_connection_register_object_path(announcer->session_bus, DBUS_PATH_DBUS, &_dbus_message_vtbl, announcer); dbus_connection_register_object_path(announcer->session_bus, GEIS_DBUS_SERVICE_PATH, &_geis_message_vtbl, announcer); dbus_bus_request_name(announcer->session_bus, GEIS_DBUS_SERVICE_INTERFACE, DBUS_NAME_FLAG_REPLACE_EXISTING, &error); if (dbus_error_is_set(&error)) { geis_error("error requesting server name from DBus session bus"); } unwind_error: dbus_error_free(&error); final_exit: return announcer; } /* * Destroys a %GeisDBusAnnouncer object. */ void geis_dbus_announcer_delete(GeisDBusAnnouncer announcer) { if (announcer) { if (announcer->session_bus) { dbus_connection_unref(announcer->session_bus); } free(announcer); } } geis-2.2.17+16.04.20160126/libgeis/geis_touch.h0000644000015600001650000000356512651717544021041 0ustar pbuserpbgroup00000000000000/** * @file geis_touch.h * @brief Geis touch module internal interface * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_TOUCH_H_ #define GEIS_TOUCH_H_ #include "geis/geis.h" /** * @defgroup geis_touchset A Touch Container * @{ */ /** * Creates a new, empty touch set. */ GeisTouchSet geis_touchset_new(); /** * Destroys a touch set and all touches contained in it. * * @param[in] touchset The touch set to destroy. */ void geis_touchset_delete(GeisTouchSet touchset); /** * Inserts a touch in to a touch set. * * @param[in] touchset A touch set. * @param[in] touch A touch. * * The set takes ownership of the touch. */ GeisStatus geis_touchset_insert(GeisTouchSet touchset, GeisTouch touch); /** @} */ /** * @defgroup geis_touch A Gesture Touch * @{ */ /** * Creates a new touch. * * @param[in] id Identifier for the new touch. */ GeisTouch geis_touch_new(GeisTouchId id); /** * Destroys a touch. * * @param[in] touch The touch to destroy. */ void geis_touch_delete(GeisTouch touch); /** * Inserts touch attr. * * @param[in] touch The touch. * @param[in] attr The attr. */ GeisStatus geis_touch_add_attr(GeisTouch touch, GeisAttr attr); /** @} */ #endif /* GEIS_TOUCH_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_timer.c0000644000015600001650000000576412651717544021035 0ustar pbuserpbgroup00000000000000/** * @file geis_timer.c * @brief Implementation of the GEIS timer module. */ /* Copyright (C) 2011-2012 Canonical Ltd * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #include "geis_config.h" #include "geis_timer.h" #include #include "geis_logging.h" #include "geis_private.h" #include #include #include #include static const int nanosecondsPerMillisecond = 1000000; /* * The timer object. */ struct GeisTimer { int fd; GeisTimerCallback callback; void *context; }; /* * Bounces the multiplexor callback into the timer callback. */ void _timer_trampoline(int fd GEIS_UNUSED, GeisBackendMultiplexorActivity ev GEIS_UNUSED, void *ctx) { GeisTimer timer = (GeisTimer)ctx; timer->callback(timer, timer->context); } /* * Creates a new timer object on a GEIS API instance. */ GeisTimer geis_timer_new(Geis geis, GeisTimerCallback callback, void *context) { GeisTimer timer = calloc(1, sizeof(struct GeisTimer)); if (!timer) { geis_error("failed to allocate timer structure"); goto final_exit; } timer->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); if (timer->fd == -1) { geis_error("error %d creating timerfd: %s", errno, strerror(errno)); goto unwind_timer; } timer->callback = callback; timer->context = context; geis_multiplex_fd(geis, timer->fd, GEIS_BE_MX_READ_AVAILABLE, _timer_trampoline, timer); goto final_exit; unwind_timer: free(timer); timer = 0; final_exit: return timer; } /* * Destroys an existing timer. */ void geis_timer_delete(GeisTimer timer) { close(timer->fd); free(timer); } /* * Cancels an outstanding timer. */ void geis_timer_cancel(GeisTimer timer) { struct itimerspec in = { { 0, 0 }, { 0, 0 } }; struct itimerspec out; int status = timerfd_settime(timer->fd, 0, &in, &out); if (status != 0) { geis_error("error %d cancelling timerfd: %s", errno, strerror(errno)); } } /* * Starts a timer object a-ticking. */ void geis_timer_start(GeisTimer timer, GeisInteger msec) { struct itimerspec in = { { 0, 0 }, { 0, msec * nanosecondsPerMillisecond } }; struct itimerspec out; int status = timerfd_settime(timer->fd, 0, &in, &out); if (status != 0) { geis_error("error %d starting timerfd: %s", errno, strerror(errno)); } } geis-2.2.17+16.04.20160126/libgeis/geis_backend_token.h0000644000015600001650000000652312651717544022503 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_token.h * @brief internal GEIS back end token public interface * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_BACKEND_TOKEN_H_ #define GEIS_BACKEND_TOKEN_H_ #include "geis/geis.h" /** * An opaque token representing a set of filter terms in a backend-specific way. */ typedef struct GeisBackendToken *GeisBackendToken; /** * The states in which a backend token may be initialized. The choices are: * all gestures or no gestures. */ typedef enum GeisBackendTokenInitState { GEIS_BACKEND_TOKEN_INIT_NONE, GEIS_BACKEND_TOKEN_INIT_ALL } GeisBackendTokenInitState; /** * Creates a new backend token. * * @param[in] geis The API instance for which the token is created. * @param[in] init_state The initial state the token should be in. * * @returns a new %GeisBackendToken initialized according to @p init_state or * NULL on failure. */ GeisBackendToken geis_backend_token_new(Geis geis, GeisBackendTokenInitState init_state); /** * Clones a new backend token from an existing one. * @param[in] token The orignal backend token. * * @returns a new %GeisBackendToken that is an identical copy of @p token or * NULL on failure. Failure is not really an option. */ GeisBackendToken geis_backend_token_clone(GeisBackendToken token); /** * Destroys a backend token. * * @param[in] token The backend token. */ void geis_backend_token_delete(GeisBackendToken token); /** * Composes two backend tokens into a new backend token. * * @param[in] lhs A backend token. * @param[in] rhs Another backend token. * * Composed tokens are effectively ANDed. */ void geis_backend_token_compose(GeisBackendToken lhs, GeisBackendToken rhs); /** * Activates a token in the back end. * * @param[in] token A backend token. * @param[in] subscription The subscription under which the token will be * activated. */ GeisStatus geis_backend_token_activate(GeisBackendToken token, GeisSubscription subscription); /** * Deactivates a token in the back end. * * @param[in] token The backend token. * @param[in] subscription The subscription for which the token will be * deactivated. */ GeisStatus geis_backend_token_deactivate(GeisBackendToken token, GeisSubscription subscription); /** * Frees the private data that the backend allocated for a given subscription * * @param[in] token The backend token. * @param[in] subscription The subscription that will have its backend private data * freed */ void geis_backend_token_free_subscription_pdata(GeisBackendToken token, GeisSubscription subscription); #endif /* GEIS_BACKEND_TOKEN_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_gesture_flick.c0000644000015600001650000001520612651717544022533 0ustar pbuserpbgroup00000000000000/** * @file geis_gesture_flick.c * @brief higher-level "flick" gesture recognizer * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_gesture_flick.h" #include "geis_class.h" #include "geis_frame.h" #include "geis_logging.h" #include "geis_private.h" #include struct GeisGestureFlick { Geis geis; GeisGestureClass flick_class; GeisBoolean enabled; }; static GeisFloat _flick_threshold_squared = 1.0f; static GeisProcessingResult _recognize_flick(GeisEvent event, void *context) { GeisProcessingResult result = GEIS_PROCESSING_IGNORED; GeisGestureFlick flick = (GeisGestureFlick)context; if (!flick->enabled) goto final_exit; switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_END: { GeisAttr attr; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("no groupset for gesture event"); goto final_exit; } GeisGroupSet groupset = geis_attr_value_to_pointer(attr); if (!groupset) { geis_warning("can not convert attr to groupset"); goto final_exit; } GeisSize i; for (i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); if (!group) { geis_warning("can not extract group %zu from groupset", i); goto final_exit; } GeisSize j; for (j = 0; j < geis_group_frame_count(group); ++j) { GeisFloat dx = 0.0f; GeisFloat dy = 0.0f; GeisFloat rv = 0.0f; GeisFrame frame = geis_group_frame(group, j); if (!frame) { geis_warning("can not extract frame %zu from group", j); goto final_exit; } GeisSize num_attrs = geis_frame_attr_count(frame); for (i = 0; i < num_attrs; ++i) { GeisAttr attr = geis_frame_attr(frame, i); GeisString attr_name = geis_attr_name(attr); if (0 == strcmp(attr_name, GEIS_CLASS_ATTRIBUTE_ID)) { GeisInteger class_id = geis_attr_value_to_integer(attr); if (class_id != GEIS_GESTURE_PRIMITIVE_DRAG) { goto final_exit; } } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X)) { dx = geis_attr_value_to_float(attr); } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y)) { dy = geis_attr_value_to_float(attr); } } rv = dx * dx + dy * dy; if (rv > _flick_threshold_squared) { geis_frame_set_is_class(frame, flick->flick_class); } } } } break; default: break; } final_exit: return result; } static GeisStatus _add_class_term(GeisBackendToken token, void *context, GeisString name, GeisFilterOperation op, void *value) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisGestureFlick flick = (GeisGestureFlick)context; if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_NAME)) { if (op == GEIS_FILTER_OP_EQ) { GeisString class_name = (GeisString)value; if (0 == strcmp(class_name, geis_gesture_class_name(flick->flick_class))) { geis_filterable_attribute_foreach(flick->geis, GEIS_FILTER_CLASS, token, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG); flick->enabled = GEIS_TRUE; } else { flick->enabled = GEIS_FALSE; } } status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_ID)) { if (op == GEIS_FILTER_OP_EQ) { GeisInteger id = *(GeisInteger*)value; if (id == geis_gesture_class_id(flick->flick_class)) { geis_filterable_attribute_foreach(flick->geis, GEIS_FILTER_CLASS, token, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG); flick->enabled = GEIS_TRUE; } else { flick->enabled = GEIS_FALSE; } } status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) { /* GeisInteger touches = *(GeisInteger*)value; */ /* must explicitly ask for high-level gestures */ /* flick->enabled = GEIS_TRUE; */ status = GEIS_STATUS_SUCCESS; } return status; } GeisGestureFlick geis_gesture_flick_new(Geis geis) { GeisSize attr_count = 0; struct GeisFilterableAttribute attrs[3]; GeisGestureFlick flick = calloc(1, sizeof(struct GeisGestureFlick)); if (!flick) { geis_error("can not create flick"); goto final_exit; } flick->geis = geis; flick->flick_class = geis_gesture_class_new(GEIS_GESTURE_FLICK, GEIS_GESTURE_ID_FLICK); geis_gesture_class_ref(flick->flick_class); geis_filterable_attribute_init(&attrs[attr_count++], GEIS_CLASS_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, _add_class_term, flick); geis_filterable_attribute_init(&attrs[attr_count++], GEIS_CLASS_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, _add_class_term, flick); geis_filterable_attribute_init(&attrs[attr_count++], GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, _add_class_term, flick); geis_register_gesture_class(geis, flick->flick_class, attr_count, attrs); geis_register_processing_callback(geis, 10, _recognize_flick, flick); final_exit: return flick; } void geis_gesture_flick_delete(GeisGestureFlick flick) { if (flick) { geis_gesture_class_unref(flick->flick_class); free(flick); } } geis-2.2.17+16.04.20160126/libgeis/geis_backend_multiplexor.h0000644000015600001650000001354012651717544023744 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_multiplexor.h * @brief internal GEIS backend multiplexor interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_BACKEND_MULTIPLEXOR_H_ #define GEIS_BACKEND_MULTIPLEXOR_H_ #include "geis/geis.h" /** * Multiplexes back end events into a single notification file descriptor. * * The GEIS API presents a single file descriptor to the application to watch * for activity notification. A back end may be monitoring activity on more * than one file descriptor. The multiplexor combines these requirements. * * Activities includes read-available, write-available, hangup-detected, and * error-detected. Only the read- and write-available actvities may be * subscribed: the other activities are always listened for and reported. */ typedef struct _GeisBackendMultiplexor *GeisBackendMultiplexor; /** * Indicates the type of activiy(ies) that occurred on a multiplexed descriptor. * * This a bit map since more than oen activity can be requested or occur on a * file descriptor at the same time. * * @var GEIS_BE_MX_READ_AVAILABLE * Indicates data is available to be read on the file descriptor. * * @var GEIS_BE_MX_WRITE_AVAILABLE * Indicates data can be writtent ot the file descriptor without blocking. * * @var GEIS_BE_MX_HANGUP_DETECTED * Indicates a hangup was detected on the file descriptor. * * @var GEIS_BE_MX_ERROR_DETECTED * Indicates an error was detected on the file descriptor. */ typedef enum _GeisBackendMultiplexorActivity { GEIS_BE_MX_READ_AVAILABLE = 1 << 0, GEIS_BE_MX_WRITE_AVAILABLE = 1 << 1, GEIS_BE_MX_HANGUP_DETECTED = 1 << 2, GEIS_BE_MX_ERROR_DETECTED = 1 << 3 } GeisBackendMultiplexorActivity; /** * Handles events occurring on multiplexed file descriptors. * * Back ends must provide a callback with this signature to the multiplexor. */ typedef void (*GeisBackendFdEventCallback)(int fd, GeisBackendMultiplexorActivity activity, void *context); /** * Constructs a new back end multiplexor. */ GeisBackendMultiplexor geis_backend_multiplexor_new(); /** * A reasonable default value for the max_events_per_pump parameter to * geis_backend_multiplexor_new(). */ #define GEIS_BE_MX_DEFAULT_EVENTS_PER_PUMP 16 /** * Destroys a back end multiplexor. * * @param[in] mx The back end multiplexor to destroy. */ void geis_backend_multiplexor_delete(GeisBackendMultiplexor mx); /** * Adds a file descriptor to a back end multiplexor. * * @param[in] mx The back end multiplexor. * @param[in] fd The file descriptor to add. * @param[in] activity The actvitiy(ies) to monitor. * @param[in] callback The function to call when a desired activity is detected. * @param[in] context A context value to pass to the callback. * * The file descriptor will be monitored for one or more activities. At least * one of GEIS_BE_MX_READ_AVAILABLE or GEIS_BE_MX_WRITE_AVAILABLE should be * passed, other activities are monitored automatically. */ void geis_backend_multiplexor_add_fd(GeisBackendMultiplexor mx, int fd, GeisBackendMultiplexorActivity activity, GeisBackendFdEventCallback callback, void *context); /** * Modifies the activities being monitored on a file descriptor. */ void geis_backend_multiplexor_modify_fd(GeisBackendMultiplexor mx, int fd, GeisBackendMultiplexorActivity activity); /** * Removes a file descriptor from a back end multiplexor. * * @param[in] mx The back end multiplexor. * @param[in] fd The file descriptor to remove. */ void geis_backend_multiplexor_remove_fd(GeisBackendMultiplexor mx, int fd); /** * Gets the file descriptor of the back end multiplexor. * * @param[in] mx The back end multiplexor. */ int geis_backend_multiplexor_fd(GeisBackendMultiplexor mx); /** * Gets the maximum number of fd events per pump. * * @param[in] mx The back end multiplexor. */ int geis_backend_multiplexor_max_events_per_pump(GeisBackendMultiplexor mx); /** * Sets the maximum fd events per pump of the multiplexor. * * @param[in] mx The back end multiplexor. * @param[in] max_events_per_pump The maximum number of fd events pumped * per call of geis_backend_multiplexor_pump(). * * This value is tunable to accommodate different back ends and * application/toolkit requirements. */ void geis_backend_multiplexor_set_max_events_per_pump(GeisBackendMultiplexor mx, int max_events_per_pump); /** * Exercises the back end multiplexor. * * @param[in] mx The back end multiplexor. * * Dispatches any events on multiplexed file descriptors to their assciated * handlers. */ GeisStatus geis_backend_multiplexor_pump(GeisBackendMultiplexor mx); #endif /* GEIS_BACKEND_MULTIPLEXOR_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_group.h0000644000015600001650000000411712651717544021045 0ustar pbuserpbgroup00000000000000/** * @file geis_group.h * @brief Geis gesture group module internal interface * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_GROUP_H_ #define GEIS_GROUP_H_ #include "geis/geis.h" #include "geis_frame.h" /** * @defgroup geis_groupset A Gesture Group Container * @{ */ /** * Creates a new, empty group set. */ GeisGroupSet geis_groupset_new(); /** * Destroys a group set and all groups contained in it. * * @param[in] groupset The group set to destroy. */ void geis_groupset_delete(GeisGroupSet groupset); /** * Inserts a gesture group into a group set. * * @param[in] groupset A group set. * @param[in] group A gesture group. * * The set takes ownership of the gesture group. */ GeisStatus geis_groupset_insert(GeisGroupSet groupset, GeisGroup group); /** @} */ /** * @defgroup geis_group A Gesture Group * @{ */ /** * Creates a new gesture group. * * @param[in] id Identifier for the new group. */ GeisGroup geis_group_new(GeisInteger id); /** * Destroys a gesture group and all gesture frames contained in it. * * @param[in] group The gesture group to destroy. */ void geis_group_delete(GeisGroup group); /** * Adds a gesture frame to a gesture group. * * @param[in] group A gesture group. * @param[in] frame A gesture frame. * * The group takes ownership of the frame object. */ GeisStatus geis_group_insert_frame(GeisGroup group, GeisFrame frame); /** @} */ #endif /* GEIS_GROUP_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_subscription.c0000644000015600001650000003771212651717551022435 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_subscription.c * @brief implementation of the GEIS v2.0 API subscription module * * Copyright 2010, 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_subscription.h" #include "geis/geis.h" #include "geis_atomic.h" #include "geis_backend_token.h" #include "geis_filter.h" #include "geis_logging.h" #include "geis_private.h" #include #include #include struct _GeisSubscription { GeisRefCount sub_refcount; GeisInteger sub_id; Geis sub_geis; GeisString sub_name; GeisSubscriptionFlags sub_flags; GeisBoolean sub_activated; GeisBackendToken sub_backend_token; GeisFilterBag sub_filters; GeisPointer sub_data; }; struct _GeisSubBag { GeisSubscription *sub_store; GeisSize sub_store_size; }; static const float sub_bag_growth_constant = 1.5f; static void _subscription_destroy(GeisSubscription); /* * Increments the reference count on a subscirption object. */ static inline GeisSubscription _subscription_ref(GeisSubscription sub) { geis_atomic_ref(&sub->sub_refcount); return sub; } /* * Decrements the reference count of a subscription object and possibly destroys * the object. */ static void _subscription_unref(GeisSubscription sub) { if (0 == geis_atomic_unref(&sub->sub_refcount)) { _subscription_destroy(sub); } } /** * Creates a new subsciption container. */ GeisSubBag geis_subscription_bag_new(GeisSize size_hint) { GeisSubBag bag = calloc(1, sizeof(struct _GeisSubBag)); if (!bag) { geis_error("failed to allocate subscription container"); goto error_exit; } bag->sub_store_size = size_hint > 2 ? size_hint : 2; bag->sub_store = calloc(bag->sub_store_size, sizeof(GeisSubscription)); if (!bag->sub_store) { geis_error("failed to allocate subscription container store"); free(bag); bag = NULL; } error_exit: return bag; } /** * Destroys a subsciption container and free any associated resources. * * Any contained subsciptions that are still valid are also destroyed. */ void geis_subscription_bag_delete(GeisSubBag bag) { geis_subscription_bag_empty(bag); free(bag->sub_store); free(bag); } /** * Gets the number of (valid) subsciptions in the subsciption container. */ GeisSize geis_subscription_bag_count(GeisSubBag bag) { GeisSize count = 0; GeisSize i; for (i = 0; i < bag->sub_store_size; ++i) { if (bag->sub_store[i]) ++count; } return count; } /* * Gets an iterator initialized to the first subscription held in a bag. */ GeisSubBagIterator geis_subscription_bag_begin(GeisSubBag bag) { if (bag->sub_store_size > 0 && bag->sub_store[0]) return &bag->sub_store[0]; return geis_subscription_bag_end(bag); } /* * Increments the subscrition bag iterator. */ GeisSubBagIterator geis_subscription_bag_iterator_next(GeisSubBag bag, GeisSubBagIterator iter) { for (++iter; (GeisSize)(iter - bag->sub_store) < bag->sub_store_size; ++iter) { if (*iter) return iter; } return geis_subscription_bag_end(bag); } /* * Gets an iterator indicating one-past-the-last sub in a bag. */ GeisSubBagIterator geis_subscription_bag_end(GeisSubBag bag GEIS_UNUSED) { return NULL; } /** * Inserts a subscription in the subscription container. */ GeisSize geis_subscription_bag_insert(GeisSubBag bag, GeisSubscription sub) { GeisSize index = -1; for (index = 0; index < bag->sub_store_size; ++index) { if (!bag->sub_store[index]) { bag->sub_store[index] = _subscription_ref(sub); goto final_exit; } } GeisSize new_store_size = ceilf(bag->sub_store_size * sub_bag_growth_constant); GeisSubscription *new_store = realloc(bag->sub_store, new_store_size * sizeof(struct _GeisSubBag)); if (!new_store) { geis_error("failed to reallocate sub bag"); index = -1; goto final_exit; } index = bag->sub_store_size; memset(&new_store[index], 0, (new_store_size - index) * sizeof(struct _GeisSubBag)); bag->sub_store = new_store; bag->sub_store_size = new_store_size; bag->sub_store[index] = _subscription_ref(sub); final_exit: return index; } void geis_subscription_bag_remove(GeisSubBag bag, GeisSubscription sub) { if (bag->sub_store[sub->sub_id]) { bag->sub_store[sub->sub_id] = NULL; _subscription_unref(sub); } geis_debug("subscription \"%s\" removed", sub->sub_name); } /* * Removes all subscriptions from a subscription container. */ void geis_subscription_bag_empty(GeisSubBag bag) { GeisSize i; for (i = 0; i < bag->sub_store_size; ++i) { if (bag->sub_store[i]) { _subscription_unref(bag->sub_store[i]); bag->sub_store[i] = NULL; } } } void geis_subscription_bag_invalidate(GeisSubBag bag) { GeisSize i; for (i = 0; i < bag->sub_store_size; ++i) { if (bag->sub_store[i]) geis_subscription_invalidate(bag->sub_store[i]); } } /** * Finds a subsciption by ID. */ GeisSubscription geis_subscription_bag_find(GeisSubBag bag, GeisInteger sub_id) { GeisSubscription sub = NULL; GeisSize i; for (i = 0; i < bag->sub_store_size; ++i) { if (bag->sub_store[i] && bag->sub_store[i]->sub_id == sub_id) { sub = bag->sub_store[i]; break; } } return sub; } /* * Activates a subscirption. */ GeisStatus geis_subscription_activate(GeisSubscription sub) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisSize i; GeisBoolean is_system = sub->sub_flags & GEIS_SUBSCRIPTION_CONT; GeisBoolean is_grab = sub->sub_flags & GEIS_SUBSCRIPTION_GRAB; /* reset any existing token */ geis_subscription_deactivate(sub); if (geis_filter_bag_count(sub->sub_filters)) { sub->sub_backend_token = geis_backend_token_new(sub->sub_geis, GEIS_BACKEND_TOKEN_INIT_NONE); } else { sub->sub_backend_token = geis_backend_token_new(sub->sub_geis, GEIS_BACKEND_TOKEN_INIT_ALL); } /* create a new token from the filter tokens and activate it */ for (i = 0; i < geis_filter_bag_count(sub->sub_filters); ++i) { GeisFilter filter = geis_filter_bag_filter(sub->sub_filters, i); geis_backend_token_compose(sub->sub_backend_token, geis_filter_token(filter)); } geis_filterable_attribute_foreach(sub->sub_geis, GEIS_FILTER_SPECIAL, sub->sub_backend_token, GEIS_GESTURE_TYPE_SYSTEM, GEIS_FILTER_OP_EQ, &is_system); geis_filterable_attribute_foreach(sub->sub_geis, GEIS_FILTER_SPECIAL, sub->sub_backend_token, "GRAB", GEIS_FILTER_OP_EQ, &is_grab); status = geis_backend_token_activate(sub->sub_backend_token, sub); return status; } /* * Deactivates a subscirption. */ GeisStatus geis_subscription_deactivate(GeisSubscription sub) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (sub->sub_backend_token) { status = geis_backend_token_deactivate(sub->sub_backend_token, sub); sub->sub_backend_token = NULL; } return status; } void geis_subscription_invalidate(GeisSubscription sub) { geis_subscription_deactivate(sub); geis_filter_bag_delete(sub->sub_filters); sub->sub_filters = NULL; geis_unref(sub->sub_geis); sub->sub_geis = NULL; } /** * Creates a new subsciption on an API instance. */ GeisSubscription geis_subscription_new(Geis geis, GeisString sub_name, GeisSubscriptionFlags sub_flags) { GeisSubscription sub = calloc(1, sizeof(struct _GeisSubscription)); if (!sub) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating subscription"); goto final_exit; } if (sub_name) { sub->sub_name = strdup(sub_name); } else { sub->sub_name = strdup(""); } if (!sub->sub_name) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating subscription name"); goto unwind_sub; } sub->sub_filters = geis_filter_bag_new(); if (!sub->sub_filters) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating subscription filters"); goto unwind_name; } sub->sub_id = geis_add_subscription(geis, sub); if (sub->sub_id < 0) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error storing subscription"); goto unwind_filters; } sub->sub_geis = geis_ref(geis); sub->sub_flags = sub_flags; sub->sub_backend_token = NULL; _subscription_ref(sub); geis_debug("created subscription \"%s\" id %d", sub->sub_name, sub->sub_id); goto final_exit; unwind_filters: geis_filter_bag_delete(sub->sub_filters); unwind_name: free((char *)sub->sub_name); unwind_sub: free(sub); sub = NULL; final_exit: return sub; } void _subscription_destroy(GeisSubscription sub) { geis_debug("destroying subscription \"%s\" id %d", sub->sub_name, sub->sub_id); geis_subscription_deactivate(sub); if (sub->sub_backend_token) { geis_backend_token_free_subscription_pdata(sub->sub_backend_token, sub); geis_backend_token_delete(sub->sub_backend_token); sub->sub_backend_token = NULL; } if (sub->sub_geis != NULL) { geis_unref(sub->sub_geis); } if (sub->sub_filters != NULL) { geis_filter_bag_delete(sub->sub_filters); } free((char *)sub->sub_name); free(sub); } /** * Frees all resources allocated for the subscription and destroys the * subscription. Use of the subscription object after this call will result in * undefined behaviour. */ GeisStatus geis_subscription_delete(GeisSubscription sub) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (!sub) { status = GEIS_STATUS_BAD_ARGUMENT; goto error_exit; } _subscription_unref(sub); status = GEIS_STATUS_SUCCESS; error_exit: return status; } /** * Retrieves the name used on creation of the subscrition. */ GeisString geis_subscription_name(GeisSubscription subscription) { return subscription->sub_name; } /** * Retrieves the identifier assigned to the subscrition on creation. * The identifier is only unique for a given API instance and identifiers may be * reused after the subscription they identify has been deleted. */ GeisInteger geis_subscription_id(GeisSubscription subscription) { return subscription->sub_id; } /** * Adds a filter to a subscription. * * @todo implement this function after the filter module is implemented */ GeisStatus geis_subscription_add_filter(GeisSubscription sub, GeisFilter filter) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (!sub) { status = GEIS_STATUS_BAD_ARGUMENT; goto error_exit; } status = geis_filter_bag_insert(sub->sub_filters, filter); if (status != GEIS_STATUS_SUCCESS) { geis_error_push(sub->sub_geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error adding filter to subscription"); goto error_exit; } else { /* since we're taking ownership of the filter, we're removing the initial reference that belonged to the API user, created in geis_filter_new(). Now the only remaining reference is the one held by our geis_filter_bag */ geis_filter_unref(filter); } error_exit: return status; } /** * Removes a filter from a subscription. * * @todo implement this function after the filter module is implemented */ GeisStatus geis_subscription_remove_filter(GeisSubscription sub, GeisFilter filter) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (!sub) { status = GEIS_STATUS_BAD_ARGUMENT; goto error_exit; } status = geis_filter_bag_remove(sub->sub_filters, filter); if (status != GEIS_STATUS_SUCCESS) { geis_error_push(sub->sub_geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error removing filter from subscription"); goto error_exit; } error_exit: return status; } /* * Gets the numvber of filters in a subscirption. */ GeisSize geis_subscription_filter_count(GeisSubscription sub) { return geis_filter_bag_count(sub->sub_filters); } /* * Gets an indicated filter from a subscription. */ GeisFilter geis_subscription_filter(GeisSubscription sub, GeisSize index) { return geis_filter_bag_filter(sub->sub_filters, index); } /* * Gets an iterator initialized to the first filter on a subscription. */ GeisFilterIterator geis_subscription_filter_begin(GeisSubscription sub) { return geis_filter_bag_begin(sub->sub_filters); } /* * Gets an iterator initialized to the one-past-the-last filter on a subscription. */ GeisFilterIterator geis_subscription_filter_end(GeisSubscription sub) { return geis_filter_bag_end(sub->sub_filters); } /* * Gets the next filter in sequence. */ GeisFilterIterator geis_subscription_filter_next(GeisSubscription sub, GeisFilterIterator iter) { return geis_filter_iterator_next(sub->sub_filters, iter); } /* * Gets an named filter from a subscription. */ GeisFilter geis_subscription_filter_by_name(GeisSubscription sub, GeisString name) { return geis_filter_bag_filter_by_name(sub->sub_filters, name); } /* * Gets the operational flags for the subscription. */ GeisSubscriptionFlags geis_subscription_flags(GeisSubscription sub) { return sub->sub_flags; } /* * Sets the operational flags for the subscription. */ GeisStatus geis_subscription_set_flags(GeisSubscription sub, GeisSubscriptionFlags flags) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (!sub->sub_activated) { sub->sub_flags = flags; status = GEIS_STATUS_SUCCESS; } return status; } /* * Gets an associated datum on the subscription. */ GeisPointer geis_subscription_pdata(GeisSubscription sub) { return sub->sub_data; } /* * Sets an associated datum on the subscription. */ void geis_subscription_set_pdata(GeisSubscription sub, GeisPointer data) { sub->sub_data = data; } /* * Gets a subscription-level configuration item. */ GeisStatus geis_subscription_get_configuration(GeisSubscription subscription, GeisString config_item_name, GeisPointer config_item_value) { GeisStatus retval = geis_get_sub_configuration(subscription->sub_geis, subscription, config_item_name, config_item_value); return retval; } /* * Sets a subscription-level configuration item. */ GeisStatus geis_subscription_set_configuration(GeisSubscription subscription, GeisString config_item_name, GeisPointer config_item_value) { GeisStatus retval = geis_set_sub_configuration(subscription->sub_geis, subscription, config_item_name, config_item_value); return retval; } geis-2.2.17+16.04.20160126/libgeis/geis_backend.c0000644000015600001650000001452312651717544021275 0ustar pbuserpbgroup00000000000000/** * @file geis_backend.c * @brief internal GEIS back end base class implementation * * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_backend.h" #include "geis_backend_protected.h" #include "geis_logging.h" #include #include typedef struct GeisBackendClass { GeisString name; GeisSize size; GeisBackendVtable vtbl; } *GeisBackendClass; struct GeisBackend { GeisBackendClass be_class; char be_data[1]; }; struct GeisBackendRegistry { GeisBackendClass be; GeisSize size; GeisSize count; }; static struct GeisBackendRegistry _be_registry = { NULL, 0, 0 }; /* * Gets the child part of the back end instance. */ static inline void * _data_from_be(GeisBackend be) { return (void *)be->be_data; } /* * Initializes a new back end class object. */ static void _backend_class_init(GeisBackendClass self, GeisString name, GeisSize size, GeisBackendVtable vtbl) { self->name = strdup(name); self->size = size; self->vtbl = vtbl; } /* * Registers back ends with the API. */ void geis_register_backend(GeisString name, GeisSize size, GeisBackendVtable vtbl) { GeisSize new_size = _be_registry.size + 1; GeisBackendClass new_be = realloc(_be_registry.be, new_size * sizeof(struct GeisBackendClass)); if (!new_be) { geis_error("error reallocating back end registry"); goto final_exit; } _backend_class_init(&new_be[_be_registry.size], name, size, vtbl); geis_debug("back end %zu registered as '%s'", _be_registry.count, name); _be_registry.be = new_be; ++_be_registry.size; ++_be_registry.count; final_exit: return; } GeisBackendToken geis_backend_create_token(GeisBackend be, GeisBackendTokenInitState init_state) { return be->be_class->vtbl->create_token(_data_from_be(be), init_state); } /* * Creates a back end by name. */ GeisBackend geis_backend_by_name(Geis geis, GeisString name) { GeisBackend backend = NULL; GeisSize i; extern void geis_include_backend_test_fixture(void); extern void geis_include_dbus_backend(void); extern void geis_include_grail_backend(void); geis_debug("creating back end of class \"%s\"", name); /* temporary references to force symbol inclusion, replace with dlopen */ geis_include_backend_test_fixture(); geis_include_dbus_backend(); geis_include_grail_backend(); for (i = 0; i < _be_registry.count; ++i) { if (0 == strcmp(_be_registry.be[i].name, name)) { size_t obj_size = sizeof(GeisBackend) + _be_registry.be[i].size; backend = malloc(obj_size); if (backend) { *(GeisBackendClass *)(backend) = &_be_registry.be[i]; _be_registry.be[i].vtbl->construct(_data_from_be(backend), geis); if (geis_error_count(geis)) { free(backend); backend = NULL; } } break; } } return backend; } /* * Destroys the back end. */ void geis_backend_delete(GeisBackend be) { if (be) { geis_debug("destroying back end %s", geis_backend_name(be)); be->be_class->vtbl->finalize(_data_from_be(be)); free(be); } } /* * Gets the name of the back end (RTTI). */ GeisString geis_backend_name(GeisBackend be) { return be->be_class->name; } GeisStatus geis_backend_gesture_accept(GeisBackend be, GeisGroup group, GeisGestureId gesture_id) { GeisStatus status = be->be_class->vtbl->accept_gesture(_data_from_be(be), group, gesture_id); return status; } GeisStatus geis_backend_gesture_reject(GeisBackend be, GeisGroup group, GeisGestureId gesture_id) { GeisStatus status = be->be_class->vtbl->reject_gesture(_data_from_be(be), group, gesture_id); return status; } GeisStatus geis_backend_activate_device(GeisBackend be, GeisDevice device) { if (be->be_class->vtbl->activate_device) return be->be_class->vtbl->activate_device(_data_from_be(be), device); return GEIS_STATUS_SUCCESS; } GeisStatus geis_backend_deactivate_device(GeisBackend be, GeisDevice device) { if (be->be_class->vtbl->deactivate_device) return be->be_class->vtbl->deactivate_device(_data_from_be(be), device); return GEIS_STATUS_SUCCESS; } /* * Gets a back end configuration value. */ GeisStatus geis_backend_get_configuration(GeisBackend be, GeisSubscription subscription, GeisString configuration_item_name, GeisPointer configuration_item_value) { return be->be_class->vtbl->get_configuration(be, subscription, configuration_item_name, configuration_item_value); } /* * Sets a back end configuration value. */ GeisStatus geis_backend_set_configuration(GeisBackend be, GeisSubscription subscription, GeisString configuration_item_name, GeisPointer configuration_item_value) { return be->be_class->vtbl->set_configuration(be, subscription, configuration_item_name, configuration_item_value); } geis-2.2.17+16.04.20160126/libgeis/Makefile.am0000644000015600001650000000527012651717544020566 0ustar pbuserpbgroup00000000000000# # @file libgeis/Makefile.am # @brief automake recipe for the GEIS v2.0 implementation # # Copyright 2010-2012 Canonical, Ltd. # # This file is part of the geis library. This library is free software; # you can redistribute it and/or modify it under the terms of version 3 of # the GNU Lesser General Public License as published by the Free Software # Foundation. # # 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # version_script = $(srcdir)/libgeis.ver SUBDIRS = backend server lib_LTLIBRARIES = libgeis.la nobase_include_HEADERS = geis/geisimpl.h libgeis_la_SOURCES = \ geis_atomic.h \ geis_attr.h geis_attr.c \ geis_backend.h geis_backend.c \ geis_backend_protected.h geis_private.h \ geis_backend_multiplexor.h geis_backend_multiplexor.c \ geis_backend_token.h geis_backend_token.c \ geis_class.h geis_class.c \ geis_device.h geis_device.c \ geis_error.h geis_error.c \ geis_event.h geis_event.c \ geis_event_queue.h geis_event_queue.c \ geis_filter.h geis_filter.c \ geis_filterable.h geis_filterable.c \ geis_filter_term.h geis_filter_term.c \ geis_frame.h geis_frame.c \ geis_gesture_flick.h geis_gesture_flick.c \ geis_group.h geis_group.c \ geis_region.h geis_region.c \ geis_subscription.h geis_subscription.c \ geis_test_api.h \ geis_timer.h geis_timer.c \ geis_touch.h geis_touch.c \ geis_v1.c geis.c libgeis_la_CPPFLAGS = \ -fvisibility=hidden \ -DGEIS_BUILDING_DSO=1 \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(srcdir)/backend \ -I$(top_srcdir)/libs/geis-dbus \ -I$(top_srcdir)/libs/geis-util \ $(DBUS_CFLAGS) \ $(GRAIL_CFLAGS) libgeis_la_LDFLAGS = \ -Wl,-z,defs -Wl,--as-needed \ -version-info 4:0:3 \ -Wl,--version-script=$(version_script) \ -lm libgeis_la_LIBADD = \ ${builddir}/backend/test_fixture/libgeis-test-fixture.la \ ${builddir}/backend/dbus/libgeis-dbus-backend.la \ ${builddir}/backend/grail/libgeis-grail-backend.la \ ${builddir}/server/libgeis-dbus-server.la \ $(top_builddir)/libs/geis-util/libgeis-util.la \ $(top_builddir)/libs/geis-dbus/libgeis-dbus.la EXTRA_DIST = $(version_script) geis-2.2.17+16.04.20160126/libgeis/geis_filterable.c0000644000015600001650000000701612651717544022016 0ustar pbuserpbgroup00000000000000/** * @file geis_filterable.c * @brief internal Geis filterable entities implementation */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor#include "geis_filterable.h" */ #include "geis_config.h" #include "geis_filterable.h" #include "geis_logging.h" #include /* * An internal struct to collect filterable attributes for facilities. */ struct FilterableAttributeBag { GeisFilterableAttribute store; GeisSize size; GeisSize count; }; /* * Constructs a new filterable attribute bag. */ FilterableAttributeBag geis_filterable_attribute_bag_new() { FilterableAttributeBag bag = calloc(1, sizeof(struct FilterableAttributeBag)); if (!bag) { geis_error("failed to allocate filterable attribute bag"); goto final_exit; } bag->size = 2; bag->count = 0; bag->store = calloc(1, sizeof(struct GeisFilterableAttribute)); if (!bag) { geis_error("failed to allocate filterable attribute bag store"); goto unwind_bag; } goto final_exit; unwind_bag: free(bag); bag = NULL; final_exit: return bag; } /* * Destroys a filterable attribute bag. */ void geis_filterable_attribute_bag_delete(FilterableAttributeBag bag) { if (bag) { GeisSize i; for (i = 0; i < bag->count; ++i) { free((char *)bag->store[i].name); } free(bag->store); } free(bag); } void geis_filterable_attribute_copy(GeisFilterableAttribute src, GeisFilterableAttribute dst) { dst->name = strdup(src->name); dst->type = src->type; dst->add_term_callback = src->add_term_callback; dst->add_term_context = src->add_term_context; } GeisFilterableAttributeBagIter geis_filterable_attribute_bag_begin(FilterableAttributeBag bag) { if (bag->count) return &bag->store[0]; return geis_filterable_attribute_bag_end(bag); } GeisFilterableAttributeBagIter geis_filterable_attribute_bag_end(FilterableAttributeBag bag GEIS_UNUSED) { return NULL; } GeisFilterableAttributeBagIter geis_filterable_attribute_bag_next(FilterableAttributeBag bag, GeisFilterableAttributeBagIter iter) { if (iter < bag->store + bag->count - 1) return ++iter; return geis_filterable_attribute_bag_end(bag); } void geis_filterable_attribute_bag_insert(FilterableAttributeBag bag, GeisFilterableAttribute fa) { GeisSize new_count = bag->count + 1; if (new_count >= bag->size) { GeisSize new_size = bag->size * 2; GeisSize allocation_size = new_size * sizeof(struct GeisFilterableAttribute); GeisFilterableAttribute new_store = realloc(bag->store, allocation_size); if (!new_store) { geis_error("failed to reallocate filterable attribute bag store"); } else { bag->store = new_store; bag->size = new_size; } } geis_filterable_attribute_copy(fa, &bag->store[bag->count]); bag->count = new_count; } geis-2.2.17+16.04.20160126/libgeis/geis_event_queue.h0000644000015600001650000000617312651717544022242 0ustar pbuserpbgroup00000000000000/** * @file geis_event_queue.h * @brief internal Geis event queue public interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_EVENT_QUEUE_H_ #define GEIS_EVENT_QUEUE_H_ #include /** * A container for event_queues. * * This is a simple FIFO container for opaque GeisEvent objetcs. * * This container does not asssume ownership of the contained GeisEvents. * Someone creates the events and pushes them into the queue, and someone pulls * the events off the queue and does something with them. * * The current implementation uses a pooled caching strategy for dynamic * allocations to minimize overhead due to high-turnover usage. */ typedef struct _GeisEventQueue *GeisEventQueue; /** * Creates a new Geis Event queue. */ GeisEventQueue geis_event_queue_new(); /** * Destroys a Geis Event queue. * * @param[in] queue The event queue. * * This function empties the queue and destroys any GeisEvents malingering * therein, then destroys the queue itself. */ void geis_event_queue_delete(GeisEventQueue queue); /** * Pushes a new event onto the back of the event queue. * * @param[in] queue The event queue. * * @retval GEIS_STATUS_SUCCESS Normal successful completion. * * @retval GEIS_STATUS_UNKNOWN_ERROR Something bad happened. */ GeisStatus geis_event_queue_enqueue(GeisEventQueue queue, GeisEvent event); /** * Indicates if an event queue is empty. * * @param[in] queue The event queue. * * @returns GEIS_TRUE if the queue contains no events, GEIS_FALSE otherwise. */ GeisBoolean geis_event_queue_is_empty(GeisEventQueue queue); /** * Pops the event off the front of the queue. * * @param[in] queue The event queue. * * @returns the next GeisEvent or NULL of the queue is empty. */ GeisEvent geis_event_queue_dequeue(GeisEventQueue queue); /** * Prototype for GEIS event matching predicate functions. */ typedef GeisBoolean (*GeisEventMatch)(GeisEvent event, void *context); /** * Removes events from a queue of they match a condition. * * @param[in] queue The event queue. * @param[in] matching A unary predicate function to indicate the events to be * removed. * @param[in] context An application-specific context value to be passed to * the matching function. */ void geis_event_queue_remove_if(GeisEventQueue queue, GeisEventMatch matching, void *context); #endif /* GEIS_EVENT_QUEUE_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_filterable.h0000644000015600001650000000737512651717544022033 0ustar pbuserpbgroup00000000000000/** * @file geis_filterable.h * @brief internal Geis filterable entities private interface */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_FILTERABLE_H_ #define GEIS_FILTERABLE_H_ #include "geis/geis.h" #include "geis_backend_token.h" /** * A callback to add a term to a back end filter token. * * The callback receives the back end filter token, a back end callback context, * the name of the attribute, a filter operation, and the filter value. * * @param[in] token The back-end filter token. * @param[in] context The back-end callback context. * @param[in] name The filterable attribute name. * @param[in] op The filter operation. * @param[in] value The filter term value. */ typedef GeisStatus (*AddTermCallback)(GeisBackendToken token, void *context, GeisString name, GeisFilterOperation op, void *value); /** * The description of an attribute that can be used in subscirption filter * terms. * * When a facility (class, device, or region) registers the attributes that can * be used to build subscription filter terms, it passes a list of these structs * and the ABI instance maintains a collection of them. The facility just needs * to indicate the name and type of the attribute and provide a callback and * context for creating the filter term. */ typedef struct GeisFilterableAttribute { GeisString name; GeisAttrType type; AddTermCallback add_term_callback; void *add_term_context; } *GeisFilterableAttribute; typedef struct FilterableAttributeBag *FilterableAttributeBag; typedef GeisFilterableAttribute GeisFilterableAttributeBagIter; /** * Handy sugar. */ static inline void geis_filterable_attribute_init(GeisFilterableAttribute fa, GeisString n, GeisAttrType t, AddTermCallback ac, void *acc) { fa->name = n; fa->type = t; fa->add_term_callback = ac; fa->add_term_context = acc; } /** * Constructs a new filterable attribute bag. */ FilterableAttributeBag geis_filterable_attribute_bag_new(); /** * Destroys a filterable attribute bag. */ void geis_filterable_attribute_bag_delete(FilterableAttributeBag bag); GeisFilterableAttributeBagIter geis_filterable_attribute_bag_begin(FilterableAttributeBag bag); GeisFilterableAttributeBagIter geis_filterable_attribute_bag_end(FilterableAttributeBag bag); GeisFilterableAttributeBagIter geis_filterable_attribute_bag_next(FilterableAttributeBag bag, GeisFilterableAttributeBagIter iter); void geis_filterable_attribute_bag_insert(FilterableAttributeBag bag, GeisFilterableAttribute fa); void geis_filterable_attribute_copy(GeisFilterableAttribute src, GeisFilterableAttribute dst); #endif /* GEIS_FILTERABLE_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_v1.c0000644000015600001650000006452412651717544020242 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_v1.c * @brief implementation of the GEIS v1.0 API instance * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "geis/geis.h" #include "geis_class.h" #include "geis_config.h" #include "geis_filter.h" #include "geis_logging.h" #include "geis_private.h" #include "geis_subscription.h" #include "geis_test_api.h" #include #include #include #define WINDOW_FILTER "geis v1" struct _GeisInstance { Geis geis; GeisSubscription subscription; GeisFilter window_filter; GeisInputFuncs input_funcs; GeisPointer input_context; GeisGestureFuncs gesture_funcs; GeisPointer gesture_cookie; GeisBoolean init_failed; }; /* maps GEIS v1 gesture names into GEIS v2 gesture attrs */ typedef struct _GeisV1AttrMap *GeisV1AttrMap; static struct _GeisV1AttrMap { const char* v1_type; const char* v2_name; GeisInteger v2_id; GeisInteger touches; } s_v1_attr_map[] = { { GEIS_GESTURE_TYPE_DRAG1, GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG, 1 }, { GEIS_GESTURE_TYPE_DRAG2, GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG, 2 }, { GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG, 3 }, { GEIS_GESTURE_TYPE_DRAG4, GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG, 4 }, { GEIS_GESTURE_TYPE_DRAG5, GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG, 5 }, { GEIS_GESTURE_TYPE_PINCH1, GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH, 1 }, { GEIS_GESTURE_TYPE_PINCH2, GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH, 2 }, { GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH, 3 }, { GEIS_GESTURE_TYPE_PINCH4, GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH, 4 }, { GEIS_GESTURE_TYPE_PINCH5, GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH, 5 }, { GEIS_GESTURE_TYPE_ROTATE1, GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE, 1 }, { GEIS_GESTURE_TYPE_ROTATE2, GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE, 2 }, { GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE, 3 }, { GEIS_GESTURE_TYPE_ROTATE4, GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE, 4 }, { GEIS_GESTURE_TYPE_ROTATE5, GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE, 5 }, { GEIS_GESTURE_TYPE_TAP1, GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP, 1 }, { GEIS_GESTURE_TYPE_TAP2, GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP, 2 }, { GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP, 3 }, { GEIS_GESTURE_TYPE_TAP4, GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP, 4 }, { GEIS_GESTURE_TYPE_TAP5, GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP, 5 }, { GEIS_GESTURE_TYPE_TOUCH1, GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH, 1 }, { GEIS_GESTURE_TYPE_TOUCH2, GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH, 2 }, { GEIS_GESTURE_TYPE_TOUCH3, GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH, 3 }, { GEIS_GESTURE_TYPE_TOUCH4, GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH, 4 }, { GEIS_GESTURE_TYPE_TOUCH5, GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH, 5 }, { GEIS_GESTURE_TYPE_FLICK1, GEIS_GESTURE_FLICK, 100, 1 }, { GEIS_GESTURE_TYPE_FLICK2, GEIS_GESTURE_FLICK, 100, 2 }, { GEIS_GESTURE_TYPE_FLICK3, GEIS_GESTURE_FLICK, 100, 3 }, { GEIS_GESTURE_TYPE_FLICK4, GEIS_GESTURE_FLICK, 100, 4 }, { GEIS_GESTURE_TYPE_FLICK5, GEIS_GESTURE_FLICK, 100, 5 }, { NULL, NULL, 0, 0 } }; static const GeisString UNKNOWN_GESTURE_TYPE = "(unknown)"; static GeisString _v1_map_v2_name_to_v1_name(GeisString v2_name, GeisInteger touches) { for (int i = 0; s_v1_attr_map[i].v1_type; ++i) { if (0 == strcmp(s_v1_attr_map[i].v2_name, v2_name) && s_v1_attr_map[i].touches == touches) { return s_v1_attr_map[i].v1_type; } } return UNKNOWN_GESTURE_TYPE; } static struct { const char *id; const char* x; const char* y; } s_touch_attr_names[] = { { GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y }, { GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y }, { GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y }, { GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y }, { GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y } }; static GeisString _generate_subscription_name(GeisXcbWinInfo* win_info) { static char buffer[32]; if (win_info) sprintf(buffer, "0x%08x", win_info->window_id); else sprintf(buffer, "mock window"); return buffer; } /* * Maps the geis v2 attrs in a frame to geis v1 attrs. */ static GeisGestureAttr * _map_frame_to_attrs(Geis geis, GeisFrame frame, GeisTouchSet touchset, GeisInteger *class_id, GeisSize *attr_count) { GeisSize num_attrs = geis_frame_attr_count(frame); GeisSize i; GeisSize free_slot = 9; /* yes, it's magic! */ GeisSize num_touches = geis_frame_touchid_count(frame) * 3; /* more magic! */ GeisSize gga_size = free_slot + num_touches + num_attrs; GeisString gesture_name = NULL; *attr_count = 0; geis_debug("num_attrs = %zu", num_attrs); GeisGestureAttr *attrs = calloc(gga_size, sizeof(GeisGestureAttr)); if (!attrs) { geis_error("can not allocate gesture attrs"); goto final_exit; } /* Determine the dominant class. */ { GeisGestureClassBag classes = geis_gesture_classes(geis); GeisSize classes_count = geis_gesture_class_bag_count(classes); GeisSize i; for (i = 0; i < classes_count; ++i) { GeisGestureClass gesture_class = NULL; GeisInteger id = 0; gesture_class = geis_gesture_class_bag_gesture_class(classes, i); id = geis_gesture_class_id(gesture_class); if (geis_frame_is_class(frame, gesture_class)) { *class_id = id; gesture_name = geis_gesture_class_name(gesture_class); if (id > 100) break; } } } /* Map V2 attrs into V1 attrs. */ for (i = 0; i < num_attrs; ++i) { GeisAttr attr = geis_frame_attr(frame, i); GeisString attr_name = geis_attr_name(attr); if (0 == strcmp(attr_name, GEIS_CLASS_ATTRIBUTE_ID)) { /* skip this, do not pass it on */ } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) { attrs[0].name = attr_name; attrs[0].type = GEIS_ATTR_TYPE_INTEGER; attrs[0].integer_val = geis_attr_value_to_integer(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) { attrs[1].name = attr_name; attrs[1].type = GEIS_ATTR_TYPE_INTEGER; attrs[1].integer_val = geis_attr_value_to_integer(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID)) { attrs[2].name = attr_name; attrs[2].type = GEIS_ATTR_TYPE_INTEGER; attrs[2].integer_val = geis_attr_value_to_integer(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID)) { attrs[3].name = attr_name; attrs[3].type = GEIS_ATTR_TYPE_INTEGER; attrs[3].integer_val = geis_attr_value_to_integer(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) { attrs[4].name = attr_name; attrs[4].type = GEIS_ATTR_TYPE_INTEGER; attrs[4].integer_val = geis_attr_value_to_integer(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) { attrs[5].name = attr_name; attrs[5].type = GEIS_ATTR_TYPE_FLOAT; attrs[5].float_val = geis_attr_value_to_float(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) { attrs[6].name = attr_name; attrs[6].type = GEIS_ATTR_TYPE_FLOAT; attrs[6].float_val = geis_attr_value_to_float(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME)) { attrs[7].name = attr_name; attrs[7].type = GEIS_ATTR_TYPE_STRING; if (!gesture_name) gesture_name = geis_attr_value_to_string(attr); ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) { num_touches = geis_attr_value_to_integer(attr); attrs[8].name = attr_name; attrs[8].type = GEIS_ATTR_TYPE_INTEGER; attrs[8].integer_val = num_touches; ++*attr_count; } else { attrs[free_slot].name = attr_name; attrs[free_slot].type = GEIS_ATTR_TYPE_FLOAT; attrs[free_slot].float_val = geis_attr_value_to_float(attr); ++free_slot; ++*attr_count; } } /* fix up the gesture name for backwards compatibility */ attrs[7].string_val = _v1_map_v2_name_to_v1_name(gesture_name, num_touches); for (i = 0; i < geis_frame_touchid_count(frame); ++i) { GeisTouch touch = geis_touchset_touch_by_id(touchset, geis_frame_touchid(frame, i)); GeisSize touch_attr_count = geis_touch_attr_count(touch); GeisSize j; for (j = 0; j < touch_attr_count; ++j) { GeisAttr attr = geis_touch_attr(touch, j); GeisString attr_name = geis_attr_name(attr); if (0 == strcmp(attr_name, GEIS_TOUCH_ATTRIBUTE_ID)) { attrs[free_slot].name = s_touch_attr_names[i].id; attrs[free_slot].type = GEIS_ATTR_TYPE_FLOAT; attrs[free_slot].float_val = geis_attr_value_to_float(attr); ++free_slot; ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_TOUCH_ATTRIBUTE_X)) { attrs[free_slot].name = s_touch_attr_names[i].x; attrs[free_slot].type = GEIS_ATTR_TYPE_FLOAT; attrs[free_slot].float_val = geis_attr_value_to_float(attr); ++free_slot; ++*attr_count; } else if (0 == strcmp(attr_name, GEIS_TOUCH_ATTRIBUTE_Y)) { attrs[free_slot].name = s_touch_attr_names[i].y; attrs[free_slot].type = GEIS_ATTR_TYPE_FLOAT; attrs[free_slot].float_val = geis_attr_value_to_float(attr); ++free_slot; ++*attr_count; } } } final_exit: return attrs; } static void _v1_event_callback(Geis geis, GeisEvent event, GeisPointer context) { GeisInstance v1_instance = (GeisInstance)context; switch (geis_event_type(event)) { case GEIS_EVENT_INIT_COMPLETE: geis_debug("received INIT event"); goto final_exit; case GEIS_EVENT_ERROR: geis_debug("received ERROR event"); v1_instance->init_failed = GEIS_TRUE; goto final_exit; case GEIS_EVENT_DEVICE_AVAILABLE: case GEIS_EVENT_DEVICE_UNAVAILABLE: case GEIS_EVENT_CLASS_AVAILABLE: case GEIS_EVENT_CLASS_CHANGED: case GEIS_EVENT_CLASS_UNAVAILABLE: geis_debug("received DEVICE/CLASS event"); goto final_exit; default: geis_debug("received GESTURE event"); break; } GeisInteger class_id = 0; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); if (!attr) { geis_error("no touchset for gesture event"); goto final_exit; } GeisTouchSet touchset = geis_attr_value_to_pointer(attr); if (!touchset) { geis_warning("can not convert attr to touchset"); goto final_exit; } attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("no groupset for gesture event"); goto final_exit; } GeisGroupSet groupset = geis_attr_value_to_pointer(attr); if (!groupset) { geis_warning("can not convert attr to groupset"); goto final_exit; } GeisSize i; for (i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); if (!group) { geis_warning("can not extract group %zu from groupset", i); goto final_exit; } GeisSize j; for (j = 0; j < geis_group_frame_count(group); ++j) { GeisSize attr_count = 0; GeisFrame frame = geis_group_frame(group, j); if (!frame) { geis_warning("can not extract frame %zu from group", j); goto final_exit; } GeisGestureAttr *attrs = _map_frame_to_attrs(geis, frame, touchset, &class_id, &attr_count); if (!attrs) { geis_error("can not allocate gesture attrs"); goto final_exit; } switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: v1_instance->gesture_funcs.start(v1_instance->gesture_cookie, class_id, geis_frame_id(frame), attr_count, attrs); break; case GEIS_EVENT_GESTURE_UPDATE: v1_instance->gesture_funcs.update(v1_instance->gesture_cookie, class_id, geis_frame_id(frame), attr_count, attrs); break; case GEIS_EVENT_GESTURE_END: v1_instance->gesture_funcs.finish(v1_instance->gesture_cookie, class_id, geis_frame_id(frame), attr_count, attrs); break; default: geis_debug("-- event ignored --"); break; } free(attrs); /* in geis v1 only the first frame counts. */ break; } /* in geis v1 only the first group counts. */ break; } final_exit: geis_event_delete(event); } GeisStatus geis_init(GeisWinInfo* win_info, GeisInstance *geis_instance) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisXcbWinInfo *xcb_win_info = (GeisXcbWinInfo*)win_info->win_info; GeisInteger window = 0; GeisInstance instance; instance = calloc(1, sizeof(struct _GeisInstance)); if (!instance) { geis_error("error allocating GEIS API instance."); goto final_exit; } if (xcb_win_info) { window = (GeisInteger)(xcb_win_info->window_id); } if (win_info->win_type == geis_win_type_str(Test)) { if (xcb_win_info) instance->geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); else instance->geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); } else { instance->geis = geis_new(GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, GEIS_INIT_SYNCHRONOUS_START, NULL); } if (!instance->geis) { goto unwind_instance; } geis_register_event_callback(instance->geis, _v1_event_callback, instance); instance->subscription = geis_subscription_new(instance->geis, _generate_subscription_name(xcb_win_info), GEIS_SUBSCRIPTION_CONT); instance->window_filter = geis_filter_new(instance->geis, WINDOW_FILTER); geis_filter_add_term(instance->window_filter, GEIS_FILTER_REGION, GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, window, NULL); status = geis_subscription_add_filter(instance->subscription, instance->window_filter); instance->init_failed = GEIS_FALSE; *geis_instance = instance; goto final_exit; unwind_instance: free(instance); final_exit: return status; } GeisStatus geis_finish(GeisInstance instance) { GeisStatus status = GEIS_STATUS_SUCCESS; geis_subscription_delete(instance->subscription); geis_delete(instance->geis); free(instance); return status; } GeisStatus geis_configuration_supported(GeisInstance geis_instance GEIS_UNUSED, int configuration_item) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; switch (configuration_item) { case GEIS_CONFIG_UNIX_FD: status = GEIS_STATUS_SUCCESS; break; } return status; } GeisStatus geis_configuration_get_value(GeisInstance instance, int configuration_item, void *value) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (!value) { return GEIS_BAD_ARGUMENT; } switch (configuration_item) { case GEIS_CONFIG_UNIX_FD: status = geis_get_configuration(instance->geis, GEIS_CONFIGURATION_FD, value); break; } return status; } /* * Sets a feature configuration value. */ GeisStatus geis_configuration_set_value(GeisInstance geis_instance GEIS_UNUSED, int configuration_item, void *value) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (!value) { return GEIS_BAD_ARGUMENT; } switch (configuration_item) { default: break; } return status; } GeisStatus geis_event_dispatch(GeisInstance instance) { geis_dispatch_events(instance->geis); return GEIS_STATUS_SUCCESS; } static GeisStatus _v1_subscribe_device(GeisInstance instance, GeisInteger device_id, const char **gesture_list) { GeisStatus result = GEIS_UNKNOWN_ERROR; if (gesture_list == GEIS_ALL_GESTURES) { geis_debug("subscribing device %d for all gestures", device_id); } else { const char **g; geis_debug("subscribing device %d for the following gestures:", device_id); for (g = gesture_list; *g; ++g) { GeisV1AttrMap v1attr; geis_debug("\t\"%s\"", *g); if (0 == strcmp(GEIS_GESTURE_TYPE_SYSTEM, *g)) { geis_subscription_set_flags(instance->subscription, GEIS_SUBSCRIPTION_CONT | GEIS_SUBSCRIPTION_GRAB); continue; } for (v1attr = s_v1_attr_map; v1attr->v1_type; ++v1attr) { if (0 == strcmp(*g, v1attr->v1_type)) { GeisFilter filter = geis_filter_clone(instance->window_filter, *g); if (!filter) { geis_error("error creating new filter"); } else { result = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_ID, GEIS_FILTER_OP_EQ, v1attr->v2_id, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, v1attr->touches, NULL); if (result != GEIS_STATUS_SUCCESS) { geis_error("error adding gesture class filter term"); } if (device_id != 0) { result = geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_ID, GEIS_FILTER_OP_EQ, device_id, NULL); if (result != GEIS_STATUS_SUCCESS) { geis_error("error adding device filter term"); } } result = geis_subscription_add_filter(instance->subscription, filter); if (result != GEIS_STATUS_SUCCESS) { geis_error("error adding gesture class filter"); } } break; } } } } return result; } GeisStatus geis_subscribe(GeisInstance instance, GeisInputDeviceId *input_list, const char* *gesture_list, GeisGestureFuncs *funcs, void *cookie) { GeisStatus result = GEIS_UNKNOWN_ERROR; /** * If there is no window filter, the instance has already been subscribed to * devices and gestures so skip. */ if (NULL == instance->window_filter) { geis_warning("instance has been subscribed twice"); return GEIS_STATUS_SUCCESS; } memcpy(&instance->gesture_funcs, funcs, sizeof(GeisGestureFuncs)); instance->gesture_cookie = cookie; /* pump the geis event queue to force device and class events to be picked up */ while (GEIS_STATUS_CONTINUE == geis_dispatch_events(instance->geis)) ; if (input_list == GEIS_ALL_INPUT_DEVICES) { result = _v1_subscribe_device(instance, 0, gesture_list); } else { GeisInputDeviceId *device_id; for (device_id = input_list; *device_id; ++device_id) { GeisStatus a_result = _v1_subscribe_device(instance, *device_id, gesture_list); if (a_result == GEIS_STATUS_SUCCESS) { result = a_result; } } } /* * If there are specific gesture classes, remove the window-id-only filter since it allows * ALL gesture classes. It will have been replaced by device-specific or * class-specific filters on the same window. */ if (gesture_list && *gesture_list) { result = geis_subscription_remove_filter(instance->subscription, instance->window_filter); if (result != GEIS_STATUS_SUCCESS) { geis_warning("error removing V1 window filter"); } instance->window_filter = NULL; } result = geis_subscription_activate(instance->subscription); return result; } /* * Unsubscribes from one or more gestures. * * Note the evil wicked dirty case from GeisGestureType* to const char**: * it turns out the API should have used const char** and apps using the API * seem to cast GeisGestureType* to const char**, but they would fail to build * from source if the API changed now and would crash and burn if the * functionality was changed, hence the brutish method here. * * My advice: move to GEIS v2.0 and avoid the whole problem. */ GeisStatus geis_unsubscribe(GeisInstance instance, GeisGestureType *gesture_list) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (gesture_list == GEIS_ALL_GESTURES) { status = geis_subscription_deactivate(instance->subscription); } else { const char **gesture_name_list = (const char **)gesture_list; const char **g; status = geis_subscription_deactivate(instance->subscription); for (g = gesture_name_list; *g; ++g) { GeisFilter filter; filter = geis_subscription_filter_by_name(instance->subscription, *g); if (filter) { geis_subscription_remove_filter(instance->subscription, filter); } } if (geis_subscription_filter_count(instance->subscription)) { status = geis_subscription_activate(instance->subscription); } } return status; } /* * Translates a GEISv2 device into a GEISv1 device and invokes the appropriate * callback. */ static void _v1_report_device(GeisInstance instance, GeisDevice device, GeisBoolean is_added) { GeisInputDeviceId device_id = 0; GeisGestureAttr *attrs = calloc(geis_device_attr_count(device) + 1, sizeof(GeisGestureAttr)); if (!attrs) { geis_error("can not allocate device attrs"); return; } for (GeisSize i = 0; i < geis_device_attr_count(device); ++i) { GeisAttr attr = geis_device_attr(device, i); if (0 == strcmp(geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_ID)) { device_id = geis_attr_value_to_integer(attr); } attrs[i].name = geis_attr_name(attr); attrs[i].type = geis_attr_type(attr); switch (attrs[i].type) { case GEIS_ATTR_TYPE_BOOLEAN: attrs[i].boolean_val = geis_attr_value_to_boolean(attr); break; case GEIS_ATTR_TYPE_FLOAT: attrs[i].float_val = geis_attr_value_to_float(attr); break; case GEIS_ATTR_TYPE_INTEGER: attrs[i].integer_val = geis_attr_value_to_integer(attr); break; case GEIS_ATTR_TYPE_STRING: attrs[i].string_val = geis_attr_value_to_string(attr); break; default: break; } } if (is_added) { instance->input_funcs.added(instance->input_context, device_id, attrs); } else { instance->input_funcs.removed(instance->input_context, device_id, attrs); } free(attrs); } /* * Handler for device events. * * Converts GEISv2 device-add and device-removed events into similar GEISv1 * callbacks. */ static void _v1_input_callback(Geis geis GEIS_UNUSED, GeisEvent event, void *context) { GeisInstance instance = (GeisInstance)context; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); if (!attr) { geis_error("no touchset for gesture event"); goto final_exit; } GeisDevice device = geis_attr_value_to_pointer(attr); if (!device) { geis_warning("can not convert attr to device"); goto final_exit; } switch (geis_event_type(event)) { case GEIS_EVENT_DEVICE_AVAILABLE: _v1_report_device(instance, device, GEIS_TRUE); break; case GEIS_EVENT_DEVICE_UNAVAILABLE: _v1_report_device(instance, device, GEIS_FALSE); break; default: geis_debug("-- event ignored --"); break; } final_exit: geis_event_delete(event); } GeisStatus geis_input_devices(GeisInstance instance, GeisInputFuncs *funcs, void *context) { GeisStatus result = GEIS_STATUS_SUCCESS; memcpy(&instance->input_funcs, funcs, sizeof(GeisInputFuncs)); instance->input_context = context; geis_register_device_callback(instance->geis, _v1_input_callback, instance); /* report pre-existing devices */ GeisDeviceBag device_bag = geis_devices(instance->geis); for (GeisSize d = 0; d != geis_device_bag_count(device_bag); ++d) { GeisDevice device = geis_device_bag_device(device_bag, d); _v1_report_device(instance, device, GEIS_TRUE); } return result; } geis-2.2.17+16.04.20160126/libgeis/geis/0000755000015600001650000000000012651717732017454 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/geis/geisimpl.h0000644000015600001650000000525612651717544021447 0ustar pbuserpbgroup00000000000000/** * geisimpl.h * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBGEIS_XCB_GEISIMPL_H_ #define LIBGEIS_XCB_GEISIMPL_H_ #include #include /* Provide some cross-platform symbol export decorations. */ #if defined _WIN32 || defined __CYGWIN__ #define GEIS_HELPER_DSO_IMPORT __declspec(dllimport) #define GEIS_HELPER_DSO_EXPORT __declspec(dllexport) #define GEIS_HELPER_DSO_LOCAL #else #if __GNUC__ >= 4 #define GEIS_HELPER_DSO_IMPORT __attribute__ ((visibility("default"))) #define GEIS_HELPER_DSO_EXPORT __attribute__ ((visibility("default"))) #define GEIS_HELPER_DSO_LOCAL __attribute__ ((visibility("hidden"))) #else #define GEIS_HELPER_DSO_IMPORT #define GEIS_HELPER_DSO_EXPORT #define GEIS_HELPER_DSO_LOCAL #endif #endif #ifdef GEIS_BUILDING_DSO #ifdef GEIS_DSO_EXPORTS #define GEIS_API GEIS_HELPER_DSO_EXPORT #else #define GEIS_API GEIS_HELPER_DSO_IMPORT #endif /* GEIS_DSO_EXPORTS */ #define GEIS_LOCAL GEIS_HELPER_DSO_LOCAL #else #define GEIS_API #define GEIS_LOCAL #endif /* GEIS_BUILDING_DSO */ /* If available, provide a NULL terminator check decoration. */ #if __GNUC__ >= 4 # define GEIS_VARARG __attribute__((sentinel(0))) #else # define GEIS_VARARG #endif /** * Portability types */ typedef size_t GeisSize; typedef uint32_t GeisBoolean; typedef int32_t GeisInteger; typedef float GeisFloat; typedef void* GeisPointer; typedef const char *GeisString; /** * @brief Magic for constructing geis win_type values. */ static inline uint32_t _geis_win_type_str(const char tag[5]) { return (((((tag[3] << 8 ) | tag[2]) << 8) | tag[1]) << 8) | tag[0]; } #define geis_win_type_str(tag) _geis_win_type_str(#tag) /** A full X11 window */ #define GEIS_XCB_FULL_WINDOW geis_win_type_str(GXWF) /** * @brief Contains XCB-specific window information */ typedef struct _GeisXcbWinInfo { const char *display_name; int *screenp; uint32_t window_id; } GeisXcbWinInfo; #endif /* LIBGEIS_XCB_GEISIMPL_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_filter.h0000644000015600001650000001105612651717544021176 0ustar pbuserpbgroup00000000000000/** * @file geis_filter.h * @brief internal Geis filter module private interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_FILTER_H_ #define GEIS_FILTER_H_ #include "geis/geis.h" #include "geis_backend_token.h" #include "geis_filter_term.h" /** * @defgroup geis_filter_container A Filter Container * @{ */ /** * An unsorted container for holding filters. */ typedef struct _GeisFilterBag *GeisFilterBag; /** * An iterator over a %GeisFilterBag. */ typedef GeisFilter *GeisFilterIterator; /** * Creates a new filter bag, */ GeisFilterBag geis_filter_bag_new(); /** * Destroys a filter bag. * * @param[in] bag The filter bag, */ void geis_filter_bag_delete(GeisFilterBag bag); /** * Gets the number of filters in the bag. * * @param[in] bag The filter bag, */ GeisSize geis_filter_bag_count(GeisFilterBag bag); /**t * Gets an indicated filter from a bag. * * @param[in] bag The filter bag. * @param[in] index The index. */ GeisFilter geis_filter_bag_filter(GeisFilterBag bag, GeisSize index); /** * Gets an indicated filter from a bag. * * @param[in] bag The filter bag. * @param[in] name The name by which to find the filter. * * Returns a NULL pointer if the named filter is not found. */ GeisFilter geis_filter_bag_filter_by_name(GeisFilterBag bag, GeisString name); /** * Gets an iterator initialized to the first filter contained in the bag. * * @param[in] bag The filter bag. */ GeisFilterIterator geis_filter_bag_begin(GeisFilterBag bag); /** * Gets an iterator initialized to one-past-the-end of the filter bag. * * @param[in] bag The filter bag. */ GeisFilterIterator geis_filter_bag_end(GeisFilterBag bag); /** * Advances the iterator to the next filter in the bag. * * @param[in] iter A %GeisFilterIterator. * * @returns an iterator pointing to the next filter in the filter bag. */ GeisFilterIterator geis_filter_iterator_next(GeisFilterBag bag, GeisFilterIterator iter); /** * Inserts a filter in the bag. * * @param[in] bag The filter bag. * @param[in] filter The filter to insert. */ GeisStatus geis_filter_bag_insert(GeisFilterBag bag, GeisFilter filter); /** * Remoes a filter from the bag. * * @param[in] bag The filter bag. * @param[in] filter The filter to remove. */ GeisStatus geis_filter_bag_remove(GeisFilterBag bag, GeisFilter filter); /** @} */ /** * @defgroup geis_filter_internals Filter Internals * @{ */ /** * Increments the reference count on a filter. * * @param[in] filter The filter. * * @returns the same GeisFilter instance with an incremented reference count. */ GeisFilter geis_filter_ref(GeisFilter filter); /** * Decrements and returns the referemce count on a filter. * * @param[in] filter The filter. * * @returns the current reference count. */ GeisSize geis_filter_unref(GeisFilter filter); /** * Gets the number of terms in the filter. * * @param[in] filter The filter. */ GeisSize geis_filter_term_count(GeisFilter filter); /** * Gets the indicated term in the filter. * * @param[in] filter The filter. * @param[in] index Indicates which term. */ GeisFilterTerm geis_filter_term(GeisFilter filter, GeisSize index); /** * Adds an already-created filter term (for internal unmarshalling). * * @param[in] filter The filter. * @param[in] term A filter term. */ GeisStatus geis_filter_add_term_internal(GeisFilter filter, GeisFilterTerm term); /** * Gets the back end token from the filter. * * @param[in] filter The filter. */ GeisBackendToken geis_filter_token(GeisFilter filter); /** * Performs the filter function on a Geis event. * * @param[in] filter The filter. * @param[in] event An event. * * The point of a filter is to pass or reject events. This function does just * that. * * @return true of the event is passed by the filter, false otherwise. */ GeisBoolean geis_filter_pass_event(GeisFilter filter, GeisEvent event); /** @} */ #endif /* GEIS_FILTER_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_filter.c0000644000015600001650000003672112651717544021177 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_filter.c * @brief implementation of the GEIS v2.0 API filter module * * Copyright 2010, 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_filter.h" #include "geis_atomic.h" #include "geis_attr.h" #include "geis_error.h" #include "geis_filter_term.h" #include "geis_logging.h" #include "geis_private.h" #include #include #include struct _GeisFilter { GeisRefCount refcount; GeisString name; Geis geis; GeisSize oid; GeisBackendToken backend_token; GeisFilterTermBag terms; }; struct _GeisFilterBag { GeisFilter *filter_store; GeisSize filter_store_size; GeisSize filter_count; }; static const int filter_bag_growth_constant = 2; static GeisSize s_filter_oid = 0; /* * Creates a new filter bag, */ GeisFilterBag geis_filter_bag_new() { GeisFilterBag bag = calloc(1, sizeof(struct _GeisFilterBag)); if (!bag) { geis_error("failed to allocate filter bag"); goto final_exit; } bag->filter_store_size = 3; bag->filter_count = 0; bag->filter_store = calloc(bag->filter_store_size, sizeof(GeisFilter)); if (!bag->filter_store) { geis_error("failed to allocate filter bag store"); goto unwind_bag; } goto final_exit; unwind_bag: free(bag); final_exit: return bag; } /* * Destroys a filter bag. */ void geis_filter_bag_delete(GeisFilterBag bag) { GeisSize i; for (i = bag->filter_count; i > 0; --i) { geis_filter_delete(bag->filter_store[i-1]); } free(bag->filter_store); free(bag); } /* * Gets the number of filters in the bag. */ GeisSize geis_filter_bag_count(GeisFilterBag bag) { return bag->filter_count; } /* * Gets an indicated filter from a bag. */ GeisFilter geis_filter_bag_filter(GeisFilterBag bag, GeisSize index) { GeisFilter filter = NULL; if (index < bag->filter_count) { filter = bag->filter_store[index]; } return filter; } /* * Gets an indicated filter from a bag. */ GeisFilter geis_filter_bag_filter_by_name(GeisFilterBag bag, GeisString name) { GeisFilter filter = NULL; GeisSize i; for (i = 0; i < bag->filter_count; ++i) { if (0 == strcmp(bag->filter_store[i]->name, name)) { filter = bag->filter_store[i]; break; } } return filter; } /* * Gets an iterator initialized to the first filter contained in the bag. */ GeisFilterIterator geis_filter_bag_begin(GeisFilterBag bag) { if (bag->filter_count > 0) return (GeisFilterIterator)bag->filter_store; return geis_filter_bag_end(bag); } /* * * Gets an iterator initialized to one-past-the-end of the filter bag. */ GeisFilterIterator geis_filter_bag_end(GeisFilterBag bag GEIS_UNUSED) { return NULL; } /* * Advances the iterator to the next filter in the bag. */ GeisFilterIterator geis_filter_iterator_next(GeisFilterBag bag, GeisFilterIterator iter) { GeisFilterIterator new_iter = iter + 1; if ((GeisSize)(new_iter - bag->filter_store) < bag->filter_count) return new_iter; return geis_filter_bag_end(bag); } /* * Inserts a filter in the bag. */ GeisStatus geis_filter_bag_insert(GeisFilterBag bag, GeisFilter filter) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->filter_count >= bag->filter_store_size) { GeisSize new_store_size = bag->filter_store_size * filter_bag_growth_constant; GeisFilter *new_store = realloc(bag->filter_store, new_store_size * sizeof(struct _GeisFilter)); if (!new_store) { geis_error("failed to reallocate filter bag"); goto error_exit; } bag->filter_store = new_store; bag->filter_store_size = new_store_size; } bag->filter_store[bag->filter_count++] = geis_filter_ref(filter); status = GEIS_STATUS_SUCCESS; goto final_exit; error_exit: geis_filter_unref(filter); final_exit: return status; } /* * Remoes a filter from the bag. */ GeisStatus geis_filter_bag_remove(GeisFilterBag bag, GeisFilter filter) { GeisSize i; GeisStatus status = GEIS_STATUS_SUCCESS; for (i = 0; i < bag->filter_count; ++i) { if (bag->filter_store[i] == filter) { GeisSize j; geis_filter_delete(bag->filter_store[i]); --bag->filter_count; for (j = i; j < bag->filter_count; ++j) { bag->filter_store[j] = bag->filter_store[j+1]; } break; } } return status; } /* * Creates a new, empty filter object. */ static GeisFilter _filter_new_empty(GeisString name) { GeisFilter filter = calloc(1, sizeof(struct _GeisFilter)); if (!filter) { geis_error("error allocating filter"); goto final_exit; } if (name) { filter->name = strdup(name); } else { filter->name = strdup(""); } if (!filter->name) { geis_error("error allocating filter name"); goto unwind_filter; } filter->oid = s_filter_oid++; goto final_exit; unwind_filter: free(filter); filter = NULL; final_exit: return filter; } /* * Creates a GEIS v2.0 filter object. */ GeisFilter geis_filter_new(Geis geis, GeisString name) { GeisFilter filter = _filter_new_empty(name); if (!filter) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); goto final_exit; } filter->terms = geis_filter_term_bag_new(0); if (!filter->terms) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating filter terms"); goto unwind_filter; } filter->backend_token = geis_backend_token_new(geis, GEIS_BACKEND_TOKEN_INIT_ALL); if (!filter->backend_token) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating filter token"); goto unwind_term_bag; } filter->geis = geis_ref(geis); geis_filter_ref(filter); goto final_exit; unwind_term_bag: geis_filter_term_bag_delete(filter->terms); unwind_filter: free((char *)filter->name); free(filter); filter = NULL; final_exit: return filter; } /* * Creates a new filter by copying an existing filter. */ GeisFilter geis_filter_clone(GeisFilter original, GeisString name) { GeisFilter filter = _filter_new_empty(name); if (!filter) { geis_error_push(original->geis, GEIS_STATUS_UNKNOWN_ERROR); goto final_exit; } filter->terms = geis_filter_term_bag_clone(original->terms); if (!filter->terms) { geis_error_push(original->geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating filter terms"); goto unwind_filter; } filter->geis = geis_ref(original->geis); filter->backend_token = geis_backend_token_clone(original->backend_token); geis_filter_ref(filter); goto final_exit; unwind_filter: free((char *)filter->name); free(filter); filter = NULL; final_exit: return filter; } /* * Destroys a GEIS v2.0 filter object. */ GeisStatus geis_filter_delete(GeisFilter filter) { GeisStatus status = GEIS_STATUS_SUCCESS; if (filter && (geis_filter_unref(filter) == 0)) { geis_unref(filter->geis); geis_backend_token_delete(filter->backend_token); geis_filter_term_bag_delete(filter->terms); free((char *)filter->name); free(filter); } return status; } /* * Gets the name given to the filter when it was created. */ GeisString geis_filter_name(GeisFilter filter) { return filter->name; } /* * Indicates if the facility is valid. */ static GeisBoolean _facility_is_valid(GeisFilterFacility facility) { return facility == GEIS_FILTER_DEVICE || facility == GEIS_FILTER_CLASS || facility == GEIS_FILTER_REGION || facility == GEIS_FILTER_SPECIAL; } /* * Indicates if the operation is valid. */ static GeisBoolean _operation_is_valid(GeisFilterOperation op) { return op == GEIS_FILTER_OP_EQ || op == GEIS_FILTER_OP_NE || op == GEIS_FILTER_OP_GT || op == GEIS_FILTER_OP_GE || op == GEIS_FILTER_OP_LT || op == GEIS_FILTER_OP_LE; } /* * Gets the attr description by name. * @todo implement this function */ static GeisAttrType _get_attr_type_for_facility(Geis geis, GeisFilterFacility facility, GeisString attr_name) { GeisAttrType type = GEIS_ATTR_TYPE_UNKNOWN; switch (facility) { case GEIS_FILTER_DEVICE: type = geis_get_device_attr_type(geis, attr_name); break; case GEIS_FILTER_CLASS: type = geis_get_class_attr_type(geis, attr_name); break; case GEIS_FILTER_REGION: type = geis_get_region_attr_type(geis, attr_name); break; case GEIS_FILTER_SPECIAL: type = geis_get_special_attr_type(geis, attr_name); break; default: break; } return type; } GeisStatus geis_filter_add_term_internal(GeisFilter filter, GeisFilterTerm term) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisAttr attr = geis_filter_term_attr(term); geis_filterable_attribute_foreach(filter->geis, geis_filter_term_facility(term), filter->backend_token, geis_attr_name(attr), geis_filter_term_operation(term), geis_attr_value(attr)); geis_filter_term_bag_insert(filter->terms, term); return status; } /* * Adds zero or more terms to a filter. */ GeisStatus geis_filter_add_term(GeisFilter filter, GeisFilterFacility facility, ...) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; va_list varargs; GeisString attr_name; if (!_facility_is_valid(facility)) { status = GEIS_STATUS_BAD_ARGUMENT; geis_error_push(filter->geis, status); geis_error("invalid filter facility"); goto final_exit; } va_start(varargs, facility); for (attr_name = va_arg(varargs, GeisString); attr_name; attr_name = va_arg(varargs, GeisString)) { GeisAttrType attr_type = _get_attr_type_for_facility(filter->geis, facility, attr_name); if (attr_type == GEIS_ATTR_TYPE_UNKNOWN) { status = GEIS_STATUS_BAD_ARGUMENT; geis_error_push(filter->geis, status); geis_error("invalid attr name \"%s\" for facility", attr_name); goto final_exit; } GeisFilterOperation op = va_arg(varargs, GeisFilterOperation); if (!_operation_is_valid(op)) { status = GEIS_STATUS_BAD_ARGUMENT; geis_error_push(filter->geis, status); geis_error("invalid filter operation"); goto final_exit; } switch (attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: { GeisBoolean value = va_arg(varargs, GeisBoolean); geis_filterable_attribute_foreach(filter->geis, facility, filter->backend_token, attr_name, op, &value); GeisAttr attr = geis_attr_new(attr_name, attr_type, &value); GeisFilterTerm term = geis_filter_term_new(facility, op, attr); geis_filter_term_bag_insert(filter->terms, term); } break; case GEIS_ATTR_TYPE_FLOAT: { GeisFloat value = va_arg(varargs, double); geis_filterable_attribute_foreach(filter->geis, facility, filter->backend_token, attr_name, op, &value); GeisAttr attr = geis_attr_new(attr_name, attr_type, &value); GeisFilterTerm term = geis_filter_term_new(facility, op, attr); geis_filter_term_bag_insert(filter->terms, term); } break; case GEIS_ATTR_TYPE_INTEGER: { GeisInteger value = va_arg(varargs, GeisInteger); geis_filterable_attribute_foreach(filter->geis, facility, filter->backend_token, attr_name, op, &value); GeisAttr attr = geis_attr_new(attr_name, attr_type, &value); GeisFilterTerm term = geis_filter_term_new(facility, op, attr); geis_filter_term_bag_insert(filter->terms, term); } break; case GEIS_ATTR_TYPE_POINTER: { GeisPointer value = va_arg(varargs, GeisPointer); geis_filterable_attribute_foreach(filter->geis, facility, filter->backend_token, attr_name, op, value); GeisAttr attr = geis_attr_new(attr_name, attr_type, value); GeisFilterTerm term = geis_filter_term_new(facility, op, attr); geis_filter_term_bag_insert(filter->terms, term); } break; case GEIS_ATTR_TYPE_STRING: { GeisString value = va_arg(varargs, GeisString); geis_filterable_attribute_foreach(filter->geis, facility, filter->backend_token, attr_name, op, (void *)value); GeisAttr attr = geis_attr_new(attr_name, attr_type, (void *)value); GeisFilterTerm term = geis_filter_term_new(facility, op, attr); geis_filter_term_bag_insert(filter->terms, term); } break; default: status = GEIS_STATUS_BAD_ARGUMENT; geis_error_push(filter->geis, status); geis_error("invalid filter argument"); goto final_exit; break; } } va_end(varargs); status = GEIS_STATUS_SUCCESS; final_exit: return status; } /* * Atomically increments filter refcount. */ GeisFilter geis_filter_ref(GeisFilter filter) { geis_atomic_ref(&filter->refcount); return filter; } /* * Atomically decrements and returns filter refcount. */ GeisSize geis_filter_unref(GeisFilter filter) { return geis_atomic_unref(&filter->refcount); } /* * Gets the number of terms in the filter. */ GeisSize geis_filter_term_count(GeisFilter filter) { return geis_filter_term_bag_count(filter->terms); } /* * Gets the indicated term in the filter. */ GeisFilterTerm geis_filter_term(GeisFilter filter, GeisSize index) { return geis_filter_term_bag_term(filter->terms, index); } /* * Gets the back end token from the filter. */ GeisBackendToken geis_filter_token(GeisFilter filter) { return filter->backend_token; } /* * Performs the filter function on a Geis event. */ GeisBoolean geis_filter_pass_event(GeisFilter filter, GeisEvent event) { GeisBoolean pass = GEIS_TRUE; for (GeisSize i = 0; i < geis_filter_term_bag_count(filter->terms); ++i) { GeisFilterTerm term = geis_filter_term_bag_term(filter->terms, i); pass &= geis_filter_term_match_event(term, event); } return pass; } geis-2.2.17+16.04.20160126/libgeis/geis_region.h0000644000015600001650000000530412651717544021173 0ustar pbuserpbgroup00000000000000/** * @file geis_region.h * @brief internal Geis region module private interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_REGION_H_ #define GEIS_REGION_H_ #include "geis/geis.h" /** * @struct _GeisRegion * * This is a refcounted object: using the internal function geis_region_ref() * will increment the reference count on the object, and geis_region_delete() * will decrement the reference count and destroy the object when the reference * count is set to zero. * * If you are handed a GeisRegion and want to keep it around, you need to ref it * and then delete it when you're done, otherwise it could disappear out from * under you. * * Because GeisRegion lifetime is affected explicitly by application action * (new and delete calls are under application control), the refcount mechanism * has been made threadsafe. */ /** * Contains regions in no particular order, with no duplicate checking. * * @note This container is not threadsafe. */ typedef struct _GeisRegionBag *GeisRegionBag; /** * Creates a new region bag. */ GeisRegionBag geis_region_bag_new(); /** * Destroys a region bag. * * @param[in] bag The region bag. */ void geis_region_bag_delete(GeisRegionBag bag); /** * Gets the number of regions held in a bag. */ GeisSize geis_region_bag_count(GeisRegionBag bag); /** * Gets an indicated region from a bag. */ GeisRegion geis_region_bag_region(GeisRegionBag bag, GeisSize index); /** * Puts a region into a bag. */ GeisStatus geis_region_bag_insert(GeisRegionBag bag, GeisRegion region); /** * Takes a region out of a bag. */ GeisStatus geis_region_bag_remove(GeisRegionBag bag, GeisRegion region); /** * Adds a reference to a region. * * @param[in] region A region. */ void geis_region_ref(GeisRegion); /** * Gets the type of the region. * * @param[in] region A region. */ GeisString geis_region_type(GeisRegion region); /** * Gets the data (if any) associated with the region type. * * @param[in] region A region. */ void *geis_region_data(GeisRegion region); #endif /* GEIS_REGION_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_filter_term.h0000644000015600001650000001105212651717544022221 0ustar pbuserpbgroup00000000000000/** * @file geis_filter_term.h * @brief internal Geis filter term module private interface * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_FILTER_TERM_H_ #define GEIS_FILTER_TERM_H_ #include "geis/geis.h" /** * @defgroup geis_filter_term Filter Terms. * @{ */ /** * One of the terms of a filter. * * A term belong to a facility (eg. device, gesture type, region) and is used to * compare (using an operation) a named attribute with a given value. */ typedef struct _GeisFilterTerm *GeisFilterTerm; /** * Creates a new filter term. * * @param[in] facility The term's facility. * @param[in] operation The term's operation. * @param[in] attr The term's attr name, type, and value */ GeisFilterTerm geis_filter_term_new(GeisFilterFacility facility, GeisFilterOperation operation, GeisAttr attr); /** * Increments the filter term's reference count. * * @param[in] term The filter term. */ GeisFilterTerm geis_filter_term_ref(GeisFilterTerm term); /** * Decrements the filter term's reference count and maybe destroys the term. * * @param[in] term The filter term. * * The number of references to the term is reduced by 1 and when it reaches 0, * the term is destroyed. */ void geis_filter_term_unref(GeisFilterTerm term); /** * Gets a filter term's facility. * * @param[in] term The filter term. */ GeisFilterFacility geis_filter_term_facility(GeisFilterTerm term); /** * Gets a filter term's operation. * * @param[in] term The filter term. */ GeisFilterOperation geis_filter_term_operation(GeisFilterTerm term); /** * Gets a filter term's attributes. * * @param[in] term The filter term. */ GeisAttr geis_filter_term_attr(GeisFilterTerm term); /** * Indicates if a filter term matches a GEIS event. * * @param[in] term The filter term. * @param[in] event A GEIS event. */ GeisBoolean geis_filter_term_match_event(GeisFilterTerm term, GeisEvent event); /** * Indicates a filter passes a device. * * @param[in] term The filter term. * @param[in] device A GEIS device. * * @returns GEIS_TRUE if the device is passed by the filter, GEIS_FALSE * otherwise. */ GeisBoolean geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device); /** @} */ /** * @defgroup geis_filter_term_container A Filter Term Container * @{ */ /** * An unsorted container for holding filter terms. * * This implementation is physically unsorted, but terms are logically grouped * by facility. * * This is a purely internal structure, as is the filter term. The bag "owns" * the term. */ typedef struct _GeisFilterTermBag *GeisFilterTermBag; /** * Creates a new, empty filter term bag, * * @param[in] store_size The initial filter store size. A value of 0 will * allocate a reasonable default size. */ GeisFilterTermBag geis_filter_term_bag_new(GeisSize store_size); /** * Creates a new filter term bag by deep-copying an existing filter term bag. * * @param[in] original The original fiter term bag. */ GeisFilterTermBag geis_filter_term_bag_clone(GeisFilterTermBag original); /** * Destroys a filter term bag. * * @param[in] bag The filter term bag. */ void geis_filter_term_bag_delete(GeisFilterTermBag bag); /** * Gets the number of filter terms in the bag. * * @param[in] bag The filter term bag. */ GeisSize geis_filter_term_bag_count(GeisFilterTermBag bag); /** * Gets an indicated filter term from a bag. * * @param[in] bag The filter bag. * @param[in] index The index. */ GeisFilterTerm geis_filter_term_bag_term(GeisFilterTermBag bag, GeisSize index); /** * Inserts a filter in the bag. * * @param[in] bag The filter bag. * @param[in] term The filter to insert. */ GeisStatus geis_filter_term_bag_insert(GeisFilterTermBag bag, GeisFilterTerm term); /** @} */ #endif /* GEIS_FILTER_TERM_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_frame.h0000644000015600001650000001011512651717544020776 0ustar pbuserpbgroup00000000000000/** * @file geis_frame.h * @brief uFrame Geis frame module internal interface * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_FRAME_H_ #define GEIS_FRAME_H_ #include "geis/geis.h" /** * @defgroup uframe_geis_frameset A Frame Container * @{ */ typedef struct _GeisFrameSet *GeisFrameSet; /** * Creates a new, empty frame set. */ GeisFrameSet geis_frameset_new(); /** * Destroys a frame set and all framees contained in it. * * @param[in] frameset The frame set to destroy. */ void geis_frameset_delete(GeisFrameSet frameset); /** * Inserts a frame in to a frame set. * * @param[in] frameset A frame set. * @param[in] frame A frame. * * The set takes ownership of the frame. */ GeisStatus geis_frameset_insert(GeisFrameSet frameset, GeisFrame frame); /** * Gets the number of framees in a frameset. * * @param[in] frameset The frameset, */ GeisSize geis_frameset_frame_count(GeisFrameSet frameset); /** * Gets an indicated frame from a frameset. * * @param[in] frameset The frameset. * @param[in] index Indicates which frame to retrieve. */ GeisFrame geis_frameset_frame(GeisFrameSet frameset, GeisSize index); /** @} */ /** * @defgroup uframe_geis_frame A Gesture Frame * @{ */ /** * Creates a new frame. * * @param[in] id Identifier for the new frame. */ GeisFrame geis_frame_new(GeisInteger id); /** * Destroys a frame. * * @param[in] frame The frame to destroy. */ void geis_frame_delete(GeisFrame frame); /** * Inserts a frame attr. * * @param[in] frame The gesture frame. * @param[in] attr The gesture attr. */ GeisStatus geis_frame_add_attr(GeisFrame frame, GeisAttr attr); /** * Inserts a touch IDinto a gesture frame. * * @param[in] frame The gesture frame. * @param[in] touchid The index of the frame in the related frame set. */ GeisStatus geis_frame_add_touchid(GeisFrame frame, GeisTouchId touchid); /** * Classifies the frame. * * @param[in] frame The gesture frame. * @param[in] gesture-class The class to which the frame belongs. * * A frame may belong to one or more gesture classes. */ GeisStatus geis_frame_set_is_class(GeisFrame frame, GeisGestureClass gesture_class); /** * Sets the frame transform matrix. * * @param[in] frame The gesture frame. * @param[in] matrix The transform matrix. This is assumed to be a 4x4 matrix * in row-major form. No bounds checking or validation is * performed. * * This function performs a depp copy of the transform matrix. */ void geis_frame_set_matrix(GeisFrame frame, const GeisFloat *matrix); /** * Indicates if a gesture frame belongs to a gesture class, by class name. * * @param[in] frame The gesture frame. * @param[in] class_name The gesture class name. * * @returns true if the gesture can currently be classified by the gesture class * name, false otherwise. */ GeisBoolean geis_frame_is_class_by_name(GeisFrame frame, GeisString class_name); /** * Gets the number of gesture classes to which the frame belongs. * * @param[in] frame The gesture frame. */ GeisSize geis_frame_class_count(GeisFrame frame); /** * Gets a gesture class to which the frame belongs. * * @param[in] frame The gesture frame. * @param[in] index Indicates the class to retrieve. */ GeisGestureClass geis_frame_class(GeisFrame frame, GeisSize index); /** @} */ #endif /* GEIS_FRAME_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_event.c0000644000015600001650000000465512651717544021034 0ustar pbuserpbgroup00000000000000/** * @file geis_event.c * @brief GeisEvent module implementation * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis/geis.h" #include "geis_attr.h" #include "geis_logging.h" #include struct _GeisEvent { GeisEventType ev_type; GeisAttrBag ev_attr_bag; }; /* * Creates a new event. */ GeisEvent geis_event_new(GeisEventType ev_type) { GeisEvent event = calloc(1, sizeof(struct _GeisEvent)); if (!event) { geis_error("unable to allocate GeisEvent"); goto final_exit; } event->ev_type = ev_type; event->ev_attr_bag = geis_attr_bag_new(4); if (!event->ev_attr_bag) { geis_error("unable to allocate GeisEvent attribute bag"); goto unwind_event; } goto final_exit; unwind_event: free(event); final_exit: return event; } /* * Destroys an event. */ void geis_event_delete(GeisEvent event) { geis_attr_bag_delete(event->ev_attr_bag); free(event); } /* * Gets the type of the event. */ GeisEventType geis_event_type(GeisEvent event) { return event->ev_type; } /* * Sets the type of the event. */ void geis_event_override_type(GeisEvent event, GeisEventType ev_type) { event->ev_type = ev_type; } /* * Gets how many attrs are in the event. */ GeisSize geis_event_attr_count(GeisEvent event) { return geis_attr_bag_count(event->ev_attr_bag); } /* * Gets an indicated attr. */ GeisAttr geis_event_attr(GeisEvent event, GeisSize index) { return geis_attr_bag_attr(event->ev_attr_bag, index); } /* * Gets a named attr. */ GeisAttr geis_event_attr_by_name(GeisEvent event, GeisString attr_name) { return geis_attr_bag_find(event->ev_attr_bag, attr_name); } /* * Adds an attr. */ GeisStatus geis_event_add_attr(GeisEvent event, GeisAttr attr) { return geis_attr_bag_insert(event->ev_attr_bag, attr); } geis-2.2.17+16.04.20160126/libgeis/geis_class.c0000644000015600001650000001551112651717544021011 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_class.c * @brief implementation of the GEIS v2.0 API Gesture Class module * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_class.h" #include "geis_atomic.h" #include "geis_attr.h" #include "geis_logging.h" #include struct _GeisGestureClass { GeisRefCount ref_count; GeisAttrBag attrs; }; struct _GeisGestureClassBag { GeisGestureClass *store; GeisSize store_size; GeisSize count; }; static const int gesture_class_bag_growth_constant = 2; /* * Creates a new class bag, */ GeisGestureClassBag geis_gesture_class_bag_new() { GeisGestureClassBag bag = calloc(1, sizeof(struct _GeisGestureClassBag)); if (!bag) { geis_error("error allocating gesture class bag"); goto final_exit; } bag->store = calloc(1, sizeof(struct _GeisGestureClass)); if (!bag->store) { geis_error("error allocating gesture class bag store"); goto unwind_bag; } bag->store_size = 1; bag->count = 0; goto final_exit; unwind_bag: free(bag); bag = NULL; final_exit: return bag; } /* * Destroys a gesture class bag. */ void geis_gesture_class_bag_delete(GeisGestureClassBag bag) { GeisSize i; for (i = bag->count; i > 0; --i) { geis_gesture_class_unref(bag->store[i-1]); } free(bag->store); free(bag); } /* * Gets the number of gesture classs in the bag. */ GeisSize geis_gesture_class_bag_count(GeisGestureClassBag bag) { return bag->count; } /* * Gets an indicated gesture class from a bag. */ GeisGestureClass geis_gesture_class_bag_gesture_class(GeisGestureClassBag bag, GeisSize index) { GeisGestureClass gesture_class = NULL; if (index >= bag->count) { geis_warning("class bag index out of range"); } else { gesture_class = bag->store[index]; } return gesture_class; } /* * Inserts a gesture class in the bag. */ GeisStatus geis_gesture_class_bag_insert(GeisGestureClassBag bag, GeisGestureClass gesture_class) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->count >= bag->store_size) { GeisSize new_store_size = bag->store_size * gesture_class_bag_growth_constant; GeisGestureClass *new_store = realloc(bag->store, new_store_size * sizeof(struct _GeisGestureClass)); if (!new_store) { geis_error("failed to reallocate class bag"); goto error_exit; } bag->store = new_store; bag->store_size = new_store_size; } bag->store[bag->count++] = gesture_class; status = GEIS_STATUS_SUCCESS; error_exit: return status; } /* * Remoes a gesture class from the bag. */ GeisStatus geis_gesture_class_bag_remove(GeisGestureClassBag bag, GeisGestureClass gesture_class) { GeisSize i; GeisStatus status = GEIS_STATUS_SUCCESS; for (i = 0; i < bag->count; ++i) { if (bag->store[i] == gesture_class) { GeisSize j; geis_gesture_class_unref(bag->store[i]); --bag->count; for (j = i; j < bag->count; ++j) { bag->store[j] = bag->store[j+1]; } break; } } return status; } /* * Creates a new, empty gesture_class. */ GeisGestureClass geis_gesture_class_new(GeisString name, GeisInteger id) { GeisAttr attr; GeisGestureClass gesture_class = calloc(1, sizeof(struct _GeisGestureClass)); if (!gesture_class) { geis_error("error allocating gesture class"); goto final_exit; } gesture_class->attrs = geis_attr_bag_new(3); if (!gesture_class->attrs) { geis_debug("error allocating attr bag"); goto unwind_gesture_class; } attr = geis_attr_new(GEIS_CLASS_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, (void *)name); if (!attr) { geis_debug("error creating gesture class name attr"); goto unwind_attrs; } geis_attr_bag_insert(gesture_class->attrs, attr); attr = geis_attr_new(GEIS_CLASS_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, &id); if (!attr) { geis_debug("error creating gesture class id attr"); goto unwind_attrs; } geis_attr_bag_insert(gesture_class->attrs, attr); geis_gesture_class_ref(gesture_class); goto final_exit; unwind_attrs: geis_attr_bag_delete(gesture_class->attrs); unwind_gesture_class: free(gesture_class); gesture_class = NULL; final_exit: return gesture_class; } /* * Destroys a gesture class. */ static void _gesture_class_delete(GeisGestureClass gesture_class) { geis_attr_bag_delete(gesture_class->attrs); free(gesture_class); } /* * Increments the reference count of a gesture class object. */ void geis_gesture_class_ref(GeisGestureClass gesture_class) { geis_atomic_ref(&gesture_class->ref_count); } /* * Decrements the reference count of a gesture class object. */ void geis_gesture_class_unref(GeisGestureClass gesture_class) { if (0 == geis_atomic_unref(&gesture_class->ref_count)) { _gesture_class_delete(gesture_class); } } /* * Gets the name of the gesture class. */ GeisString geis_gesture_class_name(GeisGestureClass gesture_class) { GeisString name = NULL; GeisAttr attr = geis_attr_bag_find(gesture_class->attrs, GEIS_CLASS_ATTRIBUTE_NAME); if (attr) { name = geis_attr_value_to_string(attr); } return name; } /** * Gets the numeric identifier of the gesture class. */ GeisInteger geis_gesture_class_id(GeisGestureClass gesture_class) { GeisInteger id = -1; GeisAttr attr = geis_attr_bag_find(gesture_class->attrs, GEIS_CLASS_ATTRIBUTE_ID); if (attr) { id = geis_attr_value_to_integer(attr); } return id; } /* * Gets the number of attributes of the gesture class. */ GeisSize geis_gesture_class_attr_count(GeisGestureClass gesture_class) { return geis_attr_bag_count(gesture_class->attrs); } /* * Gets the indicated attribute of the gesture class. */ GeisAttr geis_gesture_class_attr(GeisGestureClass gesture_class, int index) { return geis_attr_bag_attr(gesture_class->attrs, index); } /* * Inserts an attr into a gesture class. */ GeisStatus geis_gesture_class_add_attr(GeisGestureClass gesture_class, GeisAttr attr) { return geis_attr_bag_insert(gesture_class->attrs, attr); } geis-2.2.17+16.04.20160126/libgeis/geis_region.c0000644000015600001650000001306612651717544021172 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_region.c * @brief implementation of the GEIS v2.0 API region module * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_region.h" #include "geis_atomic.h" #include "geis_error.h" #include "geis_logging.h" #include #include #include struct _GeisRegion { GeisRefCount refcount; GeisString type; GeisString name; union { int windowid; } data; }; struct _GeisRegionBag { GeisRegion *region_store; GeisSize region_store_size; GeisSize region_count; }; static const int region_bag_growth_constant = 2; /* * Constructs a region bag. */ GeisRegionBag geis_region_bag_new() { GeisRegionBag bag = calloc(1, sizeof(struct _GeisRegionBag)); if (!bag) { geis_error("failed to allocate region bag"); goto final_exit; } bag->region_store_size = 3; bag->region_count = 0; bag->region_store = calloc(bag->region_store_size, sizeof(GeisRegion)); if (!bag->region_store) { geis_error("failed to allocate region bag store"); goto unwind_bag; } goto final_exit; unwind_bag: free(bag); final_exit: return bag; } /* * Destroys a region bag. */ void geis_region_bag_delete(GeisRegionBag bag) { GeisSize i; for (i = bag->region_count; i > 0; --i) { geis_region_delete(bag->region_store[i-1]); } free(bag); } /* * Gets the number of regions held in a bag. */ GeisSize geis_region_bag_count(GeisRegionBag bag) { return bag->region_count; } /* * Gets an indicated region from a bag. */ GeisRegion geis_region_bag_region(GeisRegionBag bag, GeisSize index) { GeisRegion region = NULL; if (index < bag->region_count) { region = bag->region_store[index]; } return region; } /* * Puts a region into a bag. */ GeisStatus geis_region_bag_insert(GeisRegionBag bag, GeisRegion region) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->region_count >= bag->region_store_size) { GeisSize new_store_size = bag->region_store_size * region_bag_growth_constant; GeisRegion *new_store = realloc(bag->region_store, new_store_size * sizeof(struct _GeisRegion)); if (!new_store) { geis_error("failed to reallocate region bag"); goto error_exit; } bag->region_store = new_store; bag->region_store_size = new_store_size; } bag->region_store[bag->region_count++] = region; status = GEIS_STATUS_SUCCESS; error_exit: return status; } /** * Takes a region out of a bag. */ GeisStatus geis_region_bag_remove(GeisRegionBag bag, GeisRegion region) { GeisSize i; GeisStatus status = GEIS_STATUS_SUCCESS; for (i = 0; i < bag->region_count; ++i) { if (bag->region_store[i] == region) { GeisSize j; geis_region_delete(bag->region_store[i]); --bag->region_count; for (j = i; j < bag->region_count; ++j) { bag->region_store[j] = bag->region_store[j+1]; } break; } } return status; } /* * Constructs a region. */ GeisRegion geis_region_new(Geis geis, GeisString name, GeisString init_arg_name, ...) { GeisRegion region = NULL; va_list varargs; region = calloc(1, sizeof(struct _GeisRegion)); if (!region) { geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error allocating region"); goto final_exit; } va_start(varargs, init_arg_name); while (init_arg_name) { if (0 == strcmp(init_arg_name, GEIS_REGION_X11_ROOT)) { if (region->type) { geis_warning("multiple region types requested, only using the first"); break; } region->type = strdup(init_arg_name); geis_debug("using X11 root"); } else if (0 == strcmp(init_arg_name, GEIS_REGION_X11_WINDOWID)) { if (region->type) { geis_warning("multiple region types requested, only using the first"); break; } region->type = strdup(init_arg_name); region->data.windowid = va_arg(varargs, int); geis_debug("using X11 windowid 0x%08x", region->data.windowid); } init_arg_name = va_arg(varargs, GeisString); } va_end(varargs); ++region->refcount; region->name = strdup(name); final_exit: return region; } /* * Destroys a GEIS v2.0 region. */ GeisStatus geis_region_delete(GeisRegion region) { if (0 == geis_atomic_unref(®ion->refcount)) { free((char *)region->name); free((char *)region->type); free(region); } return GEIS_STATUS_SUCCESS; } /* * Gets the name of a GEIS v2.0 region. */ GeisString geis_region_name(GeisRegion region) { return region->name; } /* * Adds a reference to a region. */ void geis_region_ref(GeisRegion region) { geis_atomic_ref(®ion->refcount); } /* * Gets the type of the region. */ GeisString geis_region_type(GeisRegion region) { return region->type; } /* * Gets the data (if any) associated with the region type. */ void * geis_region_data(GeisRegion region) { return ®ion->data; } geis-2.2.17+16.04.20160126/libgeis/geis_frame.c0000644000015600001650000001602612651717544021000 0ustar pbuserpbgroup00000000000000/** * @file geis_frame.c * @brief uFrame Geis gesture frame module implementation * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_frame.h" #include "geis_attr.h" #include "geis_logging.h" #include #include /* Use a hard-coded value for this for simplicity. */ #define MAX_FRAME_CLASSES 4 /* Use a hard-coded value for this for simplicity. */ #define MAX_FRAME_TOUCHES 16 struct _GeisFrame { GeisFrame next; GeisInteger id; GeisAttrBag attr_bag; GeisFloat matrix[16]; GeisSize class_count; GeisSize class_size; GeisGestureClass classes[MAX_FRAME_CLASSES]; GeisSize touch_count; GeisSize touch_size; GeisTouchId *touches; }; struct _GeisFrameSet { GeisSize count; GeisFrame first; }; /* * Creates a new, empty frame set. */ GeisFrameSet geis_frameset_new() { GeisFrameSet frameset = calloc(1, sizeof(struct _GeisFrameSet)); if (!frameset) { geis_error("error allocating frame set"); goto final_exit; } final_exit: return frameset; } /* * Destroys a frame set and all framees contained in it. */ void geis_frameset_delete(GeisFrameSet frameset) { GeisFrame p = frameset->first; while (p) { GeisFrame tmp = p->next; geis_frame_delete(p); p = tmp; } free(frameset); } /* * Inserts a frame into a frame set. */ GeisStatus geis_frameset_insert(GeisFrameSet frameset, GeisFrame frame) { if (frameset->count == 0) { frameset->first = frame; } else { GeisFrame p = frameset->first; while (p->next) p = p->next; p->next = frame; } ++frameset->count; return GEIS_STATUS_SUCCESS; } GeisSize geis_frameset_frame_count(GeisFrameSet frameset) { return frameset->count; } GeisFrame geis_frameset_frame(GeisFrameSet frameset, GeisSize index) { GeisFrame frame = NULL; if (index >= frameset->count) { geis_warning("frame set index out of range"); } else { GeisSize i; frame = frameset->first; for (i = 0; i < index; ++i) { frame = frame->next; } } return frame; } /* * Creates a new gesture frame. */ GeisFrame geis_frame_new(GeisInteger id) { GeisFrame frame = calloc(1, sizeof(struct _GeisFrame)); if (!frame) { geis_error("error allocating frame"); goto final_exit; } frame->attr_bag = geis_attr_bag_new(5); if (!frame->attr_bag) { geis_error("error allocating frame attr bag"); goto unwind_frame; } frame->class_size = MAX_FRAME_CLASSES; frame->touch_size = MAX_FRAME_TOUCHES; /** @todo make this configurable */ frame->touches = calloc(frame->touch_size, sizeof(GeisTouchId)); if (!frame->touches) { geis_error("error allocating frame touoches"); goto unwind_attr_bag; } frame->id = id; goto final_exit; unwind_attr_bag: geis_attr_bag_delete(frame->attr_bag); unwind_frame: free(frame); frame = NULL; final_exit: return frame; } /* * Destroys a gesture frame and all gesture frames contained in it. */ void geis_frame_delete(GeisFrame frame) { free(frame->touches); geis_attr_bag_delete(frame->attr_bag); free(frame); } /* * Gets the identifier of a gesture frame. */ GeisGestureId geis_frame_id(GeisFrame frame) { return frame->id; } /* * Marks the frame as belonging to a given class of gestures. */ GeisStatus geis_frame_set_is_class(GeisFrame frame, GeisGestureClass gesture_class) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisSize i; if (!gesture_class) { geis_error("NULL gesture class received."); return status; } for (i = 0; i < frame->class_count; ++i) { if (0 == strcmp(geis_gesture_class_name(gesture_class), geis_gesture_class_name(frame->classes[i]))) { return GEIS_TRUE; } } if (frame->class_count < frame->class_size) { frame->classes[frame->class_count++] = gesture_class; status = GEIS_TRUE; } return status; } /* * Indicates if a gesture frame belongs to a gesture class. */ GeisBoolean geis_frame_is_class(GeisFrame frame, GeisGestureClass gesture_class) { return geis_frame_is_class_by_name(frame, geis_gesture_class_name(gesture_class)); } /* * Indicates if a gesture frame belongs to a gesture class. */ GeisBoolean geis_frame_is_class_by_name(GeisFrame frame, GeisString class_name) { GeisBoolean is_class = GEIS_FALSE; GeisSize i; for (i = 0; i < frame->class_count; ++i) { if (0 == strcmp(class_name, geis_gesture_class_name(frame->classes[i]))) { is_class = GEIS_TRUE; break; } } return is_class; } GeisSize geis_frame_class_count(GeisFrame frame) { return frame->class_count; } GeisGestureClass geis_frame_class(GeisFrame frame, GeisSize index) { return frame->classes[index]; } /* * Inserts an attr. */ GeisStatus geis_frame_add_attr(GeisFrame frame, GeisAttr attr) { return geis_attr_bag_insert(frame->attr_bag, attr); } /* * Gets the number of attrs associated with a frame. */ GeisSize geis_frame_attr_count(GeisFrame frame) { return geis_attr_bag_count(frame->attr_bag); } /* * Gets an indicated attr from a frame. */ GeisAttr geis_frame_attr(GeisFrame frame, GeisSize index) { return geis_attr_bag_attr(frame->attr_bag, index); } /* * Gets a named attr from a frame. */ GeisAttr geis_frame_attr_by_name(GeisFrame frame, GeisString name) { return geis_attr_bag_find(frame->attr_bag, name); } /** * Sets the frame transform matrix. */ void geis_frame_set_matrix(GeisFrame frame, const GeisFloat *matrix) { memcpy(frame->matrix, matrix, sizeof(frame->matrix)); } /* * Gets the current transform matrix of a gesture. */ GeisFloat * geis_frame_matrix(GeisFrame frame) { return frame->matrix; } /* * Inserts a touch index into a gesture frame. */ GeisStatus geis_frame_add_touchid(GeisFrame frame, GeisTouchId touchid) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (frame->touch_count < frame->touch_size) { frame->touches[frame->touch_count++] = touchid; } return status; } /* * Gets the number of touches making up a gesture for the frame. */ GeisSize geis_frame_touchid_count(GeisFrame frame) { return frame->touch_count; } /* * Gets the index of the indicated touch within the gesture frame. */ GeisTouchId geis_frame_touchid(GeisFrame frame, GeisSize index) { if (index < frame->touch_count) { return frame->touches[index]; } return 0; } geis-2.2.17+16.04.20160126/libgeis/geis_backend_token.c0000644000015600001650000000407612651717544022477 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_token.c * @brief internal GEIS back end token implementation * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_backend_token.h" #include "geis_backend_protected.h" #include "geis_logging.h" /* * Clones a new backend token. */ GeisBackendToken geis_backend_token_clone(GeisBackendToken token) { return token->vtbl->clone(token); } /* * Destroys a backend token. */ void geis_backend_token_delete(GeisBackendToken token) { token->vtbl->finalize(token); } /* * Composes two backend tokens into a new backend token. */ void geis_backend_token_compose(GeisBackendToken lhs, GeisBackendToken rhs) { lhs->vtbl->compose(lhs, rhs); } /* * Activates a token in the back end. */ GeisStatus geis_backend_token_activate(GeisBackendToken token, GeisSubscription subscription) { geis_debug("called"); return token->vtbl->activate(token, subscription); } /** * Deactivates a token in the back end. */ GeisStatus geis_backend_token_deactivate(GeisBackendToken token, GeisSubscription subscription) { geis_debug("called"); return token->vtbl->deactivate(token, subscription); } /** * Frees the private data that the backend allocated for a given subscription */ void geis_backend_token_free_subscription_pdata(GeisBackendToken token, GeisSubscription subscription) { token->vtbl->free_subscription_pdata(token, subscription); } geis-2.2.17+16.04.20160126/libgeis/geis_backend_protected.h0000644000015600001650000000577312651717544023362 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_protected.h * @brief internal GEIS back end base class "protected" interface * * This file contains the implementation interface for the various GEIS v2 back * ends. */ /* * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_BACKEND_PROTECTED_H_ #define GEIS_BACKEND_PROTECTED_H_ #include "geis/geis.h" #include "geis_backend.h" #include "geis_backend_token.h" /** * The custom dispatch table for "derived" GEIS v2 backends. */ typedef struct GeisBackendVtable { void (* construct)(void *mem, Geis geis); void (* finalize)(GeisBackend); GeisBackendToken (* create_token)(GeisBackend, GeisBackendTokenInitState); GeisStatus (* accept_gesture)(GeisBackend, GeisGroup, GeisGestureId); GeisStatus (* reject_gesture)(GeisBackend, GeisGroup, GeisGestureId); GeisStatus (* activate_device)(GeisBackend, GeisDevice); GeisStatus (* deactivate_device)(GeisBackend, GeisDevice); GeisStatus (* get_configuration)(GeisBackend, GeisSubscription, GeisString, GeisPointer); GeisStatus (* set_configuration)(GeisBackend, GeisSubscription, GeisString, GeisPointer); } *GeisBackendVtable; /** * The custom dispatch table for backend-specific tokens. * * Backend tokens are used when creating subscriptions (including filters and * filter terms). */ typedef struct GeisBackendTokenVtable { GeisBackendToken (* clone)(GeisBackendToken); void (* finalize)(GeisBackendToken); void (* compose)(GeisBackendToken, GeisBackendToken); GeisStatus (* activate)(GeisBackendToken, GeisSubscription); GeisStatus (* deactivate)(GeisBackendToken, GeisSubscription); void (* free_subscription_pdata)(GeisBackendToken, GeisSubscription); } *GeisBackendTokenVtable; struct GeisBackendToken { GeisBackendTokenVtable vtbl; }; /** * Registers back ends with the API. * * @param[in] name The name of the back end. * @param[in] size The size of the back end data structure. * @param[in] vtbl A pointer to a (static) function dispatch table. * * This registration function should be called from a module init routine * decorated with the GCC attribute((constructor)) so the back end gets * registered with the API. */ void geis_register_backend(GeisString name, GeisSize size, GeisBackendVtable vtbl); #endif /* GEIS_BACKEND_PROTECTED_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_group.c0000644000015600001650000000734712651717544021050 0ustar pbuserpbgroup00000000000000/** * @file geis_group.c * @brief Geis gesture group module implementation * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_group.h" #include "geis_logging.h" #include struct _GeisGroup { GeisGroup next; GeisInteger id; GeisFrameSet frameset; }; struct _GeisGroupSet { GeisSize count; GeisGroup first; }; /* * Creates a new, empty group set. */ GeisGroupSet geis_groupset_new() { GeisGroupSet groupset = calloc(1, sizeof(struct _GeisGroupSet)); if (!groupset) { geis_error("error allocating gesture group set"); goto final_exit; } final_exit: return groupset; } /* * Destroys a group set and all groups contained in it. */ void geis_groupset_delete(GeisGroupSet groupset) { GeisGroup p = groupset->first; while (p) { GeisGroup tmp = p->next; geis_group_delete(p); p = tmp; } free(groupset); } /* * Inserts a gesture group into a group set. */ GeisStatus geis_groupset_insert(GeisGroupSet groupset, GeisGroup group) { if (groupset->count == 0) { groupset->first = group; } else { GeisGroup p = groupset->first; while (p->next) p = p->next; p->next = group; } ++groupset->count; return GEIS_STATUS_SUCCESS; } GeisSize geis_groupset_group_count(GeisGroupSet groupset) { return groupset->count; } GeisGroup geis_groupset_group(GeisGroupSet groupset, GeisSize index) { GeisGroup group = NULL; if (index >= groupset->count) { geis_warning("gesture group set index out of range"); } else { GeisSize i; group = groupset->first; for (i = 0; i < index; ++i) { group = group->next; } } return group; } /* * Creates a new gesture group. */ GeisGroup geis_group_new(GeisInteger id) { GeisGroup group = calloc(1, sizeof(struct _GeisGroup)); if (!group) { geis_error("error allocating gesture group"); goto final_exit; } group->frameset = geis_frameset_new(); if (!group->frameset) { geis_error("error allocating gesture group frame set"); goto unwind_group; } group->id = id; goto final_exit; unwind_group: free(group); group = NULL; final_exit: return group; } /* * Destroys a gesture group and all gesture frames contained in it. */ void geis_group_delete(GeisGroup group) { geis_frameset_delete(group->frameset); free(group); } /* * Gets the identifier of a gesture group. */ GeisInteger geis_group_id(GeisGroup group) { return group->id; } /* * Adds a gesture frame to a gesture group. */ GeisStatus geis_group_insert_frame(GeisGroup group, GeisFrame frame) { return geis_frameset_insert(group->frameset, frame); } /* * Gets the number of gesture frames in a gesture group. */ GeisSize geis_group_frame_count(GeisGroup group) { return geis_frameset_frame_count(group->frameset); } /* * Gets an indicated gesture frame from a gesture group. */ GeisFrame geis_group_frame(GeisGroup group, GeisSize index) { return geis_frameset_frame(group->frameset, index); } /* * Marks a gesture group as rejected. */ void geis_group_reject(GeisGroup group GEIS_UNUSED) { } geis-2.2.17+16.04.20160126/libgeis/geis_event_queue.c0000644000015600001650000001067112651717544022233 0ustar pbuserpbgroup00000000000000/** * @file geis_event_queue.c * @brief internal Geis event queue implementation */ /* Copyright 2010, 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_event_queue.h" #include "geis_logging.h" #include typedef struct _GeisEventQueueNode *GeisEventQueueNode; /** * A node in a GEIS event queue. The event queue is a singly-linked list. */ struct _GeisEventQueueNode { GeisEventQueueNode eq_next; GeisEvent eq_event; }; /** * A GEIS event queue. The event queue is a singly linked list with a pool of * free nodes. */ struct _GeisEventQueue { GeisEventQueueNode eq_front; GeisEventQueueNode eq_back; GeisEventQueueNode eq_pool; }; /* * Creates a new Geis Event queue. */ GeisEventQueue geis_event_queue_new() { GeisEventQueue queue = calloc(1, sizeof(struct _GeisEventQueue)); if (!queue) { geis_error("can not allocate event queue"); } return queue; } /* * Destroys a Geis Event queue. */ void geis_event_queue_delete(GeisEventQueue queue) { GeisEventQueueNode node = queue->eq_pool; while (node) { GeisEventQueueNode eq_next = node->eq_next; free(node); node = eq_next; } node = queue->eq_front; while (node) { GeisEventQueueNode eq_next = node->eq_next; geis_event_delete(node->eq_event); free(node); node = eq_next; } free(queue); } /* * Pushes a new event onto the back of the event queue. */ GeisStatus geis_event_queue_enqueue(GeisEventQueue queue, GeisEvent event) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisEventQueueNode node; if (queue->eq_pool) { node = queue->eq_pool; queue->eq_pool = node->eq_next; node->eq_next = NULL; } else { node = calloc(1, sizeof(struct _GeisEventQueueNode)); if (!node) { geis_error("can not allocate event queue node"); goto error_exit; } } node->eq_event = event; if (!queue->eq_front) { queue->eq_front = node; } if (queue->eq_back) { queue->eq_back->eq_next = node; } queue->eq_back = node; status = GEIS_STATUS_SUCCESS; error_exit: return status; } /* * Indicates if the event queue is empty. */ GeisBoolean geis_event_queue_is_empty(GeisEventQueue queue) { return queue->eq_front == NULL; } /* * Pushes a node into the front of the free pool for a queue. */ static void _geis_event_queue_add_node_to_pool(GeisEventQueue queue, GeisEventQueueNode node) { node->eq_next = queue->eq_pool; queue->eq_pool = node; } /* * Pops the event off the front of the event queue. */ GeisEvent geis_event_queue_dequeue(GeisEventQueue queue) { GeisEvent event = NULL; if (queue->eq_front) { event = queue->eq_front->eq_event; GeisEventQueueNode node = queue->eq_front; queue->eq_front = node->eq_next; _geis_event_queue_add_node_to_pool(queue, node); if (!queue->eq_front) queue->eq_back = NULL; } return event; } /* * Removes events from a queue of they match a condition. */ void geis_event_queue_remove_if(GeisEventQueue queue, GeisEventMatch matching, void *context) { GeisEventQueueNode prev = NULL; GeisEventQueueNode node = queue->eq_front; while (node) { if (matching(node->eq_event, context)) { GeisEventQueueNode matching_node = node; node = node->eq_next; if (matching_node == queue->eq_front) { queue->eq_front = matching_node->eq_next; } else { prev->eq_next = matching_node->eq_next; } if (matching_node == queue->eq_back) { queue->eq_back = prev; } geis_event_delete(matching_node->eq_event); _geis_event_queue_add_node_to_pool(queue, matching_node); } else { prev = node; node = node->eq_next; } } } geis-2.2.17+16.04.20160126/libgeis/geis_device.h0000644000015600001650000000462312651717544021152 0ustar pbuserpbgroup00000000000000/** * @file geis_device.h * @brief internal Geis Input Device module private interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_DEVICE_H_ #define GEIS_DEVICE_H_ #include "geis/geis.h" /** * @defgroup geis_device_container A Device Container * @{ */ /** * An unsorted container for holding devices. */ typedef struct _GeisDeviceBag *GeisDeviceBag; /** * Creates a new device bag, */ GeisDeviceBag geis_device_bag_new(); /** * Destroys a device bag. * * @param[in] bag The device bag, */ void geis_device_bag_delete(GeisDeviceBag bag); /** * Gets the number of devices in the bag. * * @param[in] bag The device bag, */ GeisSize geis_device_bag_count(GeisDeviceBag bag); /** * Gets an indicated device from a bag. * * @param[in] bag The device bag. * @param[in] index The index. */ GeisDevice geis_device_bag_device(GeisDeviceBag bag, GeisSize index); /** * Inserts a device in the bag. * * @param[in] bag The device bag. * @param[in] device The device to insert. */ GeisStatus geis_device_bag_insert(GeisDeviceBag bag, GeisDevice device); /** * Remoes a device from the bag. * * @param[in] bag The device bag. * @param[in] device The device to remove. */ GeisStatus geis_device_bag_remove(GeisDeviceBag bag, GeisDevice device); /** @} */ /** * @defgroup geis_device Internal Device Functions * @{ */ /** * Creates a new device. * * @param[in] name A system-specific device name. * @param[in] id A system-specific device identifier. */ GeisDevice geis_device_new(GeisString name, GeisInteger id); /** * Inserts an attr into a device. * * @param[in] device A device. * @param[in] attr An attr. */ void geis_device_add_attr(GeisDevice device, GeisAttr attr); /* @} */ #endif /* GEIS_DEVICE_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_gesture_flick.h0000644000015600001650000000175712651717544022546 0ustar pbuserpbgroup00000000000000/** * @file geis_gesture_flick.h * @brief higher-level "flick" gesture recognizer * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_GESTURE_FLICK_H_ #define GEIS_GESTURE_FLICK_H_ #include "geis/geis.h" typedef struct GeisGestureFlick *GeisGestureFlick; GeisGestureFlick geis_gesture_flick_new(Geis geis); void geis_gesture_flick_delete(GeisGestureFlick flick); #endif /* GEIS_GESTURE_FLICK_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_atomic.h0000644000015600001650000000257412651717544021172 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_atomic.c * @brief Atomic operation helpers * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_ATOMIC_H_ #define GEIS_ATOMIC_H_ /** * An atomic value used for reference counting. */ typedef unsigned int GeisRefCount; /** * Atomically increments a refcount. * * @param[in] refcount A pointer to a refcount. */ static inline void geis_atomic_ref(GeisRefCount *refcount) { __sync_fetch_and_add(refcount, 1); } /** * Atomically decrements a refcount. * * @param[in] refcount A pointer to a refcount. * * @returns the new reccount value. */ static inline GeisRefCount geis_atomic_unref(GeisRefCount *refcount) { return __sync_sub_and_fetch(refcount, 1); } #endif /* GEIS_ATOMIC_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_private.h0000644000015600001650000003666412651717544021377 0ustar pbuserpbgroup00000000000000/** * @file geis_internal.h * @brief internal interface of the GEIS API * * This file is the internal interface to the GEIS API object. It provides the * implementation hooks for plugins (back ends, servers, and extensions) to pass * information through the API. */ /* * Copyright 2010, 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_PRIVATE_H_ #define GEIS_PRIVATE_H_ #include #include "geis_error.h" #include "geis_backend.h" #include "geis_backend_token.h" #include "geis_backend_multiplexor.h" #include "geis_class.h" #include "geis_device.h" #include "geis_event_queue.h" #include "geis_filterable.h" #include "geis_region.h" #include "geis_subscription.h" /** * Increases the reference count of an API instance object. * * @param[in] geis The API instance. * * @returns the same API instance. */ Geis geis_ref(Geis geis); /** * Decremenets the reference count of an API instance object. * * @param[in] geis The API instance. * * If the reference count on the API instance object drops to zero, the object * is destroyed. */ void geis_unref(Geis geis); /** * Gets the error stack from the geis object. * * @param[in] geis The API instance. */ GeisErrorStack *geis_error_stack(Geis geis); /** * Adds a subscription to the API instance. * * @param[in] geis The API instance. * @param[in] subscription A GEIS subscirption. */ GeisSize geis_add_subscription(Geis geis, GeisSubscription subscription); /** * Adds a back end file descriptor to multiplex. * * @param[in] geis The API instance. * @param[in] fd The file descriptor to add. * @param[in] activity The file descriptor activity(ies) to monitor. * @param[in] callback The file descriptor event callback. * @param[in] context A contextual datum. */ void geis_multiplex_fd(Geis geis, int fd, GeisBackendMultiplexorActivity activity, GeisBackendFdEventCallback callback, void *context); /** * Modifies a multiplexed back end file descriptor. * * @param[in] geis The API instance. * @param[in] fd The file descriptor to add. * @param[in] activity The file descriptor activity(ies) to monitor. */ void geis_remultiplex_fd(Geis geis, int fd, GeisBackendMultiplexorActivity activity); /** * Removes a back end file descriptor from the multiplex. * * @param[in] geis The API instance. * @param[in] fd The file descriptor to remove. */ void geis_demultiplex_fd(Geis geis, int fd); /** * Posts a new event through the API. * * @param[in] geis The API instance. * @param[in] event The GEIS event. */ void geis_post_event(Geis geis, GeisEvent event); typedef enum GeisProcessingResult { GEIS_PROCESSING_IGNORED = 0, GEIS_PROCESSING_DISPOSE_EVENT = 10, GEIS_PROCESSING_COMPLETE = 20, GEIS_PROCESSING_FAIL = 99 } GeisProcessingResult; typedef GeisProcessingResult (*GeisProcessingCallback)(GeisEvent event, void *context); /** * Registers an event-processing callback. * * @param[in] geis The API instance. * @param[in] priority The event-handling priority. * @param[in] event_callback The event-handling callback. * @param[in] context The context to supply to the callback. */ void geis_register_processing_callback(Geis geis, int priority, GeisProcessingCallback event_callback, void *context); /** * Removes all matching events from all event queues. * * @param[in] geis The API instance. * @param[in] matching A unary predicate function to indicate the events to be * removed. * @param[in] context An application-specific context value to be passed to * the matching function. * * Removes any and all queued events that are indicated by the passed matching * function. */ void geis_remove_matching_events(Geis geis, GeisEventMatch matching, void *context); /** * @defgroup geis_v2_plugin Plugin Interfaces * @ingroup geis_v2 * Interfaces for plugin implementors. * * The Advanced API provides an extension capability through a defined plugin * interface. * * @{ */ /** * Resgisters a new gesture class with the API. * * @param[in] geis The API instance to which the new gesture * class will be added. * @param[in] gesture_class The new gesture class. * @param[in] filterable_attr_count The number of filterable attributes in the * following structure. * @param[in] filterable_attrs The set of attributes that may be used if * filter terms for this class. * * An extension must register a gesture class if it will be providing new * gesture class events. Any filterable attributes (other than gesture class * name, which is mandatory) must be provided. A filterable attribute for the * class name will be automatically added. */ void geis_register_gesture_class(Geis geis, GeisGestureClass gesture_class, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs); GeisGestureClassBag geis_gesture_classes(Geis geis); /** * Registers a new input device with the API. * * @param[in] geis The API instance to which the new input * device will be added. * @param[in] device The new input device. * @param[in] filterable_attr_count The number of filterable attributes in the * following structure. * @param[in] filterable_attrs The set of attributes that may be used if * filter terms for this device. */ void geis_register_device(Geis geis, GeisDevice device, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs); /** * Unregisters an existing input device with the API. * * @param[in] geis The API instance to which the new input * device will be added. * @param[in] device The input device to unregister. */ void geis_unregister_device(Geis geis, GeisDevice device); GeisDeviceBag geis_devices(Geis geis); /** * The possible selection results for a filter. */ typedef enum GeisSelectResult { GEIS_SELECT_RESULT_NONE, /**< Nothing was selected. */ GEIS_SELECT_RESULT_SOME, /**< A proper subset of data was selected. */ GEIS_SELECT_RESULT_ALL /**< All data was selected. */ } GeisSelectResult; /** * Selects devices that pass the given filter terms. * * @param[in] geis The API instance with a list of known devices. * @param[in] filter The filter used to select devices. * @param[out] bag The bag in which to place the selected devices. * * @retval GEIS_SELECT_RESULT_NONE No devices match the filter. The contents * of @p bag remains unchanged. * @retval GEIS_SELECT_RESULT_SOME Some device matches were found and added to * @p bag. * @retval GEIS_SELECT_RESULT_ALL All devices match the filetr (there were * probably no filter terms in the device * facility). The contents of @p bag remain * unchanged. */ GeisSelectResult geis_select_devices(Geis geis, GeisFilter filter, GeisDeviceBag bag); /** * @defgoup geis_v2_region_filters * @{ */ /** * Registers a new region (type) with the API. * * @param[in] geis The API instance to which the new region * will be added. * @param[in] region The new region. * @param[in] filterable_attr_count The number of filterable attributes in the * following structure. * @param[in] filterable_attrs The set of attributes that may be used if * filter terms for this class. */ void geis_register_region(Geis geis, GeisRegion region, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs); /** * Gets an iterator to the first registered filterable region attribute. * * @param[in] geis The API instance. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_begin(Geis geis); /** * Advances an iterator to the next registered filterable region attribute. * * @param[in] geis The API instance. * @param[in] iter A filterable attribute iterator. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_next(Geis geis, GeisFilterableAttributeBagIter iter); /** * Gets an iterator to the on-past-the-last registered filterable region * attribute. * * @param[in] geis The API instance. * * It is an error to dereference the returned iterator. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_end(Geis geis); /** @} */ /** * Resgisters a new special filters with the API. * * @param[in] geis The API instance to which the new region * will be added. * @param[in] filterable_attr_count The number of filterable attributes in the * following structure. * @param[in] filterable_attrs The set of attributes that may be used if * filter terms for this class. */ void geis_register_special(Geis geis, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs); /** * Invokes the filterable attribute's add_term callback for a named attribute. * * @param[in] geis The API instance. * @param[in] facility The facility. * @param[in] token The back end filter token. * @param[in] name The filter attribute name. * @param[in] op The filter operation. * @param[in] value The filter value. */ GeisStatus geis_filterable_attribute_foreach(Geis geis, GeisFilterFacility facility, GeisBackendToken token, GeisString name, GeisFilterOperation op, void *value); /** * Gets the type of a named device attr. * * @param[in] geis The API instance. * @param[in] attr_name The name of the device attr. * * Gets the type of a device attr by name, assuming the attr is known. * * There is a basic assumption that all device attrs of the same name are of the * same type. * * @returns the type of the attr, GEIS_ATTR_TYPE_UNKNOWN if the attr is unknown. */ GeisAttrType geis_get_device_attr_type(Geis geis, GeisString attr_name); /** * Gets the type of a named class attr. * * @param[in] geis The API instance. * @param[in] attr_name The name of the class attr. * * Gets the type of a class attr by name, assuming the attr is known. * * There is a basic assumption that all class attrs of the same name are of the * same type. * * @returns the type of the attr, GEIS_ATTR_TYPE_UNKNOWN if the attr is unknown. */ GeisAttrType geis_get_class_attr_type(Geis geis, GeisString attr_name); /** * Gets the type of a named region attr. * * @param[in] geis The API instance. * @param[in] attr_name The name of the region attr. * * Gets the type of a region attr by name, assuming the attr is known. * * There is a basic assumption that all region attrs of the same name are of the * same type. * * @returns the type of the attr, GEIS_ATTR_TYPE_UNKNOWN if the attr is unknown. */ GeisAttrType geis_get_region_attr_type(Geis geis, GeisString attr_name); /** * Gets the type of a named special attr. * * @param[in] geis The API instance. * @param[in] attr_name The name of the special attr. * * Gets the type of a special attr by name, assuming the attr is known. * * There is a basic assumption that all special attrs of the same name are of the * same type. * * @returns the type of the attr, GEIS_ATTR_TYPE_UNKNOWN if the attr is unknown. */ GeisAttrType geis_get_special_attr_type(Geis geis, GeisString attr_name); /** * Gets a feature configuration value. * * @param[in] geis An opaque GEIS API object. * @param[in] sub A subscription. May be NULL for global configuration * items. * @param[in] item_name Selects the configuration value to return. * @param[out] item_value Points to a buffer to contain the output value. The * actual type of this buffer depends on the * @p configuration_value_name. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GeisStatus geis_get_sub_configuration(Geis geis, GeisSubscription sub, GeisString item_name, void *item_value); /** * Sets a feature configuration value. * * @param[in] geis An opaque GEIS API object. * @param[in] sub A subscription. May be NULL for global configuration * items. * @param[in] item_name Selects the configuration value to return. * @param[in] item_value Points to a buffer to contain the output configuration * value. The actual type of this buffer depends on the * @p configuration_value_name. * * @retval GEIS_STATUS_BAD_ARGUMENT an invalid argument value was passed * @retval GEIS_STATUS_NOT_SUPPORTED the configuration value is not supported * @retval GEIS_STATUS_SUCCESS normal successful completion */ GeisStatus geis_set_sub_configuration(Geis geis, GeisSubscription sub, GeisString item_name, void *item_value); /* @} */ #endif /* GEIS_PRIVATE_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_subscription.h0000644000015600001650000001377512651717544022447 0ustar pbuserpbgroup00000000000000/** * @file geis_subscription.h * @brief internal Geis subscription modul private interface * * Copyright 2010, 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_SUBSCRIPTION_H_ #define GEIS_SUBSCRIPTION_H_ #include #include "geis_filter.h" /** * @defgroup geis_sub_container A Subscription Container * @{ */ /** * A container for subscriptions. */ typedef struct _GeisSubBag *GeisSubBag; typedef GeisSubscription* GeisSubBagIterator; /** * Creates a new Geis Subscription container. * * @param[in] hint A hint as to how many subscriptions to initially allocate in * the new container. */ GeisSubBag geis_subscription_bag_new(GeisSize size_hint); /** * Destroys a Geis Subscription container. * * @param[in] bag The bag. */ void geis_subscription_bag_delete(GeisSubBag bag); /** * Tells how any entires in a Geis Subscription container. * * @param[in] bag The bag. */ GeisSize geis_subscription_bag_count(GeisSubBag bag); /** * Gets an iterator initialized to the first subscription held in a bag. * * @param[in] bag The bag. */ GeisSubBagIterator geis_subscription_bag_begin(GeisSubBag bag); /** * Increments the subscrition bag iterator. * * @param[in] bag The bag. * @param[in] iter The iterator. */ GeisSubBagIterator geis_subscription_bag_iterator_next(GeisSubBag bag, GeisSubBagIterator iter); /** * Gets an iterator indicating one-past-the-last sub in a bag. * * @param[in] bag The bag. */ GeisSubBagIterator geis_subscription_bag_end(GeisSubBag bag); /** * Creates a new subscription object in a subscription container. * * @param[in] bag The container. * @param[in] sub The subscription to be added. * * @returns the index of the newly inserted subscription */ GeisSize geis_subscription_bag_insert(GeisSubBag bag, GeisSubscription sub); /** * Removes a subscription from a subscription container. * * @param[in] bag The subscription container. * @param[in] sub The subscription to be removed. */ void geis_subscription_bag_remove(GeisSubBag bag, GeisSubscription sub); /** * Removes all subscriptions from a subscription container. * * @param[in] bag The subscription container. */ void geis_subscription_bag_empty(GeisSubBag bag); /** * Marks all subscriptions in a bag as invalid. * * @param[in] bag The subscription container. * * See geis_subscription_invalidate. */ void geis_subscription_bag_invalidate(GeisSubBag bag); /** * Looks for an subscription in an subscription container. * * @param[in] bag The bag. */ GeisSubscription geis_subscription_bag_find(GeisSubBag bag, GeisInteger sub_id); /* @} */ /** * Gets the numvber of filters in a subscirption. * * @param[in] sub The subscription. */ GeisSize geis_subscription_filter_count(GeisSubscription sub); /** * Gets an indicated filter from a subscription. * * @param[in] sub The subscription. * @param[in] index Indicates which filter to retrieve. */ GeisFilter geis_subscription_filter(GeisSubscription sub, GeisSize index); /** * Gets an iterator initialized to the first filter on a subscription. * * @param[in] sub The subscription. */ GeisFilterIterator geis_subscription_filter_begin(GeisSubscription sub); /** * Gets an iterator initialized to the one-past-the-last filter on a subscription. * * @param[in] sub The subscription. */ GeisFilterIterator geis_subscription_filter_end(GeisSubscription sub); /** * Gets the next filter in sequence. * * @param[in] sub The subscription. * @param[in] iter A filter iterator. * * @returns an interator initialized to the next filter in sequence in the * subscription, or an iterator that is equal to geis_subscription_filter_end(). */ GeisFilterIterator geis_subscription_filter_next(GeisSubscription sub, GeisFilterIterator iter); /** * Invalidates a subscription. * * @param[in] sub The subscription. * * A subscription becomes invalid when its owning Geis instance has been * destroyed but the GeisSubscription instance has not. This can occur because * lifetime of both objects is under external control. */ void geis_subscription_invalidate(GeisSubscription sub); /** * Sets the operational flags for the subscription. * * @param[in] sub The subscription. * @param[in] flags The subscription flags. * * Changes which flags are set during construction of the subscription instance. * It is inappropriate to change the operational flags of an activated * subscription. * * @retval GEIS_STATUS_SUCCESS Normal successful completion. * @retval GEIS_STATUS_NOT_SUPPORTED Call made to an activated subcription. */ GeisStatus geis_subscription_set_flags(GeisSubscription sub, GeisSubscriptionFlags flags); /** * Gets the operational flags for the subscription. * * @param[in] sub The subscription. */ GeisSubscriptionFlags geis_subscription_flags(GeisSubscription sub); /** * Gets an associated datum from the subscription. * * @param[in] sub The subscription. */ GeisPointer geis_subscription_pdata(GeisSubscription subscription); /** * Sets an associated datum on the subscription. * * @param[in] sub The subscription. * @param[in] data Some data. */ void geis_subscription_set_pdata(GeisSubscription subscription, GeisPointer data); #endif /* GEIS_SUBSCRIPTION_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_attr.c0000644000015600001650000002706112651717544020661 0ustar pbuserpbgroup00000000000000/** * @file geis_attr.c * @brief internal GeisAttr facilities * * Copyright 2010, 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_attr.h" #include "geis_logging.h" #include #include #include #include struct _GeisAttr { GeisString attr_name; GeisAttrType attr_type; union { GeisBoolean b; GeisFloat f; GeisInteger i; GeisString s; void *p; } attr_value; void (*attr_destructor)(void* p); }; struct _GeisAttrBag { GeisAttr *attr_store; GeisSize attr_store_size; GeisSize attr_count; }; static const float attr_bag_growth_constant = 1.5f; GeisAttrBag geis_attr_bag_new(GeisSize size_hint) { GeisAttrBag bag = calloc(1, sizeof(struct _GeisAttrBag)); if (!bag) { geis_error("failed to allocate attr bag"); } else { GeisSize min_size = size_hint > 2 ? size_hint : 2; bag->attr_count = 0; bag->attr_store_size = min_size; bag->attr_store = calloc(bag->attr_store_size, sizeof(GeisAttr)); if (!bag->attr_store) { geis_error("failed to allocate attr bag store"); free(bag); bag = NULL; } } return bag; } void geis_attr_bag_delete(GeisAttrBag bag) { GeisSize i; for (i = 0; i < bag->attr_count; ++i) { geis_attr_delete(bag->attr_store[i]); } free(bag->attr_store); free(bag); } GeisSize geis_attr_bag_count(GeisAttrBag bag) { return bag->attr_count; } GeisStatus geis_attr_bag_insert(GeisAttrBag bag, GeisAttr attr) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->attr_count >= bag->attr_store_size) { GeisSize new_store_size = ceilf(bag->attr_store_size * attr_bag_growth_constant); GeisAttr *new_store = realloc(bag->attr_store, new_store_size * sizeof(struct _GeisAttr)); if (!new_store) { geis_error("failed to reallocate attr bag"); goto error_exit; } bag->attr_store = new_store; bag->attr_store_size = new_store_size; } bag->attr_store[bag->attr_count++] = attr; status = GEIS_STATUS_SUCCESS; error_exit: return status; } GeisStatus geis_attr_bag_replace(GeisAttrBag bag, GeisAttr attr) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisSize i; for (i = 0; i < bag->attr_count; ++i) { if (0 == strcmp(bag->attr_store[i]->attr_name, geis_attr_name(attr))) { geis_attr_delete(bag->attr_store[i]); bag->attr_store[i] = attr; status = GEIS_STATUS_SUCCESS; break; } } return status; } GeisAttr geis_attr_bag_attr(GeisAttrBag bag, GeisSize index) { GeisAttr attr = NULL; if (index >= bag->attr_count) { geis_error("index out of range"); } else { return bag->attr_store[index]; } return attr; } GeisAttr geis_attr_bag_find(GeisAttrBag bag, GeisString attr_name) { GeisAttr attr = NULL; GeisSize i; for (i = 0; i < bag->attr_count; ++i) { if (0 == strcmp(bag->attr_store[i]->attr_name, attr_name)) { attr = bag->attr_store[i]; break; } } return attr; } GeisAttr geis_attr_new(GeisString attr_name, GeisAttrType attr_type, void* attr_value) { GeisAttr attr = calloc(1, sizeof(struct _GeisAttr)); if (!attr) { geis_error("failed to allocate attr"); } else { attr->attr_name = strdup(attr_name); attr->attr_type = attr_type; switch (attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: attr->attr_value.b = *(GeisBoolean*)attr_value; break; case GEIS_ATTR_TYPE_FLOAT: attr->attr_value.f = *(GeisFloat*)attr_value; break; case GEIS_ATTR_TYPE_INTEGER: attr->attr_value.i = *(GeisInteger*)attr_value; break; case GEIS_ATTR_TYPE_STRING: attr->attr_value.s = (GeisString)strdup(attr_value); break; default: attr->attr_value.p = attr_value; } } return attr; } void geis_attr_delete(GeisAttr attr) { if (attr->attr_type == GEIS_ATTR_TYPE_POINTER && attr->attr_destructor) { attr->attr_destructor(attr->attr_value.p); } else if (attr->attr_type == GEIS_ATTR_TYPE_STRING) { free((char *)attr->attr_value.s); } free((void *)attr->attr_name); free(attr); } GeisString geis_attr_name(GeisAttr attr) { return attr->attr_name; } void geis_attr_set_destructor(GeisAttr attr, GeisAttrDestructor destructor) { if (attr->attr_type == GEIS_ATTR_TYPE_POINTER) { attr->attr_destructor = destructor; } } GeisAttrType geis_attr_type(GeisAttr attr) { return attr->attr_type; } void * geis_attr_value(GeisAttr attr) { if (attr->attr_type == GEIS_ATTR_TYPE_POINTER || attr->attr_type == GEIS_ATTR_TYPE_STRING) return attr->attr_value.p; else return &attr->attr_value; } GeisBoolean geis_attr_value_to_boolean(GeisAttr attr) { GeisBoolean b_value = GEIS_FALSE; switch (attr->attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: b_value = attr->attr_value.b; break; case GEIS_ATTR_TYPE_FLOAT: b_value = attr->attr_value.f != 0.0f; break; case GEIS_ATTR_TYPE_INTEGER: b_value = attr->attr_value.i != 0; break; case GEIS_ATTR_TYPE_STRING: b_value = (0 == strlen(attr->attr_value.s) || 0 != strcmp(attr->attr_value.s, "false")); break; default: break; } return b_value; } GeisFloat geis_attr_value_to_float(GeisAttr attr) { GeisFloat f_value = 0.0f; switch (attr->attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: f_value = attr->attr_value.b ? 1.0f : 0.0f; break; case GEIS_ATTR_TYPE_FLOAT: f_value = attr->attr_value.f; break; case GEIS_ATTR_TYPE_INTEGER: f_value = attr->attr_value.i; break; case GEIS_ATTR_TYPE_STRING: sscanf(attr->attr_value.s, "%f", &f_value); break; default: break; } return f_value; } GeisInteger geis_attr_value_to_integer(GeisAttr attr) { GeisInteger i_value = 0; switch (attr->attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: i_value = attr->attr_value.b ? 1 : 0; break; case GEIS_ATTR_TYPE_FLOAT: i_value = attr->attr_value.f; break; case GEIS_ATTR_TYPE_INTEGER: i_value = attr->attr_value.i; break; case GEIS_ATTR_TYPE_STRING: sscanf(attr->attr_value.s, "%d", &i_value); break; default: break; } return i_value; } GeisPointer geis_attr_value_to_pointer(GeisAttr attr) { GeisPointer p_value = NULL; switch (attr->attr_type) { case GEIS_ATTR_TYPE_POINTER: p_value = attr->attr_value.p; break; default: break; } return p_value; } GeisString geis_attr_value_to_string(GeisAttr attr) { GeisString s_value = ""; static char buf[32]; switch (attr->attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: sprintf(buf, "%s", attr->attr_value.b ? "true" : "false"); /* i18n */ s_value = buf; break; case GEIS_ATTR_TYPE_FLOAT: sprintf(buf, "%f", attr->attr_value.f); s_value = buf; break; case GEIS_ATTR_TYPE_INTEGER: sprintf(buf, "%d", attr->attr_value.i); s_value = buf; break; case GEIS_ATTR_TYPE_POINTER: sprintf(buf, "%p", attr->attr_value.p); s_value = buf; break; case GEIS_ATTR_TYPE_STRING: s_value = attr->attr_value.s; break; default: sprintf(buf, "%p", attr->attr_value.p); s_value = buf; break; } return s_value; } GeisBoolean geis_attr_compare(GeisAttr lhs, GeisAttr rhs, GeisFilterOperation op) { GeisBoolean result = GEIS_FALSE; if (lhs->attr_type != rhs->attr_type) return result; switch (lhs->attr_type) { case GEIS_ATTR_TYPE_BOOLEAN: switch (op) { case GEIS_FILTER_OP_EQ: result = lhs->attr_value.b == rhs->attr_value.b; break; case GEIS_FILTER_OP_NE: case GEIS_FILTER_OP_GT: case GEIS_FILTER_OP_LT: result = lhs->attr_value.b != rhs->attr_value.b; break; case GEIS_FILTER_OP_GE: case GEIS_FILTER_OP_LE: result = GEIS_TRUE; break; } break; case GEIS_ATTR_TYPE_FLOAT: switch (op) { case GEIS_FILTER_OP_EQ: result = lhs->attr_value.f == rhs->attr_value.f; break; case GEIS_FILTER_OP_NE: result = lhs->attr_value.f != rhs->attr_value.f; break; case GEIS_FILTER_OP_GT: result = lhs->attr_value.f > rhs->attr_value.f; break; case GEIS_FILTER_OP_GE: result = lhs->attr_value.f >= rhs->attr_value.f; break; case GEIS_FILTER_OP_LT: result = lhs->attr_value.f < rhs->attr_value.f; break; case GEIS_FILTER_OP_LE: result = lhs->attr_value.f <= rhs->attr_value.f; break; } break; case GEIS_ATTR_TYPE_INTEGER: switch (op) { case GEIS_FILTER_OP_EQ: result = lhs->attr_value.i == rhs->attr_value.i; break; case GEIS_FILTER_OP_NE: result = lhs->attr_value.i != rhs->attr_value.i; break; case GEIS_FILTER_OP_GT: result = lhs->attr_value.i > rhs->attr_value.i; break; case GEIS_FILTER_OP_GE: result = lhs->attr_value.i >= rhs->attr_value.i; break; case GEIS_FILTER_OP_LT: result = lhs->attr_value.i < rhs->attr_value.i; break; case GEIS_FILTER_OP_LE: result = lhs->attr_value.i <= rhs->attr_value.i; break; } break; case GEIS_ATTR_TYPE_POINTER: switch (op) { case GEIS_FILTER_OP_EQ: result = lhs->attr_value.p == rhs->attr_value.p; break; case GEIS_FILTER_OP_NE: result = lhs->attr_value.p != rhs->attr_value.p; break; case GEIS_FILTER_OP_GT: result = lhs->attr_value.p > rhs->attr_value.p; break; case GEIS_FILTER_OP_GE: result = lhs->attr_value.p >= rhs->attr_value.p; break; case GEIS_FILTER_OP_LT: result = lhs->attr_value.p < rhs->attr_value.p; break; case GEIS_FILTER_OP_LE: result = lhs->attr_value.p <= rhs->attr_value.p; break; } break; case GEIS_ATTR_TYPE_STRING: switch (op) { case GEIS_FILTER_OP_EQ: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) == 0; break; case GEIS_FILTER_OP_NE: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) != 0; break; case GEIS_FILTER_OP_GT: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) > 0; break; case GEIS_FILTER_OP_GE: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) >= 0; break; case GEIS_FILTER_OP_LT: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) < 0; break; case GEIS_FILTER_OP_LE: result = strcmp(lhs->attr_value.s, rhs->attr_value.s) <= 0; break; } break; default: /* no comparisons are supported on indeterminate types */ break; } return result; } geis-2.2.17+16.04.20160126/libgeis/geis_test_api.h0000644000015600001650000000257612651717544021530 0ustar pbuserpbgroup00000000000000/** * @file geis_test_api.h * @brief internal interface of the GEIS test API * * This header exposes the GEIS internal test API for use in the GEIS test * suite. */ /* * Copyright 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_TEST_API_H_ #define GEIS_TEST_API_H_ /** * Back end to use in unit testing. */ #define GEIS_INIT_MOCK_BACKEND "com.canonical.oif.backend.mock" /** * Causes device messages to be discarded from back end. * * Argument is of tyep GeisBoolean. GEIS_TRUE means device messages will be * discarded, GEIS_FALSE means messages will not be discarded. * * This cofiguration option is intended to be used with various device-related * integration and unit tests. */ #define GEIS_CONFIG_DISCARD_DEVICE_MESSAGES "com.canonical.oif.discard.device" #endif /* GEIS_TEST_API_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis.c0000644000015600001650000013036512651717544017631 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis.c * @brief implementation of the GEIS v2.0 API instance * * The GEIS API object encapsulates an entire persistent session with the * gesture recognition engine. An application should be able to support * multiple simultaneous instances of the GEIS API abject (although it would be * foolish to design an application that way). */ /* * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_private.h" #include #include "geis_atomic.h" #include "geis_attr.h" #include "geis_backend.h" #include "geis_class.h" #include "server/geis_dbus_server.h" /* @TODO replace me */ #include "geis_device.h" #include "geis_backend_multiplexor.h" #include "geis_error.h" #include "geis_event.h" #include "geis_event_queue.h" #include "geis_gesture_flick.h" #include "geis_logging.h" #include "geis_test_api.h" #include #include #include #include /** Default timeout for synchronous init (in seconds */ #define GEIS_DEFAULT_INIT_TIMEOUT 5 /** * States the GEIS instance could be in. * * @def GEIS_STATE_INITIALIZING * The instance has not yet completed its initialization sequence: some * functions will not yield valid results. * * @def GEIS_STATE_RUNNING * Initialization has completed, the instance is up and running normally. */ typedef enum _GeisState { GEIS_STATE_INITIALIZING, GEIS_STATE_RUNNING, GEIS_STATE_INIT_FAIL } _GeisState; /* * An internal structure to track processing callbacks in some order. */ typedef struct GeisProcessingEntry *GeisProcessingEntry; struct GeisProcessingEntry { GeisProcessingEntry next; int priority; GeisProcessingCallback event_callback; void *context; }; /* * The API instance. */ struct _Geis { GeisRefCount refcount; _GeisState state; GeisErrorStack error_stack; GeisSubBag subscription_bag; GeisBackendMultiplexor backend_multiplexor; GeisBackend backend; GeisBoolean backend_pending; GeisBoolean backend_use_fallback; GeisDBusServer server; /* @TODO: replace me */ GeisEventQueue input_event_queue; int input_event_signal_pipe[2]; GeisProcessingEntry processing_callbacks; GeisEventQueue output_event_queue; GeisEventCallback output_event_callback; void *output_event_callback_context; GeisEventCallback class_event_callback; void *class_event_callback_context; FilterableAttributeBag class_filterable_attributes; GeisGestureClassBag gesture_classes; GeisEventCallback device_event_callback; void *device_event_callback_context; FilterableAttributeBag device_filterable_attributes; GeisDeviceBag devices; FilterableAttributeBag region_filterable_attributes; FilterableAttributeBag special_filterable_attributes; GeisGestureFlick flick; GeisBoolean use_synchronous_start; GeisBoolean use_atomic_gestures; GeisBoolean send_tentative_events; GeisBoolean send_synchronous_events; GeisBoolean ignore_device_events; }; /* * The default event callback -- just pushes events on the internal queue */ static void _default_output_event_callback(Geis geis, GeisEvent event, void *context GEIS_UNUSED) { geis_debug("posting output event"); geis_event_queue_enqueue(geis->output_event_queue, event); } /* * Handles device events coming in from the back end. */ static GeisBoolean _device_event_handler(Geis geis, GeisEvent event) { GeisBoolean handled = GEIS_FALSE; GeisAttr attr = NULL; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); if (!attr) { geis_warning("invalid device event received from back end."); handled = GEIS_TRUE; goto final_exit; } GeisDevice device = geis_attr_value_to_pointer(attr); GeisEventType event_type = geis_event_type(event); if (event_type == GEIS_EVENT_DEVICE_AVAILABLE) { geis_device_bag_insert(geis->devices, device); geis_backend_activate_device(geis->backend, device); } if (geis->device_event_callback != GEIS_DEFAULT_EVENT_CALLBACK) { geis->device_event_callback(geis, event, geis->device_event_callback_context); handled = GEIS_TRUE; } if (event_type == GEIS_EVENT_DEVICE_UNAVAILABLE) { geis_backend_deactivate_device(geis->backend, device); geis_device_bag_remove(geis->devices, device); } final_exit: return handled; } /* * Handles class events coming in from the back end. */ static GeisBoolean _class_event_handler(Geis geis, GeisEvent event) { GeisBoolean handled = GEIS_FALSE; GeisAttr attr = NULL; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); if (!attr) { geis_warning("invalid class event received from back end."); handled = GEIS_TRUE; goto final_exit; } GeisGestureClass gesture_class = geis_attr_value_to_pointer(attr); GeisEventType event_type = geis_event_type(event); if (event_type == GEIS_EVENT_CLASS_AVAILABLE) { geis_gesture_class_bag_insert(geis->gesture_classes, gesture_class); } else if (event_type == GEIS_EVENT_CLASS_CHANGED) { /** @todo implement GEIS_EVENT_CLASS_CHANGED */ } else if (event_type == GEIS_EVENT_CLASS_UNAVAILABLE) { geis_gesture_class_bag_remove(geis->gesture_classes, gesture_class); } if (geis->class_event_callback != GEIS_DEFAULT_EVENT_CALLBACK) { geis->class_event_callback(geis, event, geis->class_event_callback_context); handled = GEIS_TRUE; } final_exit: return handled; } static void _geis_invoke_backend_fallback(Geis geis) { if (geis->backend) geis_backend_delete(geis->backend); geis_error_clear(geis); geis->backend = geis_backend_by_name(geis, GEIS_INIT_GRAIL_BACKEND); if (!geis->backend) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("can not create back end"); geis->state = GEIS_STATE_INIT_FAIL; } geis->backend_use_fallback = GEIS_FALSE; } /* * Filters and transforms raw gesture events into cooked gesture events. */ static void _input_event_handler(int fd, GeisBackendMultiplexorActivity activity, void *context) { Geis geis = (Geis)context; GeisProcessingEntry cb; if (activity & GEIS_BE_MX_READ_AVAILABLE) { GeisEvent event; /* clear the input event signal */ char buf[2]; if (read(fd, buf, 1) != 1) { geis_warning("unexpected number of bytes read from signal pipe"); } geis_debug("input event available"); event = geis_event_queue_dequeue(geis->input_event_queue); if (event) { GeisBoolean handled = 0; switch (geis_event_type(event)) { case GEIS_EVENT_DEVICE_AVAILABLE: case GEIS_EVENT_DEVICE_UNAVAILABLE: handled = _device_event_handler(geis, event); break; case GEIS_EVENT_CLASS_AVAILABLE: case GEIS_EVENT_CLASS_CHANGED: case GEIS_EVENT_CLASS_UNAVAILABLE: handled = _class_event_handler(geis, event); break; case GEIS_EVENT_INIT_COMPLETE: geis->state = GEIS_STATE_RUNNING; geis->backend_pending = GEIS_FALSE; break; case GEIS_EVENT_ERROR: if (geis->backend_pending && geis->backend_use_fallback) { _geis_invoke_backend_fallback(geis); geis->backend_pending = GEIS_FALSE; handled = GEIS_TRUE; } else { geis->state = GEIS_STATE_INIT_FAIL; } break; default: break; } for (cb = geis->processing_callbacks; cb; cb = cb->next) { switch (cb->event_callback(event, cb->context)) { case GEIS_PROCESSING_DISPOSE_EVENT: geis_event_delete(event); goto final_exit; break; case GEIS_PROCESSING_COMPLETE: goto processing_complete; break; case GEIS_PROCESSING_FAIL: geis_warning("processig error in event handler"); break; default: break; } } processing_complete: if (!handled) { geis->output_event_callback(geis, event, geis->output_event_callback_context); } } } final_exit: return; } /* * Applies the back end callback to the back end token for each filterable * attribute with a name matching the argument. */ static GeisStatus _filterable_attribute_bag_foreach(FilterableAttributeBag bag, GeisBackendToken token, GeisString name, GeisFilterOperation op, void *value) { GeisStatus status = GEIS_STATUS_SUCCESS; GeisFilterableAttributeBagIter it; for (it = geis_filterable_attribute_bag_begin(bag); it != geis_filterable_attribute_bag_end(bag); it = geis_filterable_attribute_bag_next(bag, it)) { if (0 == strcmp(it->name, name) && it->add_term_callback) { status = it->add_term_callback(token, it->add_term_context, name, op, value); } } return status; } /* * Runs filters for each regostered token in a facility. */ GeisStatus geis_filterable_attribute_foreach(Geis geis, GeisFilterFacility facility, GeisBackendToken token, GeisString name, GeisFilterOperation op, void *value) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; switch (facility) { case GEIS_FILTER_CLASS: status = _filterable_attribute_bag_foreach(geis->class_filterable_attributes, token, name, op, value); break; case GEIS_FILTER_DEVICE: status = _filterable_attribute_bag_foreach(geis->device_filterable_attributes, token, name, op, value); break; case GEIS_FILTER_REGION: status = _filterable_attribute_bag_foreach(geis->region_filterable_attributes, token, name, op, value); break; case GEIS_FILTER_SPECIAL: status = _filterable_attribute_bag_foreach(geis->special_filterable_attributes, token, name, op, value); break; default: break; } return status; } /** * Creates a new empty Geis API instance. */ static Geis geis_new_empty() { geis_error_clear(NULL); Geis geis = calloc(1, sizeof(struct _Geis)); if (!geis) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("calloc failed"); goto final_exit; } geis->state = GEIS_STATE_INITIALIZING; geis->subscription_bag = geis_subscription_bag_new(1); if (!geis->subscription_bag) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of subscroption bag failed"); free(geis); geis = NULL; goto unwind_geis; } geis->backend_multiplexor = geis_backend_multiplexor_new(); if (!geis->backend_multiplexor) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of back end multiplexor failed"); goto unwind_subscription_bag; } geis->input_event_queue = geis_event_queue_new(); if (!geis->input_event_queue) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of input event queue failed"); goto unwind_backend_mux; } if (pipe(geis->input_event_signal_pipe) < 0) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("error %d creating input event signal pipe: %s", errno, strerror(errno)); goto unwind_input_queue; } geis_backend_multiplexor_add_fd(geis->backend_multiplexor, geis->input_event_signal_pipe[0], GEIS_BE_MX_READ_AVAILABLE, _input_event_handler, geis); geis->output_event_queue = geis_event_queue_new(); if (!geis->output_event_queue) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of output event queue failed"); goto unwind_input_signal_pipe; } geis->output_event_callback = _default_output_event_callback; geis->class_filterable_attributes = geis_filterable_attribute_bag_new(); if (!geis->class_filterable_attributes) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of geis gesture class bag failed"); goto unwind_output_queue; } geis->gesture_classes = geis_gesture_class_bag_new(); if (!geis->gesture_classes) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of geis gesture class bag failed"); goto unwind_class_attrs; } geis->class_event_callback = _default_output_event_callback; geis->device_filterable_attributes = geis_filterable_attribute_bag_new(); if (!geis->device_filterable_attributes) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of geis device bag failed"); goto unwind_class_bag; } geis->devices = geis_device_bag_new(); if (!geis->devices) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("creation of geis device bag failed"); goto unwind_device_attrs; } geis->device_event_callback = _default_output_event_callback; geis->region_filterable_attributes = geis_filterable_attribute_bag_new(); if (!geis->region_filterable_attributes) { goto unwind_device_bag; } geis->special_filterable_attributes = geis_filterable_attribute_bag_new(); if (!geis->special_filterable_attributes) { goto unwind_region_attrs; } geis->use_synchronous_start = GEIS_FALSE; geis->use_atomic_gestures = GEIS_TRUE; geis->send_tentative_events = GEIS_FALSE; geis->send_synchronous_events = GEIS_FALSE; geis->ignore_device_events = GEIS_FALSE; goto final_exit; unwind_region_attrs: geis_filterable_attribute_bag_delete(geis->region_filterable_attributes); unwind_device_bag: geis_device_bag_delete(geis->devices); unwind_device_attrs: geis_filterable_attribute_bag_delete(geis->device_filterable_attributes); unwind_class_bag: geis_gesture_class_bag_delete(geis->gesture_classes); unwind_class_attrs: geis_filterable_attribute_bag_delete(geis->class_filterable_attributes); unwind_output_queue: geis_event_queue_delete(geis->output_event_queue); unwind_input_signal_pipe: close(geis->input_event_signal_pipe[0]); close(geis->input_event_signal_pipe[1]); unwind_input_queue: geis_event_queue_delete(geis->input_event_queue); unwind_backend_mux: geis_backend_multiplexor_delete(geis->backend_multiplexor); unwind_subscription_bag: geis_subscription_bag_delete(geis->subscription_bag); unwind_geis: free(geis); geis = NULL; final_exit: return geis; } typedef enum _BackendType { BACK_END_TYPE_NONE, BACK_END_TYPE_MOCK_ENGINE, BACK_END_TYPE_DBUS, BACK_END_TYPE_GRAIL, BACK_END_TYPE_XCB } BackendType; /** * Sets optional parts of a Geis API instance from a variable argument list. */ static GeisBoolean _set_valist(Geis geis, GeisString init_arg_name, va_list varargs) { GeisBoolean status = GEIS_TRUE; BackendType back_end_type = BACK_END_TYPE_NONE; while (init_arg_name) { if (0 == strcmp(init_arg_name, GEIS_INIT_SERVICE_PROVIDER)) { geis->server = geis_dbus_server_new(geis); } else if (0 == strcmp(init_arg_name, GEIS_INIT_TRACK_DEVICES)) { /* no longer supported */ } else if (0 == strcmp(init_arg_name, GEIS_INIT_TRACK_GESTURE_CLASSES)) { /* no longer supported */ } else if (0 == strcmp(init_arg_name, GEIS_INIT_SYNCHRONOUS_START)) { geis->use_synchronous_start = GEIS_TRUE; } else if (0 == strcmp(init_arg_name, GEIS_INIT_NO_ATOMIC_GESTURES)) { geis->use_atomic_gestures = GEIS_FALSE; } else if (0 == strcmp(init_arg_name, GEIS_INIT_SEND_TENTATIVE_EVENTS)) { geis->send_tentative_events = GEIS_TRUE; } else if (0 == strcmp(init_arg_name, GEIS_INIT_SEND_SYNCHRONOS_EVENTS)) { geis->send_synchronous_events = GEIS_TRUE; } else if (0 == strcmp(init_arg_name, GEIS_INIT_MOCK_BACKEND)) { if (back_end_type != BACK_END_TYPE_NONE) { geis_error("multiple back ends requested, only using last request"); } back_end_type = BACK_END_TYPE_MOCK_ENGINE; } else if (0 == strcmp(init_arg_name, GEIS_INIT_DBUS_BACKEND)) { if (back_end_type != BACK_END_TYPE_NONE) { geis_error("multiple back ends requested, only using last request"); } back_end_type = BACK_END_TYPE_DBUS; } else if (0 == strcmp(init_arg_name, GEIS_INIT_GRAIL_BACKEND)) { if (back_end_type != BACK_END_TYPE_NONE) { geis_error("multiple back ends requested, only using last request"); } back_end_type = BACK_END_TYPE_GRAIL; } else if (0 == strcmp(init_arg_name, GEIS_INIT_XCB_BACKEND)) { if (back_end_type != BACK_END_TYPE_NONE) { geis_error("multiple back ends requested, only using last request"); } back_end_type = BACK_END_TYPE_XCB; } else if(0 == strcmp(init_arg_name, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES)) { geis->ignore_device_events = GEIS_TRUE; } init_arg_name = va_arg(varargs, GeisString); } if (back_end_type == BACK_END_TYPE_MOCK_ENGINE) { geis->backend = geis_backend_by_name(geis, GEIS_INIT_MOCK_BACKEND); } else if (back_end_type == BACK_END_TYPE_DBUS) { geis->backend = geis_backend_by_name(geis, GEIS_INIT_DBUS_BACKEND); geis->backend_pending = GEIS_TRUE; } else if (back_end_type == BACK_END_TYPE_GRAIL) { geis->backend = geis_backend_by_name(geis, GEIS_INIT_GRAIL_BACKEND); } else if (back_end_type == BACK_END_TYPE_XCB) { geis->backend = geis_backend_by_name(geis, GEIS_INIT_XCB_BACKEND); } else { geis_warning("back end not specified, defaulting to DBus"); geis->backend = geis_backend_by_name(geis, GEIS_INIT_DBUS_BACKEND); geis->backend_pending = GEIS_TRUE; geis->backend_use_fallback = GEIS_TRUE; } if (!geis->backend) { if (geis->backend_pending & geis->backend_use_fallback) { _geis_invoke_backend_fallback(geis); } else { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("can not create back end"); status = GEIS_FALSE; geis->state = GEIS_STATE_INIT_FAIL; } } return status; } /** * Performs a blocking wait for a GEIS_INIT message. */ static GeisStatus _geis_wait_for_init(Geis geis) { geis_debug("waiting for initialization to complete..."); GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; int geis_fd = geis_backend_multiplexor_fd(geis->backend_multiplexor); while (1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(geis_fd, &read_fds); struct timeval timeout = { GEIS_DEFAULT_INIT_TIMEOUT, 0 }; int sstat = select(geis_fd + 1, &read_fds, NULL, NULL, &timeout); if (sstat < 0) { geis_error("error %d in select(): %s", errno, strerror(errno)); break; } else if (sstat == 0) { geis_error("failed to get init response"); break; } if (FD_ISSET(geis_fd, &read_fds)) { geis_dispatch_events(geis); if (geis->state == GEIS_STATE_RUNNING) { status = GEIS_STATUS_SUCCESS; break; } else if (geis->state == GEIS_STATE_INIT_FAIL) { break; } } } geis_debug("... initialization complete, status=%d", status); return status; } /** * Creates an initialized Geis API instance. */ Geis geis_new(GeisString init_arg_name, ...) { GeisBoolean success = GEIS_FALSE; Geis geis = geis_new_empty(); if (geis) { geis_ref(geis); va_list varargs; va_start(varargs, init_arg_name); success = _set_valist(geis, init_arg_name, varargs); va_end(varargs); } if (!success) { geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); geis_error("can not initialize GEIS API"); geis_delete(geis); geis = NULL; goto final_exit; } if (geis->use_synchronous_start) { GeisStatus status = _geis_wait_for_init(geis); if (status != GEIS_STATUS_SUCCESS) { geis_delete(geis); geis = NULL; goto final_exit; } } geis->flick = geis_gesture_flick_new(geis); final_exit: return geis; } static void _geis_destroy(Geis geis) { GeisProcessingEntry cb; cb = geis->processing_callbacks; while (cb) { GeisProcessingEntry cb_next = cb->next; free(cb); cb = cb_next; } geis_gesture_flick_delete(geis->flick); if (geis->backend) geis_backend_delete(geis->backend); if (geis->server) geis_dbus_server_delete(geis->server); geis_filterable_attribute_bag_delete(geis->special_filterable_attributes); geis_filterable_attribute_bag_delete(geis->region_filterable_attributes); geis_device_bag_delete(geis->devices); geis_filterable_attribute_bag_delete(geis->device_filterable_attributes); geis_gesture_class_bag_delete(geis->gesture_classes); geis_filterable_attribute_bag_delete(geis->class_filterable_attributes); geis_event_queue_delete(geis->output_event_queue); close(geis->input_event_signal_pipe[0]); close(geis->input_event_signal_pipe[1]); geis_event_queue_delete(geis->input_event_queue); geis_backend_multiplexor_delete(geis->backend_multiplexor); if (geis->subscription_bag) geis_subscription_bag_delete(geis->subscription_bag); free(geis); } /* * Disposes of a Geis API instance. */ GeisStatus geis_delete(Geis geis) { if (geis == NULL) { return GEIS_STATUS_BAD_ARGUMENT; } /* break circular dependencies */ if (geis->subscription_bag) { geis_subscription_bag_delete(geis->subscription_bag); geis->subscription_bag = NULL; } if (geis->backend) { geis_backend_delete(geis->backend); geis->backend = NULL; } geis_unref(geis); return GEIS_STATUS_SUCCESS; } /* * Increases the reference count of an API instance object. */ Geis geis_ref(Geis geis) { geis_atomic_ref(&geis->refcount); return geis; } /* * Decremenets the reference count of an API instance object. */ void geis_unref(Geis geis) { if (0 == geis_atomic_unref(&geis->refcount)) { _geis_destroy(geis); } } /** * Gets a named configuration item. */ GeisStatus geis_get_configuration(Geis geis, GeisString configuration_item_name, void *configuration_item_value) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (0 == strcmp(configuration_item_name, GEIS_CONFIGURATION_FD)) { *(int*)configuration_item_value = geis_backend_multiplexor_fd(geis->backend_multiplexor); status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_MAX_EVENTS)) { *(int*)configuration_item_value = geis_backend_multiplexor_max_events_per_pump(geis->backend_multiplexor); status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_ATOMIC_GESTURES)) { *(GeisBoolean*)configuration_item_value = geis->use_atomic_gestures; status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_SEND_TENTATIVE_EVENTS)) { *(GeisBoolean*)configuration_item_value = geis->send_tentative_events; status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_SEND_SYNCHRONOS_EVENTS)) { *(GeisBoolean*)configuration_item_value = geis->send_synchronous_events; status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES)) { *(GeisBoolean*)configuration_item_value = geis->ignore_device_events; status = GEIS_STATUS_SUCCESS; } else { status = geis_get_sub_configuration(geis, NULL, configuration_item_name, configuration_item_value); } return status; } /* * Gets a feature configuration value from the current back end. */ GeisStatus geis_get_sub_configuration(Geis geis, GeisSubscription sub, GeisString item_name, void *item_value) { return geis_backend_get_configuration(geis->backend, sub, item_name, item_value); } /* * gets a feature configuration value in the current back end. */ GeisStatus geis_set_sub_configuration(Geis geis, GeisSubscription sub, GeisString item_name, void *item_value) { return geis_backend_set_configuration(geis->backend, sub, item_name, item_value); } /* * Sets a named configuration item. */ GeisStatus geis_set_configuration(Geis geis, GeisString configuration_item_name, void *configuration_item_value) { GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; if (0 == strcmp(configuration_item_name, GEIS_CONFIG_MAX_EVENTS)) { int max_events = *(int *)configuration_item_value; geis_backend_multiplexor_set_max_events_per_pump(geis->backend_multiplexor, max_events); status = GEIS_STATUS_SUCCESS; } else if (0 == strcmp(configuration_item_name, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES)) { geis->ignore_device_events = *(GeisBoolean*)configuration_item_value; status = GEIS_STATUS_SUCCESS; } else { status = geis_set_sub_configuration(geis, NULL, configuration_item_name, configuration_item_value); } return status; } /* * Registers a callback to receive device change notifications. */ void geis_register_device_callback(Geis geis, GeisEventCallback event_callback, void *context) { geis->device_event_callback = event_callback; geis->device_event_callback_context = context; } /* * Registers a callback to receive gesture class change notifications. */ void geis_register_class_callback(Geis geis, GeisEventCallback event_callback, void *context) { geis->class_event_callback = event_callback; geis->class_event_callback_context = context; } /* * Registers an event-processing callback. */ void geis_register_processing_callback(Geis geis, int priority, GeisProcessingCallback event_callback, void *context) { GeisProcessingEntry new_entry = calloc(1, sizeof(struct GeisProcessingEntry)); new_entry->priority = priority; new_entry->event_callback = event_callback; new_entry->context = context; if (!geis->processing_callbacks) { geis->processing_callbacks = new_entry; } else { GeisProcessingEntry cb = NULL; GeisProcessingEntry prev = NULL; for (cb = geis->processing_callbacks; cb; cb = cb->next) { if (priority < cb->priority) { if (cb == geis->processing_callbacks) { geis->processing_callbacks = new_entry; } else { new_entry->next = prev->next; prev->next = new_entry; } break; } prev = cb; } if (!cb) { prev->next = new_entry; } } } /* * Removes all matching events from all event queues. */ void geis_remove_matching_events(Geis geis, GeisEventMatch matching, void *context) { geis_event_queue_remove_if(geis->input_event_queue, matching, context); geis_event_queue_remove_if(geis->output_event_queue, matching, context); } /* * Registers an application-supplied event callback. */ void geis_register_event_callback(Geis geis, GeisEventCallback output_event_callback, void *context) { if (output_event_callback == GEIS_DEFAULT_EVENT_CALLBACK) { geis->output_event_callback = _default_output_event_callback; } else { geis->output_event_callback = output_event_callback; } geis->output_event_callback_context = context; } /* * Pumps the GEIS v2 event loop. */ GeisStatus geis_dispatch_events(Geis geis) { GeisStatus status = geis_backend_multiplexor_pump(geis->backend_multiplexor); return status; } /* * Posts an event through the API. * * Pushes the new event onto the input event queue and signals that a new event * has arrived. */ void geis_post_event(Geis geis, GeisEvent event) { geis_event_queue_enqueue(geis->input_event_queue, event); if (write(geis->input_event_signal_pipe[1], "1", 1) != 1) { geis_error("error %d writing input event signal: %s", errno, strerror(errno)); } } /* * Pulls the next event off the queue. */ GeisStatus geis_next_event(Geis geis, GeisEvent *event) { GeisStatus status = GEIS_STATUS_EMPTY; *event = geis_event_queue_dequeue(geis->output_event_queue); if (*event) { status = geis_event_queue_is_empty(geis->output_event_queue) ? GEIS_STATUS_SUCCESS : GEIS_STATUS_CONTINUE; } return status; } /* * Adds a back end file descriptor to multiplex. */ void geis_multiplex_fd(Geis geis, int fd, GeisBackendMultiplexorActivity activity, GeisBackendFdEventCallback callback, void *context) { geis_backend_multiplexor_add_fd(geis->backend_multiplexor, fd, activity, callback, context); } /* * Modifies a multiplexed back end file descriptor. */ void geis_remultiplex_fd(Geis geis, int fd, GeisBackendMultiplexorActivity activity) { geis_backend_multiplexor_modify_fd(geis->backend_multiplexor, fd, activity); } /* * Removes a back end file descriptor from the multiplex. */ void geis_demultiplex_fd(Geis geis, int fd) { geis_backend_multiplexor_remove_fd(geis->backend_multiplexor, fd); } GeisErrorStack * geis_error_stack(Geis geis) { return &geis->error_stack; } GeisSize geis_add_subscription(Geis geis, GeisSubscription subscription) { return geis_subscription_bag_insert(geis->subscription_bag, subscription); } /* * Creates a new backend token. */ GeisBackendToken geis_backend_token_new(Geis geis, GeisBackendTokenInitState init_state) { return geis_backend_create_token(geis->backend, init_state); } /* * Resgisters a new gesture class with the API. */ void geis_register_gesture_class(Geis geis, GeisGestureClass gesture_class, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs) { GeisAttr attr = NULL; GeisEvent event = NULL; GeisSize i; /* Add the filterable attributes. */ for (i = 0; i < filterable_attr_count; ++i) { geis_filterable_attribute_bag_insert(geis->class_filterable_attributes, &filterable_attrs[i]); } geis_debug("registering class \"%s\" id %d", geis_gesture_class_name(gesture_class), geis_gesture_class_id(gesture_class)); /* Add a "new gesture class" event to the processing queue. */ event = geis_event_new(GEIS_EVENT_CLASS_AVAILABLE); attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_CLASS, GEIS_ATTR_TYPE_POINTER, gesture_class); geis_event_add_attr(event, attr); geis_post_event(geis, event); } GeisGestureClassBag geis_gesture_classes(Geis geis) { return geis->gesture_classes; } /* * Registers a new input device with the API. */ void geis_register_device(Geis geis, GeisDevice device, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs) { /* Add the filterable attributes. */ for (GeisSize i = 0; i < filterable_attr_count; ++i) { geis_filterable_attribute_bag_insert(geis->device_filterable_attributes, &filterable_attrs[i]); } if (device) { geis_debug("registering device \"%s\" id %d", geis_device_name(device), geis_device_id(device)); /* Add a "new device" event to the processing queue. */ GeisEvent event = geis_event_new(GEIS_EVENT_DEVICE_AVAILABLE); GeisAttr attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_DEVICE, GEIS_ATTR_TYPE_POINTER, device); geis_device_ref(device); geis_attr_set_destructor(attr, (GeisAttrDestructor)geis_device_unref); geis_event_add_attr(event, attr); geis_post_event(geis, event); } } /* * Unregisters an existing input device with the API. */ void geis_unregister_device(Geis geis, GeisDevice device) { GeisEvent event = NULL; GeisAttr attr = NULL; /* Add a "remove device" event to the processing queue. */ event = geis_event_new(GEIS_EVENT_DEVICE_UNAVAILABLE); attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_DEVICE, GEIS_ATTR_TYPE_POINTER, device); geis_device_ref(device); geis_attr_set_destructor(attr, (GeisAttrDestructor)geis_device_unref); geis_event_add_attr(event, attr); geis_post_event(geis, event); } GeisDeviceBag geis_devices(Geis geis) { return geis->devices; } /** * A check to see if a device has the given name. */ static GeisBoolean _device_has_name(GeisDevice device, GeisFilterOperation op, GeisString name) { GeisBoolean names_match = (0 == strcmp(geis_device_name(device), name)); return (op == GEIS_FILTER_OP_EQ && names_match) || (op == GEIS_FILTER_OP_NE && !names_match); } /** * A check to see if a device has the named boolean attribute. */ static GeisBoolean _device_has_boolean_attr(GeisDevice device, GeisFilterOperation op, GeisString attr_name, GeisBoolean match_value) { GeisBoolean has_attr = GEIS_FALSE; GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); if (device_attr) { GeisBoolean attr_value = geis_attr_value_to_boolean(device_attr); has_attr = (op == GEIS_FILTER_OP_EQ && attr_value == match_value) || (op == GEIS_FILTER_OP_NE && attr_value != match_value); } return has_attr; } /** * A check to see if a device has the named integer attribute. */ static GeisBoolean _device_has_integer_attr(GeisDevice device, GeisFilterOperation op, GeisString attr_name, GeisInteger match_value) { GeisBoolean has_attr = GEIS_FALSE; GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); if (device_attr) { GeisInteger attr_value = geis_attr_value_to_integer(device_attr); has_attr = (op == GEIS_FILTER_OP_EQ && attr_value == match_value) || (op == GEIS_FILTER_OP_NE && attr_value != match_value) || (op == GEIS_FILTER_OP_GT && attr_value > match_value) || (op == GEIS_FILTER_OP_GE && attr_value >= match_value) || (op == GEIS_FILTER_OP_LE && attr_value <= match_value) || (op == GEIS_FILTER_OP_LT && attr_value < match_value); } return has_attr; } /* * Selects devices that pass the given filter terms. * * If there are no device terms in the filter at all, then ALL devices match. * * If there are any device terms in the filter but no known devices match, then * NONE devices match. * * Otherwise, there is at least one device that matches and at least one device * filter term, so SOME devices match. */ GeisSelectResult geis_select_devices(Geis geis, GeisFilter filter, GeisDeviceBag bag) { GeisSelectResult result = GEIS_SELECT_RESULT_ALL; GeisBoolean device_terms_present = GEIS_FALSE; GeisBoolean devices_found = GEIS_FALSE; GeisSize device_count = geis_device_bag_count(geis->devices); const GeisSize term_count = geis_filter_term_count(filter); for (GeisSize i = 0; i < term_count; ++i) { GeisFilterTerm term = geis_filter_term(filter, i); if (geis_filter_term_facility(term) == GEIS_FILTER_DEVICE) { device_terms_present = GEIS_TRUE; GeisAttr attr = geis_filter_term_attr(term); GeisString name = geis_attr_name(attr); GeisFilterOperation operation = geis_filter_term_operation(term); if (0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_NAME)) { GeisString device_name = geis_attr_value_to_string(attr); for (GeisSize i = 0; i < device_count; ++i) { GeisDevice device = geis_device_bag_device(geis->devices, i); if (_device_has_name(device, operation, device_name)) { devices_found = GEIS_TRUE; geis_device_bag_insert(bag, device); } } } else if (0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH) || 0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH)) { GeisBoolean value = geis_attr_value_to_boolean(attr); for (GeisSize i = 0; i < device_count; ++i) { GeisDevice device = geis_device_bag_device(geis->devices, i); if (_device_has_boolean_attr(device, operation, name, value)) { devices_found = GEIS_TRUE; geis_device_bag_insert(bag, device); } } } else if (0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_ID) || 0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_TOUCHES)) { GeisInteger value = geis_attr_value_to_integer(attr); /* legacy special case for device ID == 0: means ALL devices in v1 */ if (value == 0) { device_terms_present = FALSE; break; } for (GeisSize i = 0; i < device_count; ++i) { GeisDevice device = geis_device_bag_device(geis->devices, i); if (_device_has_integer_attr(device, operation, name, value)) { devices_found = GEIS_TRUE; geis_device_bag_insert(bag, device); } } } } } if (device_terms_present) { if (devices_found) { result = GEIS_SELECT_RESULT_SOME; } else { result = GEIS_SELECT_RESULT_NONE; } } return result; } /* * Resgisters a new region with the API. */ void geis_register_region(Geis geis, GeisRegion region GEIS_UNUSED, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs) { GeisSize i; geis_debug("registering region"); /* Add the filterable attributes. */ for (i = 0; i < filterable_attr_count; ++i) { geis_filterable_attribute_bag_insert(geis->region_filterable_attributes, &filterable_attrs[i]); } } /* * Gets an iterator to the first registered filterable region attribute. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_begin(Geis geis) { return geis_filterable_attribute_bag_begin(geis->region_filterable_attributes); } /* * Advances an iterator to the next registered filterable region attribute. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_next(Geis geis, GeisFilterableAttributeBagIter iter) { return geis_filterable_attribute_bag_next(geis->region_filterable_attributes, iter); } /* * Gets an iterator to the on-past-the-last registered filterable region * attribute. */ GeisFilterableAttributeBagIter geis_region_filter_attrs_end(Geis geis) { return geis_filterable_attribute_bag_end(geis->region_filterable_attributes); } /* * Resgisters a new special filter with the API. */ void geis_register_special(Geis geis, GeisSize filterable_attr_count, GeisFilterableAttribute filterable_attrs) { GeisSize i; geis_debug("registering feature"); /* Add the filterable attributes. */ for (i = 0; i < filterable_attr_count; ++i) { geis_filterable_attribute_bag_insert(geis->special_filterable_attributes, &filterable_attrs[i]); } } GeisAttrType geis_get_device_attr_type(Geis geis, GeisString attr_name) { FilterableAttributeBag bag = geis->device_filterable_attributes; GeisFilterableAttributeBagIter fa; for (fa = geis_filterable_attribute_bag_begin(bag); fa != geis_filterable_attribute_bag_end(bag); fa = geis_filterable_attribute_bag_next(bag, fa)) { if (0 == strcmp(attr_name, fa->name)) { return fa->type; } } return GEIS_ATTR_TYPE_UNKNOWN; } GeisAttrType geis_get_class_attr_type(Geis geis, GeisString attr_name) { FilterableAttributeBag bag = geis->class_filterable_attributes; GeisFilterableAttributeBagIter fa; for (fa = geis_filterable_attribute_bag_begin(bag); fa != geis_filterable_attribute_bag_end(bag); fa = geis_filterable_attribute_bag_next(bag, fa)) { if (0 == strcmp(attr_name, fa->name)) { return fa->type; } } return GEIS_ATTR_TYPE_UNKNOWN; } GeisAttrType geis_get_region_attr_type(Geis geis, GeisString attr_name) { FilterableAttributeBag bag = geis->region_filterable_attributes; GeisFilterableAttributeBagIter fa; for (fa = geis_filterable_attribute_bag_begin(bag); fa != geis_filterable_attribute_bag_end(bag); fa = geis_filterable_attribute_bag_next(bag, fa)) { if (0 == strcmp(attr_name, fa->name)) { return fa->type; } } return GEIS_ATTR_TYPE_UNKNOWN; } GeisAttrType geis_get_special_attr_type(Geis geis, GeisString attr_name) { FilterableAttributeBag bag = geis->special_filterable_attributes; GeisFilterableAttributeBagIter fa; for (fa = geis_filterable_attribute_bag_begin(bag); fa != geis_filterable_attribute_bag_end(bag); fa = geis_filterable_attribute_bag_next(bag, fa)) { if (0 == strcmp(attr_name, fa->name)) { return fa->type; } } return GEIS_ATTR_TYPE_UNKNOWN; } GeisDevice geis_get_device(Geis geis, GeisInteger device_id) { GeisDevice device = NULL; for (GeisSize i = 0; i < geis_device_bag_count(geis->devices); ++i) { GeisDevice d = geis_device_bag_device(geis->devices, i); if (geis_device_id(d) == device_id) { device = d; break; } } return device; } /* * Marks a gesture as accepted. */ GeisStatus geis_gesture_accept(Geis geis, GeisGroup group, GeisGestureId gesture_id) { return geis_backend_gesture_accept(geis->backend, group, gesture_id); } /* * Marks a gesture as rejected. */ GeisStatus geis_gesture_reject(Geis geis, GeisGroup group, GeisGestureId gesture_id) { return geis_backend_gesture_reject(geis->backend, group, gesture_id); } geis-2.2.17+16.04.20160126/libgeis/geis_device.c0000644000015600001650000001470012651717544021142 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_region.c * @brief implementation of the GEIS v2.0 API Input Device module * * Copyright 2010, 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_device.h" #include "geis_atomic.h" #include "geis_attr.h" #include "geis_logging.h" #include #include struct _GeisDevice { GeisRefCount ref_count; GeisAttrBag attr_bag; }; struct _GeisDeviceBag { GeisDevice *device_store; GeisSize device_store_size; GeisSize device_count; }; static const int device_bag_growth_constant = 2; GeisDeviceBag geis_device_bag_new() { GeisDeviceBag bag = calloc(1, sizeof(struct _GeisDeviceBag)); if (!bag) { geis_error("error allocating device bag"); goto final_exit; } bag->device_store = calloc(1, sizeof(struct _GeisDevice)); if (!bag->device_store) { geis_error("error allocating device bag store"); goto unwind_bag; } bag->device_store_size = 1; bag->device_count = 0; goto final_exit; unwind_bag: free(bag); bag = NULL; final_exit: return bag; } void geis_device_bag_delete(GeisDeviceBag bag) { GeisSize i; for (i = bag->device_count; i > 0; --i) { geis_device_unref(bag->device_store[i-1]); } free(bag->device_store); free(bag); } GeisSize geis_device_bag_count(GeisDeviceBag bag) { return bag->device_count; } GeisDevice geis_device_bag_device(GeisDeviceBag bag, GeisSize index) { GeisDevice device = NULL; if (index >= bag->device_count) { geis_warning("device bag index out of range"); } else { device = bag->device_store[index]; } return device; } GeisStatus geis_device_bag_insert(GeisDeviceBag bag, GeisDevice device) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; for (GeisSize i = 0; i < bag->device_count; ++i) { if (bag->device_store[i] == device) { geis_device_ref(device); goto final_exit; } } if (bag->device_count >= bag->device_store_size) { GeisSize new_store_size = bag->device_store_size * device_bag_growth_constant; GeisDevice *new_store = realloc(bag->device_store, new_store_size * sizeof(struct _GeisDevice)); if (!new_store) { geis_error("failed to reallocate device bag"); goto final_exit; } bag->device_store = new_store; bag->device_store_size = new_store_size; } bag->device_store[bag->device_count++] = geis_device_ref(device); status = GEIS_STATUS_SUCCESS; final_exit: return status; } GeisStatus geis_device_bag_remove(GeisDeviceBag bag, GeisDevice device) { GeisSize i; GeisStatus status = GEIS_STATUS_SUCCESS; for (i = 0; i < bag->device_count; ++i) { if (bag->device_store[i] == device) { GeisSize j; geis_device_unref(bag->device_store[i]); --bag->device_count; for (j = i; j < bag->device_count; ++j) { bag->device_store[j] = bag->device_store[j+1]; } break; } } return status; } /* * Creates a new, empty device. */ GeisDevice geis_device_new(GeisString name, GeisInteger id) { GeisAttr attr; GeisDevice device = calloc(1, sizeof(struct _GeisDevice)); if (!device) { geis_error("error allocating input device"); goto final_exit; } device->attr_bag = geis_attr_bag_new(4); if (!device->attr_bag) { geis_debug("error allocating attr bag"); goto unwind_device; } attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, (void *)name); if (!attr) { geis_debug("error allocating device name attr"); goto unwind_attrs; } geis_attr_bag_insert(device->attr_bag, attr); attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, &id); if (!attr) { geis_debug("error allocating device id attr"); goto unwind_attrs; } geis_attr_bag_insert(device->attr_bag, attr); geis_device_ref(device); goto final_exit; unwind_attrs: geis_attr_bag_delete(device->attr_bag); unwind_device: free(device); device = NULL; final_exit: return device; } /* * Destroys a device. */ static void _device_delete(GeisDevice device) { geis_attr_bag_delete(device->attr_bag); free(device); } /* * Adds a reference count to a device. */ GeisDevice geis_device_ref(GeisDevice device) { geis_atomic_ref(&device->ref_count); return device; } /* * Removes a reference count from a device. */ void geis_device_unref(GeisDevice device) { if (0 == geis_atomic_unref(&device->ref_count)) { _device_delete(device); } } /* * Gets the name of the input device. */ GeisString geis_device_name(GeisDevice device) { GeisString device_name = NULL; GeisAttr name_attr = geis_attr_bag_find(device->attr_bag, GEIS_DEVICE_ATTRIBUTE_NAME); if (name_attr) { device_name = geis_attr_value_to_string(name_attr); } return device_name; } /* * Gets the system identifier of the iput device. */ GeisInteger geis_device_id(GeisDevice device) { GeisInteger device_id = -1; GeisAttr attr = geis_attr_bag_find(device->attr_bag, GEIS_DEVICE_ATTRIBUTE_ID); if (attr) { device_id = geis_attr_value_to_integer(attr); } return device_id; } /* * Gets the number of attributes of the device. */ GeisSize geis_device_attr_count(GeisDevice device) { return geis_attr_bag_count(device->attr_bag); } /* * Inserts an attr into a device. */ void geis_device_add_attr(GeisDevice device, GeisAttr attr) { geis_attr_bag_insert(device->attr_bag, attr); } /* * Gets the indicated attribute of the device. */ GeisAttr geis_device_attr(GeisDevice device, GeisSize index) { return geis_attr_bag_attr(device->attr_bag, index); } /* * Gets a named attr. */ GeisAttr geis_device_attr_by_name(GeisDevice device, GeisString attr_name) { return geis_attr_bag_find(device->attr_bag, attr_name); } geis-2.2.17+16.04.20160126/libgeis/geis_attr.h0000644000015600001650000000521512651717544020663 0ustar pbuserpbgroup00000000000000/** * @file geis_attr.h * @brief internal GeisAttr facilities * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_ATTR_H_ #define GEIS_ATTR_H_ #include typedef struct _GeisAttrBag *GeisAttrBag; typedef void (*GeisAttrDestructor)(void *); /** * Creates a new Geis Attribute container. */ GeisAttrBag geis_attr_bag_new(GeisSize size_hint); /** * Destroys a Geis Attribute container. */ void geis_attr_bag_delete(GeisAttrBag bag); /** * Tells how any entires in a Geis Attribute container. */ GeisSize geis_attr_bag_count(GeisAttrBag bag); /** * Pulls an indicated attr out of a bag. */ GeisAttr geis_attr_bag_attr(GeisAttrBag bag, GeisSize index); /** * Inserts an attribute in an attribute container. */ GeisStatus geis_attr_bag_insert(GeisAttrBag bag, GeisAttr attr); /** * Replaces an attribute in an attribute container. */ GeisStatus geis_attr_bag_replace(GeisAttrBag bag, GeisAttr attr); /** * Looks for an attribute in an attribute container. */ GeisAttr geis_attr_bag_find(GeisAttrBag bag, GeisString attr_name); /** * Creates a Geis Attribute object. */ GeisAttr geis_attr_new(GeisString attr_name, GeisAttrType attr_type, void* attr_value); /** * Destroys a Geis Attribute object. */ void geis_attr_delete(GeisAttr attr); /** * Gets the (generic) attribute value. */ void *geis_attr_value(GeisAttr attr); /** * Set a destructor for a pointer attr. * * @param[in] attr An attr. * @param[in] destructor A destrutor function for a pointer attr value. */ void geis_attr_set_destructor(GeisAttr attr, GeisAttrDestructor destructor); /** * Compares two attributes using a filter operation. * * @param[in] lhs The attr on the left-hand side of the comparison. * @param[in] rhs The attr on the right-hand side of the comparison. * @param[in] op The filter operation. * * Returns GEIS_TRUE if the comparison is true, GEIS_FALSE otherwise. */ GeisBoolean geis_attr_compare(GeisAttr lhs, GeisAttr rhs, GeisFilterOperation op); #endif /* GEIS_ATTR_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_class.h0000644000015600001650000000567412651717544021027 0ustar pbuserpbgroup00000000000000/** * @file geis_class.h * @brief internal Geis Gesture Class module private interface * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_CLASS_H_ #define GEIS_CLASS_H_ #include "geis/geis.h" /** * @defgroup geis_gesture_class_container A Gesture Class Container * @{ */ /** * An unsorted container for holding classs. */ typedef struct _GeisGestureClassBag *GeisGestureClassBag; /** * Creates a new class bag, */ GeisGestureClassBag geis_gesture_class_bag_new(); /** * Destroys a gesture class bag. * * @param[in] bag The gesture class bag, */ void geis_gesture_class_bag_delete(GeisGestureClassBag bag); /** * Gets the number of gesture classs in the bag. * * @param[in] bag The gesture class bag, */ GeisSize geis_gesture_class_bag_count(GeisGestureClassBag bag); /** * Gets an indicated gesture class from a bag. * * @param[in] bag The gesture class bag. * @param[in] index The index. */ GeisGestureClass geis_gesture_class_bag_gesture_class(GeisGestureClassBag bag, GeisSize index); /** * Inserts a gesture class in the bag. * * @param[in] bag The gesture class bag. * @param[in] gesture_class The gesture class to insert. */ GeisStatus geis_gesture_class_bag_insert(GeisGestureClassBag bag, GeisGestureClass gesture_class); /** * Remoes a gesture class from the bag. * * @param[in] bag The gesture class bag. * @param[in] gesture_class The gesture class to remove. */ GeisStatus geis_gesture_class_bag_remove(GeisGestureClassBag bag, GeisGestureClass gesture_class); /** @} */ /** * @defgroup geis_gesture_class Internal Gesture Class Functions * @{ */ /** * Creates a new gesture class. * * @param[in] name A system-specific gesture class name. * @param[in] id A system-specific gesture class identifier. */ GeisGestureClass geis_gesture_class_new(GeisString name, GeisInteger id); /** * Inserts an attr into a gesture class. * * @param[in] gesture_class A gesture class. * @param[in] attr An attr. */ GeisStatus geis_gesture_class_add_attr(GeisGestureClass gesture_class, GeisAttr attr); /** @} */ #endif /* GEIS_CLASS_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_filter_term.c0000644000015600001650000003000412651717544022212 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_filter_term.c * @brief implementation of the GEIS v2.0 API filter term module * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_filter_term.h" #include "geis_atomic.h" #include "geis_attr.h" #include "geis_error.h" #include "geis_frame.h" #include "geis_logging.h" #include #include /* * One of the terms of a filter. */ struct _GeisFilterTerm { GeisRefCount refcount; GeisFilterFacility facility; GeisFilterOperation op; GeisAttr attr; }; /* * All of the terms of a filter. */ struct _GeisFilterTermBag { GeisFilterTerm *store; GeisSize store_size; GeisSize count; }; static const GeisSize term_bag_growth_constant = 2; GeisFilterTermBag geis_filter_term_bag_new(GeisSize store_size) { GeisFilterTermBag bag = calloc(1, sizeof(struct _GeisFilterTermBag)); if (!bag) { geis_error("failed to allocate filter termbag"); goto final_exit; } bag->store_size = store_size ? store_size : 3; bag->count = 0; bag->store = calloc(bag->store_size, sizeof(GeisFilterTerm)); if (!bag->store) { geis_error("failed to allocate filter bag store"); goto unwind_bag; } goto final_exit; unwind_bag: free(bag); bag = NULL; final_exit: return bag; } /* * Creates a new filter term bag by deep-copying an existing filter term bag. */ GeisFilterTermBag geis_filter_term_bag_clone(GeisFilterTermBag original) { GeisSize i; GeisFilterTermBag bag = geis_filter_term_bag_new(original->store_size); if (!bag) { goto final_exit; } bag->count = original->count; for (i = 0; i < bag->count; ++i) { bag->store[i] = geis_filter_term_ref(original->store[i]); } final_exit: return bag; } void geis_filter_term_bag_delete(GeisFilterTermBag bag) { GeisSize i; for (i = 0; i < bag->count; ++i) { geis_filter_term_unref(bag->store[i]); } free(bag->store); free(bag); } GeisSize geis_filter_term_bag_count(GeisFilterTermBag bag) { return bag->count; } GeisFilterTerm geis_filter_term_bag_term(GeisFilterTermBag bag, GeisSize index) { GeisFilterTerm term = NULL; if (index < bag->count) { term = bag->store[index]; } return term; } GeisStatus geis_filter_term_bag_insert(GeisFilterTermBag bag, GeisFilterTerm term) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (bag->count >= bag->store_size) { GeisSize new_store_size = bag->store_size * term_bag_growth_constant; GeisFilterTerm *new_store = realloc(bag->store, new_store_size * sizeof(struct _GeisFilterTerm)); if (!new_store) { geis_error("failed to reallocate filter term bag"); goto error_exit; } bag->store = new_store; bag->store_size = new_store_size; } bag->store[bag->count++] = term; status = GEIS_STATUS_SUCCESS; goto final_exit; error_exit: final_exit: return status; } GeisFilterTerm geis_filter_term_new(GeisFilterFacility facility, GeisFilterOperation operation, GeisAttr attr) { GeisFilterTerm term = calloc(1, sizeof(struct _GeisFilterTerm)); if (!term) { geis_error("failed to allocate filter termbag"); goto final_exit; } term->facility = facility; term->op = operation; term->attr = attr; geis_filter_term_ref(term); final_exit: return term; } static void _filter_term_destroy(GeisFilterTerm term) { geis_attr_delete(term->attr); free(term); } /* * Increments the filter term's reference count. */ GeisFilterTerm geis_filter_term_ref(GeisFilterTerm term) { geis_atomic_ref(&term->refcount); return term; } /* * Decrements the filter term's reference count and maybe destroys the term. */ void geis_filter_term_unref(GeisFilterTerm term) { if (0 == geis_atomic_unref(&term->refcount)) { _filter_term_destroy(term); } } GeisFilterFacility geis_filter_term_facility(GeisFilterTerm term) { return term->facility; } GeisFilterOperation geis_filter_term_operation(GeisFilterTerm term) { return term->op; } GeisAttr geis_filter_term_attr(GeisFilterTerm term) { return term->attr; } static GeisBoolean _filter_term_device_match_event(GeisFilterTerm term, GeisFrame frame) { GeisBoolean matches = GEIS_FALSE; GeisString attr_name = NULL; if (0 == strcmp(geis_attr_name(term->attr), GEIS_DEVICE_ATTRIBUTE_ID)) { attr_name = GEIS_GESTURE_ATTRIBUTE_DEVICE_ID; } else if (0 == strcmp(geis_attr_name(term->attr), GEIS_DEVICE_ATTRIBUTE_TOUCHES)) { attr_name = GEIS_GESTURE_ATTRIBUTE_TOUCHES; } if (attr_name) { GeisAttr attr; attr = geis_frame_attr_by_name(frame, attr_name); if (attr) { return geis_attr_compare(attr, term->attr, term->op); } } return matches; } static GeisBoolean _filter_term_class_match_event(GeisFilterTerm term, GeisFrame frame) { GeisBoolean matches = GEIS_FALSE; if (0 == strcmp(geis_attr_name(term->attr), GEIS_CLASS_ATTRIBUTE_NAME)) { matches = geis_frame_is_class_by_name(frame, geis_attr_value_to_string(term->attr)); } else { GeisAttr attr = geis_frame_attr_by_name(frame, geis_attr_name(term->attr)); if (attr) { matches = geis_attr_compare(attr, term->attr, term->op); } } return matches; } static GeisBoolean _filter_term_region_match_event(GeisFilterTerm term, GeisFrame frame) { GeisBoolean matches = GEIS_FALSE; if (0 == strcmp(geis_attr_name(term->attr), GEIS_REGION_ATTRIBUTE_WINDOWID)) { GeisAttr attr; attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID); if (attr) { matches = geis_attr_compare(attr, term->attr, term->op); } } return matches; } GeisBoolean geis_filter_term_match_event(GeisFilterTerm term, GeisEvent event) { GeisBoolean matches = GEIS_FALSE; GeisEventType event_type = geis_event_type(event); if (event_type == GEIS_EVENT_GESTURE_BEGIN || event_type == GEIS_EVENT_GESTURE_UPDATE || event_type == GEIS_EVENT_GESTURE_END) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("no groupset for gesture event"); goto final_exit; } GeisGroupSet groupset = geis_attr_value_to_pointer(attr); if (!groupset) { geis_warning("can not convert attr to groupset"); goto final_exit; } for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); if (!group) { geis_warning("can not extract group %zu from groupset", i); goto final_exit; } for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); if (!frame) { geis_warning("can not extract frame %zu from group", j); goto final_exit; } switch (term->facility) { case GEIS_FILTER_DEVICE: matches = _filter_term_device_match_event(term, frame); break; case GEIS_FILTER_CLASS: matches = _filter_term_class_match_event(term, frame); break; case GEIS_FILTER_REGION: matches = _filter_term_region_match_event(term, frame); break; default: break; } } } } final_exit: return matches; } /** * Indicates if an attr string value matches a given string and condition. * * @param[in] attr The attr with a string value. * @param[in] op A match condition. * @param[in] svalue A target string value to match. * * @returns GEIS_TRUE if the attr string value matches the target string and * condition, GEIS_FALSE otherwise. */ static GeisBoolean _filter_matches_attr_string(GeisAttr attr, GeisFilterOperation op, GeisString svalue) { GeisBoolean strings_match = GEIS_FALSE; GeisString attr_value = geis_attr_value_to_string(attr); if (attr_value) { strings_match = (0 == strcmp(attr_value, svalue)); } return (op == GEIS_FILTER_OP_EQ && strings_match) || (op == GEIS_FILTER_OP_NE && !strings_match); } /** * Indicates if an attr boolean value matches a given value and condition. * * @param[in] attr The attr with a string value. * @param[in] op A match condition. * @param[in] bvalue A target boolean value to match. * * @returns GEIS_TRUE if the attr boolean value matches the target value and * condition, GEIS_FALSE otherwise. */ static GeisBoolean _filter_matches_attr_boolean(GeisAttr attr, GeisFilterOperation op, GeisBoolean bvalue) { GeisBoolean attr_value = geis_attr_value_to_boolean(attr); return (op == GEIS_FILTER_OP_EQ && attr_value == bvalue) || (op == GEIS_FILTER_OP_NE && attr_value != bvalue); } /** * Indicates if an attr integer value matches a given value and condition. * * @param[in] attr The attr with a string value. * @param[in] op A match condition. * @param[in] ivalue A target integer value to match. * * @returns GEIS_TRUE if the attr integer value matches the target value and * condition, GEIS_FALSE otherwise. */ static GeisBoolean _filter_matches_attr_integer(GeisAttr attr, GeisFilterOperation op, GeisInteger ivalue) { GeisInteger attr_value = geis_attr_value_to_integer(attr); return (op == GEIS_FILTER_OP_EQ && attr_value == ivalue) || (op == GEIS_FILTER_OP_NE && attr_value != ivalue) || (op == GEIS_FILTER_OP_GT && attr_value > ivalue) || (op == GEIS_FILTER_OP_GE && attr_value >= ivalue) || (op == GEIS_FILTER_OP_LE && attr_value <= ivalue) || (op == GEIS_FILTER_OP_LT && attr_value < ivalue); } /* * Indicates a filter passes a device. */ GeisBoolean geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device) { if (geis_filter_term_facility(term) != GEIS_FILTER_DEVICE) { return GEIS_TRUE; } GeisAttr filter_attr = geis_filter_term_attr(term); GeisString attr_name = geis_attr_name(filter_attr); GeisFilterOperation op = geis_filter_term_operation(term); if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_NAME)) { GeisString device_name = geis_device_name(device); if (device_name) { return _filter_matches_attr_string(filter_attr, op, device_name); } } else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH) || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH)) { GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); if (device_attr) { GeisBoolean device_value = geis_attr_value_to_boolean(device_attr); return _filter_matches_attr_boolean(filter_attr, op, device_value); } } else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_ID) || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_TOUCHES)) { GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); if (device_attr) { GeisInteger device_value = geis_attr_value_to_integer(device_attr); /* legacy special case for device ID == 0: means ALL devices in v1 */ if (device_value == 0) { return GEIS_TRUE; } return _filter_matches_attr_integer(filter_attr, op, device_value); } } return GEIS_FALSE; } geis-2.2.17+16.04.20160126/libgeis/geis_error.h0000644000015600001650000000216112651717544021037 0ustar pbuserpbgroup00000000000000/** * @file geis_error.h * @brief internal GEIS error facilities * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_ERROR_H_ #define GEIS_ERROR_H_ #include /* * A structure to hold the error stack */ typedef struct _GeisErrorStack { GeisStatus *store; GeisSize store_size; GeisSize error_count; } GeisErrorStack; void geis_error_clear(Geis geis); void geis_error_push(Geis geis, GeisStatus code); #endif /* GEIS_ERROR_H_ */ geis-2.2.17+16.04.20160126/libgeis/libgeis.ver0000644000015600001650000000463312651717544020670 0ustar pbuserpbgroup00000000000000GEIS_1.0 { global: geis_configuration_get_value; geis_configuration_set_value; geis_configuration_supported; geis_event_dispatch; geis_finish; geis_init; geis_input_devices; geis_subscribe; geis_unsubscribe; }; GEIS_2.0 { global: geis_attr_name; geis_attr_type; geis_attr_value_to_boolean; geis_attr_value_to_float; geis_attr_value_to_integer; geis_attr_value_to_pointer; geis_attr_value_to_string; geis_delete; geis_device_attr; geis_device_attr_count; geis_device_id; geis_device_name; geis_device_ref; geis_device_unref; geis_dispatch_events; geis_error_code; geis_error_count; geis_error_message; geis_event_attr; geis_event_attr_by_name; geis_event_attr_count; geis_event_delete; geis_event_type; geis_filter_add_term; geis_filter_clone; geis_filter_delete; geis_filter_name; geis_filter_new; geis_frame_attr; geis_frame_attr_by_name; geis_frame_attr_count; geis_frame_id; geis_frame_is_class; geis_frame_matrix; geis_frame_touchid; geis_frame_touchid_count; geis_gesture_accept; geis_gesture_class_attr; geis_gesture_class_attr_count; geis_gesture_class_id; geis_gesture_class_name; geis_gesture_class_ref; geis_gesture_class_unref; geis_gesture_reject; geis_get_configuration; geis_group_frame; geis_group_frame_count; geis_group_id; geis_group_reject; geis_groupset_group; geis_groupset_group_count; geis_new; geis_next_event; geis_region_delete; geis_region_name; geis_region_new; geis_register_class_callback; geis_register_device_callback; geis_register_event_callback; geis_set_configuration; geis_subscription_activate; geis_subscription_add_filter; geis_subscription_deactivate; geis_subscription_delete; geis_subscription_filter_by_name; geis_subscription_id; geis_subscription_name; geis_subscription_new; geis_subscription_remove_filter; geis_touch_attr; geis_touch_attr_by_name; geis_touch_attr_count; geis_touch_id; geis_touchset_touch; geis_touchset_touch_by_id; geis_touchset_touch_count; }; GEIS_2.2 { global: geis_get_device; geis_device_attr_by_name; local: *; }; GEIS_2.3 { global: geis_subscription_get_configuration; geis_subscription_set_configuration; }; geis-2.2.17+16.04.20160126/libgeis/geis_touch.c0000644000015600001650000000776412651717544021041 0ustar pbuserpbgroup00000000000000/** * @file geis_touch.c * @brief Geis touch module implementation * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_touch.h" #include "geis_attr.h" #include "geis_logging.h" #include struct _GeisTouch { GeisTouch next; GeisTouchId id; GeisAttrBag attr_bag; }; struct _GeisTouchSet { GeisSize count; GeisTouch first; }; /* * Creates a new, empty touch set. */ GeisTouchSet geis_touchset_new() { GeisTouchSet touchset = calloc(1, sizeof(struct _GeisTouchSet)); if (!touchset) { geis_error("error allocating touch set"); goto final_exit; } final_exit: return touchset; } /* * Destroys a touch set and all touches contained in it. */ void geis_touchset_delete(GeisTouchSet touchset) { GeisTouch p = touchset->first; while (p) { GeisTouch tmp = p->next; geis_touch_delete(p); p = tmp; } free(touchset); } /* * Inserts a touch into a touch set. */ GeisStatus geis_touchset_insert(GeisTouchSet touchset, GeisTouch touch) { if (touchset->count == 0) { touchset->first = touch; } else { GeisTouch p = touchset->first; while (p->next) p = p->next; p->next = touch; } ++touchset->count; return GEIS_STATUS_SUCCESS; } GeisSize geis_touchset_touch_count(GeisTouchSet touchset) { return touchset->count; } GeisTouch geis_touchset_touch(GeisTouchSet touchset, GeisSize index) { GeisTouch touch = NULL; if (index >= touchset->count) { geis_warning("touch set index out of range"); } else { GeisSize i; touch = touchset->first; for (i = 0; i < index; ++i) { touch = touch->next; } } return touch; } GeisTouch geis_touchset_touch_by_id(GeisTouchSet touchset, GeisTouchId touchid) { GeisTouch result = NULL; GeisTouch touch = touchset->first; while (touch) { if (touch->id == touchid) { result = touch; break; } touch = touch->next; } return result; } /* * Creates a new gesture touch. */ GeisTouch geis_touch_new(GeisTouchId id) { GeisTouch touch = calloc(1, sizeof(struct _GeisTouch)); if (!touch) { geis_error("error allocating touch"); goto final_exit; } touch->attr_bag = geis_attr_bag_new(2); if (!touch->attr_bag) { geis_error("error allocating touch attr bag"); goto unwind_touch; } touch->id = id; goto final_exit; unwind_touch: free(touch); touch = NULL; final_exit: return touch; } /* * Destroys a gesture touch and all gesture frames contained in it. */ void geis_touch_delete(GeisTouch touch) { geis_attr_bag_delete(touch->attr_bag); free(touch); } /* * Gets the identifier of a gesture touch. */ GeisTouchId geis_touch_id(GeisTouch touch) { return touch->id; } /* * Inserts an attr. */ GeisStatus geis_touch_add_attr(GeisTouch touch, GeisAttr attr) { return geis_attr_bag_insert(touch->attr_bag, attr); } /* * Gets the number of attrs associated with a touch. */ GeisSize geis_touch_attr_count(GeisTouch touch) { return geis_attr_bag_count(touch->attr_bag); } /* * Gets an indicated attr from a touch. */ GeisAttr geis_touch_attr(GeisTouch touch, GeisSize index) { return geis_attr_bag_attr(touch->attr_bag, index); } /* * Gets a named attr from a touch. */ GeisAttr geis_touch_attr_by_name(GeisTouch touch, GeisString name) { return geis_attr_bag_find(touch->attr_bag, name); } geis-2.2.17+16.04.20160126/libgeis/geis_backend_multiplexor.c0000644000015600001650000002373212651717544023743 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_multiplexor.c * @brief internal GEIS backend multiplexor implementation * * Copyright 2010, 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_backend_multiplexor.h" #include #include #include "geis_logging.h" #include #include #include #include typedef struct CallbackInfo *CallbackInfo; struct CallbackInfo { int fd; GeisBackendMultiplexorActivity activity; GeisBackendFdEventCallback callback; void *context; CallbackInfo next; }; typedef struct CallbackInfoBag { CallbackInfo front; CallbackInfo back; CallbackInfo pool; } *CallbackInfoBag; struct _GeisBackendMultiplexor { int mx_fd; int mx_max_events_per_pump; CallbackInfoBag mx_callback_infos; }; /* * Creates a new container for callback info. */ static CallbackInfoBag _callback_info_bag_new() { CallbackInfoBag cbib = calloc(1, sizeof(struct CallbackInfoBag)); if (!cbib) { geis_error("error allocating Callback Info bag."); } return cbib; } /* * Destroys a callback info container. */ static void _callback_info_bag_delete(CallbackInfoBag cbib) { /* Drain the pool. */ CallbackInfo cbi = cbib->pool; while (cbi) { CallbackInfo next = cbi->next; free(cbi); cbi = next; } /* Dump the bag contents. */ cbi = cbib->front; while (cbi) { CallbackInfo next = cbi->next; free(cbi); cbi = next; } free(cbib); } /* * Allocates a CallbackInfo. */ static CallbackInfo _callback_info_bag_alloc(CallbackInfoBag cbib, int fd, GeisBackendMultiplexorActivity activity, GeisBackendFdEventCallback callback, void *context) { CallbackInfo callback_info = NULL; /* Either pull a free cbi from the pool or allocate a new one. */ if (cbib->pool) { callback_info = cbib->pool; cbib->pool = callback_info->next; } else { callback_info = calloc(1, sizeof(struct CallbackInfo)); if (!callback_info) { geis_error("error allocating CallbackInfoBag"); goto final_exit; } } /* Copy the stuff in. */ callback_info->fd = fd; callback_info->activity = activity; callback_info->callback = callback; callback_info->context = context; /* Add it to the in-use list. */ if (!cbib->front) { cbib->front = callback_info; } if (cbib->back) { cbib->back->next = callback_info; } cbib->back = callback_info; final_exit: return callback_info; } /* * Finds a CallbackInfo by file descriptor. */ CallbackInfo _callback_info_bag_find_by_fd(CallbackInfoBag cbib, int fd) { CallbackInfo callback_info = NULL; for (callback_info = cbib->front; callback_info; callback_info = callback_info->next) { if (callback_info->fd == fd) { break; } } return callback_info; } /* * Deallocates a CallbackInfo. */ static void _callback_info_bag_release(CallbackInfoBag cbib, int fd) { for (CallbackInfo callback_info = cbib->front, prev = NULL; callback_info; prev = callback_info, callback_info = callback_info->next) { if (callback_info->fd == fd) { if (callback_info == cbib->front) { cbib->front = callback_info->next; } else { prev->next = callback_info->next; } if (callback_info == cbib->back) { cbib->back = prev; } callback_info->next = cbib->pool; cbib->pool = callback_info; break; } } } /** * Creates a new backend multiplexor. */ GeisBackendMultiplexor geis_backend_multiplexor_new() { GeisBackendMultiplexor mx = calloc(1, sizeof(struct _GeisBackendMultiplexor)); if (!mx) { geis_error("failed to allocate backend multiplexor"); } else { mx->mx_fd = epoll_create(5); if (mx->mx_fd < 0) { geis_error("error %d creating backend multiplexor: %s", errno, strerror(errno)); goto unwind_mx; } if (fcntl(mx->mx_fd, F_SETFD, FD_CLOEXEC) < 0) { geis_error("error %d setting close-on-exec flag: %s", errno, strerror(errno)); } mx->mx_max_events_per_pump = GEIS_BE_MX_DEFAULT_EVENTS_PER_PUMP; mx->mx_callback_infos = _callback_info_bag_new(); if (!mx->mx_callback_infos) { geis_error("failed to allocate backend multiplexor callback_infos"); goto unwind_epoll; } } goto final_exit; unwind_epoll: close(mx->mx_fd); unwind_mx: free(mx); mx = NULL; final_exit: return mx; } /** * Destroys an backend multiplexor. */ void geis_backend_multiplexor_delete(GeisBackendMultiplexor mx) { _callback_info_bag_delete(mx->mx_callback_infos); close(mx->mx_fd); free(mx); } static uint32_t _epoll_events_from_activity(GeisBackendMultiplexorActivity activity) { uint32_t events = 0; if (activity & GEIS_BE_MX_READ_AVAILABLE) events |= EPOLLIN; if (activity & GEIS_BE_MX_WRITE_AVAILABLE) events |= EPOLLOUT; return events; } /* * Adds a file descriptor to an backend multiplexor. */ void geis_backend_multiplexor_add_fd(GeisBackendMultiplexor mx, int fd, GeisBackendMultiplexorActivity activity, GeisBackendFdEventCallback callback, void *context) { CallbackInfo callback_info = _callback_info_bag_alloc(mx->mx_callback_infos, fd, activity, callback, context); struct epoll_event ev; ev.events = _epoll_events_from_activity(activity); ev.data.ptr = callback_info; int status = epoll_ctl(mx->mx_fd, EPOLL_CTL_ADD, fd, &ev); if (status < 0) { geis_error("error %d multiplexing fd %d: %s", errno, fd, strerror(errno)); } } /* * Modifies the activities being monitored on a file descriptor. */ void geis_backend_multiplexor_modify_fd(GeisBackendMultiplexor mx, int fd, GeisBackendMultiplexorActivity activity) { int status; struct epoll_event ev; CallbackInfo callback_info; callback_info = _callback_info_bag_find_by_fd(mx->mx_callback_infos, fd); callback_info->activity = activity; ev.events = _epoll_events_from_activity(activity); ev.data.ptr = callback_info; status = epoll_ctl(mx->mx_fd, EPOLL_CTL_MOD, fd, &ev); if (status < 0) { geis_error("error %d remultiplexing fd %d: %s", errno, fd, strerror(errno)); } } /** * Removes a file descriptor from a backend multiplexor. * * @todo free callback_info */ void geis_backend_multiplexor_remove_fd(GeisBackendMultiplexor mx, int fd) { _callback_info_bag_release(mx->mx_callback_infos, fd); int status = epoll_ctl(mx->mx_fd, EPOLL_CTL_DEL, fd, NULL); if (status < 0) { geis_error("error %d demultiplexing fd %d: %s", errno, fd, strerror(errno)); } } /** * Gets the single file descriptor of the backend multiplexor itself. */ int geis_backend_multiplexor_fd(GeisBackendMultiplexor mx) { return mx->mx_fd; } /** * gets the maximum number of fd events per pump. */ int geis_backend_multiplexor_max_events_per_pump(GeisBackendMultiplexor mx) { return mx->mx_max_events_per_pump; } /** * Sets the maximum number of fd events processed per pump. */ void geis_backend_multiplexor_set_max_events_per_pump(GeisBackendMultiplexor mx, int max_events_per_pump) { mx->mx_max_events_per_pump = max_events_per_pump; } /** * Dispatches events on the multiplexed file descriptors. */ GeisStatus geis_backend_multiplexor_pump(GeisBackendMultiplexor mx) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; int processed_event_count = 0; int available_event_count = 1; struct epoll_event events[4]; while (available_event_count > 0 && processed_event_count < mx->mx_max_events_per_pump) { available_event_count = epoll_wait(mx->mx_fd, events, 4, 0); if (available_event_count < 0) { geis_error("error %d in epoll_wait: %s", errno, strerror(errno)); goto error_exit; } for (int i = 0; i < available_event_count; ++i) { GeisBackendMultiplexorActivity flags = 0; if (events[i].events & EPOLLIN) flags |= GEIS_BE_MX_READ_AVAILABLE; if (events[i].events & EPOLLOUT) flags |= GEIS_BE_MX_WRITE_AVAILABLE; if (events[i].events & EPOLLHUP) flags |= GEIS_BE_MX_HANGUP_DETECTED; if (events[i].events & EPOLLERR) flags |= GEIS_BE_MX_ERROR_DETECTED; CallbackInfo callback_info = (CallbackInfo)events[i].data.ptr; geis_debug("activity 0x%x on fd %d callback_info=%p", events[i].events, callback_info->fd, (void *)callback_info); callback_info->callback(callback_info->fd, flags, callback_info->context); ++processed_event_count; } } if (available_event_count) status = GEIS_STATUS_CONTINUE; else status = GEIS_STATUS_SUCCESS; error_exit: return status; } geis-2.2.17+16.04.20160126/libgeis/backend/0000755000015600001650000000000012651717732020114 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/backend/Makefile.am0000644000015600001650000000166512651717544022161 0ustar pbuserpbgroup00000000000000# # @file libgeis/backends/Makefile.am # @brief automake recipe for the GEIS v2.0 implementation back ends # # Copyright 2010, 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # SUBDIRS = test_fixture dbus grail geis-2.2.17+16.04.20160126/libgeis/backend/grail/0000755000015600001650000000000012651717732021212 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_token.h0000644000015600001650000000517712651717544024703 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_token.h * @brief GEIS filter token for the grail-based back end */ /* * Copyright 2011-2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #ifndef GEIS_BACKEND_GRAIL_TOKEN_H_ #define GEIS_BACKEND_GRAIL_TOKEN_H_ #include "geis_backend_protected.h" /** The Grail Back End token type */ typedef struct GeisGrailToken *GeisGrailToken; GeisBackendToken geis_grail_token_new(GeisBackend be, GeisBackendTokenInitState init_state); void geis_grail_token_delete(GeisBackendToken token); /** * Callback for adding a filter term for a gesture class. */ GeisStatus geis_grail_token_add_class_term(GeisBackendToken gbtoken, void *context, GeisString name, GeisFilterOperation op, void *value); /** * Callback for adding a filter term for a device. */ GeisStatus geis_grail_token_add_device_term(GeisBackendToken gbtoken, void *context, GeisString name, GeisFilterOperation op, void *value); /** * Callback for adding a filter term for a feature. */ GeisStatus geis_grail_token_add_feature_term(GeisBackendToken gbtoken, void *context, GeisString name, GeisFilterOperation op, void *value); /** * Callback for adding a filter term for a region. */ GeisStatus geis_grail_token_add_region_term(GeisBackendToken gbtoken, void *context, GeisString name, GeisFilterOperation op, void *value); #endif /* GEIS_BACKEND_GRAIL_TOKEN_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_window_grab.c0000644000015600001650000001165312651717544026054 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_window_grab.c * @brief window grab handling for the GEIS grail back end */ /* * Copyright 2011-2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #include "geis_config.h" #include "geis_grail_window_grab.h" #include "geis_bag.h" #include "geis_logging.h" #include /** * Tracks the number of grabs for each X window. */ struct GeisGrailWindowGrab { Window window_id; int grab_count; }; typedef struct GeisGrailWindowGrab *GeisGrailWindowGrab; /** * Stores all tracked window grabs. */ struct GeisGrailWindowGrabStore { Display *display; GeisBag grabs; }; static const GeisSize _geis_grail_window_grab_store_default_size = 2; static const GeisFloat _geis_grail_window_grab_store_growth_factor = 1.7; static GeisGrailWindowGrabStore _window_grab_allocate() { GeisGrailWindowGrabStore wgs = malloc(sizeof(struct GeisGrailWindowGrabStore)); if (!wgs) { geis_error("failed to allocate window grab store"); } return wgs; } static void _window_grab_deallocate(GeisGrailWindowGrabStore wgs) { free(wgs); } /* * Constructs a new window grab store. */ GeisGrailWindowGrabStore geis_grail_window_grab_store_new(Display *display) { GeisGrailWindowGrabStore wgs = _window_grab_allocate(); if (wgs) { wgs->display = display; wgs->grabs = geis_bag_new(sizeof(struct GeisGrailWindowGrab), _geis_grail_window_grab_store_default_size, _geis_grail_window_grab_store_growth_factor); if (!wgs->grabs) { free(wgs); wgs = NULL; } } return wgs; } /* * Destroys a window grab store. */ void geis_grail_window_grab_store_delete(GeisGrailWindowGrabStore wgs) { for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i) { /* @todo: ungrab */ } geis_bag_delete(wgs->grabs); _window_grab_deallocate(wgs); } static GeisGrailWindowGrab _window_grab_store_find(GeisGrailWindowGrabStore wgs, Window window_id) { for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i) { GeisGrailWindowGrab grab = (GeisGrailWindowGrab)geis_bag_at(wgs->grabs, i); if (grab->window_id == window_id) { return grab; } } return NULL; } /* * Grabs a window through a window grab store. */ GeisStatus geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore wgs, Window window_id) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id); if (!grab) { struct GeisGrailWindowGrab new_grab = { window_id, 1 }; geis_bag_append(wgs->grabs, &new_grab); XIEventMask mask = { XIAllMasterDevices, XIMaskLen(XI_LASTEVENT), calloc(XIMaskLen(XI_LASTEVENT), sizeof(char)) }; XISetMask(mask.mask, XI_TouchBegin); XISetMask(mask.mask, XI_TouchUpdate); XISetMask(mask.mask, XI_TouchEnd); XISetMask(mask.mask, XI_TouchOwnership); XISetMask(mask.mask, XI_HierarchyChanged); XIGrabModifiers mods = { XIAnyModifier, 0 }; int xstat = XIGrabTouchBegin(wgs->display, XIAllMasterDevices, window_id, 0, &mask, 1, &mods); free(mask.mask); if (xstat) { geis_error("error %d returned from XIGrabTouchBegin()", xstat); goto final_exit; } else if (mods.status != XIGrabSuccess) { geis_error("status %d returned from XIGrabTouchBegin()", mods.status); goto final_exit; } status = GEIS_STATUS_SUCCESS; } else { ++grab->grab_count; status = GEIS_STATUS_SUCCESS; } final_exit: return status; } /* * Ungrabs a window through a window grab store. * @param window The window to ungrab. */ void geis_grail_window_grab_store_ungrab(GeisGrailWindowGrabStore wgs, Window window_id) { GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id); if (grab) { --grab->grab_count; if (0 == grab->grab_count) { XIGrabModifiers mods = { XIAnyModifier, 0 }; Status xstat = XIUngrabTouchBegin(wgs->display, XIAllMasterDevices, window_id, 1, &mods); if (xstat) { geis_error("error %d returned from XIUngrabTouchBegin()", xstat); } XSync(wgs->display, False); } } } geis-2.2.17+16.04.20160126/libgeis/backend/grail/Makefile.am0000644000015600001650000000245212651717544023252 0ustar pbuserpbgroup00000000000000# # @file libgeis/backend/grail/Makefile.am # @brief automake recipe for the GEIS v2.0 grail back end # # Copyright 2011 Canonical, Ltd. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . noinst_LTLIBRARIES = libgeis-grail-backend.la libgeis_grail_backend_la_SOURCES = \ geis_grail_token.h geis_grail_token.c \ geis_grail_backend.h geis_grail_backend.c \ geis_grail_window_grab.h geis_grail_window_grab.c \ geis_grail_xsync.h geis_grail_xsync.c \ geis_ugsubscription_store.h geis_ugsubscription_store.c libgeis_grail_backend_la_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/libs/geis-util \ $(GRAIL_CFLAGS) libgeis_grail_backend_la_LIBADD = \ $(GRAIL_LIBS) \ $(XI2_LIBS) geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_xsync.h0000644000015600001650000000471312651717544024722 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_xsync.h * @brief Handles XSync lib usage for the GEIS grail backend */ /* * Copyright 2012 Canonical Ltd. * * This file is part of GEIS. * * GEIS is free software: you can redistribute it and/or modify it * under the terms of version 3 of the GNU Lesser General Public License as * published by the Free Software Foundation. * * GEIS 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 GEIS. If not, see . */ #ifndef GEIS_BACKEND_GRAIL_XSYNC_H_ #define GEIS_BACKEND_GRAIL_XSYNC_H_ #include // For Display and XEvent #include // For uint64_t #include "geis/geisimpl.h" // For GeisBoolean /** * The opaque "X Synchronization Extension Library" handler * * It facilitates and encapsulates the use of the XSync extension. Specially * by managing the XSyncAlarm instances needed to implement timeouts. */ typedef struct GeisGrailXSync *GeisGrailXSync; /** * Constructs a new GeisGrailXSync instance. * * It returns NULL if the initialization wasn't successful. * * OBS: Having multiple GeisGrailXSync instances is not supported and doesn't * make sense. */ GeisGrailXSync geis_grail_xsync_new(Display *display); /** * Destroys the given GeisGrailXSync */ void geis_grail_xsync_delete(GeisGrailXSync xsync); /** * Creates an XSyncAlarm with the given timeout * * If there's already an XSyncAlarm with that timeout, * nothing is done. * * An XSyncAlarmNotifyEvent will be sent once that timeout * is reached on the server. */ void geis_grail_xsync_set_timeout(GeisGrailXSync xsync, uint64_t timeout); /** * Returns true if the given XEvent is an XSyncAlarmNotifyEvent for * one of the existing XSyncAlarm instances and false otherwise. * * It also takes care of destroying the XSyncAlarm that had its * timeout reached. */ GeisBoolean geis_grail_xsync_is_timeout(GeisGrailXSync xsync, const XEvent *event); /** * Gets the server time contained in the given event. * * That event must be an XSyncAlarmNotifyEvent. It will be the case when * geis_grail_xsync_is_timeout() returns GeisTrue for it. * */ uint64_t geis_grail_xsync_get_server_time(const XEvent *event); #endif // GEIS_BACKEND_GRAIL_XSYNC_H_ geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_token.c0000644000015600001650000001467012651717544024674 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_token.c * @brief GEIS filter token for the grail-based back end */ /* * Copyright 2011-2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #include "geis_config.h" #include "geis_grail_token.h" #include "geis_backend_token.h" #include "geis_grail_backend.h" #include "geis_logging.h" #include #include /* The maximum nuimber of devices supported. */ #define MAX_NUM_DEVICES 10 /* The maximum nuimber of regions supported. */ #define MAX_NUM_WINDOWS 10 struct GeisGrailToken { struct GeisBackendToken base; GeisGrailBackend be; int device_count; int devices[MAX_NUM_DEVICES]; int window_count; Window windows[MAX_NUM_WINDOWS]; }; /** * Converts from a GeisBackendToken to an XcbBackendToken. */ static inline GeisGrailToken _geis_grail_token_from_geis_token(GeisBackendToken gbt) { return (GeisGrailToken)gbt; } /** * Allocates memory for a token from a pool. */ static GeisGrailToken _geis_grail_token_allocate(void) { return calloc(1, sizeof(struct GeisGrailToken)); } /** * Returns memory for a token to a pool. */ static void _geis_grail_token_deallocate(GeisGrailToken gdt) { free(gdt); } /** * Deep-copy-constructs a token. */ static GeisBackendToken _geis_grail_token_clone(GeisBackendToken original) { GeisGrailToken new_token = calloc(1, sizeof(struct GeisGrailToken)); memcpy(new_token, _geis_grail_token_from_geis_token(original), sizeof(struct GeisGrailToken)); return (GeisBackendToken)new_token; } /** * Composes one token onto another. * * @param[in,out] lhs * @param[in] rhs */ static void _geis_grail_token_compose(GeisBackendToken lhs GEIS_UNUSED, GeisBackendToken rhs GEIS_UNUSED) { } /** * Activates a Grail back end token. * * @param[in] token A %GeisGrailToken. * @param[in] subscription The subscrition the token will be activated on. */ static GeisStatus _geis_grail_token_activate(GeisBackendToken token, GeisSubscription sub) { GeisGrailToken gdt = _geis_grail_token_from_geis_token(token); GeisStatus status = geis_grail_backend_activate_subscription(gdt->be, sub); return status; } /** * Deactivates a Grail back end token. * * @param[in] token A %GeisGrailToken. */ static GeisStatus _geis_grail_token_deactivate(GeisBackendToken token, GeisSubscription sub) { GeisGrailToken gdt = _geis_grail_token_from_geis_token(token); GeisStatus status = geis_grail_backend_deactivate_subscription(gdt->be, sub); return status; } /** * Frees the memory allocated for the GEIS subscription private data */ static void _geis_grail_token_free_subscription_pdata(GeisBackendToken token, GeisSubscription sub) { GeisGrailToken gdt = _geis_grail_token_from_geis_token(token); geis_grail_backend_free_subscription_pdata(gdt->be, sub); } /** * Creates Grail-back-end-specific back end token. */ GeisBackendToken geis_grail_token_new(GeisBackend be, GeisBackendTokenInitState init_state GEIS_UNUSED) { static struct GeisBackendTokenVtable _token_vtbl = { _geis_grail_token_clone, geis_grail_token_delete, _geis_grail_token_compose, _geis_grail_token_activate, _geis_grail_token_deactivate, _geis_grail_token_free_subscription_pdata }; GeisGrailToken token = _geis_grail_token_allocate(); if (token) { token->base.vtbl = &_token_vtbl; token->be = (GeisGrailBackend)be; } return (GeisBackendToken)token; } /** * Releases resources for a token. * * @param[in] token A %GeisGrailToken. */ void geis_grail_token_delete(GeisBackendToken token) { GeisGrailToken gdt = _geis_grail_token_from_geis_token(token); _geis_grail_token_deallocate(gdt); } GeisStatus geis_grail_token_add_class_term(GeisBackendToken gbtoken GEIS_UNUSED, void *context GEIS_UNUSED, GeisString name GEIS_UNUSED, GeisFilterOperation op GEIS_UNUSED, void *value GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; return status; } GeisStatus geis_grail_token_add_device_term(GeisBackendToken gbtoken GEIS_UNUSED, void *context GEIS_UNUSED, GeisString name GEIS_UNUSED, GeisFilterOperation op GEIS_UNUSED, void *value GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; return status; } GeisStatus geis_grail_token_add_feature_term(GeisBackendToken gbtoken GEIS_UNUSED, void *context GEIS_UNUSED, GeisString name GEIS_UNUSED, GeisFilterOperation op GEIS_UNUSED, void *value GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; return status; } GeisStatus geis_grail_token_add_region_term(GeisBackendToken gbtoken, void *context GEIS_UNUSED, GeisString name, GeisFilterOperation op, void *value) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisGrailToken token = _geis_grail_token_from_geis_token(gbtoken); if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID) && op == GEIS_FILTER_OP_EQ) { Window window = (Window)*(GeisInteger*)value; geis_debug("attr name=\"%s\" windowid=0x%x", name, (unsigned int)window); token->windows[token->window_count++] = window; status = GEIS_STATUS_SUCCESS; } return status; } geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_xsync.c0000644000015600001650000001432212651717544024712 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_xsync.c * @brief Handles XSync lib usage for the GEIS grail backend */ /* * Copyright 2012 Canonical Ltd. * * This file is part of GEIS. * * GEIS is free software: you can redistribute it and/or modify it * under the terms of version 3 of the GNU Lesser General Public License as * published by the Free Software Foundation. * * GEIS 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 GEIS. If not, see . */ #include "geis_grail_xsync.h" #include "geis_bag.h" #include "geis_logging.h" #include "geis/geis.h" #include #include struct GeisGrailAlarm { XSyncAlarm xsync_alarm; uint64_t timeout; }; struct GeisGrailXSync { Display *display; XSyncCounter server_time_counter; int xsync_event_base; GeisBag alarms; /* List of GeisGrailAlarm, describing existing alarms */ }; GeisGrailXSync geis_grail_xsync_new(Display *display) { GeisGrailXSync self = malloc(sizeof(struct GeisGrailXSync)); if (!self) { geis_error("failed to allocate new GeisGrailXSync"); goto return_failure; } self->display = display; self->xsync_event_base = -1; self->alarms = geis_bag_new(sizeof(struct GeisGrailAlarm), 4, 4.0f); if (!self->alarms) { geis_error("failed to create GeisGrailXSync.alarms bag"); goto return_failure; } /* check for the presence of the XSync extension */ int error_base; if (XSyncQueryExtension(self->display, &self->xsync_event_base, &error_base) != True) { geis_warning("XSync extension is not available"); goto return_failure; } /* initialize the XSync extension */ int major; int minor; if (XSyncInitialize(self->display, &major, &minor) != True) { geis_warning("failed to initialize XSync extension"); goto return_failure; } /* find the server-time counter */ int num_system_counters; XSyncSystemCounter *counters; counters = XSyncListSystemCounters(self->display, &num_system_counters); GeisBoolean found_counter = GEIS_FALSE; for (int i = 0; i < num_system_counters; ++i) { if (0 == strcmp(counters[i].name, "SERVERTIME")) { self->server_time_counter = counters[i].counter; found_counter = GEIS_TRUE; break; } } XSyncFreeSystemCounterList(counters); if (!found_counter) geis_warning("couldn't find SERVERTIME XSyncCounter"); return self; return_failure: if (self->alarms) geis_bag_delete(self->alarms); if (self) free(self); return NULL; } void geis_grail_xsync_delete(GeisGrailXSync self) { geis_bag_delete(self->alarms); free(self); } /** * Creates and returns an XSyncAlarm configured with the given timeout or * None on failure */ static XSyncAlarm _geis_grail_xsync_create_alarm(GeisGrailXSync self, uint64_t timeout) { XSyncAlarmAttributes alarm_attributes; alarm_attributes.trigger.counter = self->server_time_counter; alarm_attributes.trigger.value_type = XSyncAbsolute; XSyncIntsToValue(&alarm_attributes.trigger.wait_value, timeout & 0xffffffff, timeout & 0xffffffff00000000); alarm_attributes.trigger.test_type = XSyncPositiveComparison; alarm_attributes.events = True; return XSyncCreateAlarm(self->display, XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCAEvents, &alarm_attributes); } /** * Returns GEIS_TRUE if an XSyncAlarm exists for the given timeout or * GEIS_FALSE otherwise */ static GeisBoolean _geis_grail_xsync_alarm_exists_for_timeout(GeisGrailXSync self, uint64_t timeout) { for (GeisSize i = 0, alarms_count = geis_bag_count(self->alarms); i < alarms_count; ++i) { struct GeisGrailAlarm *alarm = geis_bag_at(self->alarms, i); if (alarm->timeout == timeout) return GEIS_TRUE; } return GEIS_FALSE; } void geis_grail_xsync_set_timeout(GeisGrailXSync self, uint64_t timeout) { if (_geis_grail_xsync_alarm_exists_for_timeout(self, timeout)) return; struct GeisGrailAlarm alarm; alarm.xsync_alarm = _geis_grail_xsync_create_alarm(self, timeout); if (alarm.xsync_alarm == None) { geis_error("failed to create an XSync alarm."); return; } /* make sure xserver creates the alarm now, otherwise it could in theory happen only after the desired timeout period */ XFlush(self->display); alarm.timeout = timeout; geis_bag_append(self->alarms, &alarm); } /** * If the given XSyncAlarm exists, it's destroyed, removed from the * list of alarms and the function returns GEIS_TRUE. * * If the given XSyncAlarm doesn't exist, the function returns GEIS_FALSE. */ static GeisBoolean _geis_grail_xsync_destroy_alarm(GeisGrailXSync self, XSyncAlarm xsync_alarm) { for (GeisSize i = 0, alarms_count = geis_bag_count(self->alarms); i < alarms_count; ++i) { struct GeisGrailAlarm *alarm = geis_bag_at(self->alarms, i); if (alarm->xsync_alarm == xsync_alarm) { if (XSyncDestroyAlarm(self->display, xsync_alarm) == False) geis_error("failed to destroy XSync alarm"); geis_bag_remove(self->alarms, i); return GEIS_TRUE; } } return GEIS_FALSE; } GeisBoolean geis_grail_xsync_is_timeout(GeisGrailXSync self, const XEvent *event) { if (event->type != (self->xsync_event_base + XSyncAlarmNotify)) return GEIS_FALSE; const XSyncAlarmNotifyEvent *alarm_notify = (const XSyncAlarmNotifyEvent *) event; /* If the destruction isn't successful it means that this alarm has already been destroyed due to a previous XSyncAlarmNotifyEvent. Therefore its corresponding timeout has already happened and we shouldn't confirm it again. */ return _geis_grail_xsync_destroy_alarm(self, alarm_notify->alarm); } uint64_t geis_grail_xsync_get_server_time(const XEvent *event) { const XSyncAlarmNotifyEvent *alarm_notify = (const XSyncAlarmNotifyEvent *) event; XSyncValue time = alarm_notify->counter_value; return (uint64_t)XSyncValueHigh32(time) << 32 | XSyncValueLow32(time); } geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_ugsubscription_store.h0000644000015600001650000001154612651717544026676 0ustar pbuserpbgroup00000000000000/** * @file geis_ugsubscription_store.h * @brief grail subscritpion storage */ /* * Copyright 2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #ifndef GEIS_BACKEND_GRAIL_UGSUBSCRIPTION_STORE_H_ #define GEIS_BACKEND_GRAIL_UGSUBSCRIPTION_STORE_H_ #include "geis/geis.h" #include "geis_bag.h" #include "geis_grail_window_grab.h" #include /** * A place to keep grail subscription objects. * * This is an opaque pointer. * * The store is keyed by (device_id, window_id). */ typedef GeisBag GeisUGSubscriptionStore; /** * Creates a new, empty grail subscription store. * * @returns a pointer to a valid store, or NULL to indicate failure. */ GeisUGSubscriptionStore geis_ugsubscription_store_new(); /** * Destroys a grail subscription store. * @param[in] store The grail subscription store. */ void geis_ugsubscription_delete(GeisUGSubscriptionStore store); /** * Gets a count of the number of ugsubs in the store. * @param[in] store The grail subscription store. * * @returns the number of UGSubscriptions stored within. */ GeisSize geis_ugsubscription_count(GeisUGSubscriptionStore store); /** * Gets a UGSubscription from the store. * @param[in] store The grail subscription store. * @param[in] index Indicates a ugsub. * * Gets a UGSubscription from the store at the given index. * * @returns a valid UGSubscription or NULL to indicate failure. */ UGSubscription geis_ugsubscription_get_ugsubscription_at(GeisUGSubscriptionStore store, GeisSize index); /* * Creates a new UGSubscription and adds it to the store. * @param[in] store The grail subscription store. * @param[in] filter Identifies a filter. * @param[in] device Identifies a device. * @param[in] region_id Identifies a region. * * Creates a new UGSubscription for the identified filter, device, * and region. It's added to the store. A separate grail subscription * is required for each (filter, device, window) because filters on a * geis subscription are ORed, meaning each filter may have a different * minimum touch requirement. * * @returns a valid UGSubscription or NULL to indicate failure. */ UGSubscription geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisInteger region_id); /** * Gets a UGSubscription from the store. * @param[in] store The grail subscription store. * @param[in] filter Identifies a filter. * @param[in] device Identifies a device. * @param[in] region_id Identifies a region. * * Gets a UGSubscription from the store for the identified filter, device, * and region. A separate grail subscription is required for each (filter, * device, window) because filters on a geis subscription are ORed, meaning each * filter may have a different minimum touch requirement. * * @returns a valid UGSubscription or NULL to indicate failure. */ UGSubscription geis_ugsubscription_get_ugsubscription(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisInteger region_id); /** * Releases all UGSubscriptions for a (filter, device). * @param[in] store The grail subscription store. * @param[in] filter Identifies a filter. * @param[in] device Identifies a device. * @param[in] window_grabs A window grab collection. */ void geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisGrailWindowGrabStore window_grabs); /** * Releses a UGSubscription from the store. * @param[in] store The grail subscription store. * @param[in] ugsub The UGSubscription to release. */ void geis_ugsubscription_release_ugsubscription(GeisUGSubscriptionStore store, UGSubscription ugsub); #endif /* GEIS_BACKEND_GRAIL_UGSUBSCRIPTION_STORE_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_window_grab.h0000644000015600001650000000454112651717544026057 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_window_grab.h * @brief window grab handling for the GEIS grail back end */ /* * Copyright 2011 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #ifndef GEIS_BACKEND_GRAIL_WINDOW_GRAB_H_ #define GEIS_BACKEND_GRAIL_WINDOW_GRAB_H_ #include "geis/geis.h" #include /** * The opaque Grail Window Grab Store. * * A "window grab" in this context refers to a passive grab of all multi-touch * input on a specified window. There should be only a single grab of a window * with the X server, but it's possible for multiple GEIS subscriptions to exist * for the same region (window), so they need to multiplexed and refcounted * through a subscription-independent means. * * This is that means. */ typedef struct GeisGrailWindowGrabStore *GeisGrailWindowGrabStore; /** * Constructs a new window grab store. */ GeisGrailWindowGrabStore geis_grail_window_grab_store_new(Display *display); /** * Destroys a window grab store. * * @param store A window grab store. */ void geis_grail_window_grab_store_delete(GeisGrailWindowGrabStore store); /** * Grabs a window through a window grab store. * * @param store A window grab store. * @param window The window to grab. * * @returns GEIS_STATUS_SUCCESS if the multi-touch for the window was grabbed * successfully, GEIS_STATUS_UNKNOWN_ERROR otherwise. */ GeisStatus geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore store, Window window); /** * Ungrabs a window through a window grab store. * * @param store A window grab store. * @param window The window to ungrab. */ void geis_grail_window_grab_store_ungrab(GeisGrailWindowGrabStore store, Window window); #endif /* GEIS_BACKEND_GRAIL_WINDOW_GRAB_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_ugsubscription_store.c0000644000015600001650000001320212651717544026660 0ustar pbuserpbgroup00000000000000/** * @file geis_ugsubscription_store.cpp * @brief grail subscription storage */ /* * Copyright 2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #include "geis_config.h" #include "geis_ugsubscription_store.h" #include #include "geis_logging.h" #include #include typedef struct GeisUGSubscription { GeisFilter filter; UFDevice device; GeisInteger region_id; UGSubscription ugsub; } *GeisUGSubscription; static const GeisSize _geis_grail_ugsubscription_store_default_size = 2; static const GeisFloat _geis_grail_ugsubscription_store_growth_factor = 1.7; /* * Creates a new, empty grail subscription store. */ GeisUGSubscriptionStore geis_ugsubscription_store_new() { GeisUGSubscriptionStore store = geis_bag_new(sizeof(struct GeisUGSubscription), _geis_grail_ugsubscription_store_default_size, _geis_grail_ugsubscription_store_growth_factor); return store; } /* * Destroys a grail subscription store. */ void geis_ugsubscription_delete(GeisUGSubscriptionStore store) { for (GeisSize i = 0; i < geis_bag_count(store); ++i) { struct GeisUGSubscription * s = (struct GeisUGSubscription *)geis_bag_at(store, i); grail_subscription_delete(s->ugsub); } geis_bag_delete(store); } /* * Gets a count of the number of ugsubs in the store. */ GeisSize geis_ugsubscription_count(GeisUGSubscriptionStore store) { return geis_bag_count(store); } /* * Gets a UGSubscription from the store. */ UGSubscription geis_ugsubscription_get_ugsubscription_at(GeisUGSubscriptionStore store, GeisSize index) { assert(index < geis_bag_count(store)); return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub; } /* * Creates a new UGSubscription and adds it to the store. */ UGSubscription geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisInteger region_id) { UGSubscription ugsub = NULL; UGStatus ugstatus = grail_subscription_new(&ugsub); if (ugstatus != UGStatusSuccess) { geis_error("failed to create grail subscription"); goto final_exit; } ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyDevice, &device); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription device property"); } UFWindowId window_id = frame_x11_create_window_id(region_id); ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyWindow, &window_id); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription window property"); } struct GeisUGSubscription s = { .filter = filter, .device = device, .region_id = region_id, .ugsub = ugsub }; geis_bag_append(store, &s); final_exit: return ugsub; } /* * Gets a UGSubscription from the store. */ UGSubscription geis_ugsubscription_get_ugsubscription(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisInteger region_id) { UGSubscription ugsub = NULL; for (GeisSize i = 0; i < geis_bag_count(store); ++i) { GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i); if (s->filter == filter && s->device == device && s->region_id == region_id) { ugsub = s->ugsub; break; } } return ugsub; } void geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store, GeisFilter filter, UFDevice device, GeisGrailWindowGrabStore window_grabs) { GeisSize i = 0; while (i < geis_bag_count(store)) { GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i); if (s->filter == filter && s->device == device) { UFWindowId ufwindow; UGStatus ugstatus; ugstatus = grail_subscription_get_property(s->ugsub, UGSubscriptionPropertyWindow, &ufwindow); if (ugstatus != UGStatusSuccess) { geis_warning("error %d getting subscription window", ugstatus); } else { Window window_id = frame_x11_get_window_id(ufwindow); geis_grail_window_grab_store_ungrab(window_grabs, window_id); } grail_subscription_delete(s->ugsub); geis_bag_remove(store, i); } else { ++i; } } } /* * Releses a UGSubscription from the store. */ void geis_ugsubscription_release_ugsubscription(GeisUGSubscriptionStore store GEIS_UNUSED, UGSubscription ugsub GEIS_UNUSED) { } geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_backend.h0000644000015600001650000000314312651717544025141 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_backend.h * @brief The GEIS native grail back end */ /* * Copyright 2011-2012 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #ifndef GEIS_BACKEND_GRAIL_BACKEND_H_ #define GEIS_BACKEND_GRAIL_BACKEND_H_ #include "geis/geis.h" /** The opaque Grail Back End type. */ typedef struct GeisGrailBackend *GeisGrailBackend; /** * Activates a GEIS subscription on the back end. */ GeisStatus geis_grail_backend_activate_subscription(GeisGrailBackend gbe, GeisSubscription subscription); /** * Deactivates a GEIS subscription on the back end. */ GeisStatus geis_grail_backend_deactivate_subscription(GeisGrailBackend gbe, GeisSubscription subscription); /** * Frees the memory allocated for the GEIS subscription private data */ void geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe, GeisSubscription subscription); #endif /* GEIS_BACKEND_GRAIL_BACKEND_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/grail/geis_grail_backend.c0000644000015600001650000024244612651717551025145 0ustar pbuserpbgroup00000000000000/** * @file geis_grail_backend.c * @brief GEIS grail client back end */ /* * Copyright 2011-2013 Canonical Ltd. * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #include "geis_config.h" #include "geis_grail_backend.h" #include #include "geis_attr.h" #include "geis_backend.h" #include "geis_backend_protected.h" #include "geis_bag.h" #include "geis_event.h" #include "geis_grail_token.h" #include "geis_grail_window_grab.h" #include "geis_grail_xsync.h" #include "geis_group.h" #include "geis_logging.h" #include "geis_private.h" #include "geis_subscription.h" #include "geis_test_api.h" #include "geis_touch.h" #include "geis_ugsubscription_store.h" #include #include #include #include #include #include #define GBE_MAX_TOUCHES 5 static inline GeisSize _min(GeisSize a, GeisSize b) { return (a < b) ? a : b; } static inline GeisSize _max(GeisSize a, GeisSize b) { return (a > b) ? a : b; } struct _GeisSliceState { unsigned int slice_id; uint64_t timestamp; GeisFloat angle; GeisFloat position_x; GeisFloat position_y; GeisFloat radius; unsigned int num_touches; unsigned int touch_ids[GBE_MAX_TOUCHES]; }; /** * @addtogroup geis_backend_grail GEIS Grail Back End * @ingroup geis_backends * * A GEIS Back End that wraps a grail instance. * * @{ */ /** The less opaque Grail Back End structure. */ struct GeisGrailBackend { Geis geis; /**< The parent GEIS instance. */ Display *display; /**< The X11 connection. */ Window root_window; /**< The X11 root window. */ GeisGrailXSync xsync; /**< XSync handler for setting timers. */ UFHandle frame; /**< A frame instance. */ UGHandle grail; /**< A grail instance. */ GeisBag devices; /**< The list of known devices. */ GeisGrailWindowGrabStore window_grabs; /**< A collection of window inputs */ GeisBag slice_states; /**< Gesture slice states */ GeisSubBag subscription_bag; GeisGestureClass drag_class; GeisGestureClass pinch_class; GeisGestureClass rotate_class; GeisGestureClass tap_class; GeisGestureClass touch_class; GeisBoolean send_tentative_events; GeisBoolean send_synchronous_events; }; /** Holds backend-specific information regarding a GeisSubscription */ struct GeisGrailSubscriptionData { GeisUGSubscriptionStore ugstore; /* configuration options NULL if not set by user, in which case grail defaults are used */ uint64_t *drag_timeout; float *drag_threshold; uint64_t *pinch_timeout; float *pinch_threshold; uint64_t *rotate_timeout; float *rotate_threshold; uint64_t *tap_timeout; float *tap_threshold; }; static GeisStatus _grail_be_activate_for_device(GeisGrailBackend gbe, GeisFilter filter, GeisDevice device, GeisSubscription subscription); /** * Hashes an ID from a UFDevice. * * @todo this may need to be honed a little more. */ static inline GeisInteger _grail_be_device_id_from_ufdevice(UFDevice ufdevice) { return (intptr_t)ufdevice & 0xffff; } /** * Gets the UFDevice associated with an identified device hash. */ static UFDevice _grail_be_ufdevice_from_device_id(GeisGrailBackend gbe, GeisInteger device_id) { UFDevice ufdevice = NULL; for (GeisSize i = 0; i < geis_bag_count(gbe->devices); ++i) { UFDevice *d = geis_bag_at(gbe->devices, i); if (device_id == _grail_be_device_id_from_ufdevice(*d)) { ufdevice = *d; break; } } return ufdevice; } /** * A temporary error handler for X for when the default error handler is * abort(). */ static int _grail_be_x_error_handler(Display* display, XErrorEvent* event) { char buffer[512]; XGetErrorText(display, (int)event->error_code, buffer, 511); geis_error("error %u in X detected: %s", (unsigned)event->error_code, buffer); return 0; } /** * Extracts or calculates various gesture attributes. * * @param[in] gbe the grail back end instance * @param[in] slice the grail slice received * @param[in] slice_state the current grail slice state * @param[in] delta_t the time since the previous frame * @param[out] frame the gesture frame being created */ static void _grail_be_extract_gesture_attrs(GeisGrailBackend gbe, UGSlice slice, struct _GeisSliceState *slice_state, GeisFloat delta_t, GeisFrame frame) { UGGestureTypeMask ugmask = grail_slice_get_recognized(slice); const UGTransform *C = grail_slice_get_cumulative_transform(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME, GEIS_ATTR_TYPE_STRING, "n/a")); geis_frame_set_matrix(frame, &(*C)[0][0]); if (ugmask & UGGestureTypeDrag) { geis_frame_set_is_class(frame, gbe->drag_class); GeisFloat position_x = (*C)[0][2] + grail_slice_get_original_center_x(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_POSITION_X, GEIS_ATTR_TYPE_FLOAT, &position_x)); GeisFloat position_y = (*C)[1][2] + grail_slice_get_original_center_y(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_POSITION_Y, GEIS_ATTR_TYPE_FLOAT, &position_y)); GeisFloat delta_x = position_x - slice_state->position_x; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_DELTA_X, GEIS_ATTR_TYPE_FLOAT, &delta_x)); slice_state->position_x = position_x; GeisFloat delta_y = position_y - slice_state->position_y; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_DELTA_Y, GEIS_ATTR_TYPE_FLOAT, &delta_y)); slice_state->position_y = position_y; if (delta_t > 0.0f) { GeisFloat x_velocity = delta_x / delta_t; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_VELOCITY_X, GEIS_ATTR_TYPE_FLOAT, &x_velocity)); GeisFloat y_velocity = delta_y / delta_t; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y, GEIS_ATTR_TYPE_FLOAT, &y_velocity)); } } if (ugmask & UGGestureTypePinch) { geis_frame_set_is_class(frame, gbe->pinch_class); GeisFloat ca = (*C)[0][0]; GeisFloat cb = (*C)[0][1]; GeisFloat r = sqrtf(ca*ca + cb*cb); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_RADIUS, GEIS_ATTR_TYPE_FLOAT, &r)); GeisFloat dr = r / slice_state->radius; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA, GEIS_ATTR_TYPE_FLOAT, &dr)); slice_state->radius = r; if (delta_t > 0.0f) { GeisFloat vr = (delta_t > 0.0f) ? dr / delta_t : 0.0f; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY, GEIS_ATTR_TYPE_FLOAT, &vr)); } } if (ugmask & UGGestureTypeRotate) { geis_frame_set_is_class(frame, gbe->rotate_class); GeisFloat centre_x = grail_slice_get_center_of_rotation_x(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_CENTROID_X, GEIS_ATTR_TYPE_FLOAT, ¢re_x)); GeisFloat centre_y = grail_slice_get_center_of_rotation_y(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_CENTROID_Y, GEIS_ATTR_TYPE_FLOAT, ¢re_y)); GeisFloat angle = atan2((*C)[0][1], (*C)[0][0]); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_ANGLE, GEIS_ATTR_TYPE_FLOAT, &angle)); GeisFloat da = angle - slice_state->angle; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA, GEIS_ATTR_TYPE_FLOAT, &da)); slice_state->angle = angle; if (delta_t > 0.0f) { GeisFloat va = (delta_t > 0.0f) ? da / delta_t : 0.0f; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY, GEIS_ATTR_TYPE_FLOAT, &va)); } } if (ugmask & UGGestureTypeTap) { geis_frame_set_is_class(frame, gbe->tap_class); } if (ugmask & UGGestureTypeTouch) { geis_frame_set_is_class(frame, gbe->touch_class); } } /** * Returns a grail slice state, given its id. * * @param[in] gbe the grail back end * @param[in] slice_id the id of a grail slice * * @returns a pointer to a grail slice state or NULL if there is no * grail slice state for a slice with the given id. */ struct _GeisSliceState * _grail_be_slice_state_from_id(GeisGrailBackend gbe, unsigned int slice_id) { struct _GeisSliceState *slice_state = NULL; for (GeisSize i = 0; i < geis_bag_count(gbe->slice_states); ++i) { struct _GeisSliceState *s = geis_bag_at(gbe->slice_states, i); if (s->slice_id == slice_id) { slice_state = s; break; } } return slice_state; } /** * Gets the previous slice state (if any) for a grail slice. * * @param[in] gbe the grail back end * @param[in] slice a grail slice * * @returns a pointer to a grail slice state or NULL if there is no previous * grail slice state. */ struct _GeisSliceState * _grail_be_slice_state_from_ugslice(GeisGrailBackend gbe, UGSlice slice) { return _grail_be_slice_state_from_id(gbe, grail_slice_get_id(slice)); } /** * Constructs a new slice state for a grail slise. * * @param[in] gbe the grail back end * @param[in] slice a grail slice * * @returns a pointer to a grail slice state or NULL on failure. */ struct _GeisSliceState * _grail_be_slice_state_new(GeisGrailBackend gbe, UGSlice slice) { const UGTransform *C = grail_slice_get_cumulative_transform(slice); struct _GeisSliceState new_slice_state = { .slice_id = grail_slice_get_id(slice), .timestamp = 0, .angle = 0.0f, .position_x = grail_slice_get_original_center_x(slice) + (*C)[0][2], .position_y = grail_slice_get_original_center_y(slice) + (*C)[1][2], .radius = 1.0f, .num_touches = grail_slice_get_num_touches(slice) }; /* fill up the touch_ids array */ UFTouchId touch_id; UGStatus status; for (unsigned int i = 0; i < new_slice_state.num_touches; ++i) { status = grail_slice_get_touch_id(slice, i, &touch_id); if (status == UGStatusSuccess) { new_slice_state.touch_ids[i] = touch_id; } else { geis_error("failed to get id of touch of index %u from slice with id %u", i, new_slice_state.slice_id); /* zero is a valid id but it's still better than leaving an aleatory number here */ new_slice_state.touch_ids[i] = 0; } } geis_bag_append(gbe->slice_states, &new_slice_state); return _grail_be_slice_state_from_ugslice(gbe, slice); } /** * Update a slice state for a grail slice. * * @param[in] slice_state the geis slice state * @param[in] slice a grail slice * * This function resets the slice state if the number of touches has changed. */ static void _grail_be_slice_state_update(struct _GeisSliceState *slice_state, UGSlice slice) { if (slice_state->num_touches != grail_slice_get_num_touches(slice)) { const UGTransform *C = grail_slice_get_cumulative_transform(slice); slice_state->angle = 0.0f; slice_state->position_x = grail_slice_get_original_center_x(slice) + (*C)[0][2]; slice_state->position_y = grail_slice_get_original_center_y(slice) + (*C)[1][2]; slice_state->radius = 1.0f; slice_state->num_touches = grail_slice_get_num_touches(slice); } } /** * Creates a geis event from a grail slice. * * @param[in] gbe the grail back end * @param[in] slice the grail slice * @param[in] clice_state the slice state (may be NULL) * * @returns a new geis event or NULL if no valid event can be created for the * slice. */ static GeisEvent _grail_be_geis_event_from_ugslice(GeisGrailBackend gbe, UGSlice slice, struct _GeisSliceState *slice_state) { GeisEvent geis_event = NULL; /* Retrieve the slice's recognized gestures. */ UGGestureTypeMask ugmask = grail_slice_get_recognized(slice); switch (grail_slice_get_state(slice)) { case UGGestureStateBegin: if (ugmask) geis_event = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); else if (gbe->send_tentative_events) geis_event = geis_event_new(GEIS_EVENT_TENTATIVE_BEGIN); break; case UGGestureStateUpdate: if (ugmask) if (slice_state) geis_event = geis_event_new(GEIS_EVENT_GESTURE_UPDATE); else geis_event = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); else if (gbe->send_tentative_events) geis_event = geis_event_new(GEIS_EVENT_TENTATIVE_UPDATE); break; case UGGestureStateEnd: if (slice_state) geis_event = geis_event_new(GEIS_EVENT_GESTURE_END); else if (gbe->send_tentative_events) geis_event = geis_event_new(GEIS_EVENT_TENTATIVE_END); break; } return geis_event; } static void _grail_be_set_x11_timeout(GeisGrailBackend gbe) { /* Set a timeout on the X server, if necessary. */ uint64_t timeout = grail_next_timeout(gbe->grail); if (timeout) geis_grail_xsync_set_timeout(gbe->xsync, timeout); } /** * Creates a GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED corresponding to the * "construction finished" property of the given slice. */ static GeisAttr _grail_be_create_construction_attr(UGSlice slice) { int slice_construction_finished = 0; UGStatus status = grail_slice_get_property(slice, UGSlicePropertyConstructionFinished, &slice_construction_finished); if (status != UGStatusSuccess) { geis_error("could not retrieve \"construction finished\" property from " "grail slice"); return 0; } GeisBoolean attr_value; if (slice_construction_finished) attr_value = GEIS_TRUE; else attr_value = GEIS_FALSE; GeisAttr construction_attr = geis_attr_new( GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED, GEIS_ATTR_TYPE_BOOLEAN, &attr_value); return construction_attr; } static void _grail_be_grail_fd_callback(int fd GEIS_UNUSED, GeisBackendMultiplexorActivity ev GEIS_UNUSED, void *ctx) { GeisGrailBackend gbe = (GeisGrailBackend)ctx; UGEvent event; while (grail_get_event(gbe->grail, &event) == UGStatusSuccess) { /* Extract the grail slice from the grail event. */ if (UGEventTypeSlice == grail_event_get_type(event)) { UGSlice slice; UGStatus ugstatus = grail_event_get_property(event, UGEventPropertySlice, &slice); if (ugstatus != UGStatusSuccess) { geis_error("could not retrieve slice from grail event"); goto next_event; } /* Get any previous slice state for the grail slice. */ struct _GeisSliceState *slice_state = NULL; slice_state = _grail_be_slice_state_from_ugslice(gbe, slice); /* Translate the grail slice into a geis event, maybe. */ GeisEvent geis_event = _grail_be_geis_event_from_ugslice(gbe, slice, slice_state); if (!geis_event) { goto next_event; } /* A gesture needs to start out with an initial state. */ if (GEIS_EVENT_GESTURE_BEGIN == geis_event_type(geis_event)) { slice_state = _grail_be_slice_state_new(gbe, slice); if (!slice_state) { geis_error("logic error"); geis_event_delete(geis_event); goto next_event; } } /* If the client doesn't want tentative events, tap events must be sent as * a one-shot update event. Transform begin events into update events, and * any discard any further events. */ if (!gbe->send_tentative_events && UGGestureTypeTap == grail_slice_get_recognized(slice)) { if (GEIS_EVENT_GESTURE_BEGIN == geis_event_type(geis_event)) geis_event_override_type(geis_event, GEIS_EVENT_GESTURE_UPDATE); else { geis_event_delete(geis_event); goto next_event; } } /* Updated any saved gesture state. */ uint64_t timestamp = grail_event_get_time(event); GeisFloat time_delta = 0.0f; if (slice_state) { uint64_t dt = timestamp - slice_state->timestamp; /* Skip synchronous events if not requested to send them. */ if (GEIS_EVENT_GESTURE_UPDATE == geis_event_type(geis_event) && !gbe->send_synchronous_events && dt <= 0) { geis_event_delete(geis_event); goto next_event; } time_delta = dt; slice_state->timestamp = timestamp; } _grail_be_slice_state_update(slice_state, slice); GeisGroupSet groupset = geis_groupset_new(); GeisAttr group_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_GROUPSET, GEIS_ATTR_TYPE_POINTER, groupset); geis_attr_set_destructor(group_attr, (GeisAttrDestructor)geis_groupset_delete); GeisGroup group = geis_group_new(1); geis_groupset_insert(groupset, group); GeisTouchSet touchset = geis_touchset_new(); GeisAttr touch_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_TOUCHSET, GEIS_ATTR_TYPE_POINTER, touchset); geis_attr_set_destructor(touch_attr, (GeisAttrDestructor)geis_touchset_delete); GeisFrame frame = geis_frame_new(grail_slice_get_id(slice)); geis_group_insert_frame(group, frame); GeisInteger ts = timestamp; geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_TIMESTAMP, GEIS_ATTR_TYPE_INTEGER, &ts)); UFFrame ufframe = grail_slice_get_frame(slice); UFDevice ufdevice = frame_frame_get_device(ufframe); GeisInteger geis_device_id = _grail_be_device_id_from_ufdevice(ufdevice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, GEIS_ATTR_TYPE_INTEGER, &geis_device_id)); GeisBoolean is_touchscreen = GEIS_FALSE; GeisDevice geis_device = geis_get_device(gbe->geis, geis_device_id); if (!geis_device) { geis_warning("unrecognized device %d reported", geis_device_id); } else { GeisAttr attr = geis_device_attr_by_name(geis_device, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH); is_touchscreen = (attr && geis_attr_value_to_boolean(attr)); } geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &gbe->root_window)); GeisInteger window = frame_x11_get_window_id(frame_frame_get_window_id(ufframe)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &window)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &window)); GeisInteger num_touches = grail_slice_get_num_touches(slice); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &num_touches)); GeisFloat focus_x = 0.0f; GeisFloat focus_y = 0.0f; if (is_touchscreen) { const UGTransform *C = grail_slice_get_cumulative_transform(slice); focus_x = (*C)[0][2] + grail_slice_get_original_center_x(slice); focus_y = (*C)[1][2] + grail_slice_get_original_center_y(slice); } GeisFloat bboxMinX = FLT_MAX; GeisFloat bboxMinY = FLT_MAX; GeisFloat bboxMaxX = 0.0f; GeisFloat bboxMaxY = 0.0f; for (GeisInteger t = 0; t < num_touches; ++t) { GeisTouch touch = geis_touch_new(t); if (!touch) { geis_error("can not create GEIS touch object"); continue; } UFTouchId touch_id; ugstatus = grail_slice_get_touch_id(slice, t, &touch_id); GeisInteger touch_slot = touch_id; geis_touch_add_attr(touch, geis_attr_new(GEIS_TOUCH_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, &touch_slot)); UFTouch uftouch; UFStatus ufstatus; ufstatus = frame_frame_get_touch_by_id(ufframe, touch_id, &uftouch); if (ufstatus != UFStatusSuccess) { geis_error("can not retrieve touch %ld from slice frame", (long)touch_id); continue; } if (!is_touchscreen) { focus_x = frame_touch_get_window_x(uftouch); focus_y = frame_touch_get_window_y(uftouch); } GeisFloat touch_x = 0.0f, touch_y = 0.0f; if (is_touchscreen) { touch_x = frame_touch_get_window_x(uftouch); touch_y = frame_touch_get_window_y(uftouch); } else { touch_x = frame_touch_get_device_x(uftouch); touch_y = frame_touch_get_device_y(uftouch); } bboxMinX = fmin(bboxMinX, touch_x); bboxMaxX = fmax(bboxMaxX, touch_x); geis_touch_add_attr(touch, geis_attr_new(GEIS_TOUCH_ATTRIBUTE_X, GEIS_ATTR_TYPE_FLOAT, &touch_x)); bboxMinY = fmin(bboxMinY, touch_y); bboxMaxY = fmax(bboxMaxY, touch_y); geis_touch_add_attr(touch, geis_attr_new(GEIS_TOUCH_ATTRIBUTE_Y, GEIS_ATTR_TYPE_FLOAT, &touch_y)); geis_touchset_insert(touchset, touch); geis_frame_add_touchid(frame, geis_touch_id(touch)); } geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_FOCUS_X, GEIS_ATTR_TYPE_FLOAT, &focus_x)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, GEIS_ATTR_TYPE_FLOAT, &focus_y)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1, GEIS_ATTR_TYPE_FLOAT, &bboxMinX)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1, GEIS_ATTR_TYPE_FLOAT, &bboxMinY)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2, GEIS_ATTR_TYPE_FLOAT, &bboxMaxX)); geis_frame_add_attr(frame, geis_attr_new(GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2, GEIS_ATTR_TYPE_FLOAT, &bboxMaxY)); _grail_be_extract_gesture_attrs(gbe, slice, slice_state, time_delta, frame); GeisAttr construction_attr = _grail_be_create_construction_attr(slice); geis_event_add_attr(geis_event, group_attr); geis_event_add_attr(geis_event, touch_attr); geis_event_add_attr(geis_event, construction_attr); geis_post_event(gbe->geis, geis_event); /* Destroy any saved state after the a gesture has ended. */ if (UGGestureStateEnd == grail_slice_get_state(slice)) { for (GeisSize i = 0; i < geis_bag_count(gbe->slice_states); ++i) { if (slice_state == geis_bag_at(gbe->slice_states, i)) { geis_bag_remove(gbe->slice_states, i); break; } } } } next_event: grail_event_unref(event); } _grail_be_set_x11_timeout(gbe); } /** * Activates active subscriptions for a newly-seen device. */ static void _grail_be_subscribe_new_device(GeisGrailBackend gbe, GeisDevice device) { for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag); it != geis_subscription_bag_end(gbe->subscription_bag); it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it)) { for (GeisFilterIterator fit = geis_subscription_filter_begin(*it); fit != geis_subscription_filter_end(*it); fit = geis_subscription_filter_next(*it, fit)) { GeisBoolean device_applies = GEIS_TRUE; for (GeisSize tindex = 0; tindex < geis_filter_term_count(*fit); ++tindex) { GeisFilterTerm term = geis_filter_term(*fit, tindex); if (geis_filter_term_facility(term) == GEIS_FILTER_DEVICE) { if (!geis_filter_term_match_device(term, device)) { device_applies = GEIS_FALSE; break; } } } if (device_applies) { _grail_be_activate_for_device(gbe, *fit, device, *it); } } } } /** * Removes active subscriptions for recently-removed devices. */ static void _grail_be_unsubscribe_removed_device(GeisGrailBackend gbe, UFDevice device) { for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag); it != geis_subscription_bag_end(gbe->subscription_bag); it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it)) { struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(*it); GeisUGSubscriptionStore ugstore = subscription_data->ugstore; for (GeisFilterIterator fit = geis_subscription_filter_begin(*it); fit != geis_subscription_filter_end(*it); fit = geis_subscription_filter_next(*it, fit)) { geis_ugsubscription_release_for_device(ugstore, *fit, device, gbe->window_grabs); } } } /** * Adds the axis exten attributes for a device, if available. */ static void _gbe_add_device_axis_attributes(UFDevice frame_device, GeisDevice geis_device) { UFStatus status; GeisFloat fval; UFAxis x_axis; status = frame_device_get_axis_by_type(frame_device, UFAxisTypeX, &x_axis); if (status != UFStatusSuccess) { geis_warning("failed to get X axis property from device '%s'", geis_device_name(geis_device)); } else { fval = frame_axis_get_minimum(x_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_MIN_X, GEIS_ATTR_TYPE_FLOAT, &fval)); fval = frame_axis_get_maximum(x_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_MAX_X, GEIS_ATTR_TYPE_FLOAT, &fval)); fval = frame_axis_get_resolution(x_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_RES_X, GEIS_ATTR_TYPE_FLOAT, &fval)); } UFAxis y_axis; status = frame_device_get_axis_by_type(frame_device, UFAxisTypeY, &y_axis); if (status != UFStatusSuccess) { geis_warning("failed to get Y axis property from device '%s'", geis_device_name(geis_device)); } else { fval = frame_axis_get_minimum(y_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_MIN_Y, GEIS_ATTR_TYPE_FLOAT, &fval)); fval = frame_axis_get_maximum(y_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_MAX_Y, GEIS_ATTR_TYPE_FLOAT, &fval)); fval = frame_axis_get_resolution(y_axis); geis_device_add_attr(geis_device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_RES_Y, GEIS_ATTR_TYPE_FLOAT, &fval)); } } /** * Reports an X11 device to the front end as a GEIS device. */ static void _geis_grail_add_device(GeisGrailBackend gbe, UFDevice frame_device) { UFStatus status; GeisBoolean discard_device_messages = GEIS_FALSE; geis_get_configuration(gbe->geis, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, &discard_device_messages); if (discard_device_messages) { geis_debug("device message discarded because of configuration setting"); return; } geis_bag_append(gbe->devices, &frame_device); GeisInteger device_id = _grail_be_device_id_from_ufdevice(frame_device); char *device_name = NULL; status = frame_device_get_property(frame_device, UFDevicePropertyName, &device_name); if (status != UFStatusSuccess) { geis_error("failed to get 'name' property from device"); goto final_exit; } GeisDevice geis_device = geis_device_new(device_name, device_id); if (!geis_device) { geis_error("failed to create GEIS device"); goto final_exit; } int ival; status = frame_device_get_property(frame_device, UFDevicePropertyMaxTouches, &ival); if (status != UFStatusSuccess) { geis_warning("failed to get 'touches' property from device '%s'", device_name); } else { GeisAttr attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &ival); geis_device_add_attr(geis_device, attr); } status = frame_device_get_property(frame_device, UFDevicePropertyDirect, &ival); if (status != UFStatusSuccess) { geis_warning("failed to get 'direct' property from device '%s'", device_name); } else { GeisAttr attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, &ival); geis_device_add_attr(geis_device, attr); } status = frame_device_get_property(frame_device, UFDevicePropertyIndependent, &ival); if (status != UFStatusSuccess) { geis_warning("failed to get 'independent' property from device '%s'", device_name); } else { GeisAttr attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, &ival); geis_device_add_attr(geis_device, attr); } _gbe_add_device_axis_attributes(frame_device, geis_device); /* Report the device as a filterable entity. */ static struct GeisFilterableAttribute attrs[] = { { GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, 0, NULL }, }; static GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); geis_register_device(gbe->geis, geis_device, attr_count, attrs); /* We are not going to hold a pointer to this geis_device ourselves */ geis_device_unref(geis_device); final_exit: return; } static void _geis_grail_remove_device(GeisGrailBackend gbe, UFDevice frame_device) { GeisBoolean discard_device_messages = GEIS_FALSE; geis_get_configuration(gbe->geis, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, &discard_device_messages); if (discard_device_messages) { geis_debug("device message discarded because of configuration setting"); return; } _grail_be_unsubscribe_removed_device(gbe, frame_device); for (GeisSize i = 0; i < geis_bag_count(gbe->devices); ++i) { UFDevice *device = geis_bag_at(gbe->devices, i); GeisInteger device_id = _grail_be_device_id_from_ufdevice(*device); if (device_id == _grail_be_device_id_from_ufdevice(frame_device)) { GeisDevice geis_device = geis_get_device(gbe->geis, device_id); if (!geis_device) { geis_warning("unrecognized device %d has been removed", device_id); } else { geis_unregister_device(gbe->geis, geis_device); } break; } } } /** * Processes all the frame events until the queue is empty. * * @param[in] gbe the grail back end */ static void _geis_be_flush_frame_events(GeisGrailBackend gbe) { UFEvent frame_event; while (frame_get_event(gbe->frame, &frame_event) == UFStatusSuccess) { UFEventType event_type = frame_event_get_type(frame_event); if (event_type == UFEventTypeDeviceAdded) { UFDevice frame_device; UFStatus status = frame_event_get_property(frame_event, UFEventPropertyDevice, &frame_device); if (status != UFStatusSuccess) { geis_warning("can not get device from device-added frame event"); } else { _geis_grail_add_device(gbe, frame_device); } } else if (event_type == UFEventTypeDeviceRemoved) { UFDevice frame_device; UFStatus status = frame_event_get_property(frame_event, UFEventPropertyDevice, &frame_device); if (status != UFStatusSuccess) { geis_warning("can not get device from device-removed frame event"); } else { _geis_grail_remove_device(gbe, frame_device); } } grail_process_frame_event(gbe->grail, frame_event); frame_event_unref(frame_event); _grail_be_set_x11_timeout(gbe); } } /** * Callback invoked when frame has events in the queue. * * @param[in] fd The frame file descriptor (not used). * @param[in] ev The type of FD event (not used). * @param[in] ctx The context data (the GEIS grail back end). */ static void _grail_be_frame_fd_callback(int fd GEIS_UNUSED, GeisBackendMultiplexorActivity ev GEIS_UNUSED, void *ctx) { GeisGrailBackend gbe = (GeisGrailBackend)ctx; _geis_be_flush_frame_events(gbe); } /** * Pushes X11 events into the frame filter. * * @param[in] fd The X11 file descriptor (not used). * @param[in] ev The type of FD event (not used). * @param[in] ctx The context data (the GEIS grail back end). */ static void _x11_fd_callback(int fd GEIS_UNUSED, GeisBackendMultiplexorActivity ev GEIS_UNUSED, void *ctx) { GeisGrailBackend gbe = (GeisGrailBackend)ctx; XEvent event; while (XPending(gbe->display)) { XNextEvent(gbe->display, &event); if (geis_grail_xsync_is_timeout(gbe->xsync, &event)) { uint64_t server_time = geis_grail_xsync_get_server_time(&event); if (server_time) grail_update_time(gbe->grail, server_time); continue; } XGenericEventCookie *xcookie = &event.xcookie; if (!XGetEventData(gbe->display, xcookie)) { geis_warning("failed to get X generic event data"); continue; } UFStatus frame_status = frame_x11_process_event(gbe->frame, xcookie); if (frame_status != UFStatusSuccess) { geis_warning("failed to inject X11 event"); } XFreeEventData(gbe->display, xcookie); } } /** * Checks if the X11 server supports the appropriate version of the XInput * extension. * * @param[in] gbe The grail back end * * @returns GEIS_TRUE if the X11 server provides the XInput extension of a * sufficiently recent vintage, GEIS_FALSE otherwise. */ static GeisBoolean _geis_grail_x11_has_xi2(GeisGrailBackend gbe) { GeisBoolean has_xi2 = GEIS_FALSE; /* check if the XInput extension is available at all */ int opcode; int event; int error; if (!XQueryExtension(gbe->display, "XInputExtension", &opcode, &event, &error)) { geis_error("XInput extension is not available"); goto final_exit; } /* check if it's the right version */ int major = 2; int minor = 2; if (XIQueryVersion(gbe->display, &major, &minor) == BadRequest) { geis_error("XI2 is unavailable, X Server supports only %d.%d", major, minor); goto final_exit; } has_xi2 = GEIS_TRUE; final_exit: return has_xi2; } /** * Connects to the X11 server and sets up processing on X11 events. * * @param[in] gbe The grail back end * * @returns GEIS_TRUE if a conneciton to X11 server has been successfully * extablished and it provides the minimum required functionality, * GEIS_FALSE otherwise. */ static GeisBoolean _geis_grail_open_x11_connection(GeisGrailBackend gbe) { XErrorHandler old_x_handler; GeisBoolean success = GEIS_FALSE; gbe->display = XOpenDisplay(NULL); if (!gbe->display) { geis_error("error connecting to X server"); goto final_exit; } /* verify all the necessary extensions are available */ if (!_geis_grail_x11_has_xi2(gbe)) { goto unwind_x11; } gbe->root_window = DefaultRootWindow(gbe->display); /* install an X11 event callback */ geis_multiplex_fd(gbe->geis, ConnectionNumber(gbe->display), GEIS_BE_MX_READ_AVAILABLE, _x11_fd_callback, gbe); success = GEIS_TRUE; goto final_exit; unwind_x11: old_x_handler = XSetErrorHandler(_grail_be_x_error_handler); XCloseDisplay(gbe->display); XSetErrorHandler(old_x_handler); final_exit: return success; } /** * Asks the X server for device added or removed events. */ static void _geis_grail_subscribe_x11_device_events(GeisGrailBackend gbe) { XIEventMask mask = { .deviceid = XIAllDevices, .mask_len = XIMaskLen(XI_LASTEVENT), .mask = calloc(XIMaskLen(XI_LASTEVENT), sizeof(char)) }; XISetMask(mask.mask, XI_HierarchyChanged); Status status = XISelectEvents(gbe->display, gbe->root_window, &mask, 1); if (status != Success) { geis_error("error %d selecting device-changed events on X server", status); } free(mask.mask); } /** * Reports available filterable device attrs to the front end. */ static void _geis_grail_report_devices(GeisGrailBackend gbe) { static struct GeisFilterableAttribute attrs[] = { { GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, 0, NULL }, }; static GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); geis_register_device(gbe->geis, NULL, attr_count, attrs); } /** * Reports available gesture classes to the front end. */ static void _geis_grail_report_classes(GeisGrailBackend gbe) { static struct GeisFilterableAttribute attrs[] = { { GEIS_CLASS_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, 0, NULL }, { GEIS_CLASS_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, 0, NULL } }; GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); gbe->drag_class = geis_gesture_class_new(GEIS_GESTURE_DRAG, GEIS_GESTURE_PRIMITIVE_DRAG); geis_register_gesture_class(gbe->geis, gbe->drag_class, attr_count, attrs); gbe->pinch_class = geis_gesture_class_new(GEIS_GESTURE_PINCH, GEIS_GESTURE_PRIMITIVE_PINCH); geis_register_gesture_class(gbe->geis, gbe->pinch_class, attr_count, attrs); gbe->rotate_class = geis_gesture_class_new(GEIS_GESTURE_ROTATE, GEIS_GESTURE_PRIMITIVE_ROTATE); geis_register_gesture_class(gbe->geis, gbe->rotate_class, attr_count, attrs); gbe->tap_class = geis_gesture_class_new(GEIS_GESTURE_TAP, GEIS_GESTURE_PRIMITIVE_TAP); geis_register_gesture_class(gbe->geis, gbe->tap_class, attr_count, attrs); gbe->touch_class = geis_gesture_class_new(GEIS_GESTURE_TOUCH, GEIS_GESTURE_PRIMITIVE_TOUCH); geis_register_gesture_class(gbe->geis, gbe->touch_class, attr_count, attrs); } /** * Reports available regions to the front end. */ static void _geis_grail_report_regions(GeisGrailBackend gbe) { static struct GeisFilterableAttribute attrs[] = { { GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, }; static const GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); geis_register_region(gbe->geis, NULL, attr_count, attrs); } /** * Reports a successful initialization to the front end. */ static void _geis_grail_report_init_complete(GeisGrailBackend gbe) { geis_post_event(gbe->geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE)); } /** * Constructs a Grail back end. * * @param[in] mem * @param[in] geis */ static void _geis_grail_backend_construct(void *mem, Geis geis) { GeisGrailBackend gbe = (GeisGrailBackend)mem; gbe->geis = geis; if (_geis_grail_open_x11_connection(gbe)) { gbe->xsync = geis_grail_xsync_new(gbe->display); if (!gbe->xsync) { geis_error("failed to create xsync instance"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_x11; } _geis_grail_subscribe_x11_device_events(gbe); UFStatus frame_status = frame_x11_new(gbe->display, &gbe->frame); if (frame_status != UFStatusSuccess) { geis_error("failed to create frame instance"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_xsync; } geis_multiplex_fd(gbe->geis, frame_get_fd(gbe->frame), GEIS_BE_MX_READ_AVAILABLE, _grail_be_frame_fd_callback, gbe); UGStatus grail_status = grail_new(&gbe->grail); if (grail_status != UGStatusSuccess) { geis_error("failed to create grail instance"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_frame; } geis_multiplex_fd(gbe->geis, grail_get_fd(gbe->grail), GEIS_BE_MX_READ_AVAILABLE, _grail_be_grail_fd_callback, gbe); gbe->devices = geis_bag_new(sizeof(UFDevice), geis_bag_default_init_alloc, geis_bag_default_growth_factor); if (!gbe->devices) { geis_error("failed to create UFDevices store"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_grail; } gbe->window_grabs = geis_grail_window_grab_store_new(gbe->display); if (!gbe->window_grabs) { geis_error("failed to create window grabs store"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_devices; } gbe->slice_states = geis_bag_new(sizeof(struct _GeisSliceState), geis_bag_default_init_alloc, geis_bag_default_growth_factor); if (!gbe->slice_states) { geis_error("failed to create slice times store"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_grabs; } gbe->subscription_bag = geis_subscription_bag_new(1); if (!gbe->subscription_bag) { geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); goto unwind_slice_states; } geis_get_configuration(gbe->geis, GEIS_CONFIG_SEND_TENTATIVE_EVENTS, &gbe->send_tentative_events); geis_get_configuration(gbe->geis, GEIS_CONFIG_SEND_SYNCHRONOS_EVENTS, &gbe->send_synchronous_events); _geis_grail_report_devices(gbe); _geis_grail_report_classes(gbe); _geis_grail_report_regions(gbe); _geis_grail_report_init_complete(gbe); goto final_exit; unwind_slice_states: geis_bag_delete(gbe->slice_states); unwind_grabs: geis_grail_window_grab_store_delete(gbe->window_grabs); unwind_devices: geis_bag_delete(gbe->devices); unwind_grail: geis_demultiplex_fd(gbe->geis, grail_get_fd(gbe->grail)); grail_delete(gbe->grail); unwind_frame: geis_demultiplex_fd(gbe->geis, frame_get_fd(gbe->frame)); frame_x11_delete(gbe->frame); unwind_xsync: geis_grail_xsync_delete(gbe->xsync); unwind_x11: geis_demultiplex_fd(gbe->geis, ConnectionNumber(gbe->display)); XErrorHandler old_x_handler = XSetErrorHandler(_grail_be_x_error_handler); XCloseDisplay(gbe->display); XSetErrorHandler(old_x_handler); } else { geis_error("no XInput connection established"); geis_error_push(gbe->geis, GEIS_STATUS_UNKNOWN_ERROR); } final_exit: return; } /** * Deconstructs a Grail back end. * * @param[in] be A %GeisGrailBackend. */ static void _geis_grail_backend_finalize(GeisBackend be) { GeisGrailBackend gbe = (GeisGrailBackend)be; geis_subscription_bag_delete(gbe->subscription_bag); geis_bag_delete(gbe->slice_states); geis_grail_window_grab_store_delete(gbe->window_grabs); geis_bag_delete(gbe->devices); geis_demultiplex_fd(gbe->geis, grail_get_fd(gbe->grail)); grail_delete(gbe->grail); geis_demultiplex_fd(gbe->geis, frame_get_fd(gbe->frame)); frame_x11_delete(gbe->frame); geis_grail_xsync_delete(gbe->xsync); geis_demultiplex_fd(gbe->geis, ConnectionNumber(gbe->display)); XErrorHandler old_x_handler = XSetErrorHandler(_grail_be_x_error_handler); XCloseDisplay(gbe->display); XSetErrorHandler(old_x_handler); } /* * Identify events from gestures that overlap the one that got accepted. */ static GeisBoolean _grail_be_match_overlapping_gesture_event(GeisEvent event, void *context) { struct _GeisSliceState *slice_state = (struct _GeisSliceState *)context; GeisEventType event_type = geis_event_type(event); if (event_type != GEIS_EVENT_GESTURE_BEGIN && event_type != GEIS_EVENT_GESTURE_UPDATE && event_type != GEIS_EVENT_GESTURE_END) return GEIS_FALSE; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); if (!attr) { geis_error("can not get touchset from event"); return GEIS_FALSE; } GeisTouchSet touchset = (GeisTouchSet)geis_attr_value_to_pointer(attr); attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("can not get groupset from event"); return GEIS_FALSE; } GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); /* we filter only single-gesture events (i.e. events with a single group containing a single frame) */ if (geis_groupset_group_count(groupset) != 1) return GEIS_FALSE; GeisGroup group = geis_groupset_group(groupset, 0); if (!group) { geis_error("can not get group 0 in groupset of event"); return GEIS_FALSE; } if (geis_group_frame_count(group) != 1) return GEIS_FALSE; for (GeisSize i = 0; i < geis_touchset_touch_count(touchset); ++i) { GeisTouch touch = geis_touchset_touch(touchset, i); attr = geis_touch_attr_by_name(touch, GEIS_TOUCH_ATTRIBUTE_ID); unsigned int touch_id = geis_attr_value_to_integer(attr); for (GeisSize j = 0; j < slice_state->num_touches; ++j) { if (touch_id == slice_state->touch_ids[j]) return GEIS_TRUE; } } /* There were no touch ids in common with slice_state */ return GEIS_FALSE; } /* * Asks grail to accept an identified gesture. */ GeisStatus _grail_be_accept_gesture(GeisBackend be, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_id) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisGrailBackend gbe = (GeisGrailBackend)be; unsigned id = gesture_id; UGStatus ugstatus = grail_accept_gesture(gbe->grail, id); if (ugstatus != UGStatusSuccess) { geis_error("accept failed for gesture %u", id); } else { geis_debug("gesture %u accepted", id); status = GEIS_STATUS_SUCCESS; } struct _GeisSliceState *slice_state = _grail_be_slice_state_from_id(gbe, id); /* the corresponding grail gesture might have already ended, in which case we no longer hold information over its state. */ if (slice_state) geis_remove_matching_events(gbe->geis, _grail_be_match_overlapping_gesture_event, slice_state); return status; } /* * Predicate to identify events to remove on rejection. */ static GeisBoolean _grail_be_match_gesture_event(GeisEvent event, void *context) { GeisGestureId gesture_id = *(GeisGestureId *)context; GeisEventType event_type = geis_event_type(event); if (event_type == GEIS_EVENT_GESTURE_BEGIN || event_type == GEIS_EVENT_GESTURE_UPDATE || event_type == GEIS_EVENT_GESTURE_END) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); if (!attr) { geis_error("can not get groupset from event"); return GEIS_FALSE; } GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); if (!group) { geis_error("can not get group %zu in groupset of event", i); return GEIS_FALSE; } for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); if (!frame) { geis_error("can not get frame %zu in group %zu of event", j, i); return GEIS_FALSE; } return gesture_id == geis_frame_id(frame); } } } return GEIS_FALSE; } /* * Asks grail to reject an identified gesture. */ GeisStatus _grail_be_reject_gesture(GeisBackend be, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_id) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisGrailBackend gbe = (GeisGrailBackend)be; unsigned id = gesture_id; UGStatus ugstatus = grail_reject_gesture(gbe->grail, id); if (ugstatus != UGStatusSuccess) { geis_error("rejection failed for gesture %u", id); } else { geis_debug("gesture %u rejected", id); status = GEIS_STATUS_SUCCESS; } geis_remove_matching_events(gbe->geis, _grail_be_match_gesture_event, &gesture_id); return status; } /** * Sets a given property from the first ugsub in a GEIS subscription. * * If there is more than one grail subscription mapped to a geis subscription, * only the property value from the first is retrieved assuming all the mapped * subscriptions have the same property value setting. */ static GeisStatus _grail_be_get_ugsub_property(GeisUGSubscriptionStore ugstore, UGSubscriptionProperty grail_property, GeisPointer grail_value) { GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR; if (ugstore) { for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i) { UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore, i); if (UGStatusSuccess == grail_subscription_get_property(ugsub, grail_property, grail_value)) { retval = GEIS_STATUS_SUCCESS; break; } } } return retval; } /** * Sets a given grail property to a specified value. */ static GeisStatus _grail_be_set_ugsub_property(GeisUGSubscriptionStore ugstore, UGSubscriptionProperty grail_property, GeisPointer grail_value) { /* OBS: it's still a success if there's no grail subscription */ GeisStatus retval = GEIS_STATUS_SUCCESS; for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i) { UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore, i); if (UGStatusSuccess == grail_subscription_set_property(ugsub, grail_property, grail_value)) { retval = GEIS_STATUS_SUCCESS; } else { retval = GEIS_STATUS_UNKNOWN_ERROR; } } return retval; } static GeisStatus _grail_be_get_integer_configuration(GeisUGSubscriptionStore ugstore, uint64_t *prop, UGSubscriptionProperty grail_prop, GeisPointer geis_value) { if (prop) { *((GeisInteger*)geis_value) = *prop; return GEIS_STATUS_SUCCESS; } else { return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value); } } static GeisStatus _grail_be_get_float_configuration(GeisUGSubscriptionStore ugstore, float *prop, UGSubscriptionProperty grail_prop, GeisPointer geis_value) { if (prop) { *((GeisFloat*)geis_value) = *prop; return GEIS_STATUS_SUCCESS; } else { return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value); } } /* * Dispatches the get-configuration call. */ static GeisStatus _grail_be_get_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription, GeisString item_name, GeisPointer item_value) { GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED; struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); if (!subscription_data) { return retval; } if (0 == strcmp(item_name, GEIS_CONFIG_NUM_ACTIVE_SUBSCRIPTIONS)) { struct GeisGrailSubscriptionData *sub_data = geis_subscription_pdata(subscription); *((GeisSize*)item_value) = geis_ugsubscription_count(sub_data->ugstore); retval = GEIS_STATUS_SUCCESS; } #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \ if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \ { \ retval = _grail_be_get_integer_configuration( \ subscription_data->ugstore, \ subscription_data->gesture##_timeout, \ UGSubscriptionProperty##Gesture##Timeout, \ item_value); \ } \ else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \ { \ retval = _grail_be_get_float_configuration( \ subscription_data->ugstore, \ subscription_data->gesture##_threshold, \ UGSubscriptionProperty##Gesture##Threshold, \ item_value); \ } else GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP) #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG return retval; } static GeisStatus _grail_be_set_integer_configuration(GeisUGSubscriptionStore ugstore, uint64_t **prop, UGSubscriptionProperty grail_prop, GeisPointer geis_value) { if (!*prop) *prop = malloc(sizeof(uint64_t)); **prop = *((GeisInteger*)geis_value); if (ugstore) return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop); else return GEIS_STATUS_SUCCESS; } static GeisStatus _grail_be_set_float_configuration(GeisUGSubscriptionStore ugstore, float **prop, UGSubscriptionProperty grail_prop, GeisPointer geis_value) { if (!*prop) *prop = malloc(sizeof(float)); **prop = *((GeisFloat*)geis_value); if (ugstore) return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop); else return GEIS_STATUS_SUCCESS; } /* * Dispatches the set-configuration call. */ static GeisStatus _grail_be_set_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription, GeisString item_name, GeisPointer item_value) { GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED; struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); if (!subscription_data) { subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData)); geis_subscription_set_pdata(subscription, subscription_data); } #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \ if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \ { \ retval = _grail_be_set_integer_configuration( \ subscription_data->ugstore, \ &(subscription_data->gesture##_timeout), \ UGSubscriptionProperty##Gesture##Timeout, \ item_value); \ } \ else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \ { \ retval = _grail_be_set_float_configuration( \ subscription_data->ugstore, \ &(subscription_data->gesture##_threshold), \ UGSubscriptionProperty##Gesture##Threshold, \ item_value); \ } GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE) else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP) #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG return retval; } static GeisStatus _grail_be_activate_device(GeisBackend be, GeisDevice device) { GeisStatus status = GEIS_STATUS_SUCCESS; GeisGrailBackend gbe = (GeisGrailBackend)be; _grail_be_subscribe_new_device(gbe, device); return status; } static GeisStatus _grail_be_deactivate_device(GeisBackend be, GeisDevice device) { GeisStatus status = GEIS_STATUS_SUCCESS; GeisGrailBackend gbe = (GeisGrailBackend)be; UFDevice ufdevice = _grail_be_ufdevice_from_device_id(gbe, geis_device_id(device)); _grail_be_unsubscribe_removed_device(gbe, ufdevice); return status; } static struct GeisBackendVtable gbe_vtbl = { _geis_grail_backend_construct, _geis_grail_backend_finalize, geis_grail_token_new, _grail_be_accept_gesture, _grail_be_reject_gesture, _grail_be_activate_device, _grail_be_deactivate_device, _grail_be_get_configuration, _grail_be_set_configuration }; static GeisStatus _geis_grail_filter_gestures(GeisGrailBackend gbe, GeisFilter filter, GeisSubscription sub, UGSubscription ugsub) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisSubscriptionFlags sub_flags = geis_subscription_flags(sub); /* default mask is ALL gesture (for now) */ UGGestureTypeMask default_ugmask = UGGestureTypeDrag | UGGestureTypePinch | UGGestureTypeRotate | UGGestureTypeTap | UGGestureTypeTouch; UGGestureTypeMask ugmask = 0; unsigned int start_touches = 1; unsigned int min_touches = 1; unsigned int max_touches = 5; for (GeisSize i = 0; filter && i < geis_filter_term_count(filter); ++i) { GeisFilterTerm term = geis_filter_term(filter, i); if (GEIS_FILTER_CLASS == geis_filter_term_facility(term)) { GeisAttr attr = geis_filter_term_attr(term); GeisString name = geis_attr_name(attr); GeisFilterOperation operation = geis_filter_term_operation(term); if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_NAME) && operation == GEIS_FILTER_OP_EQ) { GeisString class_name = geis_attr_value_to_string(attr); if (0 == strcmp(class_name, geis_gesture_class_name(gbe->drag_class))) ugmask |= UGGestureTypeDrag; else if (0 == strcmp(class_name, geis_gesture_class_name(gbe->pinch_class))) ugmask |= UGGestureTypePinch; else if (0 == strcmp(class_name, geis_gesture_class_name(gbe->rotate_class))) ugmask |= UGGestureTypeRotate; else if (0 == strcmp(class_name, geis_gesture_class_name(gbe->tap_class))) ugmask |= UGGestureTypeTap; else if (0 == strcmp(class_name, geis_gesture_class_name(gbe->touch_class))) ugmask |= UGGestureTypeTouch; } else if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_ID) && operation == GEIS_FILTER_OP_EQ) { GeisInteger class_id = geis_attr_value_to_integer(attr); if (class_id == geis_gesture_class_id(gbe->drag_class)) ugmask |= UGGestureTypeDrag; else if (class_id == geis_gesture_class_id(gbe->pinch_class)) ugmask |= UGGestureTypePinch; else if (class_id == geis_gesture_class_id(gbe->rotate_class)) ugmask |= UGGestureTypeRotate; else if (class_id == geis_gesture_class_id(gbe->tap_class)) ugmask |= UGGestureTypeTap; else if (class_id == geis_gesture_class_id(gbe->touch_class)) ugmask |= UGGestureTypeTouch; } else if (0 == strcmp(name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) { /* * Starting touches: filter terms are ANDed: multiple TOUCHES * terms are ANDed using the MAX operator. */ unsigned int val = geis_attr_value_to_integer(attr); switch (operation) { case GEIS_FILTER_OP_EQ: start_touches = _max(start_touches, val); min_touches = _max(min_touches, start_touches); max_touches = _min(max_touches, start_touches); break; case GEIS_FILTER_OP_NE: geis_error("unsupported comparison"); break; case GEIS_FILTER_OP_GE: start_touches = _max(start_touches, val); min_touches = _max(min_touches, start_touches); max_touches = _min(max_touches, 5); break; case GEIS_FILTER_OP_GT: start_touches = _max(start_touches, val+1); min_touches = _max(min_touches, start_touches); max_touches = _min(max_touches, 5); break; case GEIS_FILTER_OP_LE: start_touches = _max(start_touches, val); min_touches = _max(min_touches, 0); max_touches = _min(max_touches, start_touches); break; case GEIS_FILTER_OP_LT: start_touches = _max(start_touches, val-1); min_touches = _max(min_touches, 0); max_touches = _min(max_touches, start_touches); break; } } } } if (!ugmask) ugmask = default_ugmask; /* A tap gesture for a non-tentative client only sends one update event when * the tap finishes. The Recognition occurs at the very end of the gesture, * and the last grail slice is transformed into the update event. If the min * touches allows for down to one touch, the end slice will probably only have * one touch. As a work around, only allow for continuous touch gestures for * non-tap, non-tentative subscriptions. * * This puts the onus on the subscriber not to mix tap and non-tap continuous * touch gestures. In practice, this would likely only occur for geis v1 * clients, but geis v1 subscriptions are already split into separate backend * subscriptions, so this shouldn't be a problem. */ if (sub_flags & GEIS_SUBSCRIPTION_CONT && !gbe->send_tentative_events && !(ugmask & UGGestureTypeTap)) { min_touches = 1; max_touches = start_touches; } geis_debug("mask=0x%08x start=%u min=%u max=%u", ugmask, start_touches, min_touches, max_touches); UGStatus ugstatus; ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyMask, &ugmask); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription mask"); goto final_exit; } ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyTouchesStart, &start_touches); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription start touches"); goto final_exit; } ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyTouchesMinimum, &min_touches); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription min touches"); goto final_exit; } ugstatus = grail_subscription_set_property(ugsub, UGSubscriptionPropertyTouchesMaximum, &max_touches); if (ugstatus != UGStatusSuccess) { geis_error("failed to set UGSubscription max touches"); goto final_exit; } status = GEIS_STATUS_SUCCESS; final_exit: return status; } static void _geis_grail_set_ugsubscription_properties(GeisGrailBackend gbe, UGSubscription ugsub, GeisSubscription subscription) { struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); GeisBoolean geis_use_atomic_gestures = GEIS_FALSE; geis_get_configuration(gbe->geis, GEIS_CONFIG_ATOMIC_GESTURES, &geis_use_atomic_gestures); int grail_use_atomic_gestures = (geis_use_atomic_gestures == GEIS_TRUE); grail_subscription_set_property(ugsub, UGSubscriptionPropertyAtomicGestures, &grail_use_atomic_gestures); #define GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(gesture, Gesture) \ if (subscription_data->gesture##_timeout) \ { \ grail_subscription_set_property(ugsub, \ UGSubscriptionProperty##Gesture##Timeout, \ subscription_data->gesture##_timeout); \ } \ if (subscription_data->gesture##_threshold) \ { \ grail_subscription_set_property(ugsub, \ UGSubscriptionProperty##Gesture##Threshold, \ subscription_data->gesture##_threshold); \ } GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(drag, Drag); GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(pinch, Pinch); GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(rotate, Rotate); GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(tap, Tap); #undef GEIS_GRAIL_SYNC_GESTURE_PROPERTIES } /** * Activates a subscription for a (device, region). */ static GeisStatus _geis_grail_activate_for_device_region(GeisGrailBackend gbe, GeisFilter filter, GeisDevice device, GeisInteger window_id, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisInteger device_id = geis_device_id(device); UFDevice ufdevice = _grail_be_ufdevice_from_device_id(gbe, device_id); struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); GeisUGSubscriptionStore ugstore = subscription_data->ugstore; UGSubscription ugsub = geis_ugsubscription_get_ugsubscription(ugstore, filter, ufdevice, window_id); if (!ugsub) { ugsub = geis_ugsubscription_create_ugsubscription(ugstore, filter, ufdevice, window_id); _geis_grail_set_ugsubscription_properties(gbe, ugsub, subscription); } if (!ugsub) { geis_error("can not retrieve UGSubscription for (device, window)"); goto final_exit; } status = _geis_grail_filter_gestures(gbe, filter, subscription, ugsub); if (filter) geis_debug("subscription='%s' filter='%s' device=%d '%s' window=0x%08x " "ugsub=%p", geis_subscription_name(subscription), geis_filter_name(filter), device_id, geis_device_name(device), window_id, (void *)ugsub); else geis_debug("subscription='%s' no-filter device=%d '%s' window=0x%08x " "ugsub=%p", geis_subscription_name(subscription), device_id, geis_device_name(device), window_id, (void *)ugsub); status = geis_grail_window_grab_store_grab(gbe->window_grabs, window_id); if (status != GEIS_STATUS_SUCCESS) { geis_error("failed to grab input on window 0x%08x", window_id); goto final_exit; } UGStatus ugstatus = grail_subscription_activate(gbe->grail, ugsub); if (ugstatus != UGStatusSuccess) { status = GEIS_STATUS_UNKNOWN_ERROR; geis_error("failed to activate UGSubscription"); } final_exit: return status; } static GeisStatus _grail_be_activate_for_device(GeisGrailBackend gbe, GeisFilter filter, GeisDevice device, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisBoolean has_region_term = GEIS_FALSE; if (filter) { for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i) { GeisFilterTerm term = geis_filter_term(filter, i); if (GEIS_FILTER_REGION == geis_filter_term_facility(term)) { GeisInteger window_id = 0; GeisAttr attr = geis_filter_term_attr(term); GeisString name = geis_attr_name(attr); GeisFilterOperation operation = geis_filter_term_operation(term); if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID) && operation == GEIS_FILTER_OP_EQ) { window_id = geis_attr_value_to_integer(attr); has_region_term = GEIS_TRUE; status = _geis_grail_activate_for_device_region(gbe, filter, device, window_id, subscription); if (status != GEIS_STATUS_SUCCESS) { goto final_exit; } } else { geis_warning("unhandled region filter term"); } } } /* If no region terms were found, or there's no filter, use the root window. */ if (!has_region_term) { status = _geis_grail_activate_for_device_region(gbe, filter, device, gbe->root_window, subscription); } } final_exit: return status; } /** * Activates a subscription for a list of devices. */ static GeisStatus _geis_grail_activate_for_devices(GeisGrailBackend gbe, GeisFilter filter, GeisDeviceBag device_bag, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_SUCCESS; for (GeisSize d = 0; d < geis_device_bag_count(device_bag); ++d) { GeisDevice device = geis_device_bag_device(device_bag, d); status = _grail_be_activate_for_device(gbe, filter, device, subscription); if (status != GEIS_STATUS_SUCCESS) break; } return status; } static GeisStatus _geis_grail_activate_with_filters(GeisGrailBackend gbe, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; for (GeisFilterIterator it = geis_subscription_filter_begin(subscription); it != geis_subscription_filter_end(subscription); it = geis_subscription_filter_next(subscription, it)) { GeisFilter filter = *it; GeisDeviceBag selected_devices = geis_device_bag_new(); GeisSelectResult device_matches = geis_select_devices(gbe->geis, filter, selected_devices); if (device_matches == GEIS_SELECT_RESULT_ALL) { geis_debug("filter %p '%s' matches ALL devices", (void *)filter, geis_filter_name(filter)); /* Special case: no devices succeeds, in case one gets added later. */ if (geis_device_bag_count(geis_devices(gbe->geis)) == 0) status = GEIS_STATUS_SUCCESS; else status = _geis_grail_activate_for_devices(gbe, filter, geis_devices(gbe->geis), subscription); } else if (device_matches == GEIS_SELECT_RESULT_SOME) { geis_debug("filter %p '%s' matches %zu devices", (void *)filter, geis_filter_name(filter), geis_device_bag_count(selected_devices)); status = _geis_grail_activate_for_devices(gbe, filter, selected_devices, subscription); } else { geis_debug("filter %p '%s' matches NO devices", (void *)filter, geis_filter_name(filter)); status = GEIS_STATUS_SUCCESS; } geis_device_bag_delete(selected_devices); if (status != GEIS_STATUS_SUCCESS) break; } return status; } /* * Activates a GEIS subscription on the back end. */ GeisStatus geis_grail_backend_activate_subscription(GeisGrailBackend gbe, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (geis_subscription_bag_find(gbe->subscription_bag, geis_subscription_id(subscription))) { geis_warning("subscription is already activated"); goto final_exit; } struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); if (!subscription_data) { subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData)); geis_subscription_set_pdata(subscription, subscription_data); } if (subscription_data->ugstore == NULL) { subscription_data->ugstore = geis_ugsubscription_store_new(); if (!subscription_data->ugstore) { geis_error("error creating grail subscription store"); goto final_exit; } } if (geis_subscription_filter_count(subscription) > 0) { status = _geis_grail_activate_with_filters(gbe, subscription); } else { status = _geis_grail_activate_for_devices(gbe, NULL, /* no filter */ geis_devices(gbe->geis), subscription); } geis_subscription_bag_insert(gbe->subscription_bag, subscription); final_exit: return status; } /* * Deactivates a GEIS subscription on the back end. * * @todo replace this stub */ GeisStatus geis_grail_backend_deactivate_subscription(GeisGrailBackend gbe, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (!geis_subscription_bag_find(gbe->subscription_bag, geis_subscription_id(subscription))) { geis_warning("deactivating a subscription that is not active"); goto final_exit; } struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); GeisUGSubscriptionStore ugstore = subscription_data->ugstore; if (ugstore) { for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i) { UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore, i); UFWindowId ufwindow; UGStatus ugstatus; ugstatus = grail_subscription_get_property(ugsub, UGSubscriptionPropertyWindow, &ufwindow); if (ugstatus != UGStatusSuccess) { geis_warning("error %d getting subscription window", ugstatus); } else { Window window_id = frame_x11_get_window_id(ufwindow); geis_grail_window_grab_store_ungrab(gbe->window_grabs, window_id); } grail_subscription_deactivate(gbe->grail, ugsub); geis_subscription_bag_remove(gbe->subscription_bag, subscription); status = GEIS_STATUS_SUCCESS; } } final_exit: return status; } /* Frees the memory allocated for the GEIS subscription private data */ void geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe GEIS_UNUSED, GeisSubscription subscription) { struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription); if (!subscription_data) return; if (subscription_data->ugstore) geis_ugsubscription_delete(subscription_data->ugstore); free(subscription_data->drag_timeout); free(subscription_data->drag_threshold); free(subscription_data->pinch_timeout); free(subscription_data->pinch_threshold); free(subscription_data->rotate_timeout); free(subscription_data->rotate_threshold); free(subscription_data->tap_timeout); free(subscription_data->tap_threshold); free(subscription_data); geis_subscription_set_pdata(subscription, NULL); } /** * Registers the back end with the GEIS back end registry. */ static void __attribute__((constructor)) _register_grail_backend(void) { geis_register_backend(GEIS_INIT_GRAIL_BACKEND, sizeof(struct GeisGrailBackend), &gbe_vtbl); } /** A dummy routine to force linkage of this module without dlopening it */ void geis_include_grail_backend(void) { } /** @} */ geis-2.2.17+16.04.20160126/libgeis/backend/test_fixture/0000755000015600001650000000000012651717732022641 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/backend/test_fixture/Makefile.am0000644000015600001650000000065512651717544024704 0ustar pbuserpbgroup00000000000000# # @file libgeis/backend/test_fixture/Makefile.am # # Build recipes for the test fixture back end. # noinst_LTLIBRARIES = libgeis-test-fixture.la libgeis_test_fixture_la_SOURCES = \ geis_backend_test_fixture.c libgeis_test_fixture_la_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/libs/geis-util libgeis_test_fixture_la_LDFLAGS = libgeis_test_fixture_la_LIBADD = geis-2.2.17+16.04.20160126/libgeis/backend/test_fixture/geis_backend_test_fixture.c0000644000015600001650000003075712651717544030225 0ustar pbuserpbgroup00000000000000/** * @file geis_backend_test_fixture.c * @brief GEIS mock back end test fixture implementation * * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_backend.h" #include "geis_backend_protected.h" #include "geis_attr.h" #include "geis_class.h" #include "geis_device.h" #include "geis_event.h" #include "geis_filter.h" #include "geis_filter_term.h" #include "geis_frame.h" #include "geis_group.h" #include "geis_logging.h" #include "geis_private.h" #include "geis_subscription.h" #include "geis_test_api.h" #include "geis_touch.h" #include #include #include #include static inline GeisSize _min(GeisSize a, GeisSize b) { return (a < b) ? a : b; } static inline GeisSize _max(GeisSize a, GeisSize b) { return (a > b) ? a : b; } static GeisSize g_min_touches = 1; static GeisSize g_max_touches = 5; typedef struct GeisBackendTestFixture { Geis tf_geis; } *GeisBackendTestFixture; typedef struct TestBackendToken { struct GeisBackendToken base; GeisBackendTestFixture be; GeisInteger min_touches; GeisInteger max_touches; } *TestBackendToken; static inline TestBackendToken _tbtoken_from_token(GeisBackendToken bet) { return (TestBackendToken)bet; } static GeisBackendToken _token_clone(GeisBackendToken); static void _token_finalize(GeisBackendToken); static void _token_compose(GeisBackendToken, GeisBackendToken); static GeisStatus _token_activate(GeisBackendToken, GeisSubscription); static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription); static void _token_free_subscription_pdata(GeisBackendToken, GeisSubscription); static struct GeisBackendTokenVtable _token_vtbl = { _token_clone, _token_finalize, _token_compose, _token_activate, _token_deactivate, _token_free_subscription_pdata }; static GeisGestureClass g_poke_class = NULL; static GeisStatus _add_device_term(GeisBackendToken token GEIS_UNUSED, void *context GEIS_UNUSED, GeisString name, GeisFilterOperation op GEIS_UNUSED, void *value GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_SUCCESS; geis_error("called: name=%s", name); return status; } static void _create_test_devices(GeisBackendTestFixture tf) { GeisDevice device = geis_device_new("abs-test-device", 0); struct GeisFilterableAttribute attrs[] = { { GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, _add_device_term, NULL }, { GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, _add_device_term, NULL }, { GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, _add_device_term, NULL }, { GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, _add_device_term, NULL } }; GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); geis_register_device(tf->tf_geis, device, attr_count, attrs); } static GeisStatus _add_class_term(GeisBackendToken gbtoken, void *context GEIS_UNUSED, GeisString name, GeisFilterOperation op, void *value) { GeisStatus status = GEIS_STATUS_SUCCESS; TestBackendToken token = _tbtoken_from_token(gbtoken); if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_NAME) && op == GEIS_FILTER_OP_EQ) { GeisString class_name = (GeisString)value; geis_debug("called: attr=%s name=\"%s\"", name, class_name); } else if (0 == strcmp(name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) { GeisInteger touches = *(GeisInteger*)value; switch (op) { case GEIS_FILTER_OP_GT: token->min_touches = _max(token->min_touches, touches+1); break; case GEIS_FILTER_OP_GE: token->min_touches = _max(token->min_touches, touches); break; case GEIS_FILTER_OP_LT: token->max_touches = _min(touches-1, token->max_touches); break; case GEIS_FILTER_OP_LE: token->max_touches = _min(touches, token->max_touches); break; case GEIS_FILTER_OP_EQ: token->min_touches = _max(token->min_touches, touches); token->max_touches = _min(touches, token->max_touches); break; case GEIS_FILTER_OP_NE: break; } geis_debug("called: attr=%s touches=\"%d\" min=%d max=%d", name, touches, token->min_touches, token->max_touches); } return status; } static void _create_test_classes(GeisBackendTestFixture tf) { if (!g_poke_class) { g_poke_class = geis_gesture_class_new("poke", 2100); struct GeisFilterableAttribute attrs[] = { { GEIS_CLASS_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, _add_class_term, g_poke_class }, { GEIS_CLASS_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, _add_class_term, g_poke_class }, { GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, _add_class_term, g_poke_class } }; GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); geis_register_gesture_class(tf->tf_geis, g_poke_class, attr_count, attrs); } } static void _construct(void *mem, Geis geis) { GeisBackendTestFixture tf = (GeisBackendTestFixture)mem; tf->tf_geis = geis; _create_test_devices(tf); _create_test_classes(tf); geis_post_event(tf->tf_geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE)); } static void _finalize(GeisBackend be) { GeisBackendTestFixture tf GEIS_UNUSED = (GeisBackendTestFixture)be; } static GeisBackendToken _create_token(GeisBackend be, GeisBackendTokenInitState init_state) { TestBackendToken token = NULL; token = calloc(1, sizeof(struct TestBackendToken)); if (token) { token->base.vtbl = &_token_vtbl; token->be = (GeisBackendTestFixture)be; if (init_state == GEIS_BACKEND_TOKEN_INIT_ALL) { token->min_touches = g_min_touches; token->max_touches = g_max_touches; } else { token->min_touches = g_max_touches; token->max_touches = g_min_touches; } } return (GeisBackendToken)token; } static GeisStatus _gmock_accept_gesture(GeisBackend be GEIS_UNUSED, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_ID GEIS_UNUSED) { return GEIS_STATUS_SUCCESS; } static GeisStatus _gmock_reject_gesture(GeisBackend be GEIS_UNUSED, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_ID GEIS_UNUSED) { return GEIS_STATUS_SUCCESS; } static GeisStatus _gmock_get_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED, GeisString item_name GEIS_UNUSED, GeisPointer item_value GEIS_UNUSED) { return GEIS_STATUS_NOT_SUPPORTED; } static GeisStatus _gmock_set_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED, GeisString item_name GEIS_UNUSED, GeisPointer item_value GEIS_UNUSED) { return GEIS_STATUS_NOT_SUPPORTED; } static struct GeisBackendVtable tf_vtbl = { _construct, _finalize, _create_token, _gmock_accept_gesture, _gmock_reject_gesture, NULL, NULL, _gmock_get_configuration, _gmock_set_configuration }; /* * Generates a gesture event, the contets of which varies accoring to what's in * the token. */ static void _create_gesture_events_for_token(TestBackendToken token) { int i; GeisFloat attr_float; GeisInteger attr_int; GeisAttr attr = NULL; GeisEvent event = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); GeisGroupSet groupset = geis_groupset_new(); GeisGroup group = geis_group_new(1); GeisAttr group_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_GROUPSET, GEIS_ATTR_TYPE_POINTER, groupset); GeisTouchSet touchset = geis_touchset_new(); GeisAttr touch_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_TOUCHSET, GEIS_ATTR_TYPE_POINTER, touchset); GeisFrame frame = geis_frame_new(1); geis_frame_set_is_class(frame, g_poke_class); attr_int = 13; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, GEIS_ATTR_TYPE_INTEGER, &attr_int); geis_frame_add_attr(frame, attr); attr_int = 1; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_TIMESTAMP, GEIS_ATTR_TYPE_INTEGER, &attr_int); geis_frame_add_attr(frame, attr); attr_int = 2; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &attr_int); geis_frame_add_attr(frame, attr); attr_int = 3; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &attr_int); geis_frame_add_attr(frame, attr); attr_int = 4; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID, GEIS_ATTR_TYPE_INTEGER, &attr_int); geis_frame_add_attr(frame, attr); attr_float = 123.456; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_FOCUS_X, GEIS_ATTR_TYPE_FLOAT, &attr_float); geis_frame_add_attr(frame, attr); attr_float = 987.654; attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, GEIS_ATTR_TYPE_FLOAT, &attr_float); geis_frame_add_attr(frame, attr); attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME, GEIS_ATTR_TYPE_STRING, "mock gesture"); geis_frame_add_attr(frame, attr); attr = geis_attr_new(GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &token->min_touches); geis_frame_add_attr(frame, attr); for (i = 0; i < token->min_touches; ++i) { GeisTouch touch = geis_touch_new(1); geis_touchset_insert(touchset, touch); geis_frame_add_touchid(frame, geis_touch_id(touch)); } geis_group_insert_frame(group, frame); geis_groupset_insert(groupset, group); geis_event_add_attr(event, group_attr); geis_event_add_attr(event, touch_attr); geis_post_event(token->be->tf_geis, event); } static GeisBackendToken _token_clone(GeisBackendToken gbtoken) { TestBackendToken token = _tbtoken_from_token(gbtoken); TestBackendToken new_token = calloc(1, sizeof(struct TestBackendToken)); if (new_token) { memcpy(new_token, token, sizeof(struct TestBackendToken)); return &new_token->base; } return NULL; } void _token_finalize(GeisBackendToken gbtoken GEIS_UNUSED) { } void _token_compose(GeisBackendToken lhs, GeisBackendToken rhs) { TestBackendToken token1 = _tbtoken_from_token(lhs); TestBackendToken token2 = _tbtoken_from_token(rhs); token1->min_touches = _min(token1->min_touches, token2->min_touches); token1->max_touches = _max(token1->max_touches, token2->max_touches); } GeisStatus _token_activate(GeisBackendToken gbtoken, GeisSubscription subscription GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_SUCCESS; TestBackendToken token = _tbtoken_from_token(gbtoken); _create_gesture_events_for_token(token); return status; } GeisStatus _token_deactivate(GeisBackendToken gbtoken GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED) { GeisStatus status = GEIS_STATUS_SUCCESS; return status; } void _token_free_subscription_pdata(GeisBackendToken gbtoken GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED) { } __attribute__((constructor)) static void _register_test_fixture() { geis_register_backend(GEIS_INIT_MOCK_BACKEND, sizeof(struct GeisBackendTestFixture), &tf_vtbl); } /* A dummy routine to force linkage of this module without dlopening it */ void geis_include_backend_test_fixture() { } geis-2.2.17+16.04.20160126/libgeis/backend/dbus/0000755000015600001650000000000012651717732021051 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/libgeis/backend/dbus/geis_dbus_client.h0000644000015600001650000000660612651717544024535 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_client.h * @brief Interface for the GEIS DBus client. * * The GEIS DBus client offers remote GEIS functionality over a managed * DBus connection. * * This header is for internal GEIS use only and contains no client * (externally-visible) symbols. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef GEIS_DBUS_CLIENT_H_ #define GEIS_DBUS_CLIENT_H_ #include "geis/geis.h" #include "geis_dbus_dispatcher.h" typedef struct GeisDBusClient *GeisDBusClient; /** * Creates a new %GeisDBusClient object. */ GeisDBusClient geis_dbus_client_new(Geis geis); /** * Destroys a %GeisDBusClient. * * @param[in] client A GeisDBusClient. */ void geis_dbus_client_delete(GeisDBusClient client); /** * Gets the client dispatcher. * * @param[in] client A GeisDBusClient. */ GeisDBusDispatcher geis_dbus_client_dispatcher(GeisDBusClient client); /** * Signals the client the server has been located. * * @param[in] client A GeisDBusClient. */ void geis_dbus_client_server_located(GeisDBusClient client); /** * Signals the client the server has been dislocated. * * @param[in] client A GeisDBusClient. */ void geis_dbus_client_server_dislocated(GeisDBusClient client); /** * Cerates a subscription on the remote end. * * @param[in] client The client-side of the DBus connection. * @param[in] subscription The local subscription object. */ GeisStatus geis_dbus_client_subscribe(GeisDBusClient client, GeisSubscription subscription); /** * Deactivates a subscription on the remote end. * * @param[in] client The client-side of the DBus connection. * @param[in] subscription The local subscription object. */ GeisStatus geis_dbus_client_unsubscribe(GeisDBusClient client, GeisSubscription subscription); /** * Asks the remote server to accept a gesture. * * @param[in] client The client side of the DBus connection. * @param[in] group The gesture group to which the gesture belongs. * @param[in] gesture_id The gesture to accept. * * @returns GEIS_STATUS_SUCCESS on success, some other value otherwise. */ GeisStatus geis_dbus_client_accept_gesture(GeisDBusClient client, GeisGroup group, GeisGestureId gesture_id); /** * Asks the remote server to reject a gesture. * * @param[in] client The client side of the DBus connection. * @param[in] group The gesture group to which the gesture belongs. * @param[in] gesture_id The gesture to reject. * * @returns GEIS_STATUS_SUCCESS on success, some other value otherwise. */ GeisStatus geis_dbus_client_reject_gesture(GeisDBusClient client, GeisGroup group, GeisGestureId gesture_id); #endif /* GEIS_DBUS_CLIENT_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/dbus/geis_dbus_locator.c0000644000015600001650000001775312651717544024722 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_locator.c * @brief Implementation of the GEIS DBus locator. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_locator.h" #include #include "geis_dbus.h" #include "geis_logging.h" #include #include #include typedef enum GeisDBusLocatorState { GEIS_DBUS_LOCATOR_STATE_INITIALIZING, GEIS_DBUS_LOCATOR_STATE_LOCATING, GEIS_DBUS_LOCATOR_STATE_WAITING, GEIS_DBUS_LOCATOR_STATE_FINALIZING } GeisDBusLocatorState; struct GeisDBusLocator { GeisDBusClient client; GeisDBusLocatorState state; DBusConnection *session_bus; char *server_address; dbus_uint32_t serial; }; /* * Performs the act of actually locating the server. */ static void _locator_find_server(GeisDBusLocator locator) { locator->state = GEIS_DBUS_LOCATOR_STATE_LOCATING; DBusMessage *msg = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_SERVICE_PATH, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_GET_SERVER_ADDRESS); dbus_connection_send(locator->session_bus, msg, &locator->serial); dbus_message_unref(msg); } /* * A generic message handler function. */ static DBusHandlerResult _locator_message_handler(DBusConnection *connection GEIS_UNUSED, DBusMessage *message, void *user_data) { DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; GeisDBusLocator locator = (GeisDBusLocator)user_data; int type = dbus_message_get_type(message); if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { char *name; char *old_owner; char *new_owner; dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID); if (strlen(old_owner)) { geis_debug("%s has gone away", name); geis_dbus_client_server_dislocated(locator->client); result = DBUS_HANDLER_RESULT_HANDLED; } else if (strlen(new_owner)) { geis_debug("%s has appeared", name); _locator_find_server(locator); result = DBUS_HANDLER_RESULT_HANDLED; } } else if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) { if (locator->serial == dbus_message_get_reply_serial(message)) { const char *s = NULL; dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); locator->server_address = strdup(s); geis_dbus_client_server_located(locator->client); result = DBUS_HANDLER_RESULT_HANDLED; } } else if (type == DBUS_MESSAGE_TYPE_ERROR) { if (dbus_message_is_error(message, DBUS_ERROR_SERVICE_UNKNOWN)) { geis_warning("server not found!"); geis_dbus_client_server_dislocated(locator->client); result = DBUS_HANDLER_RESULT_HANDLED; } else { const char *str = NULL; dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID); geis_warning("error %s: %s", dbus_message_get_error_name(message), str); } } return result; } /* * Adds the locator watches to the dispatcher watch list. */ static dbus_bool_t _locator_add_watch(DBusWatch *watch, void *data) { dbus_bool_t status = TRUE; GeisDBusLocator locator = (GeisDBusLocator)data; GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); geis_dbus_dispatcher_register(dispatcher, locator->session_bus, watch); return status; } /* * Toggles the enabled/disabled status of the locator watches. */ static void _locator_toggle_watch(DBusWatch *watch, void *data) { GeisDBusLocator locator = (GeisDBusLocator)data; GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); geis_dbus_dispatcher_toggle_watch(dispatcher, watch); } /* * Removes the locator watches from the dispatcher watch list. */ static void _locator_remove_watch(DBusWatch *watch, void *data) { GeisDBusLocator locator = (GeisDBusLocator)data; GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); geis_dbus_dispatcher_unregister(dispatcher, watch); } /* * Creates a new GeisDBusLocator object. */ GeisDBusLocator geis_dbus_locator_new(GeisDBusClient client) { GeisDBusLocator locator = NULL; /* Fail to locate Geis on the DBus if there is no DBus session. */ if (NULL == getenv("DBUS_SESSION_BUS_ADDRESS")) { goto final_exit; } locator = calloc(1, sizeof(struct GeisDBusLocator)); if (!locator) { goto final_exit; } locator->client = client; locator->state = GEIS_DBUS_LOCATOR_STATE_INITIALIZING; /* Connect to the DBus session bus. */ DBusError error = DBUS_ERROR_INIT; locator->session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error); if (!locator->session_bus || dbus_error_is_set(&error)) { char msg[512]; snprintf(msg, sizeof(msg), "error %s connecting to session bus: %s", error.name, error.message); geis_error("%s", msg); goto unwind_error; } /* Integrate with the app event loop via the GEIS multiplexor. */ dbus_connection_set_watch_functions(locator->session_bus, _locator_add_watch, _locator_remove_watch, _locator_toggle_watch, locator, 0); /* Look for server-connect and server-disconnect messages. */ dbus_bus_add_match(locator->session_bus, "type='signal',sender='" DBUS_SERVICE_DBUS "'," \ "interface='" DBUS_INTERFACE_DBUS "'," \ "member='NameOwnerChanged'," \ "arg0='" GEIS_DBUS_SERVICE_INTERFACE "'", &error); if (dbus_error_is_set(&error)) { char msg[512]; snprintf(msg, sizeof(msg), "error %s adding match to session bus: %s", error.name, error.message); geis_error("%s", msg); goto unwind_error; } /* Install a handler for any and all messages. */ dbus_connection_add_filter(locator->session_bus, _locator_message_handler, locator, 0); /* OK, go eh? */ _locator_find_server(locator); unwind_error: dbus_error_free(&error); final_exit: return locator; } /* * Destroys a %GeisDBusLocator object. */ void geis_dbus_locator_delete(GeisDBusLocator locator) { if (locator) { if (locator->server_address) { free(locator->server_address); } if (locator->session_bus) { dbus_connection_set_watch_functions(locator->session_bus, NULL, NULL, NULL, NULL, 0); dbus_connection_remove_filter(locator->session_bus, _locator_message_handler, locator); dbus_connection_unref(locator->session_bus); } free(locator); } } char * geis_dbus_locator_server_address(GeisDBusLocator locator) { return locator->server_address; } geis-2.2.17+16.04.20160126/libgeis/backend/dbus/Makefile.am0000644000015600001650000000227112651717544023110 0ustar pbuserpbgroup00000000000000# # @file libgeis/backend/xcb/Makefile.am # @brief automake recipe for the GEIS v2.0 XCB back end # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 General Public License # along with this program. If not, see . */ #ifndef GEIS_DBUS_LOCATOR_H_ #define GEIS_DBUS_LOCATOR_H_ #include "geis/geis.h" #include "geis_dbus_client.h" typedef struct GeisDBusLocator *GeisDBusLocator; /** * Creates a new GeisDBusLocator object. * * @param[in] client A GEIS DBus CLient. */ GeisDBusLocator geis_dbus_locator_new(GeisDBusClient client); /** * Destroys a %GeisDBusLocator object. * * @param[in] locator A GeisDBusLocator. */ void geis_dbus_locator_delete(GeisDBusLocator locator); /** * Gets the currently located server address. * * @param[in] locator A GeisDBusLocator. */ char * geis_dbus_locator_server_address(GeisDBusLocator locator); #endif /* GEIS_DBUS_LOCATOR_H_ */ geis-2.2.17+16.04.20160126/libgeis/backend/dbus/geis_dbus_backend.c0000644000015600001650000001562012651717544024635 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_backend.c * @brief GEIS DBus client back end */ /* * Copyright 2011-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_backend.h" #include "geis_backend_protected.h" #include "geis_dbus_client.h" #include "geis_event.h" #include "geis_logging.h" #include "geis_private.h" /** * @addtogroup geis_backend_dbus GEIS DBus Back End * @ingroup geis_backends * * A GEIS Back End that is a DBus client, for connecting to a single central * GEIS service offering data over the DBus. * * @{ */ /** The opaque DBus Back End type. */ typedef struct GeisDBusBackend *GeisDBusBackend; /** The less opaque DBus Back End structure. */ struct GeisDBusBackend { Geis geis; GeisDBusClient dbus_client; }; /** The DBus Back End token type */ typedef struct GeisDBusToken { struct GeisBackendToken base; GeisDBusBackend be; } *GeisDBusToken; /** * Converts from a GeisBackendToken to an XcbBackendToken. */ static inline GeisDBusToken _geis_dbus_token_from_geis_token(GeisBackendToken gbt) { return (GeisDBusToken)gbt; } /** * Allocates memory for a token from a pool. */ static GeisDBusToken _geis_dbus_token_allocate(void) { return calloc(1, sizeof(struct GeisDBusToken)); } /** * Returns memory for a token to a pool. */ static void _geis_dbus_token_deallocate(GeisDBusToken gdt) { free(gdt); } /** * Deep-copy-constructs a token. */ static GeisBackendToken _geis_dbus_token_clone(GeisBackendToken original) { return original; } /** * Releases resources for a token. * * @param[in] token A %GeisDBusToken. */ static void _geis_dbus_token_finalize(GeisBackendToken token GEIS_UNUSED) { GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); _geis_dbus_token_deallocate(gdt); } /** * Composes one token onto another. * * @param[in,out] lhs * @param[in] rhs */ static void _geis_dbus_token_compose(GeisBackendToken lhs GEIS_UNUSED, GeisBackendToken rhs GEIS_UNUSED) { } /** * Activates a DBus back end token. * * @param[in] token A %GeisDBusToken. * @param[in] subscription The subscrition the token will be activated on. * * Sends a request to the server to activate a subscription with the tokenized * content. * * @returns GEIS_STATUS_SUCCESS. */ static GeisStatus _geis_dbus_token_activate(GeisBackendToken token, GeisSubscription subscription) { GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); geis_dbus_client_subscribe(gdt->be->dbus_client, subscription); return GEIS_STATUS_SUCCESS; } /** * Deactivates a DBus back end token. * * @param[in] token A %GeisDBusToken. */ static GeisStatus _geis_dbus_token_deactivate(GeisBackendToken token, GeisSubscription subscription) { GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); geis_dbus_client_unsubscribe(gdt->be->dbus_client, subscription); return GEIS_STATUS_UNKNOWN_ERROR; } static void _geis_dbus_token_free_subscription_pdata(GeisBackendToken token GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED) { } static struct GeisBackendTokenVtable _token_vtbl = { _geis_dbus_token_clone, _geis_dbus_token_finalize, _geis_dbus_token_compose, _geis_dbus_token_activate, _geis_dbus_token_deactivate, _geis_dbus_token_free_subscription_pdata }; /** * Constructs a DBus back end. * * @param[in] mem * @param[in] geis */ static void _geis_dbus_backend_construct(void *mem, Geis geis) { GeisDBusBackend gdb = (GeisDBusBackend)mem; gdb->geis = geis; gdb->dbus_client = geis_dbus_client_new(geis); if (!gdb->dbus_client) { geis_error("error creating GEIS DBus client"); geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); goto final_exit; } final_exit: return; } /** * Deconstructs a DBus back end. * * @param[in] be A %GeisDBusBackend. */ static void _geis_dbus_backend_finalize(GeisBackend be) { GeisDBusBackend gdb = (GeisDBusBackend)be; geis_dbus_client_delete(gdb->dbus_client); } /** * Creates DBus-back-end-specific back end token. */ static GeisBackendToken _geis_dbus_backend_create_token(GeisBackend be, GeisBackendTokenInitState init_state GEIS_UNUSED) { GeisDBusBackend gdb = (GeisDBusBackend)be; GeisDBusToken token = _geis_dbus_token_allocate(); if (token) { token->base.vtbl = &_token_vtbl; token->be = gdb; } return (GeisBackendToken)token; } static GeisStatus _geis_dbus_accept_gesture(GeisBackend be, GeisGroup group, GeisGestureId gesture_id) { GeisDBusBackend gdb = (GeisDBusBackend)be; return geis_dbus_client_accept_gesture(gdb->dbus_client, group, gesture_id); } static GeisStatus _geis_dbus_reject_gesture(GeisBackend be, GeisGroup group, GeisGestureId gesture_id) { GeisDBusBackend gdb = (GeisDBusBackend)be; return geis_dbus_client_reject_gesture(gdb->dbus_client, group, gesture_id); } static GeisStatus _geis_dbus_get_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED, GeisString item_name GEIS_UNUSED, GeisPointer item_value GEIS_UNUSED) { return GEIS_STATUS_NOT_SUPPORTED; } static GeisStatus _geis_dbus_set_configuration(GeisBackend be GEIS_UNUSED, GeisSubscription subscription GEIS_UNUSED, GeisString item_name GEIS_UNUSED, GeisPointer item_value GEIS_UNUSED) { return GEIS_STATUS_NOT_SUPPORTED; } static struct GeisBackendVtable gdb_vtbl = { _geis_dbus_backend_construct, _geis_dbus_backend_finalize, _geis_dbus_backend_create_token, _geis_dbus_accept_gesture, _geis_dbus_reject_gesture, NULL, NULL, _geis_dbus_get_configuration, _geis_dbus_set_configuration, }; /** * Registers the back end with the GEIS back end registry. */ static void __attribute__((constructor)) _register_dbus_backend(void) { geis_register_backend(GEIS_INIT_DBUS_BACKEND, sizeof(struct GeisDBusBackend), &gdb_vtbl); } /** A dummy routine to force linkage of this module without dlopening it */ void geis_include_dbus_backend(void) { } /** @} */ geis-2.2.17+16.04.20160126/libgeis/backend/dbus/geis_dbus_client.c0000644000015600001650000004570212651717544024530 0ustar pbuserpbgroup00000000000000/** * @file geis_dbus_client.c * @brief Implementations of the GEIS DBus client. */ /* * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "geis_config.h" #include "geis_dbus_client.h" #include "geis_dbus.h" #include "geis_dbus_class.h" #include "geis_dbus_device.h" #include "geis_dbus_gesture_event.h" #include "geis_dbus_locator.h" #include "geis_dbus_region.h" #include "geis_dbus_subscription.h" #include "geis_event.h" #include "geis_logging.h" #include "geis_private.h" #include #include typedef enum GeisDBusClientState { GEIS_DBUS_CLIENT_DISCONNECTED, /* no server available */ GEIS_DBUS_CLIENT_INITIALIZING, /* server connected, client initializing */ GEIS_DBUS_CLIENT_CONNECTING, /* server connected, not initialized */ GEIS_DBUS_CLIENT_CONNECTED /* server connected, all systems go */ } GeisDBusClientState; struct GeisDBusClient { Geis geis; GeisDBusDispatcher dispatcher; GeisDBusLocator locator; GeisDBusClientState state; DBusConnection *connection; GeisSubBag subscription_bag; }; /** * Handles a device-available message from the server. * * @param[in] client A %GeisDBusClient. * @param[in] message The %DBusMessage. */ static void _client_device_available(GeisDBusClient client, DBusMessage *message) { GeisDevice device = geis_dbus_device_device_from_available_message(message); if (device) { geis_register_device(client->geis, device, 0, NULL); } else { geis_error("no device received from remote back end"); } } /** * Handles a device-unavailable message from the server. * * @param[in] client A %GeisDBusClient. * @param[in] message The %DBusMessage. */ static void _client_device_unavailable(GeisDBusClient client, DBusMessage *message) { GeisDevice device = geis_dbus_device_device_from_unavailable_message(message); if (device) { geis_unregister_device(client->geis, device); } else { geis_error("no device received from remote back end"); } } /** * Handles a class-available message from the server. * * @param[in] client A %GeisDBusClient. * @param[in] message The %DBusMessage. */ static void _client_class_available(GeisDBusClient client, DBusMessage *message) { GeisGestureClass gesture_class; gesture_class = geis_dbus_class_class_from_available_message(message); if (gesture_class) { geis_register_gesture_class(client->geis, gesture_class, 0, NULL); } else { geis_error("no gesture class received from remote back end"); } } /** * Handles a region-available message from the server. * * @param[in] client A %GeisDBusClient. * @param[in] message The %DBusMessage. */ static void _client_region_available(GeisDBusClient client, DBusMessage *message) { GeisFilterableAttribute attr; attr = geis_dbus_region_from_region_available_message(message); if (attr) { attr->add_term_callback = 0; attr->add_term_context = 0; geis_register_region(client->geis, NULL, 1, attr); } else { geis_error("no region attr received from remote back end"); } } /** * Handles a class-unavailable message from the server. * * @param[in] client A %GeisDBusClient. * @param[in] message The %DBusMessage. */ static void _client_gesture_event(GeisDBusClient client, DBusMessage *message) { GeisEvent event = geis_dbus_gesture_event_from_message(client->geis, message); if (!event) { geis_error("no gesture event received from remote back end"); } else { geis_post_event(client->geis, event); } } /** * Processes an subscription-activate reply from the server. * * @param[in] pending A DBusPendingCall object. * @param[in] user_data The %GeisDBusClient object. */ static void _geis_dbus_client_activate_reply(DBusPendingCall *pending, void *user_data) { GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data; DBusMessage *reply = dbus_pending_call_steal_reply(pending); if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) { const char *s = NULL; dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); geis_error("error %s: %s", dbus_message_get_error_name(reply), s); } } /** * Processes a subscription-create reply from the server. * * @param[in] pending A DBusPendingCall object. * @param[in] user_data The %GeisDBusClient object. */ static void _geis_dbus_client_subscribe_reply(DBusPendingCall *pending, void *user_data) { GeisDBusClient client = (GeisDBusClient)user_data; DBusMessage *reply = dbus_pending_call_steal_reply(pending); if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) { const char *s = NULL; dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); geis_error("error %s: %s", dbus_message_get_error_name(reply), s); } else { DBusMessage *msg; DBusPendingCall *pending; DBusError error = DBUS_ERROR_INIT; dbus_int32_t client_sub_id; dbus_int32_t server_sub_id; GeisSubscription subscription; dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &client_sub_id, DBUS_TYPE_INT32, &server_sub_id, DBUS_TYPE_INVALID); if (dbus_error_is_set(&error)) { geis_error("error %s: %s", error.name, error.message); dbus_error_free(&error); } subscription = geis_subscription_bag_find(client->subscription_bag, client_sub_id); if (!subscription) { geis_error("invalid client subcription id %d returned from server", client_sub_id); } else { geis_subscription_set_pdata(subscription, (GeisPointer)(intptr_t)server_sub_id); msg = geis_dbus_subscription_activate_call_message(subscription); dbus_connection_send_with_reply(client->connection, msg, &pending, -1); dbus_message_unref(msg); if (!pending) { geis_error("error sending DBus CreateSubscription method call"); } else { dbus_pending_call_set_notify(pending, _geis_dbus_client_activate_reply, client, 0); } } } dbus_message_unref(reply); dbus_pending_call_unref(pending); } /** * Processes a deactivate-subscription reply from the server. * * @param[in] pending A DBusPendingCall object. * @param[in] user_data The %GeisDBusClient object. */ static void _geis_dbus_client_unsubscribe_reply(DBusPendingCall *pending, void *user_data) { GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data; DBusMessage *reply = dbus_pending_call_steal_reply(pending); if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) { const char *s = NULL; dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); geis_error("error %s: %s", dbus_message_get_error_name(reply), s); } else { geis_warning("signature=\"%s\"", dbus_message_get_signature(reply)); geis_warning("path=\"%s\"", dbus_message_get_path(reply)); geis_warning("interface=\"%s\"", dbus_message_get_interface(reply)); geis_warning("member=\"%s\"", dbus_message_get_member(reply)); } dbus_message_unref(reply); dbus_pending_call_unref(pending); } /** * Creates a remote subscription. */ void _dbus_client_subscribe(GeisDBusClient client, GeisSubscription subscription) { DBusPendingCall *pending_return; GeisSubscription sub = geis_subscription_bag_find(client->subscription_bag, geis_subscription_id(subscription)); if (sub && geis_subscription_pdata(sub)) { geis_warning("subscription already activated!"); } else { DBusMessage *msg = geis_dbus_subscription_create_call_message(subscription); dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1); dbus_message_unref(msg); if (!pending_return) { geis_error("error sending DBus CreateSubscription method call"); } else { dbus_pending_call_set_notify(pending_return, _geis_dbus_client_subscribe_reply, client, 0); } } } /** * Re-subscribes all existing sibscriptions when the server appears or * reappears. */ void _dbus_client_resubscribe_all(GeisDBusClient client) { GeisSubBagIterator it; for (it = geis_subscription_bag_begin(client->subscription_bag); it != geis_subscription_bag_end(client->subscription_bag); it = geis_subscription_bag_iterator_next(client->subscription_bag, it)) { geis_subscription_set_pdata(*it, 0); _dbus_client_subscribe(client, *it); } } /** * The DBus message dispatch function for the GEIS DBus client. * * @param[in] connection The %GeisDBusClient DBus connection. * @param[in] message The DBus message received. * @param[in] user_data The %GeisDBusClient. */ static DBusHandlerResult _geis_dbus_client_message_handler(DBusConnection *connection GEIS_UNUSED, DBusMessage *message, void *user_data) { DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; GeisDBusClient client = (GeisDBusClient)user_data; int type = dbus_message_get_type(message); if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) { geis_warning("server disconnected?"); result = DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_DEVICE_AVAILABLE)) { _client_device_available(client, message); result = DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_DEVICE_UNAVAILABLE)) { _client_device_unavailable(client, message); result = DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_CLASS_AVAILABLE)) { _client_class_available(client, message); result = DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_REGION_AVAILABLE)) { _client_region_available(client, message); result = DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, GEIS_DBUS_SERVICE_INTERFACE, GEIS_DBUS_INIT_COMPLETE)) { if (client->state == GEIS_DBUS_CLIENT_INITIALIZING) { geis_post_event(client->geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE)); } client->state = GEIS_DBUS_CLIENT_CONNECTED; _dbus_client_resubscribe_all(client); result = DBUS_HANDLER_RESULT_HANDLED; } else if (geis_dbus_message_is_gesture_event(message)) { _client_gesture_event(client, message); result = DBUS_HANDLER_RESULT_HANDLED; } else if (type == DBUS_MESSAGE_TYPE_ERROR) { const char *str = NULL; dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID); geis_warning("error %s: %s", dbus_message_get_error_name(message), str); } else { geis_warning("unhandled DBus %s received:", dbus_message_type_to_string(dbus_message_get_type(message))); geis_warning(" signature=\"%s\"", dbus_message_get_signature(message)); geis_warning(" sender=\"%s\"", dbus_message_get_sender(message)); geis_warning(" path=\"%s\"", dbus_message_get_path(message) ? dbus_message_get_path(message) : "(no path)"); geis_warning(" interface=\"%s\"", dbus_message_get_interface(message) ? dbus_message_get_interface(message) : "(no interface)"); geis_warning(" member=\"%s\"", dbus_message_get_member(message) ? dbus_message_get_member(message) : "(no member)"); } return result; } /** * Adds the client watches to the dispatcher watch list. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static dbus_bool_t _client_add_watch(DBusWatch *watch, void *data) { dbus_bool_t status = TRUE; GeisDBusClient client = (GeisDBusClient)data; geis_dbus_dispatcher_register(client->dispatcher, client->connection, watch); return status; } /** * Toggles the enabled/disabled status of the client watches. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static void _client_toggle_watch(DBusWatch *watch, void *data) { GeisDBusClient client = (GeisDBusClient)data; geis_dbus_dispatcher_toggle_watch(client->dispatcher, watch); } /** * Removes the client watches from the dispatcher watch list. * * @param[in] watch A %DBusWatch. * @param[in] data The %GeisDBusClientProxy. */ static void _client_remove_watch(DBusWatch *watch, void *data) { GeisDBusClient client = (GeisDBusClient)data; geis_dbus_dispatcher_unregister(client->dispatcher, watch); } /** * Connects to the GEIS server once an address is located. * * @param[in] client A %GeisDBusClient object. * @param[in] address The address of the server. */ static void _client_connect(GeisDBusClient client, const char *address) { geis_debug("server address=\"%s\"", address); DBusError error = DBUS_ERROR_INIT; client->connection = dbus_connection_open(address, &error); if (!client->connection || dbus_error_is_set(&error)) { char msg[512]; snprintf(msg, sizeof(msg), "error %s connecting to server at address %s: %s", error.name, address, error.message); geis_error("%s", msg); dbus_error_free(&error); goto final_exit; } /* Integrate with the app event loop via the GEIS multiplexor. */ dbus_connection_set_watch_functions(client->connection, _client_add_watch, _client_remove_watch, _client_toggle_watch, client, 0); /* Install a handler for any and all messages. */ dbus_connection_add_filter(client->connection, _geis_dbus_client_message_handler, client, 0); if (client->state != GEIS_DBUS_CLIENT_INITIALIZING) { client->state = GEIS_DBUS_CLIENT_CONNECTING; } final_exit: return; } /* * Creates a new GeisDBusClient. */ GeisDBusClient geis_dbus_client_new(Geis geis) { GeisDBusClient client = calloc(1, sizeof(struct GeisDBusClient)); if (!client) { goto final_exit; } client->geis = geis; client->state = GEIS_DBUS_CLIENT_INITIALIZING; client->dispatcher = geis_dbus_dispatcher_new(geis); if (!client->dispatcher) { goto unwind_client; } client->locator = geis_dbus_locator_new(client); if (!client->locator) { goto unwind_dispatcher; } client->subscription_bag = geis_subscription_bag_new(1); if (!client->subscription_bag) { goto unwind_locator; } goto final_exit; unwind_locator: geis_dbus_locator_delete(client->locator); unwind_dispatcher: geis_dbus_dispatcher_delete(client->dispatcher); unwind_client: free(client); client = NULL; final_exit: return client; } /* * Destroys a GeisDBusClient. */ void geis_dbus_client_delete(GeisDBusClient client) { geis_subscription_bag_delete(client->subscription_bag); geis_dbus_locator_delete(client->locator); if (client->connection) { dbus_connection_unref(client->connection); } geis_dbus_dispatcher_delete(client->dispatcher); free(client); } /* * Gets the client dispatcher. */ GeisDBusDispatcher geis_dbus_client_dispatcher(GeisDBusClient client) { return client->dispatcher; } /* * Signals the client the server has been located. */ void geis_dbus_client_server_located(GeisDBusClient client) { _client_connect(client, geis_dbus_locator_server_address(client->locator)); } /* * Signals the client the server has been dislocated. */ void geis_dbus_client_server_dislocated(GeisDBusClient client) { GeisEvent event = geis_event_new(GEIS_EVENT_ERROR); client->state = GEIS_DBUS_CLIENT_DISCONNECTED; geis_post_event(client->geis, event); } /* * Requests a subscription on the remote end. */ GeisStatus geis_dbus_client_subscribe(GeisDBusClient client, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_SUCCESS; if (client->state == GEIS_DBUS_CLIENT_CONNECTED) { _dbus_client_subscribe(client, subscription); } geis_subscription_bag_insert(client->subscription_bag, subscription); return status; } /* * Destroys a subscription on the remote end. */ GeisStatus geis_dbus_client_unsubscribe(GeisDBusClient client, GeisSubscription subscription) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (geis_subscription_bag_find(client->subscription_bag, geis_subscription_id(subscription))) { DBusMessage *msg; DBusPendingCall *pending_return; msg = geis_dbus_subscription_destroy_call_message(subscription); dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1); dbus_message_unref(msg); if (!pending_return) { geis_error("error sending DBus CreateSubscription method call"); goto final_exit; } dbus_pending_call_set_notify(pending_return, _geis_dbus_client_unsubscribe_reply, client, 0); geis_subscription_bag_remove(client->subscription_bag, subscription); status = GEIS_STATUS_SUCCESS; } final_exit: return status; } /* * Asks the remote server to accept a gesture. */ GeisStatus geis_dbus_client_accept_gesture(GeisDBusClient client GEIS_UNUSED, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_id GEIS_UNUSED) { return GEIS_STATUS_SUCCESS; } /* * Asks the remote server to reject a gesture. */ GeisStatus geis_dbus_client_reject_gesture(GeisDBusClient client GEIS_UNUSED, GeisGroup group GEIS_UNUSED, GeisGestureId gesture_id GEIS_UNUSED) { return GEIS_STATUS_SUCCESS; } geis-2.2.17+16.04.20160126/libgeis/geis_error.c0000644000015600001650000000551512651717544021040 0ustar pbuserpbgroup00000000000000/** * @file libgeis/geis_error.c * @brief implementation of the GEIS v2.0 API error reporting module * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include "geis_error.h" #include "geis_logging.h" #include "geis_private.h" #include static GeisErrorStack g_error_stack = { 0, 0, 0 }; static void geis_error_stack_clear(GeisErrorStack *error_stack) { error_stack->error_count = 0; } static void geis_error_stack_push(GeisErrorStack *error_stack, GeisStatus code) { if (error_stack->error_count < error_stack->store_size) { error_stack->store[error_stack->error_count++] = code; } else { error_stack->store_size += 2; error_stack->store = realloc(error_stack->store, error_stack->store_size * sizeof(GeisErrorStack )); if (!error_stack->store) { geis_error("error_stack realloc failed for size %zu", error_stack->store_size); return; } error_stack->store[error_stack->error_count++] = code; } } static GeisStatus geis_error_stack_get(GeisErrorStack *error_stack, GeisSize index) { if (index < error_stack->error_count) { return error_stack->store[index]; } return GEIS_STATUS_BAD_ARGUMENT; } void geis_error_clear(Geis geis) { if (geis) { geis_error_stack_clear(geis_error_stack(geis)); } else { geis_error_stack_clear(&g_error_stack); } } void geis_error_push(Geis geis, GeisStatus code) { if (geis) { geis_error_stack_push(geis_error_stack(geis), code); } else { geis_error_stack_push(&g_error_stack, code); } } GeisSize geis_error_count(Geis geis) { if (geis) { return geis_error_stack(geis)->error_count; } else { return g_error_stack.error_count; } } GeisStatus geis_error_code(Geis geis, GeisSize index) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; if (geis) { status = geis_error_stack_get(geis_error_stack(geis), index); } else { status = geis_error_stack_get(&g_error_stack, index); } return status; } GeisString geis_error_message(Geis geis, GeisSize index GEIS_UNUSED) { GeisString message = ""; if (geis) { } else { } return message; } geis-2.2.17+16.04.20160126/libgeis/geis_timer.h0000644000015600001650000000354412651717544021034 0ustar pbuserpbgroup00000000000000/** * @file geis_timer.h * @brief Internal interface for the GEIS timer module. */ /* Copyright (C) 2011-2012 Canonical Ltd * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . */ #ifndef GEIS_TIMER_H_ #define GEIS_TIMER_H_ #include /** * @defgroup geis_timer Integral GEIS timers * @{ */ /** * An opaque timer object. */ typedef struct GeisTimer *GeisTimer; /** * The type of the callback to be invoked on timer expiry. */ typedef void (*GeisTimerCallback)(GeisTimer timer, void *context); /** * Creates a new timer object on a GEIS API instance. * * @param[in] geis A GEIS API instance. * @param[in] callback A callback to be executed on timer expiry. * @param[in] context User context to be passed to the callback. */ GeisTimer geis_timer_new(Geis geis, GeisTimerCallback callback, void *context); /** * Destroys an existing timer. * @param timer A timer object. */ void geis_timer_delete(GeisTimer timer); /** * Cancels an outstanding timer. * @param timer A timer object. */ void geis_timer_cancel(GeisTimer timer); /** * Starts a timer object a-ticking. * @param timer A timer object. * @param msec The number of milliseconds until the timer expires. */ void geis_timer_start(GeisTimer timer, GeisInteger msec); /* @} */ #endif /* GEIS_TIMER_H_ */ geis-2.2.17+16.04.20160126/libgeis/geis_backend.h0000644000015600001650000001437112651717544021303 0ustar pbuserpbgroup00000000000000/** * @file geis_backend.h * @brief internal GEIS back end base class public interface * * Copyright 2010-2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GEIS_BACKEND_H_ #define GEIS_BACKEND_H_ #include "geis/geis.h" #include "geis_backend_token.h" /** * Provides a virtual "base class" for various GEIS back ends. * * The GEIS is an API that implements the facade pattern over some number of * actual "back end" implementations. Most internal operations of the API are * performed through this "virtual base class" interface rather than through the * concrete back ends (isn't object-oriented programming great?). */ typedef struct GeisBackend *GeisBackend; /** * Creates a back end by name. * * @param[in] name Names a back end. */ GeisBackend geis_backend_by_name(Geis geis, GeisString name); /** * Destroys the back end. * * @parameter[in] be The back end. * * This function behaves like a virtual destructor and chains through to the * concrete destructor call. */ void geis_backend_delete(GeisBackend be); /** * Gets the name of the back end. * * @parameter[in] be The back end. * * This accessor is useful for diagnostics. */ GeisString geis_backend_name(GeisBackend be); /** * Creates a new back end token. */ GeisBackendToken geis_backend_create_token(GeisBackend be, GeisBackendTokenInitState); /** * Marks a gesture as accepted by the back end. * * @param[in] be The GEIS back end. * @param[in] group The gesture group containing the accepted gesture. * @param[in] gesture_id Identifies the gesture. */ GeisStatus geis_backend_gesture_accept(GeisBackend be, GeisGroup group, GeisGestureId gesture_id); /** * Marks a gesture as rejected by the back end. * * @param[in] be The GEIS back end. * @param[in] group The gesture group containing the rejected gesture. * @param[in] gesture_id Identifies the gesture. */ GeisStatus geis_backend_gesture_reject(GeisBackend be, GeisGroup group, GeisGestureId gesture_id); /** * Tells the back end to activate a device after it's been set up. * * @param[in] be The GEIS back end. * @param[in] device The GEIS device for which subscription wll activate. * * The back end sends and event to the middle end when a new device has been * detected. The middle end sets up some structures etc., then tells the back * end to activate the device (which may actually cause some subscriptions to be * activated), then forwards the new-device event to the front end where the * application can be made aware of it. */ GeisStatus geis_backend_activate_device(GeisBackend be, GeisDevice device); /** * Tells the back end to activate a device after it's been set up. * * @param[in] be The GEIS back end. * @param[in] device The GEIS device for which subscription wll deactivate. * * See geis_backend_activate_device for more information. */ GeisStatus geis_backend_deactivate_device(GeisBackend be, GeisDevice device); /** * Gets a back end configuration value. * * @param[in] be The back end. * @param[in] subscription A subscription from the back end (or NULL * if a non-subscription configuration). * @param[in] configuration_item_name The name of a configuration item. * @param[out] configuration_item_value A pointer to a variable of the * appropriate type to receive the * configuration item value. * * @retval GEIS_STATUS_SUCCESS The configuration item is supported and the * item value has been successfully retrieved. * @retval GEIS_STATUS_NO_SUPPORTED The configuration item is not supported on * this backend. * @retval GEIS_STATUS_UNKNOWN_ERROR The configuration item is supported but an * error occurred when attempting to get the * item value. */ GeisStatus geis_backend_get_configuration(GeisBackend be, GeisSubscription subscription, GeisString configuration_item_name, GeisPointer configuration_item_value); /** * Sets a back end configuration value. * * @param[in] be The back end. * @param[in] subscription A subscription from the back end (or NULL * if a non-subscription configuration). * @param[in] configuration_item_name The name of a configuration item. * @param[in] configuration_item_value A pointer to a value to set. * * @retval GEIS_STATUS_SUCCESS The configuration item is supported and has * been successfully set. * @retval GEIS_STATUS_NO_SUPPORTED The configuration item is not supported on * this backend. * @retval GEIS_STATUS_UNKNOWN_ERROR The configuration item is supported but an * error occurred when attempting to set the * item value. */ GeisStatus geis_backend_set_configuration(GeisBackend be, GeisSubscription subscription, GeisString configuration_item_name, GeisPointer configuration_item_value); #endif /* GEIS_BACKEND_H_ */ geis-2.2.17+16.04.20160126/libgeis.pc.in0000644000015600001650000000034012651717544017454 0ustar pbuserpbgroup00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libgeis Description: Gesture Engine Implementation Support Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lgeis Cflags: -I${includedir} geis-2.2.17+16.04.20160126/testsuite/0000755000015600001650000000000012651717732017140 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/geistest/0000755000015600001650000000000012651717732020767 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/geistest/Makefile.am0000644000015600001650000000036212651717544023025 0ustar pbuserpbgroup00000000000000 bin_PROGRAMS = geistest geistest_SOURCES = \ geistest.c geistest_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ $(XCB_CFLAGS) geistest_LDADD = \ $(top_builddir)/libgeis/libgeis.la \ $(XCB_LIBS) geis-2.2.17+16.04.20160126/testsuite/geistest/geistest.c0000644000015600001650000002367612651717544023001 0ustar pbuserpbgroup00000000000000/** * geistest.c Demo code for programming against the geis interface. * * Copyright 2010 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU General Public License as published by the * Free Software Foundation. * * 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "geis_config.h" #include #include #include #include #include #include #include #include GeisSize g_smw = 0; const char* s_gestures[] = { GEIS_GESTURE_TYPE_DRAG2, GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_TYPE_PINCH2, GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_TYPE_ROTATE2, GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_TYPE_TAP2, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_TAP4, GEIS_GESTURE_TYPE_TOUCH3, GEIS_GESTURE_TYPE_TOUCH4, GEIS_GESTURE_TYPE_FLICK2, GEIS_GESTURE_TYPE_FLICK3, GEIS_GESTURE_TYPE_FLICK4, NULL }; GeisSize g_device_count = 0; GeisInputDeviceId *g_devices = GEIS_ALL_INPUT_DEVICES; static void print_attr(GeisGestureAttr *attr) { fprintf(stdout, "\tattr \"%s\" = ", attr->name); switch (attr->type) { case GEIS_ATTR_TYPE_BOOLEAN: fprintf(stdout, "%s\n", attr->boolean_val ? "true" : "false"); break; case GEIS_ATTR_TYPE_FLOAT: fprintf(stdout, "%f\n", attr->float_val); break; case GEIS_ATTR_TYPE_INTEGER: fprintf(stdout, "%d\n", attr->integer_val); break; case GEIS_ATTR_TYPE_STRING: fprintf(stdout, "\"%s\"\n", attr->string_val); break; default: fprintf(stdout, "\n"); break; } } static void input_device_added(void *cookie GEIS_UNUSED, GeisInputDeviceId device_id, void *attrs) { GeisGestureAttr *a; fprintf(stdout, "Device %d added\n", device_id); for (a = attrs; a->name; ++a) { print_attr(a); } } static void input_device_changed(void *cookie GEIS_UNUSED, GeisInputDeviceId device_id GEIS_UNUSED, void *attrs GEIS_UNUSED) { } static void input_device_removed(void *cookie GEIS_UNUSED, GeisInputDeviceId device_id, void *attrs) { GeisGestureAttr *a; fprintf(stdout, "Device %d removed\n", device_id); for (a = attrs; a->name; ++a) { print_attr(a); } } static void gesture_added(void *cookie GEIS_UNUSED, GeisGestureType gesture_type, GeisGestureId gesture_id GEIS_UNUSED, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i = 0; fprintf(stdout, "Gesture type %d added\n", gesture_type); for (i = 0; i < attr_count; ++i) print_attr(&attrs[i]); } static void gesture_removed(void *cookie GEIS_UNUSED, GeisGestureType gesture_type, GeisGestureId gesture_id GEIS_UNUSED, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i = 0; fprintf(stdout, "Gesture type %d removed\n", gesture_type); for (i = 0; i < attr_count; ++i) print_attr(&attrs[i]); } static void gesture_start(void *cookie GEIS_UNUSED, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i = 0; fprintf(stdout, "Gesture id %d type %d started\n", gesture_id, gesture_type); for (i = 0; i < attr_count; ++i) print_attr(&attrs[i]); } static void gesture_update(void *cookie GEIS_UNUSED, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i = 0; fprintf(stdout, "Gesture id %d type %d updated\n", gesture_id, gesture_type); for (i = 0; i < attr_count; ++i) print_attr(&attrs[i]); } static void gesture_finish(void *cookie GEIS_UNUSED, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i = 0; fprintf(stdout, "Gesture id %d type %d finished\n", gesture_id, gesture_type); for (i = 0; i < attr_count; ++i) print_attr(&attrs[i]); } GeisInputFuncs input_funcs = { input_device_added, input_device_changed, input_device_removed }; GeisGestureFuncs gesture_funcs = { gesture_added, gesture_removed, gesture_start, gesture_update, gesture_finish }; static void _add_device_id(GeisInteger id) { GeisInputDeviceId *d = realloc(g_devices, g_device_count + 2); if (!d) { fprintf(stderr, "error allocating device list.\n"); exit(1); } g_devices = d; g_devices[g_device_count] = id; g_devices[g_device_count+1] = 0; ++g_device_count; } int parse_opts(int argc, char* argv[], uint32_t *window_id) { int opt; while ((opt = getopt(argc, argv, "w:d:")) != -1) { switch (opt) { case 'w': *window_id = strtol(optarg, NULL, 0); break; case 'd': { GeisInteger id = strtol(optarg, NULL, 0); if (0 == id) { fprintf(stderr, "invalid device id '%s'\n'", optarg); return 0; } _add_device_id(id); } break; default: return 0; } } return 1; } static GeisInstance subscribe_window(uint32_t window_id) { GeisStatus status = GEIS_UNKNOWN_ERROR; GeisXcbWinInfo xcb_win_info = { .display_name = NULL, .screenp = NULL, .window_id = window_id }; GeisWinInfo win_info = { GEIS_XCB_FULL_WINDOW, &xcb_win_info }; GeisInstance instance; status = geis_init(&win_info, &instance); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error in geis_init\n"); return NULL; } status = geis_input_devices(instance, &input_funcs, NULL); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error subscribing to input devices\n"); return NULL; } status = geis_subscribe(instance, g_devices, s_gestures, &gesture_funcs, NULL); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error subscribing to gestures\n"); return NULL; } return instance; } static void subscribe_all_windows(GeisInstance **instance_table) { int instance_table_size = 0; xcb_connection_t *xcb = xcb_connect(NULL, NULL); if (!xcb) { fprintf(stderr, "error connecting to X server\n"); exit(1); } const xcb_setup_t *setup = xcb_get_setup(xcb); if (!setup) { fprintf(stderr, "error getting xcb setup\n"); exit(1); } xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup); while (screen.rem) { ++instance_table_size; xcb_screen_next(&screen); } *instance_table = calloc(instance_table_size, sizeof(GeisInstance)); screen = xcb_setup_roots_iterator(setup); for (int i = 0; screen.rem; ++i, xcb_screen_next(&screen)) { GeisInstance instance = subscribe_window(screen.data->root); if (!instance) { fprintf(stderr, "error subscribing window 0x%08x\n", (unsigned)screen.data->root); exit(1); } *instance_table[i] = instance; } xcb_disconnect(xcb); } int main(int argc, char* argv[]) { int result = -1; uint32_t window_id = 0; int fd = -1; GeisStatus status = GEIS_UNKNOWN_ERROR; GeisInstance *instance_table = NULL; size_t instance_table_size = 0; if (!parse_opts(argc, argv, &window_id)) { fprintf(stderr, "usage: %s windowid\n", argv[0]); return -1; } if (window_id != 0) { instance_table_size = 1; instance_table = calloc(instance_table_size, sizeof(GeisInstance)); instance_table[0] = subscribe_window(window_id); if (!instance_table[0]) { fprintf(stderr, "can not continue, exiting....\n"); goto error_exit; } } else { subscribe_all_windows(&instance_table); } status = geis_configuration_supported(instance_table[0], GEIS_CONFIG_UNIX_FD); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "GEIS does not support Unix fd\n"); goto fail_exit; } status = geis_configuration_get_value(instance_table[0], GEIS_CONFIG_UNIX_FD, &fd); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error retrieving GEIS fd\n"); goto fail_exit; } while (1) { size_t i; int fd; int max_fd = 0; fd_set read_fds; FD_ZERO(&read_fds); FD_SET(0, &read_fds); for (i = 0; i < instance_table_size; ++i) { status = geis_configuration_get_value(instance_table[i], GEIS_CONFIG_UNIX_FD, &fd); max_fd = (fd > max_fd ? fd : max_fd); FD_SET(fd, &read_fds); } int sstat = select(max_fd + 1, &read_fds, NULL, NULL, NULL); if (sstat < 0) { fprintf(stderr, "error %d in select(): %s\n", errno, strerror(errno)); break; } for (i = 0; i < instance_table_size; ++i) { status = geis_configuration_get_value(instance_table[i], GEIS_CONFIG_UNIX_FD, &fd); if (FD_ISSET(fd, &read_fds)) { geis_event_dispatch(instance_table[i]); } } if (FD_ISSET(0, &read_fds)) { break; } } fail_exit: { size_t i; for (i = 0; i < instance_table_size; ++i) { geis_finish(instance_table[i]); } } error_exit: if (instance_table_size > 0) { free(instance_table); } return result; } geis-2.2.17+16.04.20160126/testsuite/Makefile.am0000644000015600001650000000171712651717544021203 0ustar pbuserpbgroup00000000000000# # @file testsuite/Makefile.am # @brief automake recipe for the GEIS test suite # # # Copyright 2010 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # SUBDIRS = gtest x11_mocks geis-util libgeis geis2 geis1 geistest EXTRA_DIST = recordings geis-2.2.17+16.04.20160126/testsuite/gtest/0000755000015600001650000000000012651717732020266 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_geis1_fixture.cpp0000644000015600001650000000374012651717544024763 0ustar pbuserpbgroup00000000000000/** * @file gtest_geis_fixture.cpp * @brief A GTest fixture for testing the full stack through GEIS. */ /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "gtest_geis1_fixture.h" #include #include void GTestGeis1Fixture:: SetUp() { // wait for things to settle usleep(1000000); // Chain up the static class heirarchy, as if the test framework was // designed by a Java trainee with some exposure to glib but has never used // C++. ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp()); // Verify that whatever X server is in use supports the required XInput // version. int xi_major = 2; int xi_minor = 2; ASSERT_EQ(Success, XIQueryVersion(Display(), &xi_major, &xi_minor)); ASSERT_GE(xi_major, 2); ASSERT_GE(xi_minor, 2); uint32_t geis_window_id = static_cast(DefaultRootWindow(Display())); GeisXcbWinInfo xcb_win_info = { NULL, NULL, geis_window_id }; GeisWinInfo win_info = { GEIS_XCB_FULL_WINDOW, &xcb_win_info }; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_init(&win_info, &geis_)); ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_configuration_get_value(geis_, GEIS_CONFIG_UNIX_FD, &geis_fd_)); } void GTestGeis1Fixture:: TearDown() { EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_finish(geis_)); xorg::testing::Test::TearDown(); // NVI ftw. usleep(1000000); } geis-2.2.17+16.04.20160126/testsuite/gtest/Makefile.am0000644000015600001650000000146012651717544022324 0ustar pbuserpbgroup00000000000000# # @file testsuite/gtest/Makefile.am # @brief automake recipe for the geis gtest testsuite harness directory # if HAVE_GTEST check_LIBRARIES = libgtest_geis.a endif nodist_libgtest_geis_a_SOURCES = \ $(GTEST_SOURCE)/gtest-all.cc libgtest_geis_a_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\" \ $(GTEST_CPPFLAGS) if ENABLE_INTEGRATION_TESTS libgtest_geis_a_SOURCES = \ gtest_evemu_device.h gtest_evemu_device.cpp \ gtest_geis_fixture.h gtest_geis_fixture.cpp \ gtest_geis1_fixture.h gtest_geis1_fixture.cpp nodist_libgtest_geis_a_SOURCES += \ $(XORG_GTEST_SOURCE)/src/xorg-gtest-all.cpp libgtest_geis_a_CPPFLAGS += \ --std=c++0x \ $(XORG_GTEST_CPPFLAGS) \ $(EVEMU_CFLAGS) \ $(XORG_GTEST_CFLAGS) endif geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_geis1_fixture.h0000644000015600001650000000234612651717544024431 0ustar pbuserpbgroup00000000000000/** * @file gtest_geis_fixture.h * @brief A GTest fixture for testing the full stack through GEIS. */ /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef GTEST_GEIS1_FIXTURE_H_ #define GTEST_GEIS1_FIXTURE_H_ #include "geis/geis.h" #include #include /** * Fixture for testing expected attributes. */ class GTestGeis1Fixture : public xorg::testing::Test { public: void SetUp(); void TearDown(); GeisInstance geis() { return geis_; } int geis_fd() const { return geis_fd_; } private: GeisInstance geis_; int geis_fd_; }; #endif /* GTEST_GEIS1_FIXTURE_H_ */ geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_geis_fixture.cpp0000644000015600001650000001006012651717544024673 0ustar pbuserpbgroup00000000000000/** * @file gtest_geis_fixture.cpp * @brief A GTest fixture for testing the full stack through GEIS. */ /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "gtest_geis_fixture.h" #include #include #include #include GTestGeisFixture:: GTestGeisFixture() : geis_(nullptr), geis_is_initialized_(false), geis_dispatch_loop_timeout_(1), geis_event_handler_(nullptr), geis_event_loop_stop_(false) { } void GTestGeisFixture:: SetUp() { // Chain up the static class heirarchy. ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp()); // Verify that whatever X server is in use supports the required XInput // version. int xi_major = 2; int xi_minor = 2; ASSERT_EQ(Success, XIQueryVersion(Display(), &xi_major, &xi_minor)); ASSERT_GE(xi_major, 2); ASSERT_GE(xi_minor, 2); setup_geis(); EXPECT_TRUE(NULL != geis_) << "could not create GEIS instance"; add_event_callback(geis_fd(), std::bind(>estGeisFixture::geis_event_callback, this)); } void GTestGeisFixture:: TearDown() { geis_delete(geis_); xorg::testing::Test::TearDown(); } void GTestGeisFixture:: add_event_callback(int fd, EventCallback event_callback) { event_callbacks_[fd] = event_callback; } int GTestGeisFixture:: geis_fd() { GeisInteger fd; geis_get_configuration(geis_, GEIS_CONFIGURATION_FD, &fd); return fd; } void GTestGeisFixture:: setup_geis() { geis_ = geis_new(GEIS_INIT_SYNCHRONOUS_START, GEIS_INIT_NO_ATOMIC_GESTURES, NULL); } bool GTestGeisFixture:: geis_is_initialized() const { return geis_is_initialized_; } void GTestGeisFixture:: pre_event_handler(GeisEvent event) { } void GTestGeisFixture:: set_geis_event_handler(GeisEventHandler geis_event_handler) { geis_event_handler_ = geis_event_handler; } void GTestGeisFixture:: post_event_handler(GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_GESTURE_END) { geis_dispatch_stop(true); } } void GTestGeisFixture:: geis_dispatch_stop(bool do_stop) { geis_event_loop_stop_ = do_stop; } void GTestGeisFixture:: geis_event_callback() { ASSERT_NE(geis_event_handler_, nullptr) << "no geis event handler installed"; GeisStatus dstatus = geis_dispatch_events(geis_); ASSERT_TRUE(dstatus == GEIS_STATUS_CONTINUE || dstatus == GEIS_STATUS_SUCCESS); GeisEvent event; for (GeisStatus estatus = geis_next_event(geis_, &event); estatus == GEIS_STATUS_CONTINUE || estatus == GEIS_STATUS_SUCCESS; estatus = geis_next_event(geis_, &event)) { if (geis_event_type(event) == GEIS_EVENT_INIT_COMPLETE) { geis_is_initialized_ = true; } pre_event_handler(event); geis_event_handler_(geis_, event); post_event_handler(event); geis_event_delete(event); if (geis_event_loop_stop_) return; } } void GTestGeisFixture:: geis_dispatch_loop() { while (true) { if (geis_event_loop_stop_) break; int max_fd = 0; fd_set read_fds; FD_ZERO(&read_fds); for (auto h: event_callbacks_) { FD_SET(h.first, &read_fds); max_fd = std::max(max_fd, h.first); } timeval tmo = { geis_dispatch_loop_timeout_, 0 }; int sstat = select(max_fd + 1, &read_fds, NULL, NULL, &tmo); ASSERT_GT(sstat, -1) << "error in select"; if (sstat == 0) break; for (auto h: event_callbacks_) { if (FD_ISSET(h.first, &read_fds)) { h.second(); } } } } geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_evemu_device.cpp0000644000015600001650000000464012651717544024645 0ustar pbuserpbgroup00000000000000/** * @file testsuite/geis2/gtest_evemu_device.cpp * @brief OO wrapper for a evemu device */ /* * Copyright 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #include "gtest_evemu_device.h" #include #include #include #include namespace { static const char UINPUT_NODE[] = "/dev/uinput"; } // anonymous namespace Testsuite::EvemuDevice:: EvemuDevice(const std::string& propFileName) { evemu_device_ = evemu_new(NULL); if (!evemu_device_) throw std::runtime_error("Failed to create evemu device"); FILE* prop_file = std::fopen(propFileName.c_str(), "r"); if (!prop_file) throw std::runtime_error("Can not open evemu prop file " + propFileName); if (evemu_read(evemu_device_, prop_file) <= 0) { std::fclose(prop_file); throw std::runtime_error("can not read evemu device file"); } std::fclose(prop_file); evemu_fd_ = open(UINPUT_NODE, O_WRONLY); if (evemu_fd_ < 0) { evemu_delete(evemu_device_); throw std::runtime_error("Failed to open uinput node"); } if (evemu_create(evemu_device_, evemu_fd_) < 0) { close(evemu_fd_); evemu_delete(evemu_device_); throw std::runtime_error("Failed to create evemu device"); } } Testsuite::EvemuDevice:: ~EvemuDevice() { close(evemu_fd_); } std::string Testsuite::EvemuDevice:: name() const { const char* device_name = evemu_get_name(evemu_device_); if (device_name) return device_name; return ""; } void Testsuite::EvemuDevice:: play(const std::string& eventsFileName) { FILE* events_file = std::fopen(eventsFileName.c_str(), "r"); if (!events_file) throw std::runtime_error("can not open evemu events file " + eventsFileName); if (evemu_play(events_file, evemu_fd_) != 0) { std::fclose(events_file); throw std::runtime_error("can not play evemu recording"); } std::fclose(events_file); } geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_evemu_device.h0000644000015600001650000000313612651717544024311 0ustar pbuserpbgroup00000000000000/** * @file testsuite/geis2/gtest_evemu_device.h * @brief OO wrapper for a evemu device */ /* * Copyright 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 General Public License * along with this program. If not, see . */ #ifndef TESTSUITE_GEIS2_GTEST_EVEMU_DEVICE_H_ #define TESTSUITE_GEIS2_GTEST_EVEMU_DEVICE_H_ extern "C" { #include } #include namespace Testsuite { class EvemuDevice { public: /** * Creates a wrapped evemu pseudodevice. * @param[in] propFilename Names the evemy device properties file. * * @throws std::runtime_error on any failure. */ EvemuDevice(const std::string& propFileName); ~EvemuDevice(); /** * Gets the name of the device. */ std::string name() const; /** * Plays a named evemu events fil on the wrapped device. * @param[in] eventsFilename Names the events file. * * @throws std::runtime_error on any failure. */ void play(const std::string& eventsFileName); private: evemu_device* evemu_device_; int evemu_fd_; }; } // namespace Testsuite #endif // TESTSUITE_GEIS2_GTEST_EVEMU_DEVICE_H_ geis-2.2.17+16.04.20160126/testsuite/gtest/gtest_geis_fixture.h0000644000015600001650000001073712651717544024353 0ustar pbuserpbgroup00000000000000/** * @file gtest_geis_fixture.h * @brief A GTest fixture for testing the full stack through GEIS. */ /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef GTEST_GEIS_FIXTURE_H_ #define GTEST_GEIS_FIXTURE_H_ #include #include "geis/geis.h" #include #include #include /** * Fixture for testing expected attributes. */ class GTestGeisFixture : public xorg::testing::Test { public: /** * Test cases should provide an event handler function with this type * signature to perform the main test processing. */ typedef std::function GeisEventHandler; /** * A test case can extend the event-driven model with a bound callback. */ typedef std::function EventCallback; GTestGeisFixture(); void SetUp(); void TearDown(); /** * Customization point for test cases that need to synchronize their own * entities. * * @param[in] fd A file descriptor to synchronize. * @param[in] callback A function object to invoke when read activity is * detected on @p fd. */ void add_event_callback(int fd, EventCallback callback); /** * Indicates if the GEIS instance has been successfully initialized. * * Test cases can use this function in their event handler(s) to avoid * performing actions until the stack has been fully initialized. */ bool geis_is_initialized() const; /** * Sets the main loop timeout. * * @param[in] seconds The timeout (in seconds) to wait until exiting the main * event loop. * * The default timeout is 1 second. */ void geis_dispatch_loop_timeout(long seconds); /** * Customization point for common event handling for all tests run with a * fixture. * * @param[in] event The current geis event to be handled. * * The default pre-event handler does nothing. */ virtual void pre_event_handler(GeisEvent event); /** * Sets the geis dispatch loop event handler. * * @param[in] handler An event handler function. */ void set_geis_event_handler(GeisEventHandler handler); /** * Customization point for common event handling for all tests run with a * fixture. * * @param[in] event The current geis event to be handled. * * The default post-event handler calls geis_dispatch_stop(true) on a * GEIS_EVENT_GESTURE_END event. Derived test fixtures that override * this function should invoke the base class function at the end of their * processing (prefered) or else call geis_dispatch_stop(true) themselves * if appropriate. */ virtual void post_event_handler(GeisEvent event); /** * Runs the geis dispatch loop. * * The geis dipatch loop waits for geis events (and only geis events) and * dispatches them as the are repotred, until geis_dispatch_stop(true) has * been called. */ void geis_dispatch_loop(); /** * Asks the geis dispatch loop to stop and return. * * @param[in] do_stop Tells the loop to stop (true) or continue (false); */ void geis_dispatch_stop(bool do_stop); private: /** * Sets up the GEIS instance. * * This function provides a customization point for tests that need to create * the captive geis instance with different configuration options. */ virtual void setup_geis(); /** * Gets the event-watch file descriptor of the captive geis instance. */ int geis_fd(); /** * The event handler for the captive geis instance. */ void geis_event_callback(); protected: typedef std::map EventCallbacks; Geis geis_; bool geis_is_initialized_; long geis_dispatch_loop_timeout_; GeisEventHandler geis_event_handler_; bool geis_event_loop_stop_; EventCallbacks event_callbacks_; }; #endif /* GTEST_GEIS_FIXTURE_H_ */ geis-2.2.17+16.04.20160126/testsuite/geis-util/0000755000015600001650000000000012651717732021042 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/geis-util/Makefile.am0000644000015600001650000000237412651717544023105 0ustar pbuserpbgroup00000000000000# @file testsuite/geis-util/Makefile.am # @brief automake recipe for the GEIS internal utility library test suite # Copyright 2011 Canonical, Ltd. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . if HAVE_CHECK test_targets = check_geis_util else test_targets = endif TESTS = $(test_targets) check_PROGRAMS = $(test_targets) check_geis_util_SOURCES = \ check_geis_bag.c \ check_geis_util.c check_geis_util_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/libs/geis-util \ $(CHECK_CFLAGS) check_geis_util_LDADD = \ $(top_builddir)/libs/geis-util/libgeis-util.la \ $(CHECK_LIBS) \ -lm -lpthread MOSTLYCLEANFILES = \ geis_util.log \ geis_util.xml geis-2.2.17+16.04.20160126/testsuite/geis-util/check_geis_util.c0000644000015600001650000000245212651717544024333 0ustar pbuserpbgroup00000000000000/** * @file check_geis_util.c * @brief Test driver for unit testing of GEIS internal utility library. */ /* * Copyright 2011 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #define LOGFILE_PREFIX "geis_util" extern Suite *make_geis_bag_suite(); int main(int argc CK_ATTRIBUTE_UNUSED, char* argv[] CK_ATTRIBUTE_UNUSED) { int num_failed = 0; Suite *s = suite_create("\"GEIS internal utilities\""); SRunner *sr = srunner_create(s); srunner_add_suite(sr, make_geis_bag_suite()); srunner_set_log(sr, LOGFILE_PREFIX".log"); srunner_set_xml(sr, LOGFILE_PREFIX".xml"); srunner_run_all(sr, CK_NORMAL); num_failed = srunner_ntests_failed(sr); srunner_free(sr); return !(num_failed == 0); } geis-2.2.17+16.04.20160126/testsuite/geis-util/check_geis_bag.c0000644000015600001650000001073312651717544024110 0ustar pbuserpbgroup00000000000000/** * @file check_geis_bag.c * @brief Unit test for geis-util/geis_bag */ /* * Copyright 2011 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "geis_bag.h" /* fixtures */ GeisBag g_bag; struct TestStruct { int ival; char sval[32]; }; /* fixture setup */ static void construct_bag() { g_bag = geis_bag_new(sizeof(struct TestStruct), 1, geis_bag_default_growth_factor); } /* fixture teardown */ static void destroy_bag() { geis_bag_delete(g_bag); } /* verify bag construction/destruction */ START_TEST(construction) { GeisBag bag = geis_bag_new(1, geis_bag_default_init_alloc, geis_bag_default_growth_factor); fail_unless(bag != NULL, "failed to create generic bag"); geis_bag_delete(bag); } END_TEST START_TEST(append) { struct TestStruct datum = { 1, "borf" }; GeisStatus status = geis_bag_append(g_bag, &datum); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); } END_TEST START_TEST(count) { struct TestStruct datum1 = { 1, "borf" }; struct TestStruct datum2 = { 2, "barf" }; GeisSize count = geis_bag_count(g_bag); fail_unless(0 == count, "unexpected count in bag, expected %zu got %zu", 0, count); GeisStatus status = geis_bag_append(g_bag, &datum1); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); count = geis_bag_count(g_bag); fail_unless(1 == count, "unexpected count in bag: expected %zu got %zu", 1, count); status = geis_bag_append(g_bag, &datum2); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); count = geis_bag_count(g_bag); fail_unless(2 == count, "unexpected count in bag: expected %zu got %zu", 2, count); } END_TEST START_TEST(at) { struct TestStruct datum1 = { 1, "borf" }; struct TestStruct datum2 = { 2, "barf" }; GeisStatus status = geis_bag_append(g_bag, &datum1); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); status = geis_bag_append(g_bag, &datum2); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); struct TestStruct *odatum = geis_bag_at(g_bag, 0); fail_unless(datum1.ival == odatum->ival, "inserted and retrived data do not match: expected %d got %d", datum1.ival, odatum->ival); } END_TEST START_TEST(remove) { struct TestStruct datum1 = { 1, "borf" }; struct TestStruct datum2 = { 2, "barf" }; GeisStatus status = geis_bag_append(g_bag, &datum1); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); status = geis_bag_append(g_bag, &datum2); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_append()"); status = geis_bag_remove(g_bag, 0); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected result from geis_bag_remove()"); GeisSize count = geis_bag_count(g_bag); fail_unless(1 == count, "unexpected count in bag, expected %zu got %zu", 1, count); struct TestStruct *odatum = geis_bag_at(g_bag, 0); fail_unless(datum2.ival == odatum->ival, "bad retrived data: expected %d got %d", datum2.ival, odatum->ival); } END_TEST /* boilerplate */ Suite * make_geis_bag_suite() { Suite *s = suite_create("geis_bag"); TCase *create = tcase_create("geis-bag-creation"); tcase_add_test(create, construction); suite_add_tcase(s, create); TCase *usage = tcase_create("geis-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, append); tcase_add_test(usage, count); tcase_add_test(usage, at); tcase_add_test(usage, remove); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/0000755000015600001650000000000012651717732020151 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/geis2/check_version_macro.c0000644000015600001650000000070312651717544024321 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_instance_table module */ #include #include "geis/geis.h" START_TEST(existence) { #ifdef GEIS_VERSION_2_0 fail_unless(0==0); #else fail_unless(0!=0); #endif } END_TEST /* boilerplate */ Suite * make_version_macro_suite() { Suite *s = suite_create("geis_version_macro"); TCase *create = tcase_create("existence"); tcase_add_test(create, existence); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_filter.c0000644000015600001650000000362212651717544022743 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Filter Module. */ #include #include #include "libgeis/geis_test_api.h" #include /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } /* Compile-time test to ensure types are defined */ START_TEST(geis_filter_types) { GeisFilter type CK_ATTRIBUTE_UNUSED; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_filter_functions) { GeisFilter filter1; GeisFilter filter2; GeisStatus status; filter1 = geis_filter_new(g_geis, "filter1"); fail_unless(filter1 != NULL, "filter construct fail"); fail_unless(0 == strcmp(geis_filter_name(filter1), "filter1"), "filter 1 name fail"); status = geis_filter_add_term(filter1, GEIS_FILTER_CLASS, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); filter2 = geis_filter_clone(filter1,"filter2"); fail_unless(filter2 != NULL, "filter clone fail"); fail_unless(0 == strcmp(geis_filter_name(filter2), "filter2"), "filter 2 name fail"); geis_filter_delete(filter1); geis_filter_delete(filter2); } END_TEST /* boilerplate */ Suite * geis2_filter_suite_new() { TCase *filter; TCase *usage; Suite *s = suite_create("geis2_filter"); filter = tcase_create("geis2_filter"); tcase_add_test(filter, geis_filter_types); suite_add_tcase(s, filter); usage = tcase_create("subscription-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, geis_filter_functions); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_accept_ended_grail_gesture.cpp0000644000015600001650000000417512651717544030222 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Regression test for bug https://bugs.launchpad.net/geis/+bug/1015775 Checks that the following situation doesn't lead to a crash: - Geis processed the end event of a grail gesture - Geis has a number of geis events pending delivery to application - Application accepts that ended grail gesture Cause: - While checking the queue of pending events for events that should no longer be delivered due to the gesture acceptance, geis would try to use a struct with information from the ended grail gesture that also no longer exists. */ class AcceptEndedGesture : public Geis2GrailBackendBase { protected: AcceptEndedGesture() : _subscription(nullptr) {} void SendXInput2Events(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventGestureBegin(GeisEvent event); GeisSubscription _subscription; }; void AcceptEndedGesture::SendXInput2Events() { /* args: event type, touch id, X and Y */ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f); xmock_server_time += 5; /* args: touch id */ SendTouchOwnershipEvent(1); SendTouchOwnershipEvent(2); xmock_server_time += 5; SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 20.0f); SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 20.0f); xmock_server_time += 5; SendTouchEvent(XI_TouchEnd, 1, 10.0f, 30.0f); SendTouchEvent(XI_TouchEnd, 2, 20.0f, 30.0f); } void AcceptEndedGesture::OnEventInitComplete(GeisEvent event) { _subscription = CreateFilteredSubscription( "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH); ASSERT_NE(nullptr, _subscription); SendXInput2Events(); } void AcceptEndedGesture::OnEventGestureBegin(GeisEvent event) { AcceptGestureInEvent(event); } TEST_F(AcceptEndedGesture, Test) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); Run(); if (_subscription) geis_subscription_delete(_subscription); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_direct_touch_coords.cpp0000644000015600001650000002143612651717544026734 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Check that when a direct device (e.g. a touchscreen) is being used, the position of a GeisTouch will be in window coordinates instead of input device coordinates. This means that the x an y values of a GeisTouch should come from XIDeviceEvent::event_x and XIDeviceEvent::event_y and not from XIDeviceEvent::valuators.values[0] and XIDeviceEvent::valuators.values[1], like it's the case for indirect devices (such as trackpads). Regression test for https://bugs.launchpad.net/bugs/984069 */ class Geis2GrailBackend : public Geis2GrailBackendBase { protected: Geis2GrailBackend() : _subscription(nullptr) {} void SendXInput2Events(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventGestureBegin(GeisEvent event); GeisSubscription _subscription; }; void Geis2GrailBackend::SendXInput2Events() { XEvent event; XGenericEventCookie *xcookie = 0; XIDeviceEvent *device_event = 0; XITouchOwnershipEvent *ownership_event = 0; int serial = 0; event.type = GenericEvent; device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent)); device_event->serial = serial++; device_event->display = xmock_display; device_event->extension = xmock_xi2_opcode; device_event->evtype = XI_TouchBegin; device_event->time = xmock_server_time; device_event->deviceid = 0; /* The source device that originally generated the event. */ device_event->sourceid = device_event->deviceid; device_event->detail = 0; /* touch id */ device_event->root = DefaultRootWindow(xmock_display); device_event->event = DefaultRootWindow(xmock_display); device_event->child = 0; device_event->root_x = 123.0f; device_event->root_y = 456.0f; device_event->event_x = device_event->root_x; device_event->event_y = device_event->root_y; device_event->valuators.mask_len = 2; /* two bytes */ device_event->valuators.mask = (unsigned char*) malloc(2); XISetMask(device_event->valuators.mask, 0); /* X axis is present */ XISetMask(device_event->valuators.mask, 1); /* Y axis is present */ device_event->valuators.values = (double*) malloc(sizeof(double)*2); device_event->valuators.values[0] = -200.0; device_event->valuators.values[1] = -100.0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchBegin; xcookie->data = device_event; xmock_add_to_event_queue(&event); event.type = GenericEvent; device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent)); device_event->serial = serial++; device_event->display = xmock_display; device_event->extension = xmock_xi2_opcode; device_event->evtype = XI_TouchBegin; device_event->time = xmock_server_time; device_event->deviceid = 0; device_event->sourceid = device_event->deviceid; device_event->detail = 1; /* touch id */ device_event->root = DefaultRootWindow(xmock_display); device_event->event = DefaultRootWindow(xmock_display); device_event->child = 0; device_event->root_x = 222.0f; device_event->root_y = 456.0f; device_event->event_x = device_event->root_x; device_event->event_y = device_event->root_y; device_event->valuators.mask_len = 2; device_event->valuators.mask = (unsigned char*) malloc(2); XISetMask(device_event->valuators.mask, 0); XISetMask(device_event->valuators.mask, 1); device_event->valuators.values = (double*) malloc(sizeof(double)*2); device_event->valuators.values[0] = -150.0; device_event->valuators.values[1] = -100.0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchBegin; xcookie->data = device_event; xmock_add_to_event_queue(&event); xmock_server_time += 5; event.type = GenericEvent; ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent)); ownership_event->type = GenericEvent; ownership_event->serial = serial++; ownership_event->display = xmock_display; ownership_event->extension = xmock_xi2_opcode; ownership_event->evtype = XI_TouchOwnership; ownership_event->time = xmock_server_time; ownership_event->deviceid = 0; ownership_event->sourceid = ownership_event->deviceid; ownership_event->touchid = 0; ownership_event->root = DefaultRootWindow(xmock_display); ownership_event->event = DefaultRootWindow(xmock_display); ownership_event->child = 0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchOwnership; xcookie->data = ownership_event; xmock_add_to_event_queue(&event); event.type = GenericEvent; ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent)); ownership_event->type = GenericEvent; ownership_event->serial = serial++; ownership_event->display = xmock_display; ownership_event->extension = xmock_xi2_opcode; ownership_event->evtype = XI_TouchOwnership; ownership_event->time = xmock_server_time; ownership_event->deviceid = 0; ownership_event->sourceid = ownership_event->deviceid; ownership_event->touchid = 1; ownership_event->root = DefaultRootWindow(xmock_display); ownership_event->event = DefaultRootWindow(xmock_display); ownership_event->child = 0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchOwnership; xcookie->data = ownership_event; xmock_add_to_event_queue(&event); event.type = GenericEvent; device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent)); device_event->serial = serial++; device_event->display = xmock_display; device_event->extension = xmock_xi2_opcode; device_event->evtype = XI_TouchUpdate; device_event->time = xmock_server_time; device_event->deviceid = 0; device_event->sourceid = device_event->deviceid; device_event->detail = 0; device_event->root = DefaultRootWindow(xmock_display); device_event->event = DefaultRootWindow(xmock_display); device_event->child = 0; device_event->root_x = 123.0f; device_event->root_y = 466.0f; device_event->event_x = device_event->root_x; device_event->event_y = device_event->root_y; device_event->valuators.mask_len = 2; /* two bytes */ device_event->valuators.mask = (unsigned char*) malloc(2); XISetMask(device_event->valuators.mask, 0); XISetMask(device_event->valuators.mask, 1); device_event->valuators.values = (double*) malloc(sizeof(double)*2); device_event->valuators.values[0] = -200.0; device_event->valuators.values[1] = -90.0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchUpdate; xcookie->data = device_event; xmock_add_to_event_queue(&event); event.type = GenericEvent; device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent)); device_event->serial = serial++; device_event->display = xmock_display; device_event->extension = xmock_xi2_opcode; device_event->evtype = XI_TouchUpdate; device_event->time = xmock_server_time; device_event->deviceid = 0; device_event->sourceid = device_event->deviceid; device_event->detail = 1; /* touch id */ device_event->root = DefaultRootWindow(xmock_display); device_event->event = DefaultRootWindow(xmock_display); device_event->child = 0; device_event->root_x = 222.0f; device_event->root_y = 466.0f; device_event->event_x = device_event->root_x; device_event->event_y = device_event->root_y; device_event->valuators.mask_len = 2; device_event->valuators.mask = (unsigned char*) malloc(2); XISetMask(device_event->valuators.mask, 0); XISetMask(device_event->valuators.mask, 1); device_event->valuators.values = (double*) malloc(sizeof(double)*2); device_event->valuators.values[0] = -150.0; device_event->valuators.values[1] = -90.0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchUpdate; xcookie->data = device_event; xmock_add_to_event_queue(&event); } void Geis2GrailBackend::OnEventInitComplete(GeisEvent event) { _subscription = CreateFilteredSubscription( "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH); ASSERT_NE(nullptr, _subscription); SendXInput2Events(); } void Geis2GrailBackend::OnEventGestureBegin(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); GeisTouchSet geis_touch_set = (GeisTouchSet) geis_attr_value_to_pointer(attr); TouchSet touch_set(geis_touch_set); /* check that there are two touch points and that they are in window coordinates (instead of input device coordinates) */ ASSERT_EQ(2, touch_set.size()); ASSERT_TRUE(touch_set.contains(123.0f, 456.0f)); ASSERT_TRUE(touch_set.contains(222.0f, 456.0f)); } TEST_F(Geis2GrailBackend, DirectDeviceTouchCoords) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, nullptr); ASSERT_NE(nullptr, _geis); Run(); if (_subscription) geis_subscription_delete(_subscription); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_general_types.c0000644000015600001650000000135412651717544024317 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_instance_table module */ #include #include /* compile-time test to ensure required types are defined */ START_TEST(general_types) { GeisBoolean geis_boolean CK_ATTRIBUTE_UNUSED; GeisInteger geis_integer CK_ATTRIBUTE_UNUSED; GeisFloat geis_float CK_ATTRIBUTE_UNUSED; GeisPointer geis_pointer CK_ATTRIBUTE_UNUSED; GeisSize geis_size CK_ATTRIBUTE_UNUSED; GeisString geis_string CK_ATTRIBUTE_UNUSED; } END_TEST /* boilerplate */ Suite * geis2_general_types_suite_new() { Suite *s = suite_create("geis2_general_types"); TCase *create; create = tcase_create("general_types"); tcase_add_test(create, general_types); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_subscription.c0000644000015600001650000001230012651717544024173 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 subsciption module */ #include #include #include "libgeis/geis_test_api.h" #include /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } /* compile-time test to ensure required types are defined */ START_TEST(subscription_constants) { GeisSubscriptionFlags f; f = GEIS_SUBSCRIPTION_NONE | GEIS_SUBSCRIPTION_GRAB | GEIS_SUBSCRIPTION_CONT; } END_TEST START_TEST(construction) { GeisSubscription sub = geis_subscription_new(g_geis, "name", GEIS_SUBSCRIPTION_NONE); fail_unless(sub != NULL, "failed to create subscription"); fail_unless(0 == strcmp(geis_subscription_name(sub), "name"), "unexpected subscription name returned"); fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_activate(sub), "unable to activate subscription"); fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_deactivate(sub), "unable to deactivate subscription"); geis_subscription_delete(sub); } END_TEST START_TEST(filter) { GeisFilter filter = geis_filter_new(g_geis, "filter"); GeisSubscription sub = geis_subscription_new(g_geis, "name", GEIS_SUBSCRIPTION_NONE); fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_add_filter(sub, filter), "filter add fail"); filter = geis_subscription_filter_by_name(sub, "bogus"); fail_unless(filter == NULL, "bogus filter retrieval fail"); filter = geis_subscription_filter_by_name(sub, "filter"); fail_unless(filter != NULL, "filter retrieval fail"); fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_remove_filter(sub, filter), "filter remove fail"); } END_TEST START_TEST(device_filter) { GeisStatus status; GeisEvent event; GeisSubscription sub = geis_subscription_new(g_geis, "devices", GEIS_SUBSCRIPTION_NONE); while (geis_dispatch_events(g_geis) == GEIS_STATUS_CONTINUE) ; status = geis_next_event(g_geis, &event); while (status == GEIS_STATUS_SUCCESS || status == GEIS_STATUS_CONTINUE) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { GeisAttr attr; GeisDevice device; GeisFilter filter; GeisStatus fs; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); fail_if (!attr, "geis-device attr not found in device event"); device = geis_attr_value_to_pointer(attr); fail_if (!device, "geis device not found in device event"); filter = geis_filter_new(g_geis, "device filter"); fail_if(!filter, "can not create filter"); fs = geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_FILTER_OP_NE, geis_device_name(device), NULL); fail_if(fs != GEIS_STATUS_SUCCESS, "can not add device to filter"); fs = geis_subscription_add_filter(sub, filter); fail_if(fs != GEIS_STATUS_SUCCESS, "can not subscribe filter"); } else if (geis_event_type(event) == GEIS_EVENT_CLASS_AVAILABLE) { GeisAttr attr; GeisGestureClass gesture_class; GeisFilter filter; GeisStatus fs; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); fail_if (!attr, "attr not found in class event"); gesture_class = geis_attr_value_to_pointer(attr); fail_if (!gesture_class, "geis class not found in class event"); filter = geis_filter_new(g_geis, "class filter"); fail_if(!filter, "can not create filter"); fs = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_NE, geis_gesture_class_name(gesture_class), NULL); fail_if(fs != GEIS_STATUS_SUCCESS, "can not add class to filter"); fs = geis_subscription_add_filter(sub, filter); fail_if(fs != GEIS_STATUS_SUCCESS, "can not subscribe filter"); } geis_event_delete(event); if (status == GEIS_STATUS_CONTINUE) { status = geis_next_event(g_geis, &event); } else { break; } } fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_activate(sub), "unable to activate subscription"); } END_TEST /* boilerplate */ Suite * geis2_subscription_suite_new() { TCase *create; TCase *usage; Suite *s = suite_create("geis2_subscriptions"); create = tcase_create("subscription-constants"); tcase_add_test(create, subscription_constants); suite_add_tcase(s, create); usage = tcase_create("subscription-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, construction); tcase_add_test(usage, filter); tcase_add_test(usage, device_filter); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_outdated_events.cpp0000644000015600001650000001107012651717544026075 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Checks that when a gesture gets accepted, all the gesture events from overlapping gestures are removed from the queue. That ensures the client won't get events about gestures that no longer exist in the backend (GRAIL), i.e., it won't get outdated, invalid, events. Regression test for https://bugs.launchpad.net/geis/+bug/1001365 Steps: - Disable atomic gestures rules. - Subscribe for 2-touches Touch gestures. - Move 4 simultaneous touch points on a touchscreen. (feed all XInput2 events in a single burst, so that the corresponding geis events are made and queued before processing by the geis client) - Accept two non-overlapping gestures already on Gesture Begin - Check that you get gesture updates only for the two accepted gestures. */ class OutdatedEventsOverlappingGestures : public Geis2GrailBackendBase { protected: OutdatedEventsOverlappingGestures() : _subscription(nullptr) {} void SendXInput2Events(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventGestureBegin(GeisEvent event); virtual void OnEventGestureUpdate(GeisEvent event); int GetGestureIdInEvent(GeisEvent event); GeisSubscription _subscription; std::set _accepted_gestures; }; void OutdatedEventsOverlappingGestures::SendXInput2Events() { /* event type, touch id, X and Y */ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 3, 30.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 4, 40.0f, 10.0f); xmock_server_time += 5; /* touch id */ SendTouchOwnershipEvent(1); SendTouchOwnershipEvent(2); SendTouchOwnershipEvent(3); SendTouchOwnershipEvent(4); xmock_server_time += 5; SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 20.0f); SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 20.0f); SendTouchEvent(XI_TouchUpdate, 3, 30.0f, 20.0f); SendTouchEvent(XI_TouchUpdate, 4, 40.0f, 20.0f); } void OutdatedEventsOverlappingGestures::OnEventInitComplete(GeisEvent event) { _subscription = CreateFilteredSubscription( "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH); ASSERT_NE(nullptr, _subscription); SendXInput2Events(); } int OutdatedEventsOverlappingGestures::GetGestureIdInEvent(GeisEvent event) { /* We expect only one group with one gesture frame. Multiple groups with several gesture frames is just not supported or used. That is, one GeisEvent is sent for each possible gesture instead of a single GeisEvent with all possible gestures (arranged in groups). */ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); GeisGroupSet group_set = static_cast(geis_attr_value_to_pointer(attr)); EXPECT_EQ(1, geis_groupset_group_count(group_set)); GeisGroup group = geis_groupset_group(group_set, 0); EXPECT_EQ(1, geis_group_frame_count(group)); GeisFrame frame = geis_group_frame(group, 0); return geis_frame_id(frame); } void OutdatedEventsOverlappingGestures::OnEventGestureBegin(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); TouchSet touch_set(static_cast(geis_attr_value_to_pointer(attr))); ASSERT_EQ(2, touch_set.size()); /* I want to accept pairs from XI touch ids (1,2) and (3,4) */ if ((touch_set.contains(10.0f, 10.0f) && touch_set.contains(20.0f, 10.0f)) || (touch_set.contains(30.0f, 10.0f) && touch_set.contains(40.0f, 10.0f))) { AcceptGestureInEvent(event); _accepted_gestures.insert(GetGestureIdInEvent(event)); } else { RejectGestureInEvent(event); } } void OutdatedEventsOverlappingGestures::OnEventGestureUpdate(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); TouchSet touch_set(static_cast(geis_attr_value_to_pointer(attr))); ASSERT_EQ(2, touch_set.size()); /* We expect updates only from the gestures that we have previously accepted */ if (_accepted_gestures.find(GetGestureIdInEvent(event)) == _accepted_gestures.end()) { /* It's neither (1,2) nor (3,4). */ FAIL() << "Got an update from an unexpected touch pair"; } } TEST_F(OutdatedEventsOverlappingGestures, Test) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); Run(); ASSERT_EQ(2, _accepted_gestures.size()); if (_subscription) geis_subscription_delete(_subscription); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_event.c0000644000015600001650000000240512651717544022575 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Event Module. */ #include #include /* Compile-time test to ensure types are defined*/ START_TEST(geis_event_types) { GeisEventType type; type = GEIS_EVENT_DEVICE_AVAILABLE; type = GEIS_EVENT_DEVICE_UNAVAILABLE; type = GEIS_EVENT_CLASS_AVAILABLE; type = GEIS_EVENT_CLASS_CHANGED; type = GEIS_EVENT_CLASS_UNAVAILABLE; type = GEIS_EVENT_GESTURE_BEGIN; type = GEIS_EVENT_GESTURE_UPDATE; type = GEIS_EVENT_GESTURE_END; type = GEIS_EVENT_INIT_COMPLETE; type = GEIS_EVENT_USER_DEFINED; type = GEIS_EVENT_ERROR; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_event_functions) { GeisEvent event = NULL; GeisEventType t CK_ATTRIBUTE_UNUSED; GeisSize s CK_ATTRIBUTE_UNUSED; GeisAttr a CK_ATTRIBUTE_UNUSED; GeisAttr n CK_ATTRIBUTE_UNUSED; geis_event_delete(event); t = geis_event_type(event); s = geis_event_attr_count(event); a = geis_event_attr(event, 0); n = geis_event_attr_by_name(event, "none"); } END_TEST /* boilerplate */ Suite * geis2_event_suite_new() { Suite *s = suite_create("geis2_event"); TCase *event = tcase_create("geis2_event"); tcase_add_test(event, geis_event_types); suite_add_tcase(s, event); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_class.c0000644000015600001650000000531112651717544022560 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Input Gesture Class Module. */ #include #include #include "libgeis/geis_test_api.h" /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } /* Compile-time test to ensure types are defined */ START_TEST(geis_gesture_class_types) { GeisGestureClass gesture_class CK_ATTRIBUTE_UNUSED; } END_TEST /* Compile-time test to ensure constants are defined */ START_TEST(geis_gesture_class_constants) { GeisString attr_name; attr_name = GEIS_CLASS_ATTRIBUTE_NAME; attr_name = GEIS_CLASS_ATTRIBUTE_ID; attr_name = GEIS_EVENT_ATTRIBUTE_CLASS; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_gesture_class_functions) { Geis geis = NULL; GeisEventCallback callback = 0; GeisGestureClass gesture_class = NULL; GeisString n CK_ATTRIBUTE_UNUSED; GeisInteger i CK_ATTRIBUTE_UNUSED; GeisSize s CK_ATTRIBUTE_UNUSED; GeisAttr a CK_ATTRIBUTE_UNUSED; geis_register_class_callback(geis, callback, NULL); geis_gesture_class_ref(gesture_class); geis_gesture_class_unref(gesture_class); n = geis_gesture_class_name(gesture_class); i = geis_gesture_class_id(gesture_class); s = geis_gesture_class_attr_count(gesture_class); a = geis_gesture_class_attr(gesture_class, 0); } END_TEST START_TEST(receive_events) { GeisStatus status; GeisEvent event_out; int class_event_count = 0; status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); status = geis_next_event(g_geis, &event_out); while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { if (geis_event_type(event_out) == GEIS_EVENT_CLASS_AVAILABLE) { ++class_event_count; } geis_event_delete(event_out); status = geis_next_event(g_geis, &event_out); } fail_unless(class_event_count > 0, "no class events received"); } END_TEST /* boilerplate */ Suite * geis2_gesture_class_suite_new() { TCase *gesture_class; TCase *usage; Suite *s = suite_create("geis2_gesture_class"); gesture_class = tcase_create("gesture-class-api"); tcase_add_test(gesture_class, geis_gesture_class_types); tcase_add_test(gesture_class, geis_gesture_class_constants); suite_add_tcase(s, gesture_class); usage = tcase_create("gesture-class-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, receive_events); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_attrs.cpp0000644000015600001650000002741512651717544023232 0ustar pbuserpbgroup00000000000000/** * Gtest test suite for GEIS v2 attributes. * * Copyright 2012 Canonical Ltd. */ #include #include "geis/geis.h" #include "gtest_evemu_device.h" #include "gtest_geis_fixture.h" #include namespace { static const std::string TEST_DEVICE_PROP_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/device.prop"); /** * A helper class to use RAII with geis objects. * * This is a separate fixture from the gtest fixture because it is parameterized * for each test. */ class TestSubscription { public: TestSubscription(Geis geis, GeisString gesture_class) { subscription_ = geis_subscription_new(geis, "attr tests", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(subscription_ != NULL) << "can not create subscription"; filter_ = geis_filter_new(geis, "attr tests"); EXPECT_TRUE(filter_ != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter_, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, gesture_class, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter"; fs = geis_subscription_add_filter(subscription_, filter_); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter"; EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(subscription_)) << "can not activate subscription"; } ~TestSubscription() { } private: GeisSubscription subscription_; GeisFilter filter_; }; /** * Fixture for testing expected attributes. This has to be a separate class * because of the way Java reflection is used in jUnit. */ class GeisAttributeTests : public GTestGeisFixture { public: GeisAttributeTests() : evemu_device_(TEST_DEVICE_PROP_FILE), device_is_ready_(false), recording_was_sent_(false) { } void set_recording_file_name(const std::string& file_name) { recording_file_name_ = file_name; } void pre_event_handler(GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); EXPECT_TRUE(attr != NULL); GeisDevice device = (GeisDevice)geis_attr_value_to_pointer(attr); if (evemu_device_.name() == geis_device_name(device)) { device_is_ready_ = true; } } } void post_event_handler(GeisEvent event) { GTestGeisFixture::post_event_handler(event); if (geis_is_initialized() && device_is_ready_ && !recording_was_sent_) { evemu_device_.play(recording_file_name_); recording_was_sent_ = true; } } protected: Testsuite::EvemuDevice evemu_device_; bool device_is_ready_; std::string recording_file_name_; bool recording_was_sent_; }; /* * Regression test for lp:394398: rotation angle is swapped with rotation angle * delta. * * The captive "rotate90" events whould produce a rotation gesture with a final * rotation angle of somewhere around -pi/2 radians. */ TEST_F(GeisAttributeTests, rotate90) { bool found_angle = false; TestSubscription dragSubscription(geis_, GEIS_GESTURE_ROTATE); set_recording_file_name(TEST_ROOT_DIR "recordings/touchscreen_a/rotate90.record"); set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_GESTURE_END) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; GeisAttr attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_ANGLE); EXPECT_TRUE(attr != NULL) << "angle attribute not found in frame"; GeisFloat angle = geis_attr_value_to_float(attr); EXPECT_NEAR(angle, -1.6f, 0.4f); found_angle = GEIS_TRUE; return; } } } }); geis_dispatch_loop(); EXPECT_TRUE(found_angle); } /* * Regression test for lp:967267: Position delta attributes incorrect when touch * count changes. * * Some gestures continue when the number of touches changes. When this happens, * much of the gesture state is reset. This includes the original center and * cumulative transformation matrix. * * This test ensures the position delta attributes stay in a reasonable range * after a two to one touch drag transition. */ TEST_F(GeisAttributeTests, TouchChangePositionDelta) { bool found_delta = false; TestSubscription dragSubscription(geis_, GEIS_GESTURE_DRAG); set_recording_file_name(TEST_ROOT_DIR "recordings/touchscreen_a/drag_2_to_1.record"); set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: case GEIS_EVENT_GESTURE_END: { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; GeisAttr attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_DELTA_X); EXPECT_TRUE(attr != NULL) << "angle attribute not found in frame"; GeisFloat delta = geis_attr_value_to_float(attr); /* The drag is nearly vertical. All X deltas should be within 0.2% * of the screen width. On failure, the delta can vary up to 20% * of the screen width. */ int width = WidthOfScreen(DefaultScreenOfDisplay(Display())); EXPECT_NEAR(delta, 0, 0.01 * width); found_delta = GEIS_TRUE; geis_dispatch_stop(true); } } break; } } }); geis_dispatch_loop(); EXPECT_TRUE(found_delta); } /* * Regression test for lp:985916: Position deltas are incorrect when synchronous * events are not enabled. * * The position deltas should add up to the entire position change from gesture * begin to end. * * This test ensures the X position delta attributes add up to the difference * between the inital X position and the final X position. */ TEST_F(GeisAttributeTests, PositionDelta) { set_recording_file_name(TEST_ROOT_DIR "recordings/touchscreen_a/drag_2.record"); TestSubscription dragSubscription(geis_, GEIS_GESTURE_DRAG); GeisFloat initial_x; GeisFloat cumulative_delta_x = 0; set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: case GEIS_EVENT_GESTURE_END: { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; GeisAttr attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_DELTA_X); EXPECT_TRUE(attr != NULL) << "delta X attribute not found in frame"; cumulative_delta_x += geis_attr_value_to_float(attr); if (geis_event_type(event) == GEIS_EVENT_GESTURE_BEGIN) { attr = geis_frame_attr_by_name( frame, GEIS_GESTURE_ATTRIBUTE_POSITION_X); initial_x = geis_attr_value_to_float(attr); } if (geis_event_type(event) == GEIS_EVENT_GESTURE_END) { attr = geis_frame_attr_by_name( frame, GEIS_GESTURE_ATTRIBUTE_POSITION_X); GeisFloat x = geis_attr_value_to_float(attr); EXPECT_FLOAT_EQ(x - initial_x, cumulative_delta_x); } } } break; } } }); geis_dispatch_loop(); } /* * Regression test for lp:986215: Radius delta values should be a ratio instead * of a difference. * * This test ensures the radius delta attributes multiplied together equal the * final radius value. */ TEST_F(GeisAttributeTests, RadiusDelta) { TestSubscription dragSubscription(geis_, GEIS_GESTURE_PINCH); set_recording_file_name(TEST_ROOT_DIR "recordings/touchscreen_a/pinch_2.record"); GeisFloat cumulative_delta_radius = 1; set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: case GEIS_EVENT_GESTURE_END: GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; GeisAttr attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA); EXPECT_TRUE(attr != NULL) << "radius attribute not found in frame"; cumulative_delta_radius *= geis_attr_value_to_float(attr); if (geis_event_type(event) == GEIS_EVENT_GESTURE_END) { attr = geis_frame_attr_by_name( frame, GEIS_GESTURE_ATTRIBUTE_RADIUS); GeisFloat radius = geis_attr_value_to_float(attr); EXPECT_FLOAT_EQ(radius, cumulative_delta_radius); } } } break; } }); geis_dispatch_loop(); } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/geis2/Makefile.am0000644000015600001650000000537212651717544022215 0ustar pbuserpbgroup00000000000000# # @file testsuite/geis2/Makefile.am # @brief automake recipe for the geis v2.0 testsuite testing directory # test_targets = ##### check_geis2_api - Tests using Check C testing framework ##### if HAVE_CHECK test_targets += check_geis2_api endif check_geis2_api_SOURCES = \ check_attr.c \ check_class.c \ check_config.c \ check_device.c \ check_error_codes.c \ check_event.c \ check_filter.c \ check_frame.c \ check_geis_new.c \ check_general_types.c \ check_region.c \ check_subscription.c \ check_version_macro.c \ check_geis2_api.c check_geis2_api_CPPFLAGS = \ -Wno-unused -Wno-unused-function -Wno-unused-but-set-variable \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ $(CHECK_CFLAGS) check_geis2_api_LDADD = \ $(top_builddir)/libgeis/libgeis.la \ $(CHECK_LIBS) \ -lpthread #### gtest_geis2_grail_backend - Test for the GRAIL backend of Geis v2 API ##### #### using gtest ##### if HAVE_GTEST test_targets += gtest_geis2_grail_backend endif gtest_geis2_grail_backend_SOURCES = \ gtest_grail_backend.h gtest_grail_backend.cpp \ gtest_gbe_accept_ended_grail_gesture.cpp \ gtest_gbe_configure_new_devices.cpp \ gtest_gbe_deactivate_sub.cpp \ gtest_gbe_direct_touch_coords.cpp \ gtest_gbe_construction_finished.cpp \ gtest_gbe_outdated_events.cpp \ gtest_gbe_null_filter.cpp gtest_geis2_grail_backend_CPPFLAGS = \ --std=c++0x \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/testsuite/gtest \ -I$(top_srcdir)/testsuite/x11_mocks \ -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\" \ $(GTEST_CFLAGS) gtest_geis2_grail_backend_LDFLAGS = \ -export-dynamic gtest_geis2_grail_backend_LDADD = \ $(top_builddir)/testsuite/gtest/libgtest_geis.a \ $(top_builddir)/testsuite/x11_mocks/libx11_mocks.a \ $(top_builddir)/libgeis/libgeis.la \ $(GTEST_LIBS) #### gtest_geis2_api - Integration tests using xorg-gest and evemu ##### if ENABLE_INTEGRATION_TESTS test_targets += gtest_geis2_api endif gtest_geis2_api_SOURCES = \ gtest_attrs.cpp \ gtest_config.cpp \ gtest_devices.cpp \ gtest_subscriptions.cpp nodist_gtest_geis2_api_SOURCES = \ $(XORG_GTEST_SOURCE)/src/xorg-gtest_main.cpp gtest_geis2_api_CPPFLAGS = \ --std=c++0x \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/testsuite/gtest \ -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\" \ $(GTEST_CFLAGS) \ $(EVEMU_CFLAGS) \ $(XORG_GTEST_CPPFLAGS) gtest_geis2_api_LDADD = \ $(top_builddir)/testsuite/gtest/libgtest_geis.a \ $(top_builddir)/libgeis/libgeis.la \ $(XORG_GTEST_LIBS) \ $(EVEMU_LIBS) \ $(XI2_LIBS) MOSTLYCLEANFILES = \ geis2_api.log \ geis2_api.xml TESTS = $(test_targets) check_PROGRAMS = $(test_targets) geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_deactivate_sub.cpp0000644000015600001650000000343712651717544025672 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Checks that a subscription deactivation completes successfully */ class SubscriptionDeactivation : public Geis2GrailBackendBase { protected: SubscriptionDeactivation() : _subscription(nullptr) {} void SendXInput2Events(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventGestureEnd(GeisEvent event); GeisSubscription _subscription; }; void SubscriptionDeactivation::SendXInput2Events() { /* event type, touch id, X and Y */ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f); xmock_server_time += 5; /* touch id */ SendTouchOwnershipEvent(1); SendTouchOwnershipEvent(2); xmock_server_time += 5; SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 20.0f); SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 20.0f); xmock_server_time += 5; SendTouchEvent(XI_TouchEnd, 1, 10.0f, 30.0f); SendTouchEvent(XI_TouchEnd, 2, 20.0f, 30.0f); } void SubscriptionDeactivation::OnEventInitComplete(GeisEvent event) { _subscription = CreateFilteredSubscription( "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH); ASSERT_NE(nullptr, _subscription); SendXInput2Events(); } void SubscriptionDeactivation::OnEventGestureEnd(GeisEvent event) { AcceptGestureInEvent(event); GeisStatus status = geis_subscription_deactivate(_subscription); // The main point of this test. ASSERT_EQ(GEIS_STATUS_SUCCESS, status); } TEST_F(SubscriptionDeactivation, Test) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); Run(); if (_subscription) geis_subscription_delete(_subscription); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_attr.c0000644000015600001650000000236012651717544022426 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Attr Module. */ #include #include /* Compile-time test to ensure types are defined*/ START_TEST(geis_attr_types) { GeisAttrType type; type = GEIS_ATTR_TYPE_BOOLEAN; type = GEIS_ATTR_TYPE_INTEGER; type = GEIS_ATTR_TYPE_FLOAT; type = GEIS_ATTR_TYPE_POINTER; type = GEIS_ATTR_TYPE_STRING; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_attr_functions) { GeisAttr attr = 0; GeisBoolean n CK_ATTRIBUTE_UNUSED; GeisFloat f CK_ATTRIBUTE_UNUSED; GeisInteger i CK_ATTRIBUTE_UNUSED; GeisPointer p CK_ATTRIBUTE_UNUSED; GeisString s CK_ATTRIBUTE_UNUSED; GeisString name CK_ATTRIBUTE_UNUSED; GeisAttrType type CK_ATTRIBUTE_UNUSED; name = geis_attr_name(attr); type = geis_attr_type(attr); n = geis_attr_value_to_boolean(attr); f = geis_attr_value_to_float(attr); i = geis_attr_value_to_integer(attr); p = geis_attr_value_to_pointer(attr); s = geis_attr_value_to_string(attr); } END_TEST /* boilerplate */ Suite * geis2_attr_suite_new() { Suite *s = suite_create("geis2_attr"); TCase *init_args = tcase_create("geis2_attr"); tcase_add_test(init_args, geis_attr_types); suite_add_tcase(s, init_args); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_subscriptions.cpp0000644000015600001650000003527312651717544025005 0ustar pbuserpbgroup00000000000000/** * GTest-based test suite for GEIS subscription actions. * * Copyright 2012 Canonical Ltd. */ #include "gtest_evemu_device.h" #include "gtest_geis_fixture.h" #include static const std::string TEST_DEVICE_PROP_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/device.prop"); static const std::string TEST_DEVICE_EVENTS_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/rotate90.record"); /** * Tests need to make sure at least one multi-touch device is available. */ class GeisSubscriptionTests : public GTestGeisFixture { public: GeisSubscriptionTests() : evemu_device_(TEST_DEVICE_PROP_FILE), device_is_ready_(false), recording_was_sent_(false), rotate_class_(nullptr) { } void pre_event_handler(GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); EXPECT_TRUE(attr != NULL); GeisDevice device = (GeisDevice)geis_attr_value_to_pointer(attr); if (evemu_device_.name() == geis_device_name(device)) { device_is_ready_ = true; } } else if (geis_event_type(event) == GEIS_EVENT_CLASS_AVAILABLE) { GeisGestureClass gesture_class = nullptr; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); EXPECT_TRUE(attr != NULL) << "event is missing class attr"; gesture_class = (GeisGestureClass)geis_attr_value_to_pointer(attr); for (GeisSize i = 0; i < geis_gesture_class_attr_count(gesture_class); ++i) { GeisAttr attr2 = geis_gesture_class_attr(gesture_class, i); if (0 == strcmp(geis_attr_name(attr2), GEIS_CLASS_ATTRIBUTE_NAME)) { if (0 == strcmp(geis_attr_value_to_string(attr2), GEIS_GESTURE_ROTATE)) { rotate_class_ = gesture_class; } } } } } void post_event_handler(GeisEvent event) { GTestGeisFixture::post_event_handler(event); if (geis_is_initialized() && device_is_ready_ && !recording_was_sent_) { evemu_device_.play(TEST_DEVICE_EVENTS_FILE); recording_was_sent_ = true; } } protected: Testsuite::EvemuDevice evemu_device_; bool device_is_ready_; bool recording_was_sent_; GeisGestureClass rotate_class_; }; /** * Regression test for lp:937021: Geis subscription touch grabs need to check * for failure. * * This test creates two subscriptions, both attached to the root window but * each on a different X client. Since multiple subscriptions for the same * window but a different client are expected to fail using the XI2.2-based * grail back end, activating the second subscription is extected to resut in * a failure. * * This behaviour is very dependent on the particular back end used and internal * implementattion details of that back end. It is not a unit test or a * reliable group or system test. */ TEST_F(GeisSubscriptionTests, duplicate_window_subscription) { Geis geis2 = geis_new(GEIS_INIT_SYNCHRONOUS_START, GEIS_INIT_NO_ATOMIC_GESTURES, NULL); EXPECT_TRUE(geis2 != NULL) << "can not create second geis instance"; GeisInteger fd; geis_get_configuration(geis2, GEIS_CONFIGURATION_FD, &fd); GeisSubscription sub1 = geis_subscription_new(geis_, "subscription 1", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub1 != NULL) << "can not create first subscription"; GeisSubscription sub2 = geis_subscription_new(geis2, "subscription 2", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub1 != NULL) << "can not create second subscription"; GeisFilter filter1 = geis_filter_new(geis_, "root window 1"); EXPECT_TRUE(filter1 != NULL) << "can not create filter 1"; GeisStatus fs = geis_filter_add_term(filter1, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 1"; fs = geis_subscription_add_filter(sub1, filter1); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 1"; GeisFilter filter2 = geis_filter_new(geis2, "root window 2"); EXPECT_TRUE(filter2 != NULL) << "can not create filter 2"; fs = geis_filter_add_term(filter2, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 2"; fs = geis_subscription_add_filter(sub2, filter2); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 2"; bool geis1_device_is_available = false; bool geis2_device_is_available = false; /* * Special handling for the second geis instance to make sure the device has * appeared before the subscription is activated, otherwise we might get a * false positive waiting for it to get asynchronously activated. */ add_event_callback(fd, [&]() { geis_dispatch_events(geis2); GeisEvent event; for (GeisStatus estatus = geis_next_event(geis2, &event); estatus == GEIS_STATUS_CONTINUE || estatus == GEIS_STATUS_SUCCESS; estatus = geis_next_event(geis2, &event)) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { geis2_device_is_available = true; } } }); /* * The actual test can sometimes fail if the captive device has not yet been * recognized by the GEIS instances because activating subscriptions require * grabbing the device on all matching (window, device) tuples. */ set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { geis1_device_is_available = true; } if (geis1_device_is_available && geis2_device_is_available) { EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub1)) << "can not activate subscription 1"; EXPECT_NE(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub2)) << "mistakenly activated subscription 2"; geis_dispatch_stop(true); } }); geis_dispatch_loop(); geis_subscription_delete(sub2); geis_subscription_delete(sub1); geis_delete(geis2); } /** * Regression test 1 for lp:934207: gesture rejection */ TEST_F(GeisSubscriptionTests, reject_gesture) { GeisGestureId rejected_gesture_id = 0; bool gesture_rejected = false; GeisSubscription sub = geis_subscription_new(geis_, "subscription", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create subscription"; GeisFilter filter = geis_filter_new(geis_, "root window"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter"; fs = geis_subscription_add_filter(sub, filter); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter"; EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) << "can not activate subscription"; set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; if (geis_frame_is_class(frame, rotate_class_)) { if (!gesture_rejected) { rejected_gesture_id = geis_frame_id(frame); GeisStatus gs = geis_gesture_reject(geis_, group, rejected_gesture_id); EXPECT_EQ(gs, GEIS_STATUS_SUCCESS) << "rejection failed"; gesture_rejected = true; } else { EXPECT_NE(geis_frame_id(frame), rejected_gesture_id) << "gesture events after gesture rejected"; geis_dispatch_stop(true); } } } } break; } case GEIS_EVENT_GESTURE_END: geis_dispatch_stop(true); break; default: break; } }); geis_dispatch_loop(); EXPECT_EQ(gesture_rejected, true) << "gesture was never rejected"; geis_subscription_delete(sub); } /** * Regression test 2 for lp:934207: gesture acceptance */ TEST_F(GeisSubscriptionTests, accept_gesture) { bool gesture_accepted = false; bool gesture_ended = false; GeisSubscription sub = geis_subscription_new(geis_, "subscription", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create subscription"; GeisFilter filter = geis_filter_new(geis_, "root window"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter"; fs = geis_subscription_add_filter(sub, filter); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter"; EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) << "can not activate subscription"; set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; if (!gesture_accepted && geis_frame_is_class(frame, rotate_class_)) { GeisStatus gs = geis_gesture_accept(geis_, group, geis_frame_id(frame)); EXPECT_EQ(gs, GEIS_STATUS_SUCCESS) << "aceptance failed"; gesture_accepted = true; } } } break; } case GEIS_EVENT_GESTURE_END: gesture_ended = true; break; default: break; } }); geis_dispatch_loop(); EXPECT_EQ(gesture_accepted, true) << "gesture was never accepted"; EXPECT_EQ(gesture_ended, true) << "gesture did not end"; geis_subscription_delete(sub); } /** * Regression test for lp:968736: Windows are sometimes not ungrabbed on * subscription deactivation. * * When a subscription is deactivated, the touch grab on the window must be * ungrabbed. This test deactivates a subscription and then tries to grab the * window through a different X connection. */ TEST_F(GeisSubscriptionTests, WindowUngrab) { GeisSubscription sub = geis_subscription_new(geis_, "subscription", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create first subscription"; GeisFilter filter = geis_filter_new(geis_, "root window"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter"; fs = geis_subscription_add_filter(sub, filter); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter"; EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) << "can not activate subscription"; geis_subscription_deactivate(sub); ::Display* display2 = XOpenDisplay(NULL); XIEventMask mask; mask.deviceid = XIAllMasterDevices; mask.mask_len = XIMaskLen(XI_LASTEVENT); mask.mask = reinterpret_cast(calloc(mask.mask_len, sizeof(char))); XISetMask(mask.mask, XI_TouchBegin); XISetMask(mask.mask, XI_TouchUpdate); XISetMask(mask.mask, XI_TouchEnd); XISetMask(mask.mask, XI_TouchOwnership); XISetMask(mask.mask, XI_HierarchyChanged); XIGrabModifiers mods = { XIAnyModifier, 0 }; Window win = DefaultRootWindow(display2); XIGrabTouchBegin(display2, XIAllMasterDevices, win, 0, &mask, 1, &mods); free(mask.mask); EXPECT_EQ(XIGrabSuccess, mods.status); geis_subscription_delete(sub); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_geis2_api.c0000644000015600001650000000330112651717544023312 0ustar pbuserpbgroup00000000000000/** * test driver for unit testing of geis internals */ #include extern Suite *make_version_macro_suite(); extern Suite *geis2_general_types_suite_new(); extern Suite *geis2_error_codes_suite_new(); extern Suite *geis2_device_suite_new(); extern Suite *geis2_gesture_class_suite_new(); extern Suite *geis2_geis_new_suite_new(); extern Suite *geis2_config_suite_new(); extern Suite *geis2_attr_suite_new(); extern Suite *geis2_region_suite_new(); extern Suite *geis2_filter_suite_new(); extern Suite *geis2_subscription_suite_new(); extern Suite *geis2_event_suite_new(); extern Suite *geis2_gesture_frame_suite_new(); int main(int argc CK_ATTRIBUTE_UNUSED, char* argv[] CK_ATTRIBUTE_UNUSED) { int num_failed = 0; Suite *s = suite_create("\"GEIS v2.0 API\""); SRunner *sr = srunner_create(s); srunner_add_suite(sr, make_version_macro_suite()); srunner_add_suite(sr, geis2_general_types_suite_new()); srunner_add_suite(sr, geis2_error_codes_suite_new()); srunner_add_suite(sr, geis2_geis_new_suite_new()); srunner_add_suite(sr, geis2_config_suite_new()); srunner_add_suite(sr, geis2_attr_suite_new()); srunner_add_suite(sr, geis2_device_suite_new()); srunner_add_suite(sr, geis2_gesture_class_suite_new()); srunner_add_suite(sr, geis2_region_suite_new()); srunner_add_suite(sr, geis2_filter_suite_new()); srunner_add_suite(sr, geis2_subscription_suite_new()); srunner_add_suite(sr, geis2_event_suite_new()); srunner_add_suite(sr, geis2_gesture_frame_suite_new()); srunner_set_log(sr, "geis2_api.log"); srunner_set_xml(sr, "geis2_api.xml"); srunner_run_all(sr, CK_NORMAL); num_failed = srunner_ntests_failed(sr); srunner_free(sr); return !(num_failed == 0); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_device.c0000644000015600001650000000542712651717544022722 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Input Device Module. */ #include #include #include "libgeis/geis_test_api.h" /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_DEVICES, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } /* Compile-time test to ensure types and constants are defined */ START_TEST(geis_device_types) { GeisString attr_name CK_ATTRIBUTE_UNUSED; /* Types */ GeisEventType type CK_ATTRIBUTE_UNUSED; /* 5.3 Events */ attr_name = GEIS_EVENT_ATTRIBUTE_DEVICE; /* 5.1.2 Device Attributes */ attr_name = GEIS_DEVICE_ATTRIBUTE_NAME; attr_name = GEIS_DEVICE_ATTRIBUTE_ID; attr_name = GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH; attr_name = GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH; attr_name = GEIS_DEVICE_ATTRIBUTE_TOUCHES; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_device_functions) { Geis geis = NULL; GeisEventCallback callback = 0; GeisDevice device = NULL; GeisString n CK_ATTRIBUTE_UNUSED; GeisInteger i CK_ATTRIBUTE_UNUSED; GeisSize s CK_ATTRIBUTE_UNUSED; GeisAttr a CK_ATTRIBUTE_UNUSED; geis_register_device_callback(geis, callback, NULL); geis_device_ref(device); geis_device_unref(device); n = geis_device_name(device); i = geis_device_id(device); s = geis_device_attr_count(device); a = geis_device_attr(device, 0); } END_TEST START_TEST(receive_events) { GeisStatus status; GeisEvent event_out; int device_event_count = 0; status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); status = geis_next_event(g_geis, &event_out); while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { if (geis_event_type(event_out) == GEIS_EVENT_DEVICE_AVAILABLE) { ++device_event_count; } geis_event_delete(event_out); status = geis_next_event(g_geis, &event_out); } fail_unless(device_event_count > 0, "no device events received"); GeisDevice failer = geis_get_device(g_geis, 123); fail_unless(failer == NULL, "unexpected device retrieved"); GeisDevice gooder = geis_get_device(g_geis, 0); fail_unless(gooder != NULL, "failed to retrive cached device"); } END_TEST /* boilerplate */ Suite * geis2_device_suite_new() { TCase *device; TCase *usage; Suite *s = suite_create("geis2_device"); device = tcase_create("device-api"); tcase_add_test(device, geis_device_types); suite_add_tcase(s, device); usage = tcase_create("device-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, receive_events); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_config.cpp0000644000015600001650000001561012651717544023334 0ustar pbuserpbgroup00000000000000/** * Gtest test suite for GEIS v2 configuration items. * * Copyright 2012 Canonical Ltd. */ #include "geis/geis.h" #include "gtest_evemu_device.h" #include "gtest_geis_fixture.h" #include namespace { static const std::string TEST_DEVICE_PROP_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/device.prop"); static const std::string TEST_DEVICE_EVENTS_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/drag_with_3s_pause.record"); /** * Fixture for testing expected attributes. */ class Geis2ConfigTests : public GTestGeisFixture { public: Geis2ConfigTests(); void SetUp(); void TearDown(); void pre_event_handler(GeisEvent event); void post_event_handler(GeisEvent event); void memoizeDragClass(GeisEvent event); void recognizeDevice(GeisEvent event); protected: Testsuite::EvemuDevice evemu_device_; bool device_is_ready_; bool recording_was_sent_; GeisSubscription subscription_; GeisFilter filter_; GeisGestureClass drag_class_; }; Geis2ConfigTests:: Geis2ConfigTests() : evemu_device_(TEST_DEVICE_PROP_FILE), device_is_ready_(false), recording_was_sent_(false), subscription_(nullptr), filter_(nullptr), drag_class_(nullptr) { } void Geis2ConfigTests:: SetUp() { GTestGeisFixture::SetUp(); subscription_ = geis_subscription_new(geis_, "config", GEIS_SUBSCRIPTION_NONE); ASSERT_TRUE(subscription_ != NULL) << "can not create subscription"; filter_ = geis_filter_new(geis_, "config"); ASSERT_TRUE(filter_ != NULL) << "can not create filter"; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_filter_add_term(filter_, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1, NULL)) << "can not add class to filter"; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_add_filter(subscription_, filter_)) << "can not subscribe filter"; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(subscription_)) <<"can not activate subscription"; } void Geis2ConfigTests:: TearDown() { geis_subscription_delete(subscription_); GTestGeisFixture::TearDown(); } void Geis2ConfigTests:: pre_event_handler(GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { recognizeDevice(event); } else if (geis_event_type(event) == GEIS_EVENT_CLASS_AVAILABLE) { memoizeDragClass(event); } } void Geis2ConfigTests:: post_event_handler(GeisEvent event) { GTestGeisFixture::post_event_handler(event); if (geis_is_initialized() && device_is_ready_ && !recording_was_sent_) { evemu_device_.play(TEST_DEVICE_EVENTS_FILE); recording_was_sent_ = true; } } void Geis2ConfigTests:: memoizeDragClass(GeisEvent event) { GeisGestureClass gesture_class = nullptr; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); EXPECT_TRUE(attr != NULL) << "event is missing class attr"; gesture_class = (GeisGestureClass)geis_attr_value_to_pointer(attr); for (GeisSize i = 0; i < geis_gesture_class_attr_count(gesture_class); ++i) { GeisAttr attr2 = geis_gesture_class_attr(gesture_class, i); if (0 == strcmp(geis_attr_name(attr2), GEIS_CLASS_ATTRIBUTE_NAME)) { if (0 == strcmp(geis_attr_value_to_string(attr2), GEIS_GESTURE_DRAG)) { drag_class_ = gesture_class; } } } } void Geis2ConfigTests:: recognizeDevice(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); EXPECT_TRUE(attr != NULL); GeisDevice device = (GeisDevice)geis_attr_value_to_pointer(attr); if (evemu_device_.name() == geis_device_name(device)) { device_is_ready_ = true; } } /* * Tries to recognize a drag that takes too long and fails. This uses the * default drag timeout property and proves the recorded gesture is not * recognized as a drag. */ TEST_F(Geis2ConfigTests, dragWithLongTimeoutXFail) { bool recognized_gesture = false; set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_GESTURE_BEGIN) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; if (geis_frame_is_class(frame, drag_class_)) { recognized_gesture = GEIS_TRUE; geis_dispatch_stop(true); } } } } }); geis_dispatch_loop(); EXPECT_FALSE(recognized_gesture); } /* * Tries to recognize the same drag that takes too long and succeeds because the * timeout has been adjusted. */ TEST_F(Geis2ConfigTests, dragWithLongTimeout) { bool recognized_gesture = false; set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_GESTURE_BEGIN || geis_event_type(event) == GEIS_EVENT_GESTURE_UPDATE) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); EXPECT_TRUE(attr != NULL) << "event is missing groupset attr"; GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr); EXPECT_TRUE(groupset != NULL) << "event is missing groupset"; for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) { GeisGroup group = geis_groupset_group(groupset, i); EXPECT_TRUE(group != NULL) << "group " << i << " not found in groupset"; for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) { GeisFrame frame = geis_group_frame(group, j); EXPECT_TRUE(frame != NULL) << "frame " << j << " not found in group"; if (geis_frame_is_class(frame, drag_class_)) { recognized_gesture = GEIS_TRUE; geis_dispatch_stop(true); } } } } if (geis_is_initialized() && device_is_ready_) { GeisInteger timeout = 4000; // 4 s should be good enough EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_set_configuration(subscription_, GEIS_CONFIG_DRAG_TIMEOUT, &timeout)) << "can not set drag timeout"; } }); geis_dispatch_loop(); EXPECT_TRUE(recognized_gesture); } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_null_filter.cpp0000644000015600001650000000132612651717544025222 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Checks trying to delete a null filter doesn't cause problems. Regression test for https://bugs.launchpad.net/nux/+bug/1080386 */ class DeleteNullFilter : public Geis2GrailBackendBase { protected: virtual void OnEventInitComplete(GeisEvent event); }; void DeleteNullFilter::OnEventInitComplete(GeisEvent event) { GeisFilter filter = nullptr; geis_filter_delete(filter); // please don't crash } TEST_F(DeleteNullFilter, Test) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); Run(); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_grail_backend.h0000644000015600001650000000404312651717544024277 0ustar pbuserpbgroup00000000000000#ifndef GTEST_GRAIL_BACKEND_H #define GTEST_GRAIL_BACKEND_H #include #include #include #include class Touch { public: Touch(GeisTouch geis_touch); int id; float x; float y; friend std::ostream& operator<<(std::ostream& os, const Touch& touch); }; class TouchSet : public std::vector { public: TouchSet(GeisTouchSet geis_touch_set); bool contains(float x, float y); friend std::ostream& operator<<(std::ostream& os, const TouchSet& touch_set); }; class Geis2GrailBackendBase : public ::testing::Test { protected: Geis2GrailBackendBase() : _geis(nullptr), _xevent_serial_number(0) {} virtual ~Geis2GrailBackendBase() {} /* Dispatch and process Geis events in a loop until there are no more events. */ void Run(); /* Creates (and activates) a GeisSubscription with the given name and with filters for the given number of touches and gesture class. */ GeisSubscription CreateFilteredSubscription(GeisString name, GeisSize num_touches, GeisString gesture_class); void CreateXMockTouchScreenDevice(); void DestroyXMockDevices(); virtual void OnEventInitComplete(GeisEvent event) {} virtual void OnEventClassAvailable(GeisEvent event) {} virtual void OnEventGestureBegin(GeisEvent event) {} virtual void OnEventGestureUpdate(GeisEvent event) {} virtual void OnEventGestureEnd(GeisEvent event) {} void SendTouchEvent(int event_type, int touch_id, float x, float y); void SendTouchOwnershipEvent(int touch_id); void AcceptGestureInEvent(GeisEvent event); void RejectGestureInEvent(GeisEvent event); void GetGestureTimestampInEvent(GeisInteger *timestamp, GeisEvent event); Geis _geis; /* holds the serial number to be used on the next synthetic XEvent */ int _xevent_serial_number; private: bool DispatchAndProcessEvents(); void AcceptRejectGestureInEvent(GeisEvent event, bool accept); }; #endif // GTEST_GRAIL_BACKEND_H geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_grail_backend.cpp0000644000015600001650000002402712651717544024636 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" Touch::Touch(GeisTouch geis_touch) { GeisAttr attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_X); x = geis_attr_value_to_float(attr); attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_Y); y = geis_attr_value_to_float(attr); attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_ID); id = geis_attr_value_to_integer(attr); } std::ostream& operator<<(std::ostream& os, const Touch& touch) { std::cout << "(id=" << touch.id << ",x=" << touch.x << ",y=" << touch.y << ")"; return os; } TouchSet::TouchSet(GeisTouchSet geis_touch_set) { int count = geis_touchset_touch_count(geis_touch_set); for (int i = 0; i < count; ++i) push_back(Touch(geis_touchset_touch(geis_touch_set, i))); } bool TouchSet::contains(float x, float y) { for (auto touch : *this) { if (touch.x == x && touch.y == y) return true; } return false; } std::ostream& operator<<(std::ostream& os, const TouchSet& touch_set) { bool first = true; std::cout << "{"; for (auto touch : touch_set) { if (first) first = false; else std::cout << ", "; std::cout << touch; } std::cout << "}"; return os; } GeisSubscription Geis2GrailBackendBase::CreateFilteredSubscription( GeisString name, GeisSize num_touches, GeisString gesture_class) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisFilter filter = nullptr; GeisSubscription sub = nullptr; sub = geis_subscription_new(_geis, name, GEIS_SUBSCRIPTION_NONE); filter = geis_filter_new(_geis, "filter"); if (filter == nullptr) {ADD_FAILURE(); return nullptr;} status = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, gesture_class, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, num_touches, nullptr); if (status != GEIS_STATUS_SUCCESS) {ADD_FAILURE(); return nullptr;} status = geis_filter_add_term(filter, GEIS_FILTER_REGION, GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, DefaultRootWindow(xmock_display), nullptr); if (status != GEIS_STATUS_SUCCESS) {ADD_FAILURE(); return nullptr;} status = geis_subscription_add_filter(sub, filter); if (status != GEIS_STATUS_SUCCESS) {ADD_FAILURE(); return nullptr;} status = geis_subscription_activate(sub); if (status != GEIS_STATUS_SUCCESS) {ADD_FAILURE(); return nullptr;} return sub; } void Geis2GrailBackendBase::CreateXMockTouchScreenDevice() { xmock_devices_count = 1; xmock_devices = (XIDeviceInfo*) calloc(xmock_devices_count, sizeof(XIDeviceInfo)); XITouchClassInfo *touch_info = (XITouchClassInfo*) malloc(sizeof(XITouchClassInfo)); touch_info->type = XITouchClass; touch_info->sourceid = 0; touch_info->mode = XIDirectTouch; touch_info->num_touches = 5; XIValuatorClassInfo *x_axis_info = (XIValuatorClassInfo*) malloc(sizeof(XIValuatorClassInfo)); x_axis_info->type = XIValuatorClass; x_axis_info->sourceid = 0; x_axis_info->number = 0; /* identifies it as being the X axis */ x_axis_info->min = -500.0; x_axis_info->max = 500.0; x_axis_info->resolution = 3000; /* counts/meter */ XIValuatorClassInfo *y_axis_info = (XIValuatorClassInfo*) malloc(sizeof(XIValuatorClassInfo)); y_axis_info->type = XIValuatorClass; y_axis_info->sourceid = 0; y_axis_info->number = 1; /* identifies it as being the Y axis */ y_axis_info->min = -500.0; y_axis_info->max = 500.0; y_axis_info->resolution = 3000; XIAnyClassInfo **classes = (XIAnyClassInfo**) malloc(sizeof(XIAnyClassInfo*)*3); classes[0] = (XIAnyClassInfo*) touch_info; classes[1] = (XIAnyClassInfo*) x_axis_info; classes[2] = (XIAnyClassInfo*) y_axis_info; xmock_devices[0].deviceid = 0; xmock_devices[0].name = const_cast("Fake Touch Screen"); xmock_devices[0].use = XISlavePointer; xmock_devices[0].attachment = 1; xmock_devices[0].enabled = True; xmock_devices[0].num_classes = 3; xmock_devices[0].classes = classes; } void Geis2GrailBackendBase::DestroyXMockDevices() { for (int i = 0; i < xmock_devices_count; ++i) { for (int j = 0; j < xmock_devices[i].num_classes; ++j) free(xmock_devices[i].classes[j]); free(xmock_devices[i].classes); } free(xmock_devices); } bool Geis2GrailBackendBase::DispatchAndProcessEvents() { bool got_events = false; GeisEvent event; GeisStatus status; status = geis_dispatch_events(_geis); if (status != GEIS_STATUS_SUCCESS && status != GEIS_STATUS_CONTINUE) {ADD_FAILURE(); return false;} status = geis_next_event(_geis, &event); if (status != GEIS_STATUS_SUCCESS && status != GEIS_STATUS_CONTINUE && status != GEIS_STATUS_EMPTY) {ADD_FAILURE(); return false;} if (status == GEIS_STATUS_SUCCESS || status == GEIS_STATUS_CONTINUE) got_events = true; while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { switch (geis_event_type(event)) { case GEIS_EVENT_INIT_COMPLETE: OnEventInitComplete(event); break; case GEIS_EVENT_CLASS_AVAILABLE: OnEventClassAvailable(event); break; case GEIS_EVENT_GESTURE_BEGIN: OnEventGestureBegin(event); break; case GEIS_EVENT_GESTURE_UPDATE: OnEventGestureUpdate(event); break; case GEIS_EVENT_GESTURE_END: OnEventGestureEnd(event); break; default: break; } geis_event_delete(event); status = geis_next_event(_geis, &event); } return got_events; } void Geis2GrailBackendBase::Run() { bool got_events; do { got_events = DispatchAndProcessEvents(); } while (got_events); } void Geis2GrailBackendBase::SendTouchEvent( int event_type, int touch_id, float x, float y) { XEvent event; XGenericEventCookie *xcookie = 0; XIDeviceEvent *device_event = 0; event.type = GenericEvent; device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent)); device_event->serial = _xevent_serial_number++; device_event->display = xmock_display; device_event->extension = xmock_xi2_opcode; device_event->evtype = event_type; device_event->time = xmock_server_time; device_event->deviceid = 0; device_event->sourceid = device_event->deviceid; device_event->detail = touch_id; device_event->root = DefaultRootWindow(xmock_display); device_event->event = DefaultRootWindow(xmock_display); device_event->child = 0; device_event->root_x = x; device_event->root_y = y; device_event->event_x = device_event->root_x; device_event->event_y = device_event->root_y; device_event->valuators.mask_len = 2; device_event->valuators.mask = (unsigned char*) malloc(2); XISetMask(device_event->valuators.mask, 0); XISetMask(device_event->valuators.mask, 1); device_event->valuators.values = (double*) malloc(sizeof(double)*2); device_event->valuators.values[0] = 0; /* just change the coordinate system */ device_event->valuators.values[1] = 0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = event_type; xcookie->data = device_event; xmock_add_to_event_queue(&event); } void Geis2GrailBackendBase::SendTouchOwnershipEvent(int touch_id) { XEvent event; XGenericEventCookie *xcookie = 0; XITouchOwnershipEvent *ownership_event = 0; event.type = GenericEvent; ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent)); ownership_event->type = GenericEvent; ownership_event->serial = _xevent_serial_number++; ownership_event->display = xmock_display; ownership_event->extension = xmock_xi2_opcode; ownership_event->evtype = XI_TouchOwnership; ownership_event->time = xmock_server_time; ownership_event->deviceid = 0; ownership_event->sourceid = ownership_event->deviceid; ownership_event->touchid = touch_id; ownership_event->root = DefaultRootWindow(xmock_display); ownership_event->event = DefaultRootWindow(xmock_display); ownership_event->child = 0; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_TouchOwnership; xcookie->data = ownership_event; xmock_add_to_event_queue(&event); } void Geis2GrailBackendBase::AcceptRejectGestureInEvent( GeisEvent event, bool accept) { /* We expect only one group with one gesture frame. Multiple groups with several gesture frames is just not supported or used. That is, one GeisEvent is sent for each possible gesture instead of a single GeisEvent with all possible gestures (arranged in groups). */ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); GeisGroupSet group_set = static_cast(geis_attr_value_to_pointer(attr)); ASSERT_EQ(1, geis_groupset_group_count(group_set)); GeisGroup group = geis_groupset_group(group_set, 0); ASSERT_EQ(1, geis_group_frame_count(group)); GeisFrame frame = geis_group_frame(group, 0); GeisStatus status; if (accept) { status = geis_gesture_accept(_geis, group, geis_frame_id(frame)); } else { status = geis_gesture_reject(_geis, group, geis_frame_id(frame)); } ASSERT_EQ(GEIS_STATUS_SUCCESS, status); } void Geis2GrailBackendBase::AcceptGestureInEvent(GeisEvent event) { AcceptRejectGestureInEvent(event, true); } void Geis2GrailBackendBase::RejectGestureInEvent(GeisEvent event) { AcceptRejectGestureInEvent(event, false); } void Geis2GrailBackendBase::GetGestureTimestampInEvent(GeisInteger *timestamp, GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); GeisGroupSet group_set = static_cast(geis_attr_value_to_pointer(attr)); ASSERT_EQ(1, geis_groupset_group_count(group_set)); GeisGroup group = geis_groupset_group(group_set, 0); ASSERT_EQ(1, geis_group_frame_count(group)); GeisFrame frame = geis_group_frame(group, 0); attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP); ASSERT_NE(nullptr, attr); *timestamp = geis_attr_value_to_integer(attr); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_geis_new.c0000644000015600001650000000201012651717544023244 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 API instance creation. */ #include #include #include "libgeis/geis_test_api.h" /* compile-time test to ensure required init args are defined*/ START_TEST(geis_init_args) { GeisString init_arg; init_arg = GEIS_INIT_SERVICE_PROVIDER; init_arg = GEIS_INIT_TRACK_DEVICES; init_arg = GEIS_INIT_TRACK_GESTURE_CLASSES; } END_TEST /* compile-time test to ensure required functions are defined */ START_TEST(geis_new_and_delete) { GeisStatus status; Geis geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); fail_unless(geis != NULL, "failed to create GEIS v2.0 API instance"); status = geis_delete(geis); fail_unless(status == GEIS_STATUS_SUCCESS, "geis_delete failed"); } END_TEST /* boilerplate */ Suite * geis2_geis_new_suite_new() { Suite *s = suite_create("geis2_geis_init"); TCase *create = tcase_create("geis_init"); tcase_add_test(create, geis_init_args); tcase_add_test(create, geis_new_and_delete); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_frame.c0000644000015600001650000001276312651717544022556 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 Gesture Frame Module. */ #include #include #include "libgeis/geis_test_api.h" #include #define MAX_CLASS_COUNT 10 /* fixtures */ static Geis g_geis; static GeisSubscription g_sub; static GeisSize g_class_count = 0; static GeisGestureClass g_class[MAX_CLASS_COUNT]; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); g_sub = geis_subscription_new(g_geis, "test", 0); geis_subscription_activate(g_sub); } /* fixture teardown */ static void destroy_geis() { geis_subscription_delete(g_sub); geis_delete(g_geis); } /* Compile-time test to ensure types are defined */ START_TEST(geis_gesture_frame_types) { GeisGroup group CK_ATTRIBUTE_UNUSED; GeisGroupSet groupset CK_ATTRIBUTE_UNUSED; GeisTouch touch CK_ATTRIBUTE_UNUSED; GeisTouchSet touchset CK_ATTRIBUTE_UNUSED; GeisFrame frame CK_ATTRIBUTE_UNUSED; GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED; } END_TEST /* Compile-time test to ensure constants are defined */ START_TEST(geis_gesture_frame_constants) { GeisString attr_name; attr_name = GEIS_GESTURE_ATTRIBUTE_ANGLE; attr_name = GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA; attr_name = GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY; attr_name = GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1; attr_name = GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1; attr_name = GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2; attr_name = GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2; attr_name = GEIS_GESTURE_ATTRIBUTE_DELTA_X; attr_name = GEIS_GESTURE_ATTRIBUTE_DELTA_Y; attr_name = GEIS_GESTURE_ATTRIBUTE_RADIUS; attr_name = GEIS_GESTURE_ATTRIBUTE_POSITION_X; attr_name = GEIS_GESTURE_ATTRIBUTE_POSITION_Y; attr_name = GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA; attr_name = GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY; attr_name = GEIS_GESTURE_ATTRIBUTE_VELOCITY_X; attr_name = GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y; attr_name = GEIS_EVENT_ATTRIBUTE_GROUPSET; attr_name = GEIS_EVENT_ATTRIBUTE_TOUCHSET; } END_TEST /* Compile-and-link-time test to verify required functions exist */ START_TEST(geis_gesture_frame_functions) { GeisGroupSet groupset = NULL; GeisSize size CK_ATTRIBUTE_UNUSED; size = geis_groupset_group_count(groupset); } END_TEST START_TEST(receive_events) { GeisStatus status; GeisEvent event; int gesture_event_count = 0; status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); status = geis_next_event(g_geis, &event); while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { if (geis_event_type(event) == GEIS_EVENT_GESTURE_BEGIN) { GeisSize i; GeisTouchSet touchset; GeisGroupSet groupset; GeisBoolean is_poke = GEIS_FALSE; GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); fail_if(!attr, "touchset attr not found in gesture event"); touchset = geis_attr_value_to_pointer(attr); fail_if(!touchset, "touchset not found in gesture event attr"); attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); fail_if(!attr, "groupset attr not found in gesture event"); groupset = geis_attr_value_to_pointer(attr); fail_if(!groupset, "groupset not found in gesture event attr"); for (i= 0; i < geis_groupset_group_count(groupset); ++i) { GeisSize j; GeisGroup group = geis_groupset_group(groupset, i); fail_if(!group, "group %d not found in groupset", i); for (j=0; j < geis_group_frame_count(group); ++j) { GeisSize k; GeisSize c; GeisFrame frame = geis_group_frame(group, j); fail_if(!frame, "frame %d not found in group", j); for (c=0; c < g_class_count; ++c) { if (0 == strcmp(geis_gesture_class_name(g_class[c]), "poke")) { is_poke = geis_frame_is_class(frame, g_class[c]); break; } } fail_if(!is_poke, "gesture is not of expect type"); for (k = 0; k < geis_frame_touchid_count(frame); ++k) { GeisSize touchid = geis_frame_touchid(frame, k); GeisTouch touch = geis_touchset_touch_by_id(touchset, touchid); fail_if(!touch, "touch %d not found in touch set", touchid); } } } ++gesture_event_count; } else if (geis_event_type(event) == GEIS_EVENT_CLASS_AVAILABLE) { GeisAttr attr; GeisGestureClass gesture_class; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); fail_if (!attr, "attr not found in class event"); gesture_class = geis_attr_value_to_pointer(attr); fail_if (!gesture_class, "geis class not found in class event"); g_class[g_class_count++] = gesture_class; } geis_event_delete(event); status = geis_next_event(g_geis, &event); } fail_unless(gesture_event_count > 0, "no gesture events received"); } END_TEST /* boilerplate */ Suite * geis2_gesture_frame_suite_new() { Suite *s = suite_create("geis2_gesture_frame"); TCase *gesture_frame; TCase *usage; gesture_frame = tcase_create("gesture-frame-api"); tcase_add_test(gesture_frame, geis_gesture_frame_types); tcase_add_test(gesture_frame, geis_gesture_frame_constants); suite_add_tcase(s, gesture_frame); usage = tcase_create("gesture-frame-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, receive_events); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_configure_new_devices.cpp0000644000015600001650000001311012651717544027231 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Regression test for bug LP#1045785 https://bugs.launchpad.net/geis/+bug/1045785 Steps to reproduce the issue: 1 - create a subscription, set some configuration options (geis_subscription_set_configuration) and activate it. 2 - connect a new multitouch device to your computer (e.g. pair an Apple Magic Trackpad) Expected outcome: Gestures from that new multitouch device follow the configurations set by the subscription. */ class ConfigureNewDevice : public Geis2GrailBackendBase { protected: ConfigureNewDevice(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventClassAvailable(GeisEvent event); virtual void OnEventGestureBegin(GeisEvent event); void CreateSubscription(); void SendXInput2Events(); /* signals that a new device has been added */ void SendXIDeviceAddedEvent(); GeisSubscription _subscription; GeisGestureClass _drag_class; }; ConfigureNewDevice::ConfigureNewDevice() : _subscription(nullptr), _drag_class(nullptr) { } void ConfigureNewDevice::OnEventInitComplete(GeisEvent event) { CreateSubscription(); /* The new device comes only after the subscription has been created and configured */ CreateXMockTouchScreenDevice(); SendXIDeviceAddedEvent(); SendXInput2Events(); } void ConfigureNewDevice::OnEventClassAvailable(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS); GeisGestureClass gesture_class = reinterpret_cast(geis_attr_value_to_pointer(attr)); if (strcmp(geis_gesture_class_name(gesture_class), GEIS_GESTURE_DRAG) == 0) { _drag_class = gesture_class; geis_gesture_class_ref(gesture_class); } } void ConfigureNewDevice::OnEventGestureBegin(GeisEvent event) { /* There should be no drag gesture since we set a huge drag threshold. */ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); GeisGroupSet group_set = reinterpret_cast(geis_attr_value_to_pointer(attr)); GeisGroup group = geis_groupset_group(group_set, 0); GeisFrame frame = geis_group_frame(group, 0); ASSERT_NE(nullptr, _drag_class); GeisBoolean is_drag = geis_frame_is_class(frame, _drag_class); ASSERT_FALSE(is_drag); } void ConfigureNewDevice::CreateSubscription() { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisFilter filter = nullptr; _subscription = geis_subscription_new(_geis, "2-fingers drag", GEIS_SUBSCRIPTION_NONE); filter = geis_filter_new(_geis, "filter"); ASSERT_NE(nullptr, filter); status = geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 2, nullptr); ASSERT_EQ(GEIS_STATUS_SUCCESS, status); status = geis_filter_add_term(filter, GEIS_FILTER_REGION, GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, DefaultRootWindow(xmock_display), nullptr); ASSERT_EQ(GEIS_STATUS_SUCCESS, status); status = geis_subscription_add_filter(_subscription, filter); ASSERT_EQ(GEIS_STATUS_SUCCESS, status); /* Set a huge threshold (in meters) so that no drag can be recognized */ GeisFloat drag_threshold = 1000.0f; status = geis_subscription_set_configuration(_subscription, GEIS_CONFIG_DRAG_THRESHOLD, &drag_threshold); ASSERT_EQ(GEIS_STATUS_SUCCESS, status); status = geis_subscription_activate(_subscription); ASSERT_EQ(GEIS_STATUS_SUCCESS, status); } void ConfigureNewDevice::SendXInput2Events() { /* Emulate a simple 2 fingers drag */ /* event type, touch id, X and Y */ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f); SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f); xmock_server_time += 2; /* touch id */ SendTouchOwnershipEvent(1); SendTouchOwnershipEvent(2); xmock_server_time += 20; SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 25.0f); SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 25.0f); xmock_server_time += 20; SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 35.0f); SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 35.0f); xmock_server_time += 20; SendTouchEvent(XI_TouchEnd, 1, 10.0f, 50.0f); SendTouchEvent(XI_TouchEnd, 2, 20.0f, 50.0f); } void ConfigureNewDevice::SendXIDeviceAddedEvent() { XEvent event; XGenericEventCookie *xcookie = 0; XIHierarchyEvent *hierarchy_event; XIHierarchyInfo *info; info = (XIHierarchyInfo*)calloc(1, sizeof(XIHierarchyInfo)); info->deviceid = xmock_devices[0].deviceid; info->enabled = True; info->flags = XISlaveAdded; hierarchy_event = (XIHierarchyEvent*)calloc(1, sizeof(XIHierarchyEvent)); hierarchy_event->type = GenericEvent; hierarchy_event->serial = _xevent_serial_number++; hierarchy_event->display = xmock_display; hierarchy_event->extension = xmock_xi2_opcode; hierarchy_event->evtype = XI_HierarchyChanged; hierarchy_event->time = xmock_server_time; hierarchy_event->flags = XISlaveAdded; hierarchy_event->num_info = 1; hierarchy_event->info = info; event.type = GenericEvent; xcookie = &event.xcookie; xcookie->extension = xmock_xi2_opcode; xcookie->evtype = XI_HierarchyChanged; xcookie->data = hierarchy_event; xmock_add_to_event_queue(&event); } TEST_F(ConfigureNewDevice, Test) { _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); Run(); if (_subscription) geis_subscription_delete(_subscription); if (_drag_class) geis_gesture_class_unref(_drag_class); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/check_error_codes.c0000644000015600001650000000120512651717544023757 0ustar pbuserpbgroup00000000000000/** * unit tests for GEIS v2.0 error codes */ #include #include /* compile-time test to ensure required types are defined */ START_TEST(error_codes) { GeisStatus error = GEIS_STATUS_SUCCESS ; error = GEIS_STATUS_CONTINUE; error = GEIS_STATUS_EMPTY; error = GEIS_STATUS_NOT_SUPPORTED; error = GEIS_STATUS_BAD_ARGUMENT; error = GEIS_STATUS_UNKNOWN_ERROR; } END_TEST /* boilerplate */ Suite * geis2_error_codes_suite_new() { Suite *s = suite_create("geis2_error_codes"); TCase *create = tcase_create("error_codes"); tcase_add_test(create, error_codes); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_config.c0000644000015600001650000000241712651717544022724 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_geis_config module */ #include #include "geis/geis.h" #include "libgeis/geis_test_api.h" /* fixtures */ static Geis geis; /* fixture setup */ static void construct_geis() { geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(geis); } START_TEST(get_success) { int fd = -1; GeisStatus status = geis_get_configuration(geis, GEIS_CONFIGURATION_FD, &fd); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected return status from geis_get_configuration()"); fail_unless(fd >= 0, "invalid Unix FD returned"); } END_TEST /* verify table find operation (negative results) */ START_TEST(get_fail) { int fd = -1; GeisStatus status = geis_get_configuration(geis, "no such configuration", &fd); fail_unless(status == GEIS_STATUS_NOT_SUPPORTED, "unexpected return status from geis_get_configuration()"); } END_TEST /* boilerplate */ Suite * geis2_config_suite_new() { Suite *s = suite_create("geis2_configuration"); TCase *usage = tcase_create("table-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, get_success); tcase_add_test(usage, get_fail); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/check_region.c0000644000015600001650000000245712651717544022746 0ustar pbuserpbgroup00000000000000/** * Unit tests for GEIS v2.0 region module */ #include #include #include "libgeis/geis_test_api.h" #include /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } /* compile-time test to ensure required types are defined */ START_TEST(region_constants) { GeisString ini; ini = GEIS_REGION_X11_ROOT; ini = GEIS_REGION_X11_WINDOWID; } END_TEST START_TEST(construction) { GeisRegion sub = geis_region_new(g_geis, "name", GEIS_REGION_X11_ROOT, NULL); fail_unless(sub != NULL, "failed to create region"); fail_unless(0 == strcmp(geis_region_name(sub), "name"), "unexpected region name returned"); geis_region_delete(sub); } END_TEST /* boilerplate */ Suite * geis2_region_suite_new() { Suite *s = suite_create("geis2_region"); TCase *creation; TCase *usage; creation = tcase_create("region-constants"); tcase_add_test(creation, region_constants); suite_add_tcase(s, creation); usage = tcase_create("region-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, construction); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/geis2/lp891731.py0000755000015600001650000001662212651717544021646 0ustar pbuserpbgroup00000000000000#!/usr/bin/python # # When a device filter term is added to a subscription and there is no device # present to match the filter, the term causes ALL devices to be selected # instead of NONE. This is the reverse to how filters should work. # # The error occurred when filtering on any of GEIS_DEVICE_ATTRIBUTE_NAME, # GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, or GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH # attributes. # # Here's how the test works. There are two devices: device1 is the device on # which all input is actaully occurring. We have subscribed to device2 by name # but not device1, so we shouldn;t be seeing any gesture events coming in. If # we do, the bug has obtained and we fail. If we don't and the timer goes off, # assume success. # # Just to assure everything is working, there's an option to subscribe to # device1 as well, in which case we should see events only on device1. # # Because this test tool talks to kernel input devices (through evdev), it must # be run as root. # # # Copyright 2011 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # import argparse import evemu import geis import glib import os import sys class Tester(object): def __init__(self, args): super(Tester, self).__init__() self._args = args self._has_filter = False self._device_1_id = 0 # need to guarabtee there is a device we can feed events to self._device1 = evemu.Device( self._find_data_file("../recordings/test_device1/device.prop")) device2 = evemu.Device( self._find_data_file("../recordings/test_device2/device.prop")) self._device_2_name = device2.name # need a geis instance self._geis = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES) self._sub = geis.Subscription(self._geis) def _find_data_file(self, filename): f = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), filename) return open(f) def get_fd(self): return self._geis.get_configuration(geis.GEIS_CONFIGURATION_FD) def create_subscriptions(self): """ Creates a filter to allow only gesture events from device2. """ print "create_subscriptions" filt = geis.Filter(self._geis, "lp-891731") filt.add_term(geis.GEIS_FILTER_DEVICE, (geis.GEIS_DEVICE_ATTRIBUTE_NAME, geis.GEIS_FILTER_OP_EQ, self._device_2_name)) self._sub.add_filter(filt) self._has_filter = True print ".. self._args.force=%s" % self._args.force if self._args.force: filt = geis.Filter(self._geis, "force") filt.add_term(geis.GEIS_FILTER_DEVICE, (geis.GEIS_DEVICE_ATTRIBUTE_NAME, geis.GEIS_FILTER_OP_EQ, self._device1.name)) self._sub.add_filter(filt) def do_init_complete(self, event): """ Creates a subscription ONLY on the second device and generates input ONLY from the first device. """ print "do_init_complete" self.create_subscriptions() self._sub.activate() self._device1.play( self._find_data_file("../recordings/test_device1/events.record")) def do_device_available(self, event): """ Verifies and remembers the two devices as their reported. """ device = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_DEVICE] print "do_device_available: %s" % device.name() if device.name() == self._device1.name: self._device_1_id = device.id() print ".. device id = %s" % self._device_1_id def do_gesture_event(self, event): print "do_gesture_event" if not (self._device_1_id > 0 and self._has_filter): print "devices and filter not set up before other events received." sys.exit(1) if self._args.dry_run: return groupset = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_GROUPSET] if self._args.force: for group in groupset: for frame in group: for (k, v) in frame.attrs().iteritems(): if (k == geis.GEIS_GESTURE_ATTRIBUTE_DEVICE_ID and v != self._device_1_id): print "test fail: incorrect device ID, expected %d got %d" % (self._device_1_id, v) sys.exit(1) print "test successful (forced)" sys.exit(0) print "test failed: unsubscribed events received" sys.exit(1) def do_other_event(self, event): print "do_other_event" def dispatch_events(self): """ Performs GEIS event loop processing. """ print "Tester.dispatch_events" geis_event_action = { geis.GEIS_EVENT_INIT_COMPLETE: self.do_init_complete.im_func, geis.GEIS_EVENT_GESTURE_BEGIN: self.do_gesture_event.im_func, geis.GEIS_EVENT_GESTURE_UPDATE: self.do_gesture_event.im_func, geis.GEIS_EVENT_GESTURE_END: self.do_gesture_event.im_func, geis.GEIS_EVENT_DEVICE_AVAILABLE: self.do_device_available.im_func, } status = self._geis.dispatch_events() while status == geis.GEIS_STATUS_CONTINUE: status = self._geis.dispatch_events() try: while True: event = self._geis.next_event() geis_event_action.get(event.type(), self.do_other_event.im_func)(self, event) except geis.NoMoreEvents: pass return True def dispatch_test_events(fd, condition, g): print "dispatch_test_events" return g.dispatch_events() def test_timeout(): print "timed out, assuming success" exit(0) class Options(argparse.ArgumentParser): def __init__(self): super(Options, self).__init__(description='test case for LP:891731') self.add_argument('-d', '--dry-run', action='store_true', dest='dry_run', help='force the test to bypass by subscribing to no input source') self.add_argument('-f', '--force', action='store_true', dest='force', help='force the test to pass by subscribing to the input source') self.add_argument('-t', '--timeout', action='store', default='5000', dest='timeout', type=int, help='milliseconds to wait before ending test') if __name__ == '__main__': try: options = Options() args = options.parse_args() tester = Tester(args) ml = glib.MainLoop() glib.timeout_add(args.timeout, test_timeout) glib.io_add_watch(tester.get_fd(), glib.IO_IN, dispatch_test_events, tester) ml.run() except KeyboardInterrupt: pass except argparse.ArgumentError as ex: print ex sys,exit(1) geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_gbe_construction_finished.cpp0000644000015600001650000000706212651717544027311 0ustar pbuserpbgroup00000000000000#include "gtest_grail_backend.h" #include "x11_mocks.h" /* Check that GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED is properly filled. */ class ConstructionFinishedProperty : public Geis2GrailBackendBase { protected: ConstructionFinishedProperty() : _subscription(nullptr), _got_update_with_construction_finished(false) {} void SendFirstBatchOfXInput2Events(); void SendSecondBatchOfXInput2Events(); virtual void OnEventInitComplete(GeisEvent event); virtual void OnEventGestureBegin(GeisEvent event); virtual void OnEventGestureUpdate(GeisEvent event); GeisSubscription _subscription; bool _got_update_with_construction_finished; }; void ConstructionFinishedProperty::SendFirstBatchOfXInput2Events() { xmock_server_time = 0; SendTouchEvent(XI_TouchBegin, 0, 123.0f, 456.0f); SendTouchEvent(XI_TouchBegin, 1, 222.0f, 456.0f); xmock_server_time = 5; SendTouchOwnershipEvent(0); SendTouchOwnershipEvent(1); SendTouchEvent(XI_TouchUpdate, 0, 123.0f, 466.0f); SendTouchEvent(XI_TouchUpdate, 1, 222.0f, 466.0f); } void ConstructionFinishedProperty::SendSecondBatchOfXInput2Events() { /* Go past composition time (i.e. time window where new touches can be grouped with existing ones to make new gestures) */ xmock_server_time = 70; SendTouchEvent(XI_TouchUpdate, 0, 123.0f, 466.0f); SendTouchEvent(XI_TouchUpdate, 1, 222.0f, 466.0f); xmock_server_time = 80; SendTouchEvent(XI_TouchEnd, 0, 123.0f, 476.0f); SendTouchEvent(XI_TouchEnd, 1, 222.0f, 476.0f); } void ConstructionFinishedProperty::OnEventInitComplete(GeisEvent event) { _subscription = CreateFilteredSubscription( "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH); ASSERT_NE(nullptr, _subscription); } void ConstructionFinishedProperty::OnEventGestureBegin(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED); GeisBoolean construction_finished = geis_attr_value_to_boolean(attr); ASSERT_EQ(GEIS_FALSE, construction_finished); } void ConstructionFinishedProperty::OnEventGestureUpdate(GeisEvent event) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED); GeisBoolean construction_finished = geis_attr_value_to_boolean(attr); GeisInteger timestamp; GetGestureTimestampInEvent(×tamp, event); if (timestamp < 60) { /* below composition time. Construction cannot be finished just yet */ ASSERT_EQ(GEIS_FALSE, construction_finished); } else { /* we're past composition time and therefore grail will send a slice with "construction finished" set to true. geis must follow suit. */ ASSERT_EQ(GEIS_TRUE, construction_finished); _got_update_with_construction_finished = true; } } TEST_F(ConstructionFinishedProperty, Test) { CreateXMockTouchScreenDevice(); _geis = geis_new(GEIS_INIT_GRAIL_BACKEND, GEIS_INIT_NO_ATOMIC_GESTURES, nullptr); ASSERT_NE(nullptr, _geis); /* geis emits event stating that its initialization has finished */ Run(); /* begin XInput touches */ SendFirstBatchOfXInput2Events(); /* geis should receive an XAlarm event. geis updates grail time to 60. grail touches timeout (they get beyond composition time) which causes construction to finish. */ Run(); /* end XInput touches */ SendSecondBatchOfXInput2Events(); /* gesture ends */ Run(); ASSERT_TRUE(_got_update_with_construction_finished); if (_subscription) geis_subscription_delete(_subscription); geis_delete(_geis); DestroyXMockDevices(); } geis-2.2.17+16.04.20160126/testsuite/geis2/gtest_devices.cpp0000644000015600001650000002442212651717544023512 0ustar pbuserpbgroup00000000000000/** * GTEst test suite for GEIS v2 device handling. * * Copyright 2012-2013 Canonical Ltd. */ #include "geis/geis.h" #include "gtest_evemu_device.h" #include "gtest_geis_fixture.h" #include "libgeis/geis_test_api.h" #include namespace { static const std::string TEST_DEVICE_PROP_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/device.prop"); static const std::string TEST_DEVICE_EVENTS_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/rotate90.record"); /** * Fixture for testing device handling. * This is a separate class because gtest uses Java reflection. */ class GeisBasicDeviceTests : public GTestGeisFixture { void setup_geis() { geis_ = geis_new(GEIS_INIT_SYNCHRONOUS_START, GEIS_INIT_NO_ATOMIC_GESTURES, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, NULL); } }; /** * Fixture for testing device handling. * This is a separate class because gtest uses Java reflection. */ class GeisAdvancedDeviceTests : public GTestGeisFixture { void setup_geis() { new_device_.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); geis_ = geis_new(GEIS_INIT_TRACK_DEVICES, NULL); geis_initialized_in_callback_ = false; device_count_ = 0; } public: std::unique_ptr new_device_; bool geis_initialized_in_callback_; int device_count_; GeisSubscription subscription_; }; TEST_F(GeisBasicDeviceTests, filterWithNoDevices) { GeisSubscription sub = geis_subscription_new(geis_, "no devices", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create subscription"; GeisFilter filter = geis_filter_new(geis_, "rotate"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device filter"; geis_filter_delete(filter); geis_subscription_delete(sub); } /* * Test case 1 for lp:944822 -- device added after subscription activated. * * Creates a subscriptions with a device filter (there are no devices present in * the system). When initializatiom signalled as complete, device events are * reenabled in the geis instance and a new device is added. When the * device-added event is received, a recording is run through the device. * Gesture events should be detected. */ TEST_F(GeisBasicDeviceTests, addDeviceSubscription) { std::unique_ptr new_device; GeisBoolean device_has_been_created = GEIS_FALSE; GeisBoolean gesture_events_received = GEIS_FALSE; GeisSubscription sub = geis_subscription_new(geis_, "no devices", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create subscription"; GeisFilter filter = geis_filter_new(geis_, "rotate"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; fs = geis_subscription_add_filter(sub, filter); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; set_geis_event_handler([&](Geis, GeisEvent event) { switch (geis_event_type(event)) { case GEIS_EVENT_INIT_COMPLETE: { EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) << "can not activate subscription"; GeisBoolean off = GEIS_FALSE; geis_set_configuration(geis_, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, &off); new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); device_has_been_created = GEIS_TRUE; break; } case GEIS_EVENT_DEVICE_AVAILABLE: new_device->play(TEST_DEVICE_EVENTS_FILE); break; case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: { EXPECT_EQ(device_has_been_created, GEIS_TRUE) << "gesture events without device"; gesture_events_received = device_has_been_created; } default: break; } }); geis_dispatch_loop(); EXPECT_TRUE(gesture_events_received) << "no gesture events received"; EXPECT_TRUE(device_has_been_created) << "no device created"; geis_subscription_delete(sub); } /* * Test case 2 for lp:944822 -- device removed after subscription activated. * * This test really just makes sure nothing segfaults on device removal. */ TEST_F(GeisBasicDeviceTests, removeDeviceSubscription) { std::unique_ptr new_device; GeisSubscription sub = geis_subscription_new(geis_, "remove devices", GEIS_SUBSCRIPTION_NONE); EXPECT_TRUE(sub != NULL) << "can not create subscription"; GeisFilter filter = geis_filter_new(geis_, "rotate"); EXPECT_TRUE(filter != NULL) << "can not create filter"; GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE, NULL); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; fs = geis_subscription_add_filter(sub, filter); EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_INIT_COMPLETE) { GeisBoolean off = GEIS_FALSE; geis_set_configuration(geis_, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, &off); new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); } else if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) << "can not activate subscription"; new_device.reset(); } else if (geis_event_type(event) == GEIS_EVENT_DEVICE_UNAVAILABLE) { geis_dispatch_stop(true); } }); geis_dispatch_loop(); geis_subscription_delete(sub); } /* * Test case for lp:987539: report X and Y axis extents. * * This test creates a devicve with known X and Y extents and verifies the * extent attributes are reported with the expected values. */ TEST_F(GeisBasicDeviceTests, deviceAttrs) { GeisBoolean off = GEIS_FALSE; geis_set_configuration(geis_, GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, &off); Testsuite::EvemuDevice test_device(TEST_DEVICE_PROP_FILE); set_geis_event_handler([&](Geis, GeisEvent event) { if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE) { GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); EXPECT_TRUE(attr != NULL); GeisDevice device = (GeisDevice)geis_attr_value_to_pointer(attr); ASSERT_TRUE(test_device.name() == geis_device_name(device)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_MIN_X); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(0.0f, geis_attr_value_to_float(attr)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_MAX_X); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(9600.0f, geis_attr_value_to_float(attr)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_RES_X); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(0.0f, geis_attr_value_to_float(attr)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_MIN_Y); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(0.0f, geis_attr_value_to_float(attr)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_MAX_Y); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(7200.0f, geis_attr_value_to_float(attr)); attr = geis_device_attr_by_name(device, GEIS_DEVICE_ATTRIBUTE_RES_Y); ASSERT_TRUE(attr != NULL); EXPECT_FLOAT_EQ(0.0f, geis_attr_value_to_float(attr)); } }); geis_dispatch_loop(); } /** * GEIS event callback to verify lp:1252447. * * This bug reveals that subscriptions created in an event callback when the * INIT_COMPLETE event is received never get activated for devices that are * present at GEIS start time. */ static void lp_1252447_event_callback(::Geis geis, GeisEvent event, void* context) { GeisAdvancedDeviceTests* fixture = (GeisAdvancedDeviceTests*)context; switch (geis_event_type(event)) { case GEIS_EVENT_INIT_COMPLETE: { fixture->geis_initialized_in_callback_ = true; fixture->subscription_ = geis_subscription_new(geis, "any device", GEIS_SUBSCRIPTION_NONE); GeisFilter filter = geis_filter_new(geis, "filter"); geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 2, NULL); EXPECT_EQ(geis_subscription_add_filter(fixture->subscription_, filter), GEIS_STATUS_SUCCESS); EXPECT_EQ(geis_subscription_activate(fixture->subscription_), GEIS_STATUS_SUCCESS); break; } case GEIS_EVENT_DEVICE_AVAILABLE: { ++fixture->device_count_; GeisSize active_sub_count = 0; geis_subscription_get_configuration(fixture->subscription_, GEIS_CONFIG_NUM_ACTIVE_SUBSCRIPTIONS, &active_sub_count); EXPECT_GT(active_sub_count, 0); break; } default: break; } } TEST_F(GeisAdvancedDeviceTests, initialDeviceRegistrationWithCallbacks) { geis_register_event_callback(geis_, lp_1252447_event_callback, this); geis_register_device_callback(geis_, lp_1252447_event_callback, this); set_geis_event_handler([&](Geis, GeisEvent event) { }); geis_dispatch_loop(); ASSERT_TRUE(geis_initialized_in_callback_); ASSERT_GT(device_count_, 0); } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/libgeis/0000755000015600001650000000000012651717732020556 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/libgeis/check_filter.c0000644000015600001650000000454012651717544023350 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis filter module */ #include #include "geis_filter.h" #include "geis_test_api.h" #include /* fixtures */ static Geis g_geis; static GeisFilterBag g_filter_bag; static GeisString g_filter_name = "filter"; /* fixture setup */ static void construct_bag() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); g_filter_bag = geis_filter_bag_new(); } /* fixture teardown */ static void destroy_bag() { geis_filter_bag_delete(g_filter_bag); geis_delete(g_geis); } /* verify bag construction/destruction */ START_TEST(construct) { GeisFilterBag bag = geis_filter_bag_new(); fail_unless(bag != NULL, "failed to create filter bag"); geis_filter_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(insert_filter) { GeisFilter filter = geis_filter_new(g_geis, g_filter_name); geis_filter_bag_insert(g_filter_bag, filter); fail_unless(geis_filter_bag_count(g_filter_bag) == 1, "unexpected bag size after insertion"); } END_TEST /* verify bag removal */ START_TEST(remove_filter) { GeisFilter filter = geis_filter_new(g_geis, g_filter_name); geis_filter_bag_insert(g_filter_bag, filter); fail_unless(geis_filter_bag_count(g_filter_bag) == 1, "unexpected bag size after insertion"); geis_filter_bag_remove(g_filter_bag, filter); fail_unless(geis_filter_bag_count(g_filter_bag) == 0, "unexpected bag size after removal"); } END_TEST START_TEST(expand) { GeisSize i; for (i = 0; i < 24; ++i) { GeisSize count; char name[32]; sprintf(name, "%04zu", i); GeisFilter filter = geis_filter_new(g_geis, name); geis_filter_bag_insert(g_filter_bag, filter); count = geis_filter_bag_count(g_filter_bag); fail_unless(count == (i+1), "unexpected bag size %ld after insertion, expected %d", count, i+1); } } END_TEST /* boilerplate */ Suite * make_filter_suite() { Suite *s = suite_create("geis2-filter"); TCase *create = tcase_create("filter-bag-creation"); tcase_add_test(create, construct); suite_add_tcase(s, create); TCase *usage = tcase_create("filter-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, insert_filter); tcase_add_test(usage, remove_filter); tcase_add_test(usage, expand); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_subscription.c0000644000015600001650000000605512651717544024612 0ustar pbuserpbgroup00000000000000/** * internal unit tests for the GEIS v2.0 subscription module */ #include #include "geis/geis.h" #include "geis_subscription.h" #include "geis_test_api.h" #include /* fixtures */ static Geis g_geis; static GeisSubBag g_sub_bag; static const GeisString test_sub_string = "zot!"; /* fixture setup */ static void construct_bag() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); g_sub_bag = geis_subscription_bag_new(1); } /* fixture teardown */ static void destroy_bag() { geis_subscription_bag_delete(g_sub_bag); geis_delete(g_geis); } /* verify bag construction/destruction */ START_TEST(construction) { GeisSubBag bag = geis_subscription_bag_new(1); fail_unless(bag != NULL, "failed to create subscription bag"); fail_unless(geis_subscription_bag_count(bag) == 0, "unexpected size"); geis_subscription_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(insertion) { GeisSubscription sub = geis_subscription_new(g_geis, "test-sub", GEIS_SUBSCRIPTION_NONE); geis_subscription_bag_insert(g_sub_bag, sub); fail_unless(geis_subscription_bag_count(g_sub_bag) == 1, "unexpected bag size after insertion"); } END_TEST /* verify bag find operation (positive results) */ START_TEST(find_success) { GeisSubscription sub2; GeisSubscription sub1 = geis_subscription_new(g_geis, "test-sub", GEIS_SUBSCRIPTION_NONE); GeisSize id = geis_subscription_bag_insert(g_sub_bag, sub1); sub2 = geis_subscription_bag_find(g_sub_bag, id); fail_if(sub2 == NULL, "expected instance not found"); fail_unless(0 == strcmp(geis_subscription_name(sub1), geis_subscription_name(sub2)), "unexpected subscription name returned"); } END_TEST /* verify bag find operation (negative results) */ START_TEST(find_fail) { GeisSubscription sub = geis_subscription_bag_find(g_sub_bag, 999); fail_unless(sub == NULL, "unexpected instance found"); } END_TEST START_TEST(expansion) { int i; for (i = 0; i < 24; ++i) { char name[32]; sprintf(name, "%04d", i); GeisSubscription sub = geis_subscription_new(g_geis, name, GEIS_SUBSCRIPTION_NONE); fail_if(geis_subscription_id(sub) != i, "unexpected subscription ID returned"); } } END_TEST /* boilerplate */ Suite * make_subscription_suite() { Suite *s = suite_create("geis2-subscriptions"); TCase *create = tcase_create("sub-bag-creation"); tcase_add_test(create, construction); suite_add_tcase(s, create); TCase *usage = tcase_create("sub-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, insertion); tcase_add_test(usage, find_success); tcase_add_test(usage, find_fail); tcase_add_test(usage, expansion); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_error_reporting.c0000644000015600001650000000140312651717544025300 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_instance_table module */ #include #include "geis/geis.h" #include "libgeis/geis_error.h" START_TEST(global_error_stack) { GeisSize i = 0; geis_error_clear(NULL); geis_error_push(NULL, GEIS_STATUS_SUCCESS); fail_unless(geis_error_count(NULL) == 1, "unexpected error stack size"); for (i=0; i < geis_error_count(NULL); ++i) { fail_unless(geis_error_code(NULL, i) == GEIS_STATUS_SUCCESS, "unexpected status code retrieved"); } } END_TEST /* boilerplate */ Suite * make_error_reporting_suite() { Suite *s = suite_create("geis2-error-reporting"); TCase *create = tcase_create("error-reporting"); tcase_add_test(create, global_error_stack); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_class.c0000644000015600001650000000517312651717544023173 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis gesture class module */ #include #include "libgeis/geis_class.h" #include /* fixtures */ static GeisGestureClassBag g_gesture_class_bag; static GeisString g_gesture_class_name = "gesture_class"; static GeisInteger g_gesture_class_id = 12; /* fixture setup */ static void construct_bag() { g_gesture_class_bag = geis_gesture_class_bag_new(); } /* fixture teardown */ static void destroy_bag() { geis_gesture_class_bag_delete(g_gesture_class_bag); } /* verify bag construction/destruction */ START_TEST(construct) { GeisGestureClassBag bag = geis_gesture_class_bag_new(); fail_unless(bag != NULL, "failed to create gesture class bag"); geis_gesture_class_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(insert_class) { GeisGestureClass gesture_class = geis_gesture_class_new(g_gesture_class_name, g_gesture_class_id); geis_gesture_class_bag_insert(g_gesture_class_bag, gesture_class); fail_unless(geis_gesture_class_bag_count(g_gesture_class_bag) == 1, "unexpected bag size after insertion"); } END_TEST /* verify bag removal */ START_TEST(remove_class) { GeisGestureClass gesture_class = geis_gesture_class_new(g_gesture_class_name, g_gesture_class_id); geis_gesture_class_bag_insert(g_gesture_class_bag, gesture_class); fail_unless(geis_gesture_class_bag_count(g_gesture_class_bag) == 1, "unexpected bag size after insertion"); geis_gesture_class_bag_remove(g_gesture_class_bag, gesture_class); fail_unless(geis_gesture_class_bag_count(g_gesture_class_bag) == 0, "unexpected bag size after removal"); } END_TEST START_TEST(expand) { GeisSize i; for (i = 0; i < 24; ++i) { GeisSize count; char name[32]; sprintf(name, "%04zu", i); GeisGestureClass gesture_class = geis_gesture_class_new(name, i); geis_gesture_class_bag_insert(g_gesture_class_bag, gesture_class); count = geis_gesture_class_bag_count(g_gesture_class_bag); fail_unless(count == (i+1), "unexpected bag size %ld after insertion, expected %d", count, i+1); } } END_TEST /* boilerplate */ Suite * make_gesture_class_suite() { Suite *s = suite_create("geis2-gesture_class"); TCase *create = tcase_create("gesture-class-bag-creation"); tcase_add_test(create, construct); suite_add_tcase(s, create); TCase *usage = tcase_create("gesture-class-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, insert_class); tcase_add_test(usage, remove_class); tcase_add_test(usage, expand); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/Makefile.am0000644000015600001650000000443412651717544022620 0ustar pbuserpbgroup00000000000000# # @file testsuite/libgeis/Makefile.am # @brief automake recipe for the GEIS v2.0 internals unit test suite # # # Copyright 2010, 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # if HAVE_CHECK test_targets = check_geis2_internals else test_targets = endif compile_tests = check-c-compile check-cxx-compile test_cppflags = \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis TESTS = $(test_targets) $(compile_tests) check_PROGRAMS = $(test_targets) $(compile_tests) check_c_compile_SOURCES = check-c-compile.c check_c_compile_CPPFLAGS = $(test_cppflags) check_c_compile_LDADD = $(top_builddir)/libgeis/libgeis.la check_cxx_compile_SOURCES = check-cxx-compile.cpp check_cxx_compile_CPPFLAGS = $(test_cppflags) check_cxx_compile_LDADD = $(top_builddir)/libgeis/libgeis.la check_geis2_internals_SOURCES = \ check_attr.c \ check_backend_multiplexor.c \ check_backend_token.c \ check_class.c \ check_device.c \ check_error_reporting.c \ check_event_queue.c \ check_filter.c \ check_filter_term.c \ check_geis_private.c \ check_region.c \ check_subscription.c \ check_select_devices.c \ check_timer.c \ check_geis2_internals.c check_geis2_internals_CPPFLAGS = \ $(test_cppflags) \ $(CHECK_CFLAGS) # # Link against the (non-distributed) static libgeis to pick up the # internal symbols. # check_geis2_internals_LDADD = \ $(top_builddir)/libgeis/.libs/libgeis.a \ $(DBUS_LIBS) \ $(GRAIL_LIBS) \ $(X11XCB_LIBS) \ $(XCB_LIBS) \ $(XI2_LIBS) \ $(CHECK_LIBS) \ -lm -ldl -lpthread MOSTLYCLEANFILES = \ geis2_internals.log \ geis2_internals.xml geis-2.2.17+16.04.20160126/testsuite/libgeis/check_event_queue.c0000644000015600001650000000714312651717544024412 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_event_queue module */ #include #include "geis/geis.h" #include "libgeis/geis_event.h" #include "libgeis/geis_event_queue.h" /* fixtures */ static GeisEventQueue g_queue; /* fixture setup */ static void construct_event_queue() { g_queue = geis_event_queue_new(); } /* fixture teardown */ static void destroy_event_queue() { geis_event_queue_delete(g_queue); } /* verify event queue construction/destruction */ START_TEST(construction) { construct_event_queue(); fail_unless(g_queue != NULL, "failed to create the event queue"); fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty"); destroy_event_queue(); } END_TEST /* verify event_queue insertion */ START_TEST(enqueue_dequeue) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisEvent event1 = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); GeisEvent event2 = geis_event_new(GEIS_EVENT_GESTURE_END); GeisEvent ev; ev = geis_event_queue_dequeue(g_queue); fail_unless(ev == NULL, "unexpected failure at pop(0)"); status = geis_event_queue_enqueue(g_queue, event1); fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event1)"); fail_unless(!geis_event_queue_is_empty(g_queue), "queue is unexpectedly empty"); status = geis_event_queue_enqueue(g_queue, event2); fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event2)"); ev = geis_event_queue_dequeue(g_queue); fail_unless(ev != NULL, "failure at dequeue(1)"); fail_unless(ev == event1, "unexpected value returned from front(1)"); ev = geis_event_queue_dequeue(g_queue); fail_unless(ev != NULL, "failure at dequeue(2)"); fail_unless(ev == event2, "unexpected value returned from front(2)"); ev = geis_event_queue_dequeue(g_queue); fail_unless(ev == NULL, "failure at dequeue(3)"); fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty"); } END_TEST /* verify event_queue remove_if */ static GeisBoolean _is_event_type(GeisEvent event, void* context) { GeisEventType event_type = *(GeisEventType*)context; return geis_event_type(event) == event_type; } START_TEST(remove_if) { GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; GeisEvent event1 = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); status = geis_event_queue_enqueue(g_queue, event1); fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event1)"); GeisEvent event2 = geis_event_new(GEIS_EVENT_USER_DEFINED); status = geis_event_queue_enqueue(g_queue, event2); fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event2)"); GeisEvent event3 = geis_event_new(GEIS_EVENT_GESTURE_END); status = geis_event_queue_enqueue(g_queue, event3); fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event3)"); GeisEventType event_type = GEIS_EVENT_USER_DEFINED; geis_event_queue_remove_if(g_queue, _is_event_type, &event_type); event_type = GEIS_EVENT_GESTURE_BEGIN; geis_event_queue_remove_if(g_queue, _is_event_type, &event_type); event_type = GEIS_EVENT_GESTURE_END; geis_event_queue_remove_if(g_queue, _is_event_type, &event_type); fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty"); } END_TEST /* boilerplate */ Suite * make_event_queue_suite() { Suite *s = suite_create("geis2-event-queue"); TCase *create = tcase_create("event-queue-creation"); tcase_add_test(create, construction); suite_add_tcase(s, create); TCase *usage = tcase_create("event-queue-operation"); tcase_add_checked_fixture(usage, construct_event_queue, destroy_event_queue); tcase_add_test(usage, enqueue_dequeue); tcase_add_test(usage, remove_if); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_timer.c0000644000015600001650000000637412651717544023212 0ustar pbuserpbgroup00000000000000/** * internal unit tests for the GEIS v2.0 subscription module */ #pragma GCC diagnostic ignored "-Wunused-result" #include #include "geis/geis.h" #include "geis_timer.h" #include "geis_test_api.h" #include #include #include #include /* fixtures */ static Geis g_geis; int g_geis_fd; static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); geis_get_configuration(g_geis, GEIS_CONFIGURATION_FD, &g_geis_fd); } static void destroy_geis() { geis_delete(g_geis); } static void _timer_callback(GeisTimer timer CK_ATTRIBUTE_UNUSED, void *context) { int efd = *(int *)context; uint64_t datum = 1; (void)write(efd, &datum, sizeof(datum)); } START_TEST(timer_expire) { int timer_fired = 0; int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); GeisTimer timer = geis_timer_new(g_geis, _timer_callback, &efd); geis_timer_start(timer, 100); while (1) { int status = 0; int max_fd = (g_geis_fd > efd ? g_geis_fd : efd) + 1; struct timeval tm; fd_set fds; FD_ZERO(&fds); FD_SET(g_geis_fd, &fds); FD_SET(efd, &fds); tm.tv_sec = 1; tm.tv_usec = 0; status = select(max_fd + 1, &fds, NULL, NULL, &tm); if (status < 0) { fail_if(status < 0, "error in select"); break; } if (status == 0) { fail_if(status == 0, "no events detected"); break; } else if (FD_ISSET(g_geis_fd, &fds)) { geis_dispatch_events(g_geis); } if (FD_ISSET(efd, &fds)) { timer_fired = 1; break; } } geis_timer_delete(timer); close(efd); fail_unless(timer_fired, "timer did not fire"); } END_TEST START_TEST(timer_cancel) { static const int timer_timeout = 100; /* milliseconds */ static const int microseconds_per_millisecond = 1000; int timer_cancelled = 0; int timer_fired = 0; int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); GeisTimer timer = geis_timer_new(g_geis, _timer_callback, &efd); geis_timer_start(timer, timer_timeout); while (1) { int status = 0; int max_fd = (g_geis_fd > efd ? g_geis_fd : efd) + 1; struct timeval tm; fd_set fds; FD_ZERO(&fds); FD_SET(g_geis_fd, &fds); FD_SET(efd, &fds); tm.tv_sec = 0; tm.tv_usec = 1 * microseconds_per_millisecond; /* 1 millisecond */ status = select(max_fd + 1, &fds, NULL, NULL, &tm); if (status < 0) { fail_if(status < 0, "error in select"); break; } if (status == 0) { if (timer_cancelled) break; geis_timer_cancel(timer); timer_cancelled = 1; tm.tv_usec = timer_timeout * microseconds_per_millisecond * 2; } else if (FD_ISSET(g_geis_fd, &fds)) { geis_dispatch_events(g_geis); } if (FD_ISSET(efd, &fds)) { timer_fired = 1; break; } } geis_timer_delete(timer); close(efd); fail_if(timer_fired, "timer fired after cancellation"); } END_TEST /* boilerplate */ Suite * make_timer_suite() { Suite *s = suite_create("geis2-geis-timer"); TCase *usage = tcase_create("timer"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, timer_expire); tcase_add_test(usage, timer_cancel); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_geis2_internals.c0000644000015600001650000000342512651717544025154 0ustar pbuserpbgroup00000000000000/** * test driver for unit testing of geis v2.0 internals */ #include #define LOGFILE_PREFIX "geis2_internals" extern Suite *make_attr_suite(); extern Suite *make_backend_event_posting_suite(); extern Suite *make_backend_multiplexor_suite(); extern Suite *make_backend_token_suite(); extern Suite *make_device_suite(); extern Suite *make_error_reporting_suite(); extern Suite *make_event_queue_suite(); extern Suite *make_filter_suite(); extern Suite *make_filter_term_suite(); extern Suite *make_gesture_class_suite(); extern Suite *make_region_suite(); extern Suite *make_select_devices_suite(); extern Suite *make_subscription_suite(); extern Suite *make_timer_suite(); int main(int argc CK_ATTRIBUTE_UNUSED, char* argv[] CK_ATTRIBUTE_UNUSED) { int num_failed = 0; Suite *s = suite_create("\"GEIS v2.0 internals\""); SRunner *sr = srunner_create(s); srunner_add_suite(sr, make_error_reporting_suite()); srunner_add_suite(sr, make_attr_suite()); srunner_add_suite(sr, make_event_queue_suite()); srunner_add_suite(sr, make_backend_multiplexor_suite()); srunner_add_suite(sr, make_backend_token_suite()); srunner_add_suite(sr, make_backend_event_posting_suite()); srunner_add_suite(sr, make_device_suite()); srunner_add_suite(sr, make_gesture_class_suite()); srunner_add_suite(sr, make_region_suite()); srunner_add_suite(sr, make_filter_suite()); srunner_add_suite(sr, make_filter_term_suite()); srunner_add_suite(sr, make_select_devices_suite()); srunner_add_suite(sr, make_subscription_suite()); srunner_add_suite(sr, make_timer_suite()); srunner_set_log(sr, LOGFILE_PREFIX".log"); srunner_set_xml(sr, LOGFILE_PREFIX".xml"); srunner_run_all(sr, CK_NORMAL); num_failed = srunner_ntests_failed(sr); srunner_free(sr); return !(num_failed == 0); } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_attr.c0000644000015600001650000000676212651717544023045 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis_attr_bag module */ #include #include "libgeis/geis_attr.h" #include /* fixtures */ static GeisAttrBag g_attr_bag; static const GeisString test_attr_string = "zot!"; /* fixture setup */ static void construct_bag() { g_attr_bag = geis_attr_bag_new(1); } /* fixture teardown */ static void destroy_bag() { geis_attr_bag_delete(g_attr_bag); } /* verify bag construction/destruction */ START_TEST(construction) { GeisAttrBag bag = geis_attr_bag_new(1); fail_unless(bag != NULL, "failed to create attr bag"); geis_attr_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(insertion) { GeisAttr attr = geis_attr_new("test-attr", GEIS_ATTR_TYPE_STRING, (void*)test_attr_string); geis_attr_bag_insert(g_attr_bag, attr); fail_unless(geis_attr_bag_count(g_attr_bag) == 1, "unexpected bag size after insertion"); } END_TEST /* verify bag get operation (positive results) */ START_TEST(get_success) { GeisAttr dst_attr; GeisAttr src_attr = geis_attr_new("test-attr", GEIS_ATTR_TYPE_STRING, (void*)test_attr_string); geis_attr_bag_insert(g_attr_bag, src_attr); dst_attr = geis_attr_bag_attr(g_attr_bag, 0); fail_if(dst_attr == NULL, "expected instance not found"); fail_unless(0 == strcmp(geis_attr_value_to_string(dst_attr), test_attr_string), "unexpected attribute value returned"); } END_TEST /* verify bag get operation (negative results) */ START_TEST(get_fail) { GeisAttr attr = geis_attr_bag_attr(g_attr_bag, 5); fail_unless(attr == NULL, "unexpected instance indexed"); } END_TEST /* verify bag find operation (positive results) */ START_TEST(find_success) { GeisAttr dst_attr; GeisAttr src_attr = geis_attr_new("test-attr", GEIS_ATTR_TYPE_STRING, (void*)test_attr_string); geis_attr_bag_insert(g_attr_bag, src_attr); dst_attr = geis_attr_bag_find(g_attr_bag, "test-attr"); fail_if(dst_attr == NULL, "expected instance not found"); fail_unless(0 == strcmp(geis_attr_value_to_string(dst_attr), test_attr_string), "unexpected attribute value returned"); } END_TEST /* verify bag find operation (negative results) */ START_TEST(find_fail) { GeisAttr attr = geis_attr_bag_find(g_attr_bag, "bogus"); fail_unless(attr == NULL, "unexpected instance found"); } END_TEST START_TEST(expansion) { GeisSize i; for (i = 0; i < 24; ++i) { GeisSize count; char name[32]; sprintf(name, "%04zu", i); GeisAttr attr = geis_attr_new(name, GEIS_ATTR_TYPE_INTEGER, &i); geis_attr_bag_insert(g_attr_bag, attr); count = geis_attr_bag_count(g_attr_bag); fail_unless(count == (i+1), "unexpected bag size %ld after insertion, expected %d", count, i+1); } } END_TEST /* boilerplate */ Suite * make_attr_suite() { Suite *s = suite_create("geis2-attrs"); TCase *create = tcase_create("attr-bag-creation"); tcase_add_test(create, construction); suite_add_tcase(s, create); TCase *usage = tcase_create("attr-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, insertion); tcase_add_test(usage, get_success); tcase_add_test(usage, get_fail); tcase_add_test(usage, find_success); tcase_add_test(usage, find_fail); tcase_add_test(usage, expansion); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_backend_multiplexor.c0000644000015600001650000000615212651717544026117 0ustar pbuserpbgroup00000000000000/** * internal unit tests for the GEIS v2.0 backend_multiplexor module */ #include #include #include "geis/geis.h" #include "libgeis/geis_backend_multiplexor.h" #include #include #include /* fixtures */ static GeisBackendMultiplexor g_mx; /* fixture setup */ static void construct_mx() { g_mx = geis_backend_multiplexor_new(); } /* fixture teardown */ static void destroy_mx() { geis_backend_multiplexor_delete(g_mx); } static void testcase_event_callback(int fd, GeisBackendMultiplexorActivity event CK_ATTRIBUTE_UNUSED, void *context) { char buf[2]; ssize_t ssize CK_ATTRIBUTE_UNUSED; ssize = read(fd, buf, 1); *(int *)context += 1; } /* verify bag construction/destruction */ START_TEST(construction) { construct_mx(); fail_unless(g_mx != NULL, "failed to create backend_multiplexor"); fail_unless(geis_backend_multiplexor_fd(g_mx) >= 0, "invalid MX fd"); fail_unless(geis_backend_multiplexor_max_events_per_pump(g_mx) == GEIS_BE_MX_DEFAULT_EVENTS_PER_PUMP, "unexpected max fd per pump value"); destroy_mx(); } END_TEST /* verify multiplexor wait */ START_TEST(mx_wait) { int pfd[2]; int mx_fd = geis_backend_multiplexor_fd(g_mx); int called = 0; int status = 0; int first_time = 1; fail_unless(pipe(pfd) == 0, "error %d creating self-pipe: %d", errno, strerror(errno)); geis_backend_multiplexor_add_fd(g_mx, pfd[0], GEIS_BE_MX_READ_AVAILABLE, testcase_event_callback, &called); while (1) { fd_set fds; FD_ZERO(&fds); FD_SET(mx_fd, &fds); struct timeval tm; tm.tv_sec = 0; tm.tv_usec = 5000; status = select(mx_fd+1, &fds, NULL, NULL, &tm); fail_if(status < 0, "error in select"); if (status < 0) { break; } else if (0 == status) { fail_unless(first_time, "select timed out before read"); if (!first_time) { break; } first_time = 0; ssize_t ssize = write(pfd[1], "1", 1); fail_unless(ssize == 1, "error writing to self-pipe"); } else { geis_backend_multiplexor_pump(g_mx); break; } } fail_if(called == 0, "MX event callback not called"); fail_if(called > 1, "MX event callback called too many times"); } END_TEST START_TEST(mx_config) { geis_backend_multiplexor_set_max_events_per_pump(g_mx, 24); fail_unless(geis_backend_multiplexor_max_events_per_pump(g_mx) == 24, "unexpected max fd per pump value"); } END_TEST /* boilerplate */ Suite * make_backend_multiplexor_suite() { Suite *s = suite_create("geis2-backend-multiplexor"); TCase *create = tcase_create("backend-multiplexor-creation"); tcase_add_test(create, construction); suite_add_tcase(s, create); TCase *usage = tcase_create("backend-multiplexor-usage"); tcase_add_checked_fixture(usage, construct_mx, destroy_mx); tcase_add_test(usage, mx_wait); tcase_add_test(usage, mx_config); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_filter_term.c0000644000015600001650000001054512651717544024401 0ustar pbuserpbgroup00000000000000/** * @file check_filter_term.c * @brief unit tests for GEIS filter terms * * Copyright 2012 Canonical Ltd. */ #include #include "libgeis/geis_attr.h" #include "libgeis/geis_device.h" #include "libgeis/geis_filter_term.h" /* verify filter term construction/destruction */ START_TEST(construct) { GeisInteger ival = 0; GeisAttr attr = geis_attr_new("dummy", GEIS_ATTR_TYPE_INTEGER, &ival); fail_unless(attr != NULL, "failed to create filter term attr"); GeisFilterTerm term = geis_filter_term_new(GEIS_FILTER_SPECIAL, GEIS_FILTER_OP_NE, attr); fail_unless(term != NULL, "failed to create filter term"); geis_filter_term_unref(term); } END_TEST /* verify device filtering capability */ START_TEST(device_filter) { GeisString device_name = "direct"; GeisAttr name_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, (void *)device_name); fail_unless(name_attr != NULL, "failed to create name filter term attr"); GeisFilterTerm name_term = geis_filter_term_new(GEIS_FILTER_DEVICE, GEIS_FILTER_OP_NE, name_attr); fail_unless(name_term != NULL, "failed to create id filter term"); GeisBoolean is_direct = GEIS_TRUE; GeisAttr direct_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, &is_direct); fail_unless(direct_attr != NULL, "failed to create direct filter term attr"); GeisFilterTerm direct_term = geis_filter_term_new(GEIS_FILTER_DEVICE, GEIS_FILTER_OP_EQ, direct_attr); fail_unless(direct_term != NULL, "failed to create direct filter term"); GeisInteger id = 1; GeisAttr id_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, &id); fail_unless(id_attr != NULL, "failed to create id filter term attr"); GeisFilterTerm id_term = geis_filter_term_new(GEIS_FILTER_DEVICE, GEIS_FILTER_OP_EQ, id_attr); fail_unless(id_term != NULL, "failed to create id filter term"); GeisDevice direct_device = geis_device_new(device_name, id); GeisAttr device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, &is_direct); fail_unless(device_attr != NULL, "failed to create direct filter term attr"); geis_device_add_attr(direct_device, device_attr); GeisDevice indirect_device = geis_device_new("indirect", id + 1); GeisBoolean passed = GEIS_FALSE; passed = geis_filter_term_match_device(name_term, direct_device); fail_unless(passed != GEIS_TRUE, "direct device was passed by name term"); passed = geis_filter_term_match_device(name_term, indirect_device); fail_unless(passed == GEIS_TRUE, "indirect device was not passed by name term"); passed = geis_filter_term_match_device(direct_term, direct_device); fail_unless(passed == GEIS_TRUE, "direct device was not passed by direct term"); passed = geis_filter_term_match_device(direct_term, indirect_device); fail_unless(passed != GEIS_TRUE, "indirect device was passed by direct term"); passed = geis_filter_term_match_device(id_term, direct_device); fail_unless(passed == GEIS_TRUE, "direct device was not passed by id term"); passed = geis_filter_term_match_device(id_term, indirect_device); fail_unless(passed != GEIS_TRUE, "indirect device was passed by id term"); geis_device_unref(direct_device); geis_device_unref(indirect_device); geis_filter_term_unref(name_term); geis_filter_term_unref(direct_term); geis_filter_term_unref(id_term); } END_TEST /* boilerplate */ Suite * make_filter_term_suite() { Suite *s = suite_create("geis2-filter-term"); TCase *create = tcase_create("filter-term-creation"); tcase_add_test(create, construct); suite_add_tcase(s, create); TCase *usage = tcase_create("filter-term-usage"); tcase_add_test(usage, device_filter); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_select_devices.c0000644000015600001650000001166612651717544025053 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis filter module */ #include #include "geis_attr.h" #include "geis_private.h" #include "geis_test_api.h" static const char* device_1_name = "device 1"; /* fixtures */ Geis g_geis; static void construct_geis() { static struct GeisFilterableAttribute attrs[] = { { GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_ATTR_TYPE_STRING, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_ID, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, { GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, 0, NULL }, }; static GeisSize attr_count = sizeof(attrs) / sizeof(struct GeisFilterableAttribute); int ival = 2; int bval = GEIS_TRUE; g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); GeisDevice device = geis_device_new(device_1_name, 1); geis_device_add_attr(device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &ival)); geis_register_device(g_geis, device, attr_count, attrs); device = geis_device_new("device 2", 2); geis_device_add_attr(device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &ival)); geis_device_add_attr(device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_ATTR_TYPE_BOOLEAN, &bval)); geis_register_device(g_geis, device, attr_count, attrs); ++ival; device = geis_device_new("device 3", 3); geis_device_add_attr(device, geis_attr_new(GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_ATTR_TYPE_INTEGER, &ival)); geis_register_device(g_geis, device, attr_count, attrs); while (geis_dispatch_events(g_geis) == GEIS_STATUS_CONTINUE) ; } static void destroy_geis() { geis_delete(g_geis); } /* should select ALL devices */ START_TEST(select_all) { GeisDeviceBag device_bag = geis_device_bag_new(); GeisFilter filter = geis_filter_new(g_geis, "no device terms"); GeisSelectResult matches = geis_select_devices(g_geis, filter, device_bag); fail_unless(matches == GEIS_SELECT_RESULT_ALL, "unexpected match result"); geis_device_bag_delete(device_bag); } END_TEST /* should select SOME devices */ START_TEST(select_some_name) { GeisDeviceBag device_bag = geis_device_bag_new(); GeisFilter filter = geis_filter_new(g_geis, "just device 1"); geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, device_1_name, NULL); GeisSelectResult matches = geis_select_devices(g_geis, filter, device_bag); fail_unless(matches == GEIS_SELECT_RESULT_SOME, "unexpected match result"); geis_device_bag_delete(device_bag); } END_TEST /* should select SOME devices */ START_TEST(select_some_indirect) { GeisDeviceBag device_bag = geis_device_bag_new(); GeisFilter filter = geis_filter_new(g_geis, "just ndirect devices"); geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_NE, GEIS_FALSE, NULL); GeisSelectResult matches = geis_select_devices(g_geis, filter, device_bag); fail_unless(matches == GEIS_SELECT_RESULT_SOME, "unexpected match result"); geis_device_bag_delete(device_bag); } END_TEST /* should select SOME devices */ START_TEST(select_some_touches) { GeisDeviceBag device_bag = geis_device_bag_new(); GeisFilter filter = geis_filter_new(g_geis, "just 3-touch devices"); geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 2, NULL); GeisSelectResult matches = geis_select_devices(g_geis, filter, device_bag); fail_unless(matches == GEIS_SELECT_RESULT_SOME, "unexpected match result"); geis_device_bag_delete(device_bag); } END_TEST /* should select NONE device */ START_TEST(select_none) { GeisDeviceBag device_bag = geis_device_bag_new(); GeisFilter filter = geis_filter_new(g_geis, "just 4-touch devices"); geis_filter_add_term(filter, GEIS_FILTER_DEVICE, GEIS_DEVICE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 3, NULL); GeisSelectResult matches = geis_select_devices(g_geis, filter, device_bag); fail_unless(matches == GEIS_SELECT_RESULT_NONE, "unexpected match result"); geis_device_bag_delete(device_bag); } END_TEST /* boilerplate */ Suite * make_select_devices_suite() { Suite *s = suite_create("geis2-select_devices"); TCase *usage = tcase_create("device-selection"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, select_all); tcase_add_test(usage, select_some_name); tcase_add_test(usage, select_some_indirect); tcase_add_test(usage, select_some_touches); tcase_add_test(usage, select_none); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_device.c0000644000015600001650000000602012651717544023315 0ustar pbuserpbgroup00000000000000/** * unit tests for the geis device module */ #include #include "libgeis/geis_device.h" #include "libgeis/geis_attr.h" #include /* fixtures */ static GeisDeviceBag g_device_bag; static GeisString g_device_name = "device"; static GeisInteger g_device_id = 12; /* fixture setup */ static void construct_bag() { g_device_bag = geis_device_bag_new(); } /* fixture teardown */ static void destroy_bag() { geis_device_bag_delete(g_device_bag); } /* verify bag construction/destruction */ START_TEST(construct) { GeisDeviceBag bag = geis_device_bag_new(); fail_unless(bag != NULL, "failed to create device bag"); geis_device_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(insert_device) { GeisDevice device = geis_device_new(g_device_name, g_device_id); geis_device_bag_insert(g_device_bag, device); fail_unless(geis_device_bag_count(g_device_bag) == 1, "unexpected bag size after insertion"); } END_TEST /* verify bag removal */ START_TEST(remove_device) { GeisDevice device = geis_device_new(g_device_name, g_device_id); geis_device_bag_insert(g_device_bag, device); fail_unless(geis_device_bag_count(g_device_bag) == 1, "unexpected bag size after insertion"); geis_device_bag_remove(g_device_bag, device); fail_unless(geis_device_bag_count(g_device_bag) == 0, "unexpected bag size after removal"); } END_TEST /* * Verify retrieval by name works. */ START_TEST(attribute_name) { GeisDevice device = geis_device_new(g_device_name, g_device_id); GeisAttr in_attr, out_attr; const char *attribute_name = "TEST_ATTRIBUTE"; int attr_value = 60; fail_if(geis_device_attr_by_name(device, attribute_name) != NULL); in_attr = geis_attr_new(attribute_name, GEIS_ATTR_TYPE_INTEGER, (void*)&attr_value); geis_device_add_attr(device, in_attr); out_attr = geis_device_attr_by_name(device, attribute_name); fail_if(out_attr == NULL); fail_if(geis_attr_value_to_integer(out_attr) != attr_value); } END_TEST START_TEST(expand) { GeisSize i; for (i = 0; i < 24; ++i) { GeisSize count; char name[32]; sprintf(name, "%04zu", i); GeisDevice device = geis_device_new(name, i); geis_device_bag_insert(g_device_bag, device); count = geis_device_bag_count(g_device_bag); fail_unless(count == (i+1), "unexpected bag size %ld after insertion, expected %d", count, i+1); } } END_TEST /* boilerplate */ Suite * make_device_suite() { Suite *s = suite_create("geis2-device"); TCase *create = tcase_create("device-bag-creation"); tcase_add_test(create, construct); suite_add_tcase(s, create); TCase *usage = tcase_create("device-bag-usage"); tcase_add_checked_fixture(usage, construct_bag, destroy_bag); tcase_add_test(usage, insert_device); tcase_add_test(usage, remove_device); tcase_add_test(usage, expand); suite_add_tcase(s, usage); TCase *dev_attr = tcase_create("device-attributes"); tcase_add_test(usage, attribute_name); suite_add_tcase(s, dev_attr); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check-cxx-compile.cpp0000644000015600001650000000063612651717544024573 0ustar pbuserpbgroup00000000000000/* * A small application that tests that compiling + linking works * on a C++ compiler. */ #include #include #include "geis_config.h" #include "geis_test_api.h" int main(int argc GEIS_UNUSED, char **argv GEIS_UNUSED) { Geis g = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); if(!g) { printf("This really should not be happening.\n"); return 1; } return 0; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_region.c0000644000015600001650000000522112651717544023343 0ustar pbuserpbgroup00000000000000/** * internal unit tests for the GEIS v2.0 region module * * Note the public API is checked through the geis2 testsuite. */ #include #include "geis/geis.h" #include "geis_test_api.h" #include "geis_region.h" #include /* fixtures */ static Geis g_geis; static GeisRegionBag g_region_bag; static uint16_t g_sample_windowid = 0x11; /* fixture setup */ static void construct_bag() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); g_region_bag = geis_region_bag_new(1); } /* fixture teardown */ static void destroy_bag() { geis_region_bag_delete(g_region_bag); geis_delete(g_geis); } START_TEST(region_access) { GeisRegion region; region = geis_region_new(g_geis, "test01", GEIS_REGION_X11_WINDOWID, g_sample_windowid, NULL); fail_unless(0 == strcmp(geis_region_type(region), GEIS_REGION_X11_WINDOWID), "bad region type"); fail_unless(g_sample_windowid == *(int *)geis_region_data(region), "bad region data"); } END_TEST /* verify bag construction/destruction */ START_TEST(bag_construction) { GeisRegionBag bag = geis_region_bag_new(); fail_unless(bag != NULL, "failed to create region bag"); fail_unless(geis_region_bag_count(bag) == 0, "unexpected size"); geis_region_bag_delete(bag); } END_TEST /* verify bag insertion */ START_TEST(bag_insertion) { GeisRegion region; region = geis_region_new(g_geis, "test02", GEIS_REGION_X11_ROOT, NULL); geis_region_bag_insert(g_region_bag, region); fail_unless(geis_region_bag_count(g_region_bag) == 1, "unexpected bag size after insertion"); } END_TEST START_TEST(bag_expansion) { int i; GeisRegion region; for (i = 0; i < 24; ++i) { char name[32]; sprintf(name, "%04d", i); region = geis_region_new(g_geis, name, GEIS_REGION_X11_ROOT, NULL); geis_region_bag_insert(g_region_bag, region); int size = geis_region_bag_count(g_region_bag); fail_if((size - 1) != i, "expected region bag size %d, got %d", i, size); } } END_TEST /* boilerplate */ Suite * make_region_suite() { Suite *s = suite_create("geis2-region"); TCase *create = tcase_create("region-access"); tcase_add_test(create, region_access); suite_add_tcase(s, create); TCase *bag_create = tcase_create("region-bag-creation"); tcase_add_test(bag_create, bag_construction); suite_add_tcase(s, bag_create); TCase *bag_usage = tcase_create("region-bag-usage"); tcase_add_checked_fixture(bag_usage, construct_bag, destroy_bag); tcase_add_test(bag_usage, bag_insertion); tcase_add_test(bag_usage, bag_expansion); suite_add_tcase(s, bag_usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_geis_private.c0000644000015600001650000001304212651717544024541 0ustar pbuserpbgroup00000000000000/** * internal unit test for the back end event posting interface */ #include #include #include "geis/geis.h" #include "geis_event.h" #include "geis_private.h" #include "geis_test_api.h" #include #include #include /* fixtures */ Geis g_geis; static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); } static void destroy_geis() { geis_delete(g_geis); } static void testcase_event_callback(int fd, GeisBackendMultiplexorActivity event CK_ATTRIBUTE_UNUSED, void *context) { char buf[2]; ssize_t ssize CK_ATTRIBUTE_UNUSED; ssize = read(fd, buf, 1); *(int *)context += 1; } START_TEST(backend_post) { GeisStatus status; GeisEvent event_in = geis_event_new(GEIS_EVENT_GESTURE_END); GeisEvent event_out; /* empty the event queue */ while (GEIS_STATUS_CONTINUE == geis_dispatch_events(g_geis)) ; while (GEIS_STATUS_CONTINUE == geis_next_event(g_geis, &event_out)) geis_event_delete(event_out); /* verify a single event */ geis_post_event(g_geis, event_in); status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); status = geis_next_event(g_geis, &event_out); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_next_event"); fail_unless(geis_event_type(event_in) == geis_event_type(event_out), "event in and event out types do not match"); /* verify a multiple events */ geis_post_event(g_geis, event_in); geis_post_event(g_geis, event_in); status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); status = geis_next_event(g_geis, &event_out); fail_unless(status == GEIS_STATUS_CONTINUE, "expected CONTINUE status from geis_next_event"); status = geis_next_event(g_geis, &event_out); fail_unless(status == GEIS_STATUS_SUCCESS, "expected SUCCESS status from geis_next_event"); geis_event_delete(event_in); } END_TEST /* Check selective queue removal. */ static GeisBoolean _is_event_type(GeisEvent event, void* context) { GeisEventType event_type = *(GeisEventType*)context; return geis_event_type(event) == event_type; } START_TEST(remove_matching) { GeisStatus status; /* empty the event queue */ while (GEIS_STATUS_CONTINUE == geis_dispatch_events(g_geis)) ; GeisEvent event_out; while (GEIS_STATUS_CONTINUE == geis_next_event(g_geis, &event_out)) geis_event_delete(event_out); /* push 3 controlled events into the queue */ GeisEvent event_in_1 = geis_event_new(GEIS_EVENT_GESTURE_BEGIN); geis_post_event(g_geis, event_in_1); GeisEvent event_in_2 = geis_event_new(GEIS_EVENT_USER_DEFINED); geis_post_event(g_geis, event_in_2); GeisEvent event_in_3 = geis_event_new(GEIS_EVENT_GESTURE_END); geis_post_event(g_geis, event_in_3); /* remove the middle event */ GeisEventType event_type = GEIS_EVENT_USER_DEFINED; geis_remove_matching_events(g_geis, _is_event_type, &event_type); /* verify it's no longer in the queue */ status = geis_dispatch_events(g_geis); fail_unless(status == GEIS_STATUS_SUCCESS, "unexpected status from geis_dispatch_events"); for (status = geis_next_event(g_geis, &event_out); status != GEIS_STATUS_EMPTY; status = geis_next_event(g_geis, &event_out)) { fail_if(GEIS_EVENT_USER_DEFINED == geis_event_type(event_out), "event was not successfully removed"); geis_event_delete(event_out); } } END_TEST START_TEST(multiplex_fd) { int pfd[2]; int geis_fd; int called = 0; int status = 0; int first_time = 1; GeisEvent event_out; GeisStatus gstat = geis_get_configuration(g_geis, GEIS_CONFIGURATION_FD, &geis_fd); fail_unless(gstat == GEIS_STATUS_SUCCESS, "unable to get GEIS fd"); fail_unless(pipe(pfd) == 0, "error %d creating self-pipe: %d", errno, strerror(errno)); geis_multiplex_fd(g_geis, pfd[0], GEIS_BE_MX_READ_AVAILABLE, testcase_event_callback, &called); /* empty the event queue */ while (GEIS_STATUS_CONTINUE == geis_dispatch_events(g_geis)) ; while (GEIS_STATUS_CONTINUE == geis_next_event(g_geis, &event_out)) geis_event_delete(event_out); while (1) { fd_set fds; FD_ZERO(&fds); FD_SET(geis_fd, &fds); struct timeval tm; tm.tv_sec = 0; tm.tv_usec = 5000; status = select(geis_fd+1, &fds, NULL, NULL, &tm); fail_if(status < 0, "error in select"); if (status < 0) { break; } else if (0 == status) { fail_unless(first_time, "select timed out before read"); if (!first_time) { break; } first_time = 0; ssize_t ssize = write(pfd[1], "1", 1); fail_unless(ssize == 1, "error writing to self-pipe"); } else { geis_dispatch_events(g_geis); break; } } fail_if(called == 0, "event callback not called"); fail_if(called > 1, "event callback called too many times"); } END_TEST /* boilerplate */ Suite * make_backend_event_posting_suite() { Suite *s = suite_create("geis2-geis-private"); TCase *usage = tcase_create("backend-event-posting"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, backend_post); tcase_add_test(usage, remove_matching); tcase_add_test(usage, multiplex_fd); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check-c-compile.c0000644000015600001650000000063312651717544023650 0ustar pbuserpbgroup00000000000000/* * A small application that tests that compiling + linking works * on a C compiler. */ #include #include #include "geis_config.h" #include "geis_test_api.h" int main(int argc GEIS_UNUSED, char **argv GEIS_UNUSED) { Geis g = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); if(!g) { printf("This really should not be happening.\n"); return 1; } return 0; } geis-2.2.17+16.04.20160126/testsuite/libgeis/check_backend_token.c0000644000015600001650000000232212651717544024646 0ustar pbuserpbgroup00000000000000/** * internal unit tests for the GEIS v2.0 internal backend token interface */ #include #include "geis/geis.h" #include "geis_backend_token.h" #include "geis_private.h" #include "geis_test_api.h" /* fixtures */ static Geis g_geis; /* fixture setup */ static void construct_geis() { g_geis = geis_new(GEIS_INIT_MOCK_BACKEND, NULL); } /* fixture teardown */ static void destroy_geis() { geis_delete(g_geis); } START_TEST(creation) { GeisBackendToken token1 = NULL; GeisBackendToken token2 = NULL; token1 = geis_backend_token_new(g_geis, GEIS_BACKEND_TOKEN_INIT_ALL); fail_if(token1 == NULL, "failed to create token1"); token2 = geis_backend_token_clone(token1); fail_if(token2 == NULL, "failed to create token2"); fail_if(token2 == token1, "token clone failed"); geis_backend_token_compose(token1, token2); geis_backend_token_delete(token2); geis_backend_token_delete(token1); } END_TEST /* boilerplate */ Suite * make_backend_token_suite() { Suite *s = suite_create("geis2-backend-tokens"); TCase *usage = tcase_create("token-usage"); tcase_add_checked_fixture(usage, construct_geis, destroy_geis); tcase_add_test(usage, creation); suite_add_tcase(s, usage); return s; } geis-2.2.17+16.04.20160126/testsuite/x11_mocks/0000755000015600001650000000000012651717732020745 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/x11_mocks/Makefile.am0000644000015600001650000000036312651717544023004 0ustar pbuserpbgroup00000000000000# # @file testsuite/x11_mocks/Makefile.am # @brief automake recipe for the X11 mockups # check_LIBRARIES = libx11_mocks.a libx11_mocks_a_SOURCES = \ x11_mocks.h x11_mocks.c libx11_mocks_a_CPPFLAGS = \ --std=c99 \ -Wno-unused-parameter geis-2.2.17+16.04.20160126/testsuite/x11_mocks/x11_mocks.h0000644000015600001650000000144312651717544022726 0ustar pbuserpbgroup00000000000000#ifndef X11_MOCKS_H #define X11_MOCKS_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif extern int xmock_xi2_opcode; extern int xmock_xi2_event_base; extern int xmock_xi2_error_base; extern int xmock_xsync_event_base; extern int xmock_xsync_error_base; extern Display *xmock_display; extern uint64_t xmock_server_time; /* to be filled by user. A copy of it will be returned by each XIQueryDevice call */ extern XIDeviceInfo *xmock_devices; extern int xmock_devices_count; /* Adds the given XEvent to the xmock event queue. The Diplay connection will signal that there are pending events */ extern void xmock_add_to_event_queue(const XEvent* event); #ifdef __cplusplus } #endif #endif geis-2.2.17+16.04.20160126/testsuite/x11_mocks/x11_mocks.c0000644000015600001650000002111512651717544022717 0ustar pbuserpbgroup00000000000000/* needed to break into 'Display' struct internals. */ #define XLIB_ILLEGAL_ACCESS #include #include "x11_mocks.h" #include #include #include #include int xmock_xi2_opcode = 42; int xmock_xi2_event_base = 40000; int xmock_xi2_error_base = 40000; int xmock_xsync_event_base = 50000; int xmock_xsync_error_base = 50000; Display *xmock_display = NULL; uint64_t xmock_server_time = 0; XIDeviceInfo *xmock_devices = NULL; int xmock_devices_count = 0; /* id to be used for the next alarm that gets created */ XSyncAlarm _xmock_next_alarm = 1; struct EventQueueItem { XEvent event; struct EventQueueItem *next; } *xmock_event_queue = NULL; #define XMOCK_PRINT_FUNCTION _xmock_print_function(__func__) void _xmock_print_function(const char *function) { static int debug_enabled = -1; if (debug_enabled == -1) { if (getenv("XMOCK_DEBUG")) debug_enabled = 1; else debug_enabled = 0; } if (debug_enabled) printf("XMOCK: %s mock called.\n", function); } void xmock_add_to_event_queue(const XEvent *event) { struct EventQueueItem *new_item = malloc(sizeof(struct EventQueueItem)); new_item->event = *event; new_item->next = NULL; if (!xmock_event_queue) { xmock_event_queue = new_item; } else { struct EventQueueItem *last_item = xmock_event_queue; while (last_item->next) { last_item = last_item->next; } last_item->next = new_item; } static const uint64_t num = 1; if (write(xmock_display->fd, &num, sizeof(num)) != sizeof(num)) { fprintf(stderr, "ERROR: failed to update eventfd instance,\n"); exit(1); } } Display *XOpenDisplay(_Xconst char *display_name) { XMOCK_PRINT_FUNCTION; (void)display_name; Display *display = (Display*)calloc(1, sizeof(Display)); display->fd = eventfd(0, EFD_NONBLOCK); display->default_screen = 0; display->nscreens = 1; display->screens = (Screen*)calloc(1, sizeof(Screen)); display->screens[0].root = 1; xmock_display = display; return display; } int XCloseDisplay(Display *display) { XMOCK_PRINT_FUNCTION; close(display->fd); free(display->screens); free(display); xmock_display = NULL; return 0; } int XSync(Display *display, Bool discard) { (void)display; (void)discard; return 0; } int XFlush(Display *display) { (void)display; return 0; } Bool XQueryExtension(Display *display, const char *name, int *major_opcode_return, int *first_event_return, int *first_error_return) { XMOCK_PRINT_FUNCTION; (void)display; (void)name; /* assuming name == "XInputExtension" */ *major_opcode_return = xmock_xi2_opcode; *first_event_return = xmock_xi2_event_base; *first_error_return = xmock_xi2_error_base; return True; } int XPending(Display *display) { XMOCK_PRINT_FUNCTION; (void)display; int pending_events_count = 0; struct EventQueueItem *item = xmock_event_queue; while (item != NULL) { ++pending_events_count; item = item->next; } return pending_events_count; } int XNextEvent(Display *display, XEvent *event_return) { XMOCK_PRINT_FUNCTION; (void)display; if (xmock_event_queue) { uint64_t num = 1; ssize_t bytes_read = read(xmock_display->fd, &num, sizeof(num)); (void)bytes_read; *event_return = xmock_event_queue->event; struct EventQueueItem *removed_item = xmock_event_queue; xmock_event_queue = xmock_event_queue->next; free(removed_item); } else { /* not going to block... */ } return 0; } Bool XGetEventData(Display *display, XGenericEventCookie *cookie) { XMOCK_PRINT_FUNCTION; (void)display; (void)cookie; return True; } void XFreeEventData(Display *display, XGenericEventCookie *cookie) { XMOCK_PRINT_FUNCTION; (void)display; if (cookie->data && cookie->extension == xmock_xi2_opcode) { if (cookie->evtype == XI_TouchBegin || cookie->evtype == XI_TouchUpdate || cookie->evtype == XI_TouchEnd) { XIDeviceEvent *device_event = (XIDeviceEvent*) cookie->data; free(device_event->valuators.mask); free(device_event->valuators.values); } else if (cookie->evtype == XI_HierarchyChanged) { XIHierarchyEvent *hierarchy_event = (XIHierarchyEvent*) cookie->data; for (int i = 0; i < hierarchy_event->num_info; ++i) { free(&(hierarchy_event->info[i])); } } free(cookie->data); } } XIDeviceInfo* XIQueryDevice(Display * display, int deviceid, int * ndevices_return) { XMOCK_PRINT_FUNCTION; (void)display; (void)deviceid; /* assuming XIAllDevices */ XIDeviceInfo *devices; devices = calloc(xmock_devices_count, sizeof(XIDeviceInfo)); for (int i = 0; i < xmock_devices_count; ++i) { devices[i] = xmock_devices[i]; } *ndevices_return = xmock_devices_count; return devices; } void XIFreeDeviceInfo(XIDeviceInfo *info) { XMOCK_PRINT_FUNCTION; free(info); } Status XIQueryVersion(Display *display, int *major_version_inout, int *minor_version_inout) { XMOCK_PRINT_FUNCTION; (void)display; *major_version_inout = 2; *minor_version_inout = 2; return Success; } Status XISelectEvents(Display *display, Window win, XIEventMask *masks, int num_masks) { XMOCK_PRINT_FUNCTION; (void)display; (void)win; (void)masks; (void)num_masks; return Success; } int XIGrabTouchBegin( Display* display, int deviceid, Window grab_window, int owner_events, XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout) { XMOCK_PRINT_FUNCTION; (void)display; (void)deviceid; (void)grab_window; (void)owner_events; (void)mask; for (int i = 0; i < num_modifiers; ++i) { modifiers_inout[i].status = XIGrabSuccess; } return 0; } Status XIUngrabTouchBegin( Display* display, int deviceid, Window grab_window, int num_modifiers, XIGrabModifiers *modifiers) { XMOCK_PRINT_FUNCTION; (void)display; (void)deviceid; (void)grab_window; (void)num_modifiers; (void)modifiers; return Success; } Status XIAllowTouchEvents( Display* display, int deviceid, unsigned int touchid, Window grab_window, int event_mode) { XMOCK_PRINT_FUNCTION; (void)display; (void)deviceid; (void)touchid; (void)grab_window; (void)event_mode; return Success; } Status XSyncQueryExtension( Display* dpy, int* event_base_return, int* error_base_return) { XMOCK_PRINT_FUNCTION; (void)dpy; *event_base_return = xmock_xsync_event_base; *error_base_return = xmock_xsync_error_base; return True; } Status XSyncInitialize( Display* dpy, int* major_version_return, int* minor_version_return) { XMOCK_PRINT_FUNCTION; (void)dpy; *major_version_return = 1; *minor_version_return = 0; return True; } XSyncSystemCounter *XSyncListSystemCounters( Display* dpy, int* n_counters_return) { XMOCK_PRINT_FUNCTION; (void)dpy; *n_counters_return = 1; XSyncSystemCounter *sys_counter = malloc(sizeof(XSyncSystemCounter)); sys_counter->name = "SERVERTIME"; sys_counter->counter = 1; sys_counter->resolution.hi = 1; sys_counter->resolution.lo = 0; return sys_counter; } void XSyncFreeSystemCounterList(XSyncSystemCounter* list) { XMOCK_PRINT_FUNCTION; free(list); } XSyncAlarm XSyncCreateAlarm( Display* dpy, unsigned long values_mask, XSyncAlarmAttributes* values) { XMOCK_PRINT_FUNCTION; (void)dpy; (void)values_mask; XSyncAlarmNotifyEvent alarm_notify; alarm_notify.type = xmock_xsync_event_base + XSyncAlarmNotify; alarm_notify.alarm = _xmock_next_alarm; alarm_notify.counter_value = values->trigger.wait_value; xmock_add_to_event_queue((XEvent*)&alarm_notify); XSyncValue time = values->trigger.wait_value; uint64_t timeout = (uint64_t)XSyncValueHigh32(time) << 32 | (uint64_t)XSyncValueLow32(time); xmock_server_time = timeout + 1; return _xmock_next_alarm++; } Status XSyncDestroyAlarm( Display* dpy, XSyncAlarm alarm) { XMOCK_PRINT_FUNCTION; (void)dpy; (void)alarm; return Success; } void XSyncIntsToValue( XSyncValue* pv, unsigned int l, int h) { XMOCK_PRINT_FUNCTION; pv->hi = h; pv->lo = l; } int XSyncValueHigh32(XSyncValue v) { XMOCK_PRINT_FUNCTION; return v.hi; } unsigned int XSyncValueLow32(XSyncValue v) { XMOCK_PRINT_FUNCTION; return v.lo; } geis-2.2.17+16.04.20160126/testsuite/manual-tests/0000755000015600001650000000000012651717732021555 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/manual-tests/select-region.txt0000644000015600001650000000212512651717544025057 0ustar pbuserpbgroup00000000000000Filter by Window ================ These tests verify the "select by window" filter is functional. Filter by Window ---------------- #. Run tools/geisview/geisview with the debug trave activate and a window selected. For example, :: GEIS_DEBUG=3 geisview --backend grail --window 0x4800006 Outcome A line similar to the following should appear in the debug output. :: GEIS(debug)-_geis_grail_activate_for_device_region:635 subscribing for device 55568 'N-Trig MultiTouch', window 0x04800006 No Filter by Window ------------------- #. Determine the X root window id using the following command. :: xwininfo -root | grep "Window id" | cut -d' ' -f4 #. Run tools/geisview/geisview with the debug trace active For example, :: GEIS_DEBUG=3 geisview --backend grail Outcome A line similar to the following should appear in the debug output. :: GEIS(debug)-_geis_grail_activate_for_device_region:635 subscribing for device 56400 'N-Trig MultiTouch', window 0x0000015d where the 'window' value is the same as the root window id determined in the first step above. geis-2.2.17+16.04.20160126/testsuite/manual-tests/gesture_events.txt0000644000015600001650000000073212651717544025363 0ustar pbuserpbgroup00000000000000Gesture Events ============== This test shows that gesture evnts are received. Touchscreen 2-drag ------------------ #. run ``sudo evemu-device testsuite/manual-tests/touchscreen.desc &`` and record the name of the device created #. run ``tools/geisview/geisview --backend grail`` #. run ``sudo evemu-play /dev/input/eventNN #undef _XOPEN_SOURCE #include "geis/geis.h" #include "gtest_evemu_device.h" #include #include namespace { const std::string TEST_DEVICE_PROP_FILE(TEST_ROOT_DIR "recordings/apple_magic_trackpad/device.prop"); /* * A special fixture that does not have any GEIS instances yet. */ class Geis1InstanceTests : public xorg::testing::Test { public: Geis1InstanceTests() : evemu_device_(TEST_DEVICE_PROP_FILE), device_count_(0) { } void device_seen() { ++device_count_; } int device_seen_count() const { return device_count_; } private: Testsuite::EvemuDevice evemu_device_; int device_count_; }; /* * Regression test for lp:973539. * * The problem would only occur if an appropriate X server was * unavailable or did not support the required XI2.2 functionality. * */ TEST_F(Geis1InstanceTests, noX11Server) { char* old_display = getenv("DISPLAY"); ASSERT_TRUE(old_display != NULL); unsetenv("DISPLAY"); GeisXcbWinInfo xcb_win_info = { NULL, NULL, 0 }; GeisWinInfo win_info = { GEIS_XCB_FULL_WINDOW, &xcb_win_info }; GeisInstance geis; ASSERT_NE(GEIS_STATUS_SUCCESS, geis_init(&win_info, &geis)); setenv("DISPLAY", old_display, ~0); } static void input_device_added(void *context, GeisInputDeviceId device_id GEIS_UNUSED, void *attrs GEIS_UNUSED) { Geis1InstanceTests* fixture = static_cast(context); fixture->device_seen(); } static void null_device_function(void *context GEIS_UNUSED, GeisInputDeviceId device_id GEIS_UNUSED, void *attrs GEIS_UNUSED) { } static GeisInputFuncs input_funcs = { input_device_added, null_device_function, null_device_function }; TEST_F(Geis1InstanceTests, reportDevices) { GeisXcbWinInfo xcb_win_info = { NULL, NULL, 0 }; GeisWinInfo win_info = { GEIS_XCB_FULL_WINDOW, &xcb_win_info }; GeisInstance geis; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_init(&win_info, &geis)); ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_input_devices(geis, &input_funcs, this)); EXPECT_GT(device_seen_count(), 0) << "no devices seen"; } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/geis1/check_subscription.c0000644000015600001650000001061412651717544024200 0ustar pbuserpbgroup00000000000000/** * @file check_subscription.c * @brief Unit tests for GEIS v1 subscriptions * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #define GEIS_TEST_WINDOW geis_win_type_str(Test) static const char* s_gestures[] = { GEIS_GESTURE_TYPE_DRAG2, GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_TYPE_PINCH2, GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_TYPE_ROTATE2, GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_TYPE_TAP2, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_TAP4, NULL }; static void gesture_added(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } static void gesture_removed(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } /* * Checks for special values generated by the mock back end. */ static void gesture_start(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } static void gesture_update(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } static void gesture_finish(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } /* fixtures */ static GeisInstance g_instance; /* fixture setup */ static void construct_instance() { GeisStatus status; GeisXcbWinInfo x_win_info = { .display_name = NULL, .screenp = NULL, .window_id = 1 }; GeisWinInfo win_info = { GEIS_TEST_WINDOW, &x_win_info }; status = geis_init(&win_info, &g_instance); } /* fixture teardown */ static void destroy_instance() { geis_finish(g_instance); } static void construct_subscription() { GeisStatus status; GeisGestureFuncs gesture_funcs; gesture_funcs.added = gesture_added; gesture_funcs.removed = gesture_removed; gesture_funcs.start = gesture_start; gesture_funcs.update = gesture_update; gesture_funcs.finish = gesture_finish; status = geis_subscribe(g_instance, GEIS_ALL_INPUT_DEVICES, s_gestures, &gesture_funcs, &gesture_funcs); } static void dispatch_events() { GeisGestureFuncs gesture_funcs; memset(&gesture_funcs, 0, sizeof(GeisGestureFuncs)); geis_event_dispatch(g_instance); } /* regression test for LP: #754135 */ START_TEST(check_persistence) { construct_subscription(); dispatch_events(); } END_TEST Suite * geis1_subscription_new() { Suite *s = suite_create("geis1_subscription"); TCase *test; test = tcase_create("lp754135"); tcase_add_checked_fixture(test, construct_instance, destroy_instance); tcase_add_test(test, check_persistence); suite_add_tcase(s, test); return s; } geis-2.2.17+16.04.20160126/testsuite/geis1/gtest_attrs.cpp0000644000015600001650000000670512651717544023230 0ustar pbuserpbgroup00000000000000/** * Gtest test suite for GEIS v1 attributes. * * Copyright 2012 Canonical Ltd. */ #include #include "geis/geis.h" #include "gtest_evemu_device.h" #include "gtest_geis1_fixture.h" #include #include #include #include namespace { const std::string TEST_DEVICE_PROP_FILE(TEST_ROOT_DIR "recordings/apple_magic_trackpad/device.prop"); const std::string TEST_DEVICE_EVENTS_FILE(TEST_ROOT_DIR "recordings/apple_magic_trackpad/four_tap.record"); /** * Fixture for testing expected attributes. This has to be a separate class * because of the way Java reflection is used in jUnit. */ class Geis1AttributeTests : public GTestGeis1Fixture { public: Geis1AttributeTests() : evemu_device_(TEST_DEVICE_PROP_FILE), saw_four_tap(false) { } void GestureUpdate(GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs); protected: Testsuite::EvemuDevice evemu_device_; bool saw_four_tap; }; void gesture_begin(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { FAIL() << "received unexpected gesture begin event"; } void gesture_update(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { Geis1AttributeTests* fixture = reinterpret_cast(cookie); fixture->GestureUpdate(type, id, count, attrs); } void gesture_end(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { FAIL() << "received unexpected gesture end event"; } void gesture_null_func(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { } void Geis1AttributeTests::GestureUpdate(GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { EXPECT_EQ(GEIS_GESTURE_PRIMITIVE_TAP, type); EXPECT_FALSE(saw_four_tap); for (int i = 0; i < count; i++) { GeisGestureAttr attr = attrs[i]; if (strcmp(attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0) { ASSERT_EQ(4, attr.integer_val); saw_four_tap = true; return; } } } /* * Regression test for lp:957331, lp:957334, and lp:957344: geis v1 tap handling * * A geis v1 four tap system subscription is created, and a four tap gesture is * replayed on a touchpad device. * * Expected: One four touch tap gesture update event is received. No other * events should be seen. */ TEST_F(Geis1AttributeTests, tap_touch_count) { static const char* gestures[] = { GEIS_GESTURE_TYPE_TAP4, GEIS_GESTURE_TYPE_SYSTEM, }; static GeisGestureFuncs callbacks = { &gesture_null_func, &gesture_null_func, &gesture_begin, &gesture_update, &gesture_update, }; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_subscribe(geis(), GEIS_ALL_INPUT_DEVICES, gestures, &callbacks, this)); evemu_device_.play(TEST_DEVICE_EVENTS_FILE); while (1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(geis_fd(), &read_fds); timeval tmo = { 1, 0 }; int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo); EXPECT_GT(sstat, -1) << "error in select"; if (sstat == 0) break; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_event_dispatch(geis())); } EXPECT_TRUE(saw_four_tap); } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/geis1/Makefile.am0000644000015600001650000000330012651717544022201 0ustar pbuserpbgroup00000000000000# # @file testsuite/geis1/Makefile.am # @brief automake recipe for the geis v1.0 testsuite unit testing directory # test_targets = if HAVE_CHECK test_targets += check_geis1_api endif if ENABLE_INTEGRATION_TESTS test_targets += gtest_geis1_instance gtest_geis1_api endif TESTS = $(test_targets) check_PROGRAMS = $(test_targets) check_geis1_api_SOURCES = \ check_instance.c \ check_gesture_types.c \ check_gesture_attrs.c \ check_subscription.c \ check_geis1_api.c check_geis1_api_CFLAGS = \ -Wno-unused-but-set-variable \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ $(CHECK_CFLAGS) check_geis1_api_LDADD = \ $(top_builddir)/libgeis/libgeis.la \ $(CHECK_LIBS) gtest_geis1_api_SOURCES = \ gtest_attrs.cpp \ gtest_devices.cpp \ gtest_subscription.cpp nodist_gtest_geis1_api_SOURCES = \ $(XORG_GTEST_SOURCE)/src/xorg-gtest_main.cpp gtest_geis1_api_CPPFLAGS = \ --std=c++0x \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libgeis \ -I$(top_srcdir)/testsuite/gtest \ -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\" \ $(GTEST_CFLAGS) \ $(EVEMU_CFLAGS) \ $(XORG_GTEST_CPPFLAGS) gtest_geis1_api_LDADD = \ $(top_builddir)/testsuite/gtest/libgtest_geis.a \ $(top_builddir)/libgeis/libgeis.la \ $(XORG_GTEST_LIBS) \ $(EVEMU_LIBS) \ $(XI2_LIBS) gtest_geis1_instance_SOURCES = gtest_instance.cpp nodist_gtest_geis1_instance_SOURCES = $(nodist_gtest_geis1_api_SOURCES) gtest_geis1_instance_CPPFLAGS = $(gtest_geis1_api_CPPFLAGS) gtest_geis1_instance_LDADD = $(gtest_geis1_api_LDADD) MOSTLYCLEANFILES = \ geis1_api.log \ geis1_api.xml geis-2.2.17+16.04.20160126/testsuite/geis1/check_gesture_attrs.c0000644000015600001650000001221312651717544024344 0ustar pbuserpbgroup00000000000000/** * @file check_gesture_attrs.c * @brief Unit tests for GEIS v1 gesture attrs * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #define GEIS_TEST_WINDOW geis_win_type_str(Test) static const char* s_gestures[] = { GEIS_GESTURE_TYPE_DRAG2, GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_TYPE_PINCH2, GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_TYPE_ROTATE2, GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_TYPE_TAP2, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_TAP4, NULL }; struct test_data_t { int count_728606; int count_732104; }; static void gesture_added(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } static void gesture_removed(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } /* * Checks for special values generated by the mock back end. */ static void gesture_start(void *cookie, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count, GeisGestureAttr *attrs) { GeisSize i; struct test_data_t *test_data = (struct test_data_t*)cookie; for (i = 0; i < attr_count; ++i) { if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) && fabs(attrs[i].float_val - 123.456) < 0.01) { ++test_data->count_728606; } else if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) && fabs(attrs[i].float_val - 987.654) < 0.01) { ++test_data->count_728606; } else if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) && attrs[i].integer_val == 1) { ++test_data->count_732104; } } } static void gesture_update(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } static void gesture_finish(void *cookie CK_ATTRIBUTE_UNUSED, GeisGestureType gesture_type CK_ATTRIBUTE_UNUSED, GeisGestureId gesture_id CK_ATTRIBUTE_UNUSED, GeisSize attr_count CK_ATTRIBUTE_UNUSED, GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED) { } GeisGestureFuncs gesture_funcs = { gesture_added, gesture_removed, gesture_start, gesture_update, gesture_finish }; /* fixtures */ static GeisInstance g_instance; /* fixture setup */ static void construct_instance() { GeisStatus status; GeisXcbWinInfo x_win_info = { .display_name = NULL, .screenp = NULL, .window_id = 1 }; GeisWinInfo win_info = { GEIS_TEST_WINDOW, &x_win_info }; status = geis_init(&win_info, &g_instance); } /* fixture teardown */ static void destroy_instance() { geis_finish(g_instance); } START_TEST(receive_events) { GeisStatus status; struct test_data_t test_data; memset(&test_data, 0, sizeof(test_data)); status = geis_subscribe(g_instance, GEIS_ALL_INPUT_DEVICES, s_gestures, &gesture_funcs, &test_data); fail_unless(status == GEIS_STATUS_SUCCESS, "subscription failed"); while (GEIS_STATUS_CONTINUE == geis_event_dispatch(g_instance)) ; /* Regression test for bug LP: #728606. */ fail_unless(test_data.count_728606 == 2, "unexpected count for LP:728606: expected 2, got %d", test_data.count_728606); fail_unless(test_data.count_732104 == 0, "unexpected count for LP:732104: expected 0, got %d", test_data.count_732104); } END_TEST Suite * geis1_gesture_attrs_new() { Suite *s = suite_create("geis1_gesture_attrs"); TCase *test; test = tcase_create("lp728606"); tcase_add_checked_fixture(test, construct_instance, destroy_instance); tcase_add_test(test, receive_events); suite_add_tcase(s, test); return s; } geis-2.2.17+16.04.20160126/testsuite/geis1/check_instance.c0000644000015600001650000000306312651717544023260 0ustar pbuserpbgroup00000000000000/** * @file check_instance.c * @brief Unit testing driver for GEIS v1 API geisInstance functions. * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #define GEIS_TEST_WINDOW geis_win_type_str(Test) /* compile-time test to ensure required functions are defined */ START_TEST(geis_init_and_finish) { GeisStatus status; GeisInstance instance; GeisWinInfo win_info = { GEIS_TEST_WINDOW, NULL }; status = geis_init(&win_info, &instance); fail_unless(status == GEIS_STATUS_SUCCESS, "geis_init failed"); status = geis_finish(instance); fail_unless(status == GEIS_STATUS_SUCCESS, "geis_finish failed"); } END_TEST Suite * geis1_instance_suite_new() { TCase *create; Suite *s = suite_create("geis1_instance_suite"); create = tcase_create("geis_init"); tcase_add_test(create, geis_init_and_finish); suite_add_tcase(s, create); return s; } geis-2.2.17+16.04.20160126/testsuite/geis1/check_gesture_types.c0000644000015600001650000000470112651717544024356 0ustar pbuserpbgroup00000000000000/** * @file check_gesture_types.c * @brief Unit tests for GEIS v1 gesture types * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include START_TEST(gesture_types) { GeisInteger geis_type; GeisString geis_type_name; geis_type = GEIS_GESTURE_PRIMITIVE_DRAG; geis_type = GEIS_GESTURE_PRIMITIVE_PINCH; geis_type = GEIS_GESTURE_PRIMITIVE_ROTATE; geis_type = GEIS_GESTURE_PRIMITIVE_TAP; geis_type = GEIS_GESTURE_PRIMITIVE_TOUCH; geis_type_name = GEIS_GESTURE_TYPE_DRAG1; geis_type_name = GEIS_GESTURE_TYPE_DRAG2; geis_type_name = GEIS_GESTURE_TYPE_DRAG3; geis_type_name = GEIS_GESTURE_TYPE_DRAG4; geis_type_name = GEIS_GESTURE_TYPE_DRAG5; geis_type_name = GEIS_GESTURE_TYPE_PINCH1; geis_type_name = GEIS_GESTURE_TYPE_PINCH2; geis_type_name = GEIS_GESTURE_TYPE_PINCH3; geis_type_name = GEIS_GESTURE_TYPE_PINCH4; geis_type_name = GEIS_GESTURE_TYPE_PINCH5; geis_type_name = GEIS_GESTURE_TYPE_ROTATE1; geis_type_name = GEIS_GESTURE_TYPE_ROTATE2; geis_type_name = GEIS_GESTURE_TYPE_ROTATE3; geis_type_name = GEIS_GESTURE_TYPE_ROTATE4; geis_type_name = GEIS_GESTURE_TYPE_ROTATE5; geis_type_name = GEIS_GESTURE_TYPE_TAP1; geis_type_name = GEIS_GESTURE_TYPE_TAP2; geis_type_name = GEIS_GESTURE_TYPE_TAP3; geis_type_name = GEIS_GESTURE_TYPE_TAP4; geis_type_name = GEIS_GESTURE_TYPE_TAP5; geis_type_name = GEIS_GESTURE_TYPE_TOUCH1; geis_type_name = GEIS_GESTURE_TYPE_TOUCH2; geis_type_name = GEIS_GESTURE_TYPE_TOUCH3; geis_type_name = GEIS_GESTURE_TYPE_TOUCH4; geis_type_name = GEIS_GESTURE_TYPE_TOUCH5; } END_TEST Suite * geis1_gesture_types_new() { Suite *s = suite_create("geis1_gesture_types"); TCase *test; test = tcase_create("gesture_types"); tcase_add_test(test, gesture_types); suite_add_tcase(s, test); return s; } geis-2.2.17+16.04.20160126/testsuite/geis1/check_geis1_api.c0000644000015600001650000000304412651717544023314 0ustar pbuserpbgroup00000000000000/** * @file check_geis1_api.c * @brief Unit testing driver for GEIS v1 API. * * Copyright 2011 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * 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 program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include extern Suite *geis1_instance_suite_new(); extern Suite *geis1_gesture_types_new(); extern Suite *geis1_gesture_attrs_new(); extern Suite *geis1_subscription_new(); int main(int argc CK_ATTRIBUTE_UNUSED, char* argv[] CK_ATTRIBUTE_UNUSED) { int num_failed = 0; Suite *s = suite_create("GEIS v1.0 API"); SRunner *sr = srunner_create(s); srunner_add_suite(sr, geis1_instance_suite_new()); srunner_add_suite(sr, geis1_gesture_types_new()); srunner_add_suite(sr, geis1_gesture_attrs_new()); srunner_add_suite(sr, geis1_subscription_new()); srunner_set_log(sr, "geis1_api.log"); srunner_set_xml(sr, "geis1_api.xml"); srunner_run_all(sr, CK_NORMAL); num_failed = srunner_ntests_failed(sr); srunner_free(sr); return !(num_failed == 0); } geis-2.2.17+16.04.20160126/testsuite/geis1/gtest_subscription.cpp0000644000015600001650000000276012651717544024614 0ustar pbuserpbgroup00000000000000/** * Gtest test suite for GEIS v1 subscriptions. * * Copyright 2012 Canonical Ltd. */ #include "geis/geis.h" #include "gtest_geis1_fixture.h" #include namespace { /** * Fixture for testing expected attributes. This has to be a separate class * because of the way Java reflection is used in jUnit. */ class Geis1SubscriptionTests : public GTestGeis1Fixture { }; void gesture_null_func(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { } /* * Regression test for lp:936815. * * Ths test would segfault in geis_filter_delete() before the fix for lp:936815 * was applied. The problem only obtained when more than one gesture type was * subscribed. * */ TEST_F(Geis1SubscriptionTests, basic) { static const char* gestures[] = { GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_TYPE_TOUCH3, GEIS_GESTURE_TYPE_DRAG4, GEIS_GESTURE_TYPE_TAP4, GEIS_GESTURE_TYPE_ROTATE4, GEIS_GESTURE_TYPE_PINCH4, GEIS_GESTURE_TYPE_TOUCH4, GEIS_GESTURE_TYPE_SYSTEM, NULL }; static GeisGestureFuncs callbacks = { &gesture_null_func, &gesture_null_func, &gesture_null_func, &gesture_null_func, &gesture_null_func, }; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_subscribe(geis(), GEIS_ALL_INPUT_DEVICES, gestures, &callbacks, this)); } } // anonymous namespace geis-2.2.17+16.04.20160126/testsuite/geis1/gtest_devices.cpp0000644000015600001650000000634612651717544023516 0ustar pbuserpbgroup00000000000000/** * GTest test suite for GEIS v1 device handling. * * Copyright 2012 Canonical Ltd. */ #include "geis/geis.h" #include "gtest_evemu_device.h" #include "gtest_geis1_fixture.h" #include "libgeis/geis_test_api.h" #include static const std::string TEST_DEVICE_PROP_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/device.prop"); static const std::string TEST_DEVICE_EVENTS_FILE( TEST_ROOT_DIR "recordings/touchscreen_a/drag_2.record"); /** * Fixture for testing device handling. * This is a separate class because gtest uses Java reflection. */ class Geis1DeviceTests : public GTestGeis1Fixture { public: Geis1DeviceTests() : saw_events_(false) {} void GestureUpdate(GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs); void UseNewDevice(); protected: void CreateNewDevice(); std::unique_ptr new_device_; bool saw_events_; }; namespace { void gesture_update_func(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { Geis1DeviceTests* fixture = reinterpret_cast(cookie); fixture->GestureUpdate(type, id, count, attrs); } void gesture_null_func(void* cookie, GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { } void device_added_func(void* cookie, GeisInputDeviceId deviceId, void* attrs) { Geis1DeviceTests* fixture = reinterpret_cast(cookie); fixture->UseNewDevice(); } void device_null_func(void* cookie, GeisInputDeviceId deviceId, void* attrs) { } } // namespace void Geis1DeviceTests::GestureUpdate(GeisGestureType type, GeisGestureId id, GeisSize count, GeisGestureAttr* attrs) { saw_events_ = true; } void Geis1DeviceTests::CreateNewDevice() { new_device_.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); } void Geis1DeviceTests::UseNewDevice() { new_device_->play(TEST_DEVICE_EVENTS_FILE); } /* * Test case for lp:1009270 -- Geis v1 does not report gestures for new devices * * Creates a subscription before a device is present. A device is added, and * then events are played. Gesture events should be detected. */ TEST_F(Geis1DeviceTests, addDeviceSubscription) { static const char* gestures[] = { GEIS_GESTURE_TYPE_DRAG2, NULL }; static GeisGestureFuncs callbacks = { &gesture_null_func, &gesture_null_func, &gesture_null_func, &gesture_update_func, &gesture_null_func, }; static GeisInputFuncs inputfuncs = { &device_added_func, &device_null_func, &device_null_func, }; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_input_devices(geis(), &inputfuncs, this)); ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_subscribe(geis(), GEIS_ALL_INPUT_DEVICES, gestures, &callbacks, this)); CreateNewDevice(); while (1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(geis_fd(), &read_fds); timeval tmo = { 1, 0 }; int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo); EXPECT_GT(sstat, -1) << "error in select"; if (sstat == 0) break; ASSERT_EQ(GEIS_STATUS_SUCCESS, geis_event_dispatch(geis())); } EXPECT_TRUE(saw_events_); } geis-2.2.17+16.04.20160126/testsuite/recordings/0000755000015600001650000000000012651717732021277 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/recordings/test_device1/0000755000015600001650000000000012651717732023656 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/recordings/test_device1/device.prop0000644000015600001650000000150712651717544026023 0ustar pbuserpbgroup00000000000000N: Test Device1 I: 0011 0002 0007 01b1 P: 09 00 00 00 00 00 00 00 B: 00 0b 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 03 00 00 00 00 00 B: 01 20 64 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 02 00 00 00 00 00 00 00 00 B: 03 03 00 00 11 00 80 60 02 B: 04 00 00 00 00 00 00 00 00 B: 05 00 00 00 00 00 00 00 00 B: 11 00 00 00 00 00 00 00 00 B: 12 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 A: 00 1472 5888 0 0 A: 01 1408 4820 0 0 A: 18 0 255 0 0 A: 1c 0 15 0 0 A: 2f 0 1 0 0 A: 35 1472 5888 0 0 A: 36 1408 4820 0 0 A: 39 0 65535 0 0 geis-2.2.17+16.04.20160126/testsuite/recordings/test_device1/events.record0000644000015600001650000001616512651717544026374 0ustar pbuserpbgroup00000000000000E: 1323109478.604936 0003 0039 52 E: 1323109478.604938 0003 0035 3367 E: 1323109478.604939 0003 0036 2268 E: 1323109478.604942 0003 0000 3367 E: 1323109478.604943 0003 0001 2268 E: 1323109478.604944 0003 0018 9 E: 1323109478.604944 0003 001c 13 E: 1323109478.604945 0001 0145 1 E: 1323109478.604947 0000 0000 0 E: 1323109478.629818 0003 0035 3363 E: 1323109478.629822 0003 0000 3363 E: 1323109478.629825 0003 001c 12 E: 1323109478.629827 0000 0000 0 E: 1323109478.641338 0003 0035 3373 E: 1323109478.641340 0003 0036 2187 E: 1323109478.641343 0003 0000 3373 E: 1323109478.641343 0003 0001 2187 E: 1323109478.641344 0003 0018 10 E: 1323109478.641345 0003 001c 14 E: 1323109478.641347 0000 0000 0 E: 1323109478.653409 0003 0018 11 E: 1323109478.653411 0003 001c 12 E: 1323109478.653413 0000 0000 0 E: 1323109478.665509 0003 0035 3389 E: 1323109478.665510 0003 0036 2151 E: 1323109478.665513 0003 0000 3389 E: 1323109478.665514 0003 0001 2151 E: 1323109478.665514 0003 0018 12 E: 1323109478.665517 0000 0000 0 E: 1323109478.676566 0003 0035 3406 E: 1323109478.676568 0003 0036 2106 E: 1323109478.676571 0003 0000 3406 E: 1323109478.676572 0003 0001 2106 E: 1323109478.676573 0003 0018 15 E: 1323109478.676573 0003 001c 11 E: 1323109478.676575 0000 0000 0 E: 1323109478.688397 0003 0035 3413 E: 1323109478.688398 0003 0036 2055 E: 1323109478.688399 0003 0000 3413 E: 1323109478.688400 0003 0001 2055 E: 1323109478.688400 0003 0018 19 E: 1323109478.688401 0003 001c 10 E: 1323109478.688402 0000 0000 0 E: 1323109478.701637 0003 0035 3432 E: 1323109478.701639 0003 0036 2013 E: 1323109478.701641 0003 0000 3432 E: 1323109478.701642 0003 0001 2013 E: 1323109478.701643 0003 0018 27 E: 1323109478.701644 0003 001c 8 E: 1323109478.701646 0000 0000 0 E: 1323109478.724960 0003 0035 2458 E: 1323109478.724961 0003 0036 3190 E: 1323109478.724962 0003 002f 1 E: 1323109478.724962 0003 0039 53 E: 1323109478.724962 0003 0035 3424 E: 1323109478.724962 0003 0036 1977 E: 1323109478.724963 0001 014a 1 E: 1323109478.724963 0003 0000 3424 E: 1323109478.724964 0003 0001 1977 E: 1323109478.724964 0003 0018 42 E: 1323109478.724965 0003 001c 5 E: 1323109478.724965 0001 0145 0 E: 1323109478.724966 0001 014d 1 E: 1323109478.724966 0000 0000 0 E: 1323109478.748390 0003 002f 0 E: 1323109478.748391 0003 0035 2380 E: 1323109478.748391 0003 0036 3220 E: 1323109478.748394 0003 002f 1 E: 1323109478.748394 0003 0035 3416 E: 1323109478.748394 0003 0036 1961 E: 1323109478.748396 0003 0000 3416 E: 1323109478.748396 0003 0001 1961 E: 1323109478.748397 0003 0018 49 E: 1323109478.748400 0000 0000 0 E: 1323109478.772694 0003 002f 0 E: 1323109478.772695 0003 0035 2372 E: 1323109478.772695 0003 0036 3212 E: 1323109478.772696 0003 002f 1 E: 1323109478.772696 0003 0035 3412 E: 1323109478.772697 0003 0036 1953 E: 1323109478.772698 0003 0000 3412 E: 1323109478.772699 0003 0001 1953 E: 1323109478.772699 0003 0018 51 E: 1323109478.772701 0000 0000 0 E: 1323109478.797052 0003 002f 0 E: 1323109478.797053 0003 0035 2402 E: 1323109478.797054 0003 0036 3216 E: 1323109478.797058 0003 002f 1 E: 1323109478.797059 0003 0035 3415 E: 1323109478.797060 0003 0036 1956 E: 1323109478.797066 0003 0000 3415 E: 1323109478.797066 0003 0001 1956 E: 1323109478.797067 0003 0018 53 E: 1323109478.797069 0000 0000 0 E: 1323109478.821436 0003 002f 0 E: 1323109478.821437 0003 0035 2472 E: 1323109478.821438 0003 0036 3192 E: 1323109478.821443 0003 002f 1 E: 1323109478.821443 0003 0035 3506 E: 1323109478.821444 0003 0036 1986 E: 1323109478.821450 0003 0000 3506 E: 1323109478.821451 0003 0001 1986 E: 1323109478.821451 0003 0018 54 E: 1323109478.821454 0000 0000 0 E: 1323109478.845271 0003 002f 0 E: 1323109478.845272 0003 0035 2592 E: 1323109478.845272 0003 0036 3196 E: 1323109478.845273 0003 002f 1 E: 1323109478.845273 0003 0035 3675 E: 1323109478.845274 0003 0036 2012 E: 1323109478.845275 0003 0000 3675 E: 1323109478.845275 0003 0001 2012 E: 1323109478.845275 0003 0018 55 E: 1323109478.845277 0000 0000 0 E: 1323109478.870003 0003 002f 0 E: 1323109478.870004 0003 0035 2816 E: 1323109478.870005 0003 0036 3178 E: 1323109478.870008 0003 002f 1 E: 1323109478.870008 0003 0035 3866 E: 1323109478.870009 0003 0036 2030 E: 1323109478.870010 0003 0000 3866 E: 1323109478.870011 0003 0001 2030 E: 1323109478.870012 0003 0018 56 E: 1323109478.870015 0000 0000 0 E: 1323109478.893759 0003 002f 0 E: 1323109478.893760 0003 0035 2994 E: 1323109478.893760 0003 0036 3166 E: 1323109478.893763 0003 002f 1 E: 1323109478.893763 0003 0035 4069 E: 1323109478.893764 0003 0036 2019 E: 1323109478.893766 0003 0000 4069 E: 1323109478.893767 0003 0001 2019 E: 1323109478.893771 0000 0000 0 E: 1323109478.918183 0003 002f 0 E: 1323109478.918183 0003 0035 3162 E: 1323109478.918184 0003 0036 3132 E: 1323109478.918187 0003 002f 1 E: 1323109478.918187 0003 0035 4214 E: 1323109478.918188 0003 0036 2006 E: 1323109478.918190 0003 0000 4214 E: 1323109478.918190 0003 0001 2006 E: 1323109478.918194 0000 0000 0 E: 1323109478.941450 0003 002f 0 E: 1323109478.941451 0003 0035 3250 E: 1323109478.941452 0003 0036 3124 E: 1323109478.941456 0003 002f 1 E: 1323109478.941456 0003 0035 4282 E: 1323109478.941457 0003 0036 1974 E: 1323109478.941460 0003 0000 4282 E: 1323109478.941461 0003 0001 1974 E: 1323109478.941467 0000 0000 0 E: 1323109478.966043 0003 002f 0 E: 1323109478.966044 0003 0035 3274 E: 1323109478.966045 0003 0036 3132 E: 1323109478.966048 0003 002f 1 E: 1323109478.966048 0003 0035 4296 E: 1323109478.966049 0003 0036 1973 E: 1323109478.966050 0003 0000 4296 E: 1323109478.966051 0003 0001 1973 E: 1323109478.966055 0000 0000 0 E: 1323109478.990133 0003 002f 0 E: 1323109478.990134 0003 0035 3282 E: 1323109478.990135 0003 0036 3180 E: 1323109478.990138 0003 002f 1 E: 1323109478.990138 0003 0035 4299 E: 1323109478.990138 0003 0036 1992 E: 1323109478.990140 0003 0000 4299 E: 1323109478.990141 0003 0001 1992 E: 1323109478.990145 0000 0000 0 E: 1323109479.014380 0003 002f 0 E: 1323109479.014381 0003 0035 3270 E: 1323109479.014382 0003 0036 3264 E: 1323109479.014385 0003 002f 1 E: 1323109479.014385 0003 0035 4142 E: 1323109479.014386 0003 0036 3230 E: 1323109479.014388 0001 014a 0 E: 1323109479.014389 0003 0000 4142 E: 1323109479.014390 0003 0001 3230 E: 1323109479.014391 0003 0018 17 E: 1323109479.014395 0000 0000 0 E: 1323109479.026385 0003 002f 0 E: 1323109479.026386 0003 0035 3326 E: 1323109479.026387 0003 0036 3086 E: 1323109479.026388 0003 002f 1 E: 1323109479.026388 0003 0039 -1 E: 1323109479.026390 0003 0000 3326 E: 1323109479.026391 0003 0001 3086 E: 1323109479.026392 0003 0018 7 E: 1323109479.026393 0003 001c 15 E: 1323109479.026394 0001 0145 1 E: 1323109479.026395 0001 014d 0 E: 1323109479.026396 0000 0000 0 E: 1323109479.038191 0003 002f 0 E: 1323109479.038192 0003 0035 3446 E: 1323109479.038197 0003 0000 3446 E: 1323109479.038199 0003 0018 4 E: 1323109479.038206 0000 0000 0 E: 1323109479.050230 0003 0039 -1 E: 1323109479.050234 0003 0018 2 E: 1323109479.050235 0003 001c 0 E: 1323109479.050236 0001 0145 0 E: 1323109479.050237 0000 0000 0 E: 1323109479.075276 0003 0018 1 E: 1323109479.075278 0000 0000 0 E: 1323109479.099762 0003 0018 0 E: 1323109479.099764 0000 0000 0 E: 1323109479.654050 0003 0018 1 E: 1323109479.654052 0000 0000 0 E: 1323109479.689390 0003 0018 0 E: 1323109479.689391 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/apple_magic_trackpad/0000755000015600001650000000000012651717732025411 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/recordings/apple_magic_trackpad/device.prop0000644000015600001650000000155212651717544027556 0ustar pbuserpbgroup00000000000000N: Apple Magic Trackpad (Virtual Test Device) I: 0005 05ac 030e 0160 P: 00 00 00 00 00 00 00 00 B: 00 1b 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 03 00 01 00 00 00 00 00 B: 01 20 e4 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 02 00 00 00 00 00 00 00 00 B: 03 03 00 00 00 00 00 73 02 B: 04 10 00 00 00 00 00 00 00 B: 05 00 00 00 00 00 00 00 00 B: 11 00 00 00 00 00 00 00 00 B: 12 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 A: 00 -2909 3167 4 0 A: 01 -2456 2565 4 0 A: 30 0 255 4 0 A: 31 0 255 4 0 A: 34 -31 32 1 0 A: 35 -2909 3167 4 0 A: 36 -2456 2565 4 0 A: 39 0 15 0 0 geis-2.2.17+16.04.20160126/testsuite/recordings/apple_magic_trackpad/four_tap.record0000644000015600001650000000423312651717544030433 0ustar pbuserpbgroup00000000000000E: 1331064360.324674 0003 0039 0 E: 1331064360.324676 0003 0030 168 E: 1331064360.324678 0003 0031 228 E: 1331064360.324679 0003 0034 0 E: 1331064360.324681 0003 0035 56 E: 1331064360.324682 0003 0036 -371 E: 1331064360.324684 0000 0002 0 E: 1331064360.324674 0003 0039 1 E: 1331064360.324676 0003 0030 168 E: 1331064360.324678 0003 0031 228 E: 1331064360.324679 0003 0034 0 E: 1331064360.324681 0003 0035 156 E: 1331064360.324682 0003 0036 -371 E: 1331064360.324684 0000 0002 0 E: 1331064360.324674 0003 0039 2 E: 1331064360.324676 0003 0030 168 E: 1331064360.324678 0003 0031 228 E: 1331064360.324679 0003 0034 0 E: 1331064360.324681 0003 0035 256 E: 1331064360.324682 0003 0036 -371 E: 1331064360.324684 0000 0002 0 E: 1331064360.324674 0003 0039 3 E: 1331064360.324676 0003 0030 168 E: 1331064360.324678 0003 0031 228 E: 1331064360.324679 0003 0034 0 E: 1331064360.324681 0003 0035 356 E: 1331064360.324682 0003 0036 -371 E: 1331064360.324684 0000 0002 0 E: 1331064360.324686 0001 014a 1 E: 1331064360.324687 0001 0145 1 E: 1331064360.324689 0003 0000 56 E: 1331064360.324691 0003 0001 -371 E: 1331064360.324692 0000 0000 0 E: 1331064360.358384 0003 0039 0 E: 1331064360.358386 0003 0030 0 E: 1331064360.358387 0003 0031 0 E: 1331064360.358388 0003 0034 0 E: 1331064360.358390 0003 0035 56 E: 1331064360.358391 0003 0036 -371 E: 1331064360.358393 0000 0002 0 E: 1331064360.358384 0003 0039 1 E: 1331064360.358386 0003 0030 0 E: 1331064360.358387 0003 0031 0 E: 1331064360.358388 0003 0034 0 E: 1331064360.358390 0003 0035 156 E: 1331064360.358391 0003 0036 -371 E: 1331064360.358393 0000 0002 0 E: 1331064360.358384 0003 0039 2 E: 1331064360.358386 0003 0030 0 E: 1331064360.358387 0003 0031 0 E: 1331064360.358388 0003 0034 0 E: 1331064360.358390 0003 0035 256 E: 1331064360.358391 0003 0036 -371 E: 1331064360.358393 0000 0002 0 E: 1331064360.358384 0003 0039 3 E: 1331064360.358386 0003 0030 0 E: 1331064360.358387 0003 0031 0 E: 1331064360.358388 0003 0034 0 E: 1331064360.358390 0003 0035 356 E: 1331064360.358391 0003 0036 -371 E: 1331064360.358393 0000 0002 0 E: 1331064360.358398 0000 0000 0 E: 1331064360.369463 0001 014a 0 E: 1331064360.369464 0001 0145 0 E: 1331064360.369466 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/0000755000015600001650000000000012651717732024121 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/device.prop0000644000015600001650000000151012651717544026260 0ustar pbuserpbgroup00000000000000N: Touchscreen (type A) Test Device I: 0003 1b96 0001 0110 P: 00 00 00 00 00 00 00 00 B: 00 0b 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 04 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 02 00 00 00 00 00 00 00 00 B: 03 03 00 00 00 00 00 73 00 B: 04 00 00 00 00 00 00 00 00 B: 05 00 00 00 00 00 00 00 00 B: 11 00 00 00 00 00 00 00 00 B: 12 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 A: 00 0 9600 75 0 A: 01 0 7200 78 0 A: 30 0 9600 200 0 A: 31 0 7200 150 0 A: 34 0 1 0 0 A: 35 0 9600 75 0 A: 36 0 7200 78 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/pinch_2.record0000644000015600001650000005475312651717544026662 0ustar pbuserpbgroup00000000000000E: 1334936017.793211 0003 0000 5524 E: 1334936017.793213 0003 0001 2043 E: 1334936017.793213 0003 0035 5524 E: 1334936017.793214 0003 0036 2043 E: 1334936017.793215 0003 0034 0 E: 1334936017.793215 0003 0030 312 E: 1334936017.793216 0003 0031 204 E: 1334936017.793216 0000 0002 0 E: 1334936017.793301 0001 014d 1 E: 1334936017.793302 0001 014a 1 E: 1334936017.793303 0000 0000 0 E: 1334936017.803241 0003 0000 5525 E: 1334936017.803243 0003 0001 2058 E: 1334936017.803244 0003 0035 5525 E: 1334936017.803245 0003 0036 2058 E: 1334936017.803246 0003 0034 0 E: 1334936017.803247 0003 0030 312 E: 1334936017.803247 0003 0031 204 E: 1334936017.803248 0000 0002 0 E: 1334936017.803278 0003 0035 3825 E: 1334936017.803279 0003 0036 5333 E: 1334936017.803280 0003 0034 0 E: 1334936017.803280 0003 0030 312 E: 1334936017.803281 0003 0031 306 E: 1334936017.803282 0000 0002 0 E: 1334936017.803394 0000 0000 0 E: 1334936017.815216 0003 0000 5521 E: 1334936017.815217 0003 0001 2075 E: 1334936017.815218 0003 0035 5521 E: 1334936017.815218 0003 0036 2075 E: 1334936017.815219 0003 0034 0 E: 1334936017.815219 0003 0030 312 E: 1334936017.815219 0003 0031 204 E: 1334936017.815220 0000 0002 0 E: 1334936017.815233 0003 0035 3826 E: 1334936017.815234 0003 0036 5319 E: 1334936017.815234 0003 0034 0 E: 1334936017.815235 0003 0030 312 E: 1334936017.815235 0003 0031 306 E: 1334936017.815236 0000 0002 0 E: 1334936017.815286 0000 0000 0 E: 1334936017.827266 0003 0000 5531 E: 1334936017.827268 0003 0001 2149 E: 1334936017.827269 0003 0035 5531 E: 1334936017.827270 0003 0036 2149 E: 1334936017.827272 0003 0034 0 E: 1334936017.827273 0003 0030 312 E: 1334936017.827274 0003 0031 204 E: 1334936017.827275 0000 0002 0 E: 1334936017.827307 0003 0035 3830 E: 1334936017.827309 0003 0036 5340 E: 1334936017.827310 0003 0034 0 E: 1334936017.827311 0003 0030 468 E: 1334936017.827312 0003 0031 306 E: 1334936017.827313 0000 0002 0 E: 1334936017.827437 0000 0000 0 E: 1334936017.841313 0003 0000 5534 E: 1334936017.841315 0003 0001 2143 E: 1334936017.841316 0003 0035 5534 E: 1334936017.841317 0003 0036 2143 E: 1334936017.841318 0003 0034 0 E: 1334936017.841319 0003 0030 312 E: 1334936017.841321 0003 0031 204 E: 1334936017.841322 0000 0002 0 E: 1334936017.841355 0003 0035 3854 E: 1334936017.841356 0003 0036 5351 E: 1334936017.841357 0003 0034 0 E: 1334936017.841358 0003 0030 468 E: 1334936017.841359 0003 0031 306 E: 1334936017.841360 0000 0002 0 E: 1334936017.841485 0000 0000 0 E: 1334936017.853324 0003 0000 5521 E: 1334936017.853326 0003 0001 2161 E: 1334936017.853327 0003 0035 5521 E: 1334936017.853328 0003 0036 2161 E: 1334936017.853329 0003 0034 0 E: 1334936017.853331 0003 0030 312 E: 1334936017.853332 0003 0031 204 E: 1334936017.853333 0000 0002 0 E: 1334936017.853366 0003 0035 3836 E: 1334936017.853367 0003 0036 5339 E: 1334936017.853368 0003 0034 0 E: 1334936017.853369 0003 0030 468 E: 1334936017.853370 0003 0031 306 E: 1334936017.853371 0000 0002 0 E: 1334936017.853496 0000 0000 0 E: 1334936017.865301 0003 0000 5522 E: 1334936017.865303 0003 0001 2179 E: 1334936017.865304 0003 0035 5522 E: 1334936017.865306 0003 0036 2179 E: 1334936017.865308 0003 0034 0 E: 1334936017.865309 0003 0030 312 E: 1334936017.865310 0003 0031 204 E: 1334936017.865312 0000 0002 0 E: 1334936017.865356 0003 0035 3839 E: 1334936017.865357 0003 0036 5340 E: 1334936017.865358 0003 0034 0 E: 1334936017.865359 0003 0030 468 E: 1334936017.865360 0003 0031 306 E: 1334936017.865362 0000 0002 0 E: 1334936017.865487 0000 0000 0 E: 1334936017.877283 0003 0000 5526 E: 1334936017.877284 0003 0001 2186 E: 1334936017.877286 0003 0035 5526 E: 1334936017.877287 0003 0036 2186 E: 1334936017.877288 0003 0034 0 E: 1334936017.877289 0003 0030 312 E: 1334936017.877290 0003 0031 204 E: 1334936017.877291 0000 0002 0 E: 1334936017.877324 0003 0035 3848 E: 1334936017.877325 0003 0036 5362 E: 1334936017.877326 0003 0034 0 E: 1334936017.877327 0003 0030 468 E: 1334936017.877328 0003 0031 306 E: 1334936017.877329 0000 0002 0 E: 1334936017.877480 0000 0000 0 E: 1334936017.891333 0003 0000 5511 E: 1334936017.891335 0003 0001 2195 E: 1334936017.891336 0003 0035 5511 E: 1334936017.891337 0003 0036 2195 E: 1334936017.891338 0003 0034 0 E: 1334936017.891340 0003 0030 312 E: 1334936017.891341 0003 0031 306 E: 1334936017.891342 0000 0002 0 E: 1334936017.891375 0003 0035 3847 E: 1334936017.891376 0003 0036 5338 E: 1334936017.891377 0003 0034 0 E: 1334936017.891378 0003 0030 468 E: 1334936017.891379 0003 0031 306 E: 1334936017.891380 0000 0002 0 E: 1334936017.891505 0000 0000 0 E: 1334936017.905300 0003 0000 5507 E: 1334936017.905302 0003 0001 2200 E: 1334936017.905303 0003 0035 5507 E: 1334936017.905304 0003 0036 2200 E: 1334936017.905306 0003 0034 0 E: 1334936017.905307 0003 0030 468 E: 1334936017.905308 0003 0031 306 E: 1334936017.905309 0000 0002 0 E: 1334936017.905342 0003 0035 3853 E: 1334936017.905343 0003 0036 5349 E: 1334936017.905344 0003 0034 0 E: 1334936017.905345 0003 0030 468 E: 1334936017.905346 0003 0031 408 E: 1334936017.905347 0000 0002 0 E: 1334936017.905472 0000 0000 0 E: 1334936017.917333 0003 0000 5496 E: 1334936017.917335 0003 0001 2215 E: 1334936017.917336 0003 0035 5496 E: 1334936017.917337 0003 0036 2215 E: 1334936017.917338 0003 0034 0 E: 1334936017.917339 0003 0030 312 E: 1334936017.917340 0003 0031 306 E: 1334936017.917342 0000 0002 0 E: 1334936017.917374 0003 0035 3856 E: 1334936017.917375 0003 0036 5348 E: 1334936017.917377 0003 0034 0 E: 1334936017.917378 0003 0030 468 E: 1334936017.917379 0003 0031 408 E: 1334936017.917380 0000 0002 0 E: 1334936017.917505 0000 0000 0 E: 1334936017.931304 0003 0000 5495 E: 1334936017.931306 0003 0001 2244 E: 1334936017.931307 0003 0035 5495 E: 1334936017.931308 0003 0036 2244 E: 1334936017.931309 0003 0034 0 E: 1334936017.931310 0003 0030 468 E: 1334936017.931311 0003 0031 306 E: 1334936017.931313 0000 0002 0 E: 1334936017.931345 0003 0035 3858 E: 1334936017.931347 0003 0036 5337 E: 1334936017.931348 0003 0034 0 E: 1334936017.931349 0003 0030 468 E: 1334936017.931350 0003 0031 408 E: 1334936017.931351 0000 0002 0 E: 1334936017.931477 0000 0000 0 E: 1334936017.945302 0003 0000 5449 E: 1334936017.945303 0003 0001 2324 E: 1334936017.945304 0003 0035 5449 E: 1334936017.945305 0003 0036 2324 E: 1334936017.945307 0003 0034 0 E: 1334936017.945308 0003 0030 312 E: 1334936017.945309 0003 0031 306 E: 1334936017.945310 0000 0002 0 E: 1334936017.945343 0003 0035 3874 E: 1334936017.945344 0003 0036 5307 E: 1334936017.945345 0003 0034 0 E: 1334936017.945346 0003 0030 624 E: 1334936017.945347 0003 0031 408 E: 1334936017.945348 0000 0002 0 E: 1334936017.945474 0000 0000 0 E: 1334936017.959284 0003 0000 5429 E: 1334936017.959286 0003 0001 2346 E: 1334936017.959287 0003 0035 5429 E: 1334936017.959288 0003 0036 2346 E: 1334936017.959289 0003 0034 0 E: 1334936017.959290 0003 0030 468 E: 1334936017.959291 0003 0031 306 E: 1334936017.959293 0000 0002 0 E: 1334936017.959325 0003 0035 3907 E: 1334936017.959326 0003 0036 5278 E: 1334936017.959328 0003 0034 0 E: 1334936017.959329 0003 0030 468 E: 1334936017.959330 0003 0031 408 E: 1334936017.959331 0000 0002 0 E: 1334936017.959456 0000 0000 0 E: 1334936017.971334 0003 0000 5397 E: 1334936017.971336 0003 0001 2447 E: 1334936017.971337 0003 0035 5397 E: 1334936017.971338 0003 0036 2447 E: 1334936017.971339 0003 0034 0 E: 1334936017.971340 0003 0030 468 E: 1334936017.971341 0003 0031 306 E: 1334936017.971343 0000 0002 0 E: 1334936017.971375 0003 0035 3931 E: 1334936017.971377 0003 0036 5225 E: 1334936017.971378 0003 0034 0 E: 1334936017.971379 0003 0030 468 E: 1334936017.971380 0003 0031 306 E: 1334936017.971381 0000 0002 0 E: 1334936017.971507 0000 0000 0 E: 1334936017.985288 0003 0000 5358 E: 1334936017.985289 0003 0001 2516 E: 1334936017.985291 0003 0035 5358 E: 1334936017.985292 0003 0036 2516 E: 1334936017.985293 0003 0034 0 E: 1334936017.985294 0003 0030 312 E: 1334936017.985295 0003 0031 306 E: 1334936017.985296 0000 0002 0 E: 1334936017.985329 0003 0035 3957 E: 1334936017.985330 0003 0036 5158 E: 1334936017.985331 0003 0034 0 E: 1334936017.985332 0003 0030 312 E: 1334936017.985333 0003 0031 306 E: 1334936017.985334 0000 0002 0 E: 1334936017.985460 0000 0000 0 E: 1334936017.999287 0003 0000 5338 E: 1334936017.999289 0003 0001 2588 E: 1334936017.999291 0003 0035 5338 E: 1334936017.999292 0003 0036 2588 E: 1334936017.999294 0003 0034 0 E: 1334936017.999295 0003 0030 468 E: 1334936017.999296 0003 0031 306 E: 1334936017.999298 0000 0002 0 E: 1334936017.999350 0003 0035 3992 E: 1334936017.999351 0003 0036 5124 E: 1334936017.999353 0003 0034 0 E: 1334936017.999354 0003 0030 468 E: 1334936017.999356 0003 0031 306 E: 1334936017.999357 0000 0002 0 E: 1334936017.999551 0000 0000 0 E: 1334936018.011309 0003 0000 5314 E: 1334936018.011310 0003 0001 2649 E: 1334936018.011311 0003 0035 5314 E: 1334936018.011313 0003 0036 2649 E: 1334936018.011314 0003 0034 0 E: 1334936018.011315 0003 0030 312 E: 1334936018.011316 0003 0031 204 E: 1334936018.011317 0000 0002 0 E: 1334936018.011350 0003 0035 4018 E: 1334936018.011351 0003 0036 5042 E: 1334936018.011352 0003 0034 0 E: 1334936018.011353 0003 0030 468 E: 1334936018.011354 0003 0031 306 E: 1334936018.011355 0000 0002 0 E: 1334936018.011479 0000 0000 0 E: 1334936018.025324 0003 0000 5299 E: 1334936018.025325 0003 0001 2695 E: 1334936018.025326 0003 0035 5299 E: 1334936018.025328 0003 0036 2695 E: 1334936018.025329 0003 0034 0 E: 1334936018.025330 0003 0030 312 E: 1334936018.025331 0003 0031 306 E: 1334936018.025332 0000 0002 0 E: 1334936018.025365 0003 0035 4064 E: 1334936018.025366 0003 0036 5001 E: 1334936018.025367 0003 0034 0 E: 1334936018.025368 0003 0030 312 E: 1334936018.025369 0003 0031 306 E: 1334936018.025370 0000 0002 0 E: 1334936018.025549 0000 0000 0 E: 1334936018.037285 0003 0000 5273 E: 1334936018.037287 0003 0001 2761 E: 1334936018.037288 0003 0035 5273 E: 1334936018.037289 0003 0036 2761 E: 1334936018.037291 0003 0034 0 E: 1334936018.037292 0003 0030 312 E: 1334936018.037293 0003 0031 306 E: 1334936018.037294 0000 0002 0 E: 1334936018.037326 0003 0035 4088 E: 1334936018.037328 0003 0036 4987 E: 1334936018.037329 0003 0034 0 E: 1334936018.037330 0003 0030 312 E: 1334936018.037331 0003 0031 204 E: 1334936018.037332 0000 0002 0 E: 1334936018.037456 0000 0000 0 E: 1334936018.049295 0003 0000 5244 E: 1334936018.049296 0003 0001 2785 E: 1334936018.049297 0003 0035 5244 E: 1334936018.049298 0003 0036 2785 E: 1334936018.049300 0003 0034 0 E: 1334936018.049301 0003 0030 312 E: 1334936018.049302 0003 0031 306 E: 1334936018.049303 0000 0002 0 E: 1334936018.049335 0003 0035 4122 E: 1334936018.049336 0003 0036 4974 E: 1334936018.049337 0003 0034 0 E: 1334936018.049339 0003 0030 312 E: 1334936018.049340 0003 0031 306 E: 1334936018.049341 0000 0002 0 E: 1334936018.049465 0000 0000 0 E: 1334936018.063302 0003 0000 5235 E: 1334936018.063304 0003 0001 2813 E: 1334936018.063305 0003 0035 5235 E: 1334936018.063306 0003 0036 2813 E: 1334936018.063307 0003 0034 0 E: 1334936018.063308 0003 0030 468 E: 1334936018.063310 0003 0031 306 E: 1334936018.063311 0000 0002 0 E: 1334936018.063343 0003 0035 4135 E: 1334936018.063344 0003 0036 4950 E: 1334936018.063345 0003 0034 0 E: 1334936018.063346 0003 0030 468 E: 1334936018.063347 0003 0031 306 E: 1334936018.063349 0000 0002 0 E: 1334936018.063473 0000 0000 0 E: 1334936018.077329 0003 0000 5216 E: 1334936018.077331 0003 0001 2842 E: 1334936018.077332 0003 0035 5216 E: 1334936018.077333 0003 0036 2842 E: 1334936018.077334 0003 0034 0 E: 1334936018.077335 0003 0030 312 E: 1334936018.077336 0003 0031 204 E: 1334936018.077338 0000 0002 0 E: 1334936018.077370 0003 0035 4152 E: 1334936018.077371 0003 0036 4913 E: 1334936018.077372 0003 0034 0 E: 1334936018.077373 0003 0030 468 E: 1334936018.077374 0003 0031 306 E: 1334936018.077376 0000 0002 0 E: 1334936018.077500 0000 0000 0 E: 1334936018.091268 0003 0000 5195 E: 1334936018.091270 0003 0001 2895 E: 1334936018.091271 0003 0035 5195 E: 1334936018.091272 0003 0036 2895 E: 1334936018.091273 0003 0034 0 E: 1334936018.091274 0003 0030 468 E: 1334936018.091275 0003 0031 306 E: 1334936018.091276 0000 0002 0 E: 1334936018.091308 0003 0035 4171 E: 1334936018.091309 0003 0036 4880 E: 1334936018.091310 0003 0034 0 E: 1334936018.091311 0003 0030 468 E: 1334936018.091312 0003 0031 306 E: 1334936018.091314 0000 0002 0 E: 1334936018.091438 0000 0000 0 E: 1334936018.103278 0003 0000 5169 E: 1334936018.103280 0003 0001 2957 E: 1334936018.103281 0003 0035 5169 E: 1334936018.103282 0003 0036 2957 E: 1334936018.103283 0003 0034 0 E: 1334936018.103284 0003 0030 312 E: 1334936018.103285 0003 0031 306 E: 1334936018.103287 0000 0002 0 E: 1334936018.103319 0003 0035 4204 E: 1334936018.103320 0003 0036 4850 E: 1334936018.103321 0003 0034 0 E: 1334936018.103322 0003 0030 312 E: 1334936018.103323 0003 0031 306 E: 1334936018.103324 0000 0002 0 E: 1334936018.103448 0000 0000 0 E: 1334936018.119265 0003 0000 5129 E: 1334936018.119267 0003 0001 3002 E: 1334936018.119268 0003 0035 5129 E: 1334936018.119269 0003 0036 3002 E: 1334936018.119270 0003 0034 0 E: 1334936018.119271 0003 0030 312 E: 1334936018.119272 0003 0031 306 E: 1334936018.119274 0000 0002 0 E: 1334936018.119306 0003 0035 4220 E: 1334936018.119307 0003 0036 4834 E: 1334936018.119308 0003 0034 0 E: 1334936018.119309 0003 0030 312 E: 1334936018.119310 0003 0031 306 E: 1334936018.119312 0000 0002 0 E: 1334936018.119436 0000 0000 0 E: 1334936018.133315 0003 0000 5119 E: 1334936018.133317 0003 0001 3078 E: 1334936018.133318 0003 0035 5119 E: 1334936018.133319 0003 0036 3078 E: 1334936018.133320 0003 0034 0 E: 1334936018.133321 0003 0030 312 E: 1334936018.133323 0003 0031 204 E: 1334936018.133324 0000 0002 0 E: 1334936018.133356 0003 0035 4269 E: 1334936018.133357 0003 0036 4806 E: 1334936018.133358 0003 0034 0 E: 1334936018.133359 0003 0030 468 E: 1334936018.133360 0003 0031 306 E: 1334936018.133361 0000 0002 0 E: 1334936018.133486 0000 0000 0 E: 1334936018.145302 0003 0000 5091 E: 1334936018.145303 0003 0001 3096 E: 1334936018.145304 0003 0035 5091 E: 1334936018.145306 0003 0036 3096 E: 1334936018.145307 0003 0034 0 E: 1334936018.145308 0003 0030 312 E: 1334936018.145309 0003 0031 306 E: 1334936018.145310 0000 0002 0 E: 1334936018.145342 0003 0035 4273 E: 1334936018.145343 0003 0036 4793 E: 1334936018.145345 0003 0034 0 E: 1334936018.145346 0003 0030 468 E: 1334936018.145347 0003 0031 306 E: 1334936018.145348 0000 0002 0 E: 1334936018.145472 0000 0000 0 E: 1334936018.159413 0003 0000 5062 E: 1334936018.159415 0003 0001 3121 E: 1334936018.159417 0003 0035 5062 E: 1334936018.159418 0003 0036 3121 E: 1334936018.159419 0003 0034 0 E: 1334936018.159421 0003 0030 312 E: 1334936018.159423 0003 0031 306 E: 1334936018.159424 0000 0002 0 E: 1334936018.159476 0003 0035 4288 E: 1334936018.159478 0003 0036 4746 E: 1334936018.159480 0003 0034 0 E: 1334936018.159481 0003 0030 468 E: 1334936018.159483 0003 0031 306 E: 1334936018.159485 0000 0002 0 E: 1334936018.159653 0000 0000 0 E: 1334936018.173323 0003 0000 5053 E: 1334936018.173325 0003 0001 3148 E: 1334936018.173326 0003 0035 5053 E: 1334936018.173327 0003 0036 3148 E: 1334936018.173328 0003 0034 0 E: 1334936018.173329 0003 0030 312 E: 1334936018.173330 0003 0031 306 E: 1334936018.173331 0000 0002 0 E: 1334936018.173364 0003 0035 4310 E: 1334936018.173365 0003 0036 4734 E: 1334936018.173366 0003 0034 0 E: 1334936018.173367 0003 0030 468 E: 1334936018.173368 0003 0031 306 E: 1334936018.173369 0000 0002 0 E: 1334936018.173493 0000 0000 0 E: 1334936018.189303 0003 0000 5018 E: 1334936018.189305 0003 0001 3177 E: 1334936018.189306 0003 0035 5018 E: 1334936018.189308 0003 0036 3177 E: 1334936018.189309 0003 0034 0 E: 1334936018.189310 0003 0030 468 E: 1334936018.189311 0003 0031 306 E: 1334936018.189312 0000 0002 0 E: 1334936018.189345 0003 0035 4324 E: 1334936018.189346 0003 0036 4690 E: 1334936018.189347 0003 0034 0 E: 1334936018.189348 0003 0030 312 E: 1334936018.189349 0003 0031 306 E: 1334936018.189350 0000 0002 0 E: 1334936018.189475 0000 0000 0 E: 1334936018.201303 0003 0000 4992 E: 1334936018.201305 0003 0001 3252 E: 1334936018.201306 0003 0035 4992 E: 1334936018.201307 0003 0036 3252 E: 1334936018.201308 0003 0034 0 E: 1334936018.201309 0003 0030 312 E: 1334936018.201310 0003 0031 306 E: 1334936018.201312 0000 0002 0 E: 1334936018.201344 0003 0035 4358 E: 1334936018.201345 0003 0036 4683 E: 1334936018.201346 0003 0034 0 E: 1334936018.201347 0003 0030 312 E: 1334936018.201348 0003 0031 306 E: 1334936018.201349 0000 0002 0 E: 1334936018.201475 0000 0000 0 E: 1334936018.217306 0003 0000 4991 E: 1334936018.217307 0003 0001 3279 E: 1334936018.217309 0003 0035 4991 E: 1334936018.217310 0003 0036 3279 E: 1334936018.217311 0003 0034 0 E: 1334936018.217312 0003 0030 312 E: 1334936018.217313 0003 0031 306 E: 1334936018.217314 0000 0002 0 E: 1334936018.217347 0003 0035 4396 E: 1334936018.217348 0003 0036 4664 E: 1334936018.217350 0003 0034 0 E: 1334936018.217351 0003 0030 312 E: 1334936018.217352 0003 0031 306 E: 1334936018.217353 0000 0002 0 E: 1334936018.217478 0000 0000 0 E: 1334936018.227285 0003 0000 4965 E: 1334936018.227286 0003 0001 3320 E: 1334936018.227287 0003 0035 4965 E: 1334936018.227289 0003 0036 3320 E: 1334936018.227290 0003 0034 0 E: 1334936018.227291 0003 0030 312 E: 1334936018.227292 0003 0031 306 E: 1334936018.227293 0000 0002 0 E: 1334936018.227326 0003 0035 4418 E: 1334936018.227327 0003 0036 4595 E: 1334936018.227328 0003 0034 0 E: 1334936018.227329 0003 0030 468 E: 1334936018.227330 0003 0031 306 E: 1334936018.227331 0000 0002 0 E: 1334936018.227455 0000 0000 0 E: 1334936018.247303 0003 0000 4954 E: 1334936018.247304 0003 0001 3310 E: 1334936018.247306 0003 0035 4954 E: 1334936018.247307 0003 0036 3310 E: 1334936018.247308 0003 0034 0 E: 1334936018.247309 0003 0030 312 E: 1334936018.247310 0003 0031 306 E: 1334936018.247311 0000 0002 0 E: 1334936018.247344 0003 0035 4440 E: 1334936018.247345 0003 0036 4557 E: 1334936018.247346 0003 0034 0 E: 1334936018.247347 0003 0030 468 E: 1334936018.247348 0003 0031 306 E: 1334936018.247349 0000 0002 0 E: 1334936018.247474 0000 0000 0 E: 1334936018.265362 0003 0001 3346 E: 1334936018.265364 0003 0035 4954 E: 1334936018.265365 0003 0036 3346 E: 1334936018.265366 0003 0034 0 E: 1334936018.265367 0003 0030 468 E: 1334936018.265368 0003 0031 306 E: 1334936018.265369 0000 0002 0 E: 1334936018.265402 0003 0035 4477 E: 1334936018.265403 0003 0036 4528 E: 1334936018.265404 0003 0034 0 E: 1334936018.265405 0003 0030 468 E: 1334936018.265406 0003 0031 306 E: 1334936018.265407 0000 0002 0 E: 1334936018.265531 0000 0000 0 E: 1334936018.281343 0003 0000 4946 E: 1334936018.281345 0003 0001 3341 E: 1334936018.281346 0003 0035 4946 E: 1334936018.281347 0003 0036 3341 E: 1334936018.281348 0003 0034 0 E: 1334936018.281349 0003 0030 468 E: 1334936018.281350 0003 0031 306 E: 1334936018.281352 0000 0002 0 E: 1334936018.281384 0003 0035 4493 E: 1334936018.281385 0003 0036 4499 E: 1334936018.281386 0003 0034 0 E: 1334936018.281387 0003 0030 468 E: 1334936018.281388 0003 0031 204 E: 1334936018.281389 0000 0002 0 E: 1334936018.281514 0000 0000 0 E: 1334936018.295302 0003 0000 4948 E: 1334936018.295304 0003 0001 3353 E: 1334936018.295305 0003 0035 4948 E: 1334936018.295306 0003 0036 3353 E: 1334936018.295307 0003 0034 0 E: 1334936018.295309 0003 0030 468 E: 1334936018.295310 0003 0031 306 E: 1334936018.295311 0000 0002 0 E: 1334936018.295343 0003 0035 4502 E: 1334936018.295344 0003 0036 4421 E: 1334936018.295345 0003 0034 0 E: 1334936018.295346 0003 0030 468 E: 1334936018.295347 0003 0031 306 E: 1334936018.295349 0000 0002 0 E: 1334936018.295473 0000 0000 0 E: 1334936018.311306 0003 0000 4918 E: 1334936018.311307 0003 0001 3397 E: 1334936018.311309 0003 0035 4918 E: 1334936018.311310 0003 0036 3397 E: 1334936018.311311 0003 0034 0 E: 1334936018.311312 0003 0030 468 E: 1334936018.311313 0003 0031 204 E: 1334936018.311314 0000 0002 0 E: 1334936018.311347 0003 0035 4626 E: 1334936018.311348 0003 0036 4342 E: 1334936018.311349 0003 0034 0 E: 1334936018.311350 0003 0030 312 E: 1334936018.311351 0003 0031 306 E: 1334936018.311352 0000 0002 0 E: 1334936018.311476 0000 0000 0 E: 1334936018.323333 0003 0000 4926 E: 1334936018.323334 0003 0001 3374 E: 1334936018.323335 0003 0035 4926 E: 1334936018.323337 0003 0036 3374 E: 1334936018.323338 0003 0034 0 E: 1334936018.323339 0003 0030 312 E: 1334936018.323340 0003 0031 204 E: 1334936018.323341 0000 0002 0 E: 1334936018.323374 0003 0035 4691 E: 1334936018.323375 0003 0036 4296 E: 1334936018.323376 0003 0034 0 E: 1334936018.323377 0003 0030 468 E: 1334936018.323378 0003 0031 306 E: 1334936018.323379 0000 0002 0 E: 1334936018.323503 0000 0000 0 E: 1334936018.335325 0003 0000 4934 E: 1334936018.335327 0003 0001 3394 E: 1334936018.335328 0003 0035 4934 E: 1334936018.335329 0003 0036 3394 E: 1334936018.335330 0003 0034 0 E: 1334936018.335331 0003 0030 312 E: 1334936018.335332 0003 0031 306 E: 1334936018.335334 0000 0002 0 E: 1334936018.335366 0003 0035 4738 E: 1334936018.335367 0003 0036 4209 E: 1334936018.335368 0003 0034 0 E: 1334936018.335369 0003 0030 312 E: 1334936018.335370 0003 0031 204 E: 1334936018.335372 0000 0002 0 E: 1334936018.335517 0000 0000 0 E: 1334936018.347300 0003 0000 4931 E: 1334936018.347301 0003 0001 3391 E: 1334936018.347303 0003 0035 4931 E: 1334936018.347304 0003 0036 3391 E: 1334936018.347305 0003 0034 0 E: 1334936018.347306 0003 0030 312 E: 1334936018.347307 0003 0031 306 E: 1334936018.347308 0000 0002 0 E: 1334936018.347341 0003 0035 4760 E: 1334936018.347342 0003 0036 4159 E: 1334936018.347343 0003 0034 0 E: 1334936018.347344 0003 0030 312 E: 1334936018.347345 0003 0031 306 E: 1334936018.347346 0000 0002 0 E: 1334936018.347470 0000 0000 0 E: 1334936018.363307 0003 0000 4939 E: 1334936018.363308 0003 0001 3384 E: 1334936018.363309 0003 0035 4939 E: 1334936018.363310 0003 0036 3384 E: 1334936018.363312 0003 0034 0 E: 1334936018.363313 0003 0030 468 E: 1334936018.363314 0003 0031 306 E: 1334936018.363315 0000 0002 0 E: 1334936018.363470 0000 0000 0 E: 1334936018.371385 0003 0000 4950 E: 1334936018.371386 0003 0001 3358 E: 1334936018.371388 0003 0035 4950 E: 1334936018.371389 0003 0036 3358 E: 1334936018.371390 0003 0034 0 E: 1334936018.371391 0003 0030 468 E: 1334936018.371392 0003 0031 306 E: 1334936018.371393 0000 0002 0 E: 1334936018.371547 0000 0000 0 E: 1334936018.381356 0003 0000 4951 E: 1334936018.381358 0003 0001 3354 E: 1334936018.381359 0003 0035 4951 E: 1334936018.381360 0003 0036 3354 E: 1334936018.381361 0003 0034 1 E: 1334936018.381362 0003 0030 306 E: 1334936018.381363 0003 0031 156 E: 1334936018.381365 0000 0002 0 E: 1334936018.381519 0000 0000 0 E: 1334936018.391284 0003 0000 4928 E: 1334936018.391287 0003 0035 4928 E: 1334936018.391288 0003 0036 3354 E: 1334936018.391289 0003 0034 1 E: 1334936018.391290 0003 0030 204 E: 1334936018.391291 0003 0031 156 E: 1334936018.391292 0000 0002 0 E: 1334936018.391447 0000 0000 0 E: 1334936018.425499 0001 014d 0 E: 1334936018.425501 0001 014a 0 E: 1334936018.425502 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/rotate90.record0000644000015600001650000011007412651717544026774 0ustar pbuserpbgroup00000000000000E: 1329930134.797285 0003 0035 3773 E: 1329930134.797288 0003 0036 1964 E: 1329930134.797291 0003 0034 0 E: 1329930134.797293 0003 0030 360 E: 1329930134.797296 0003 0031 154 E: 1329930134.797298 0000 0002 0 E: 1329930134.797301 0001 014a 1 E: 1329930134.797304 0003 0000 3773 E: 1329930134.797307 0003 0001 1964 E: 1329930134.797311 0000 0000 0 E: 1329930134.811279 0003 0035 3709 E: 1329930134.811283 0003 0036 1969 E: 1329930134.811285 0003 0034 0 E: 1329930134.811288 0003 0030 360 E: 1329930134.811290 0003 0031 308 E: 1329930134.811293 0000 0002 0 E: 1329930134.811297 0003 0000 3757 E: 1329930134.811302 0000 0000 0 E: 1329930134.823093 0003 0035 3697 E: 1329930134.823096 0003 0036 1938 E: 1329930134.823099 0003 0034 0 E: 1329930134.823101 0003 0030 360 E: 1329930134.823104 0003 0031 308 E: 1329930134.823106 0000 0002 0 E: 1329930134.823110 0003 0000 3742 E: 1329930134.823115 0000 0000 0 E: 1329930134.831093 0003 0035 3758 E: 1329930134.831097 0003 0036 1958 E: 1329930134.831100 0003 0034 0 E: 1329930134.831103 0003 0030 360 E: 1329930134.831105 0003 0031 308 E: 1329930134.831108 0000 0002 0 E: 1329930134.831111 0003 0035 3464 E: 1329930134.831113 0003 0036 4590 E: 1329930134.831116 0003 0034 1 E: 1329930134.831118 0003 0030 308 E: 1329930134.831121 0003 0031 180 E: 1329930134.831123 0000 0002 0 E: 1329930134.831130 0000 0000 0 E: 1329930134.841093 0003 0035 3750 E: 1329930134.841097 0003 0036 1983 E: 1329930134.841099 0003 0034 1 E: 1329930134.841102 0003 0030 462 E: 1329930134.841104 0003 0031 360 E: 1329930134.841107 0000 0002 0 E: 1329930134.841109 0003 0035 3448 E: 1329930134.841112 0003 0036 4590 E: 1329930134.841114 0003 0034 1 E: 1329930134.841117 0003 0030 308 E: 1329930134.841119 0003 0031 180 E: 1329930134.841122 0000 0002 0 E: 1329930134.841129 0000 0000 0 E: 1329930134.853089 0003 0035 3758 E: 1329930134.853092 0003 0036 1979 E: 1329930134.853095 0003 0034 0 E: 1329930134.853097 0003 0030 360 E: 1329930134.853100 0003 0031 308 E: 1329930134.853102 0000 0002 0 E: 1329930134.853105 0003 0035 3455 E: 1329930134.853107 0003 0036 4552 E: 1329930134.853110 0003 0034 0 E: 1329930134.853112 0003 0030 360 E: 1329930134.853115 0003 0031 308 E: 1329930134.853117 0000 0002 0 E: 1329930134.853124 0000 0000 0 E: 1329930134.865085 0003 0035 3765 E: 1329930134.865089 0003 0036 1985 E: 1329930134.865091 0003 0034 0 E: 1329930134.865094 0003 0030 360 E: 1329930134.865096 0003 0031 308 E: 1329930134.865099 0000 0002 0 E: 1329930134.865101 0003 0035 3445 E: 1329930134.865104 0003 0036 4546 E: 1329930134.865106 0003 0034 0 E: 1329930134.865109 0003 0030 360 E: 1329930134.865111 0003 0031 308 E: 1329930134.865114 0000 0002 0 E: 1329930134.865121 0000 0000 0 E: 1329930134.877081 0003 0035 3763 E: 1329930134.877085 0003 0036 1990 E: 1329930134.877087 0003 0034 0 E: 1329930134.877090 0003 0030 360 E: 1329930134.877092 0003 0031 308 E: 1329930134.877095 0000 0002 0 E: 1329930134.877097 0003 0035 3449 E: 1329930134.877100 0003 0036 4551 E: 1329930134.877102 0003 0034 0 E: 1329930134.877105 0003 0030 540 E: 1329930134.877107 0003 0031 308 E: 1329930134.877110 0000 0002 0 E: 1329930134.877117 0000 0000 0 E: 1329930134.889107 0003 0035 3761 E: 1329930134.889111 0003 0036 1996 E: 1329930134.889115 0003 0034 0 E: 1329930134.889117 0003 0030 360 E: 1329930134.889120 0003 0031 308 E: 1329930134.889122 0000 0002 0 E: 1329930134.889125 0003 0035 3461 E: 1329930134.889128 0003 0036 4564 E: 1329930134.889130 0003 0034 0 E: 1329930134.889133 0003 0030 540 E: 1329930134.889135 0003 0031 308 E: 1329930134.889138 0000 0002 0 E: 1329930134.889146 0000 0000 0 E: 1329930134.909099 0003 0035 3772 E: 1329930134.909102 0003 0036 2001 E: 1329930134.909105 0003 0034 0 E: 1329930134.909107 0003 0030 540 E: 1329930134.909110 0003 0031 154 E: 1329930134.909112 0000 0002 0 E: 1329930134.909115 0003 0035 3444 E: 1329930134.909117 0003 0036 4550 E: 1329930134.909120 0003 0034 0 E: 1329930134.909122 0003 0030 540 E: 1329930134.909125 0003 0031 308 E: 1329930134.909127 0000 0002 0 E: 1329930134.909135 0000 0000 0 E: 1329930134.921096 0003 0035 3786 E: 1329930134.921100 0003 0036 2001 E: 1329930134.921102 0003 0034 1 E: 1329930134.921105 0003 0030 462 E: 1329930134.921107 0003 0031 360 E: 1329930134.921110 0000 0002 0 E: 1329930134.921112 0003 0035 3447 E: 1329930134.921115 0003 0036 4548 E: 1329930134.921117 0003 0034 0 E: 1329930134.921120 0003 0030 360 E: 1329930134.921122 0003 0031 308 E: 1329930134.921125 0000 0002 0 E: 1329930134.921129 0003 0000 3753 E: 1329930134.921134 0000 0000 0 E: 1329930134.933099 0003 0035 3789 E: 1329930134.933103 0003 0036 1993 E: 1329930134.933105 0003 0034 0 E: 1329930134.933108 0003 0030 540 E: 1329930134.933110 0003 0031 462 E: 1329930134.933113 0000 0002 0 E: 1329930134.933116 0003 0035 3450 E: 1329930134.933118 0003 0036 4540 E: 1329930134.933121 0003 0034 0 E: 1329930134.933123 0003 0030 540 E: 1329930134.933126 0003 0031 308 E: 1329930134.933128 0000 0002 0 E: 1329930134.933135 0000 0000 0 E: 1329930134.947097 0003 0035 3793 E: 1329930134.947101 0003 0036 2036 E: 1329930134.947104 0003 0034 0 E: 1329930134.947106 0003 0030 540 E: 1329930134.947109 0003 0031 308 E: 1329930134.947111 0000 0002 0 E: 1329930134.947114 0003 0035 3465 E: 1329930134.947116 0003 0036 4509 E: 1329930134.947119 0003 0034 0 E: 1329930134.947121 0003 0030 360 E: 1329930134.947124 0003 0031 154 E: 1329930134.947126 0000 0002 0 E: 1329930134.947130 0003 0000 3763 E: 1329930134.947133 0003 0001 1982 E: 1329930134.947136 0000 0000 0 E: 1329930134.957081 0003 0035 3805 E: 1329930134.957085 0003 0036 2101 E: 1329930134.957087 0003 0034 0 E: 1329930134.957090 0003 0030 540 E: 1329930134.957092 0003 0031 308 E: 1329930134.957095 0000 0002 0 E: 1329930134.957097 0003 0035 3444 E: 1329930134.957100 0003 0036 4524 E: 1329930134.957102 0003 0034 0 E: 1329930134.957105 0003 0030 360 E: 1329930134.957107 0003 0031 308 E: 1329930134.957110 0000 0002 0 E: 1329930134.957114 0003 0000 3773 E: 1329930134.957117 0003 0001 2041 E: 1329930134.957120 0000 0000 0 E: 1329930134.969091 0003 0035 3835 E: 1329930134.969094 0003 0036 2027 E: 1329930134.969097 0003 0034 0 E: 1329930134.969099 0003 0030 540 E: 1329930134.969102 0003 0031 308 E: 1329930134.969104 0000 0002 0 E: 1329930134.969107 0003 0035 3465 E: 1329930134.969109 0003 0036 4511 E: 1329930134.969112 0003 0034 0 E: 1329930134.969114 0003 0030 360 E: 1329930134.969117 0003 0031 154 E: 1329930134.969120 0000 0002 0 E: 1329930134.969123 0003 0000 3788 E: 1329930134.969128 0000 0000 0 E: 1329930134.979107 0003 0035 3848 E: 1329930134.979111 0003 0036 2016 E: 1329930134.979113 0003 0034 0 E: 1329930134.979116 0003 0030 540 E: 1329930134.979118 0003 0031 308 E: 1329930134.979121 0000 0002 0 E: 1329930134.979124 0003 0035 3449 E: 1329930134.979126 0003 0036 4548 E: 1329930134.979128 0003 0034 0 E: 1329930134.979131 0003 0030 360 E: 1329930134.979134 0003 0031 308 E: 1329930134.979136 0000 0002 0 E: 1329930134.979140 0003 0000 3803 E: 1329930134.979145 0000 0000 0 E: 1329930134.991093 0003 0035 3886 E: 1329930134.991096 0003 0036 2017 E: 1329930134.991098 0003 0034 0 E: 1329930134.991101 0003 0030 540 E: 1329930134.991104 0003 0031 462 E: 1329930134.991106 0000 0002 0 E: 1329930134.991109 0003 0035 3465 E: 1329930134.991112 0003 0036 4519 E: 1329930134.991115 0003 0034 0 E: 1329930134.991118 0003 0030 360 E: 1329930134.991122 0003 0031 154 E: 1329930134.991125 0000 0002 0 E: 1329930134.991130 0003 0000 3844 E: 1329930134.991135 0000 0000 0 E: 1329930135.013278 0003 0035 3966 E: 1329930135.013282 0003 0036 2026 E: 1329930135.013284 0003 0034 0 E: 1329930135.013287 0003 0030 540 E: 1329930135.013289 0003 0031 462 E: 1329930135.013292 0000 0002 0 E: 1329930135.013294 0003 0035 3464 E: 1329930135.013297 0003 0036 4521 E: 1329930135.013299 0003 0034 0 E: 1329930135.013302 0003 0030 360 E: 1329930135.013304 0003 0031 308 E: 1329930135.013307 0000 0002 0 E: 1329930135.013311 0003 0000 3905 E: 1329930135.013316 0000 0000 0 E: 1329930135.025095 0003 0035 4043 E: 1329930135.025099 0003 0036 2018 E: 1329930135.025101 0003 0034 0 E: 1329930135.025104 0003 0030 540 E: 1329930135.025106 0003 0031 308 E: 1329930135.025109 0000 0002 0 E: 1329930135.025111 0003 0035 3458 E: 1329930135.025114 0003 0036 4521 E: 1329930135.025116 0003 0034 0 E: 1329930135.025119 0003 0030 360 E: 1329930135.025121 0003 0031 308 E: 1329930135.025124 0000 0002 0 E: 1329930135.025128 0003 0000 3974 E: 1329930135.025133 0000 0000 0 E: 1329930135.035073 0003 0035 4144 E: 1329930135.035076 0003 0036 1964 E: 1329930135.035079 0003 0034 0 E: 1329930135.035081 0003 0030 360 E: 1329930135.035084 0003 0031 308 E: 1329930135.035086 0000 0002 0 E: 1329930135.035089 0003 0035 3450 E: 1329930135.035091 0003 0036 4541 E: 1329930135.035094 0003 0034 0 E: 1329930135.035096 0003 0030 360 E: 1329930135.035099 0003 0031 308 E: 1329930135.035101 0000 0002 0 E: 1329930135.035105 0003 0000 4144 E: 1329930135.035108 0003 0001 2021 E: 1329930135.035112 0000 0000 0 E: 1329930135.045062 0003 0035 4178 E: 1329930135.045065 0003 0036 1996 E: 1329930135.045067 0003 0034 0 E: 1329930135.045070 0003 0030 360 E: 1329930135.045072 0003 0031 308 E: 1329930135.045075 0000 0002 0 E: 1329930135.045077 0003 0035 3445 E: 1329930135.045080 0003 0036 4554 E: 1329930135.045082 0003 0034 0 E: 1329930135.045085 0003 0030 360 E: 1329930135.045087 0003 0031 308 E: 1329930135.045090 0000 0002 0 E: 1329930135.045096 0000 0000 0 E: 1329930135.055084 0003 0035 4267 E: 1329930135.055087 0003 0036 1987 E: 1329930135.055089 0003 0034 0 E: 1329930135.055092 0003 0030 360 E: 1329930135.055094 0003 0031 308 E: 1329930135.055097 0000 0002 0 E: 1329930135.055099 0003 0035 3458 E: 1329930135.055102 0003 0036 4538 E: 1329930135.055104 0003 0034 0 E: 1329930135.055107 0003 0030 360 E: 1329930135.055109 0003 0031 308 E: 1329930135.055112 0000 0002 0 E: 1329930135.055116 0003 0000 4205 E: 1329930135.055120 0000 0000 0 E: 1329930135.065084 0003 0035 4312 E: 1329930135.065087 0003 0036 2004 E: 1329930135.065090 0003 0034 0 E: 1329930135.065092 0003 0030 360 E: 1329930135.065095 0003 0031 308 E: 1329930135.065097 0000 0002 0 E: 1329930135.065100 0003 0035 3451 E: 1329930135.065102 0003 0036 4534 E: 1329930135.065105 0003 0034 0 E: 1329930135.065107 0003 0030 360 E: 1329930135.065110 0003 0031 308 E: 1329930135.065112 0000 0002 0 E: 1329930135.065116 0003 0000 4258 E: 1329930135.065121 0000 0000 0 E: 1329930135.077095 0003 0035 4461 E: 1329930135.077099 0003 0036 2045 E: 1329930135.077101 0003 0034 0 E: 1329930135.077104 0003 0030 540 E: 1329930135.077106 0003 0031 308 E: 1329930135.077109 0000 0002 0 E: 1329930135.077111 0003 0035 3458 E: 1329930135.077114 0003 0036 4538 E: 1329930135.077116 0003 0034 0 E: 1329930135.077119 0003 0030 360 E: 1329930135.077121 0003 0031 308 E: 1329930135.077124 0000 0002 0 E: 1329930135.077128 0003 0000 4461 E: 1329930135.077132 0000 0000 0 E: 1329930135.087057 0003 0035 4497 E: 1329930135.087061 0003 0036 2070 E: 1329930135.087063 0003 0034 0 E: 1329930135.087066 0003 0030 540 E: 1329930135.087068 0003 0031 308 E: 1329930135.087071 0000 0002 0 E: 1329930135.087073 0003 0035 3463 E: 1329930135.087076 0003 0036 4524 E: 1329930135.087078 0003 0034 0 E: 1329930135.087080 0003 0030 360 E: 1329930135.087083 0003 0031 308 E: 1329930135.087086 0000 0002 0 E: 1329930135.087090 0003 0001 2033 E: 1329930135.087094 0000 0000 0 E: 1329930135.099096 0003 0035 4614 E: 1329930135.099099 0003 0036 2116 E: 1329930135.099102 0003 0034 0 E: 1329930135.099105 0003 0030 540 E: 1329930135.099107 0003 0031 308 E: 1329930135.099110 0000 0002 0 E: 1329930135.099112 0003 0035 3459 E: 1329930135.099115 0003 0036 4539 E: 1329930135.099117 0003 0034 0 E: 1329930135.099120 0003 0030 360 E: 1329930135.099122 0003 0031 308 E: 1329930135.099125 0000 0002 0 E: 1329930135.099129 0003 0000 4614 E: 1329930135.099132 0003 0001 2074 E: 1329930135.099136 0000 0000 0 E: 1329930135.119125 0003 0035 4725 E: 1329930135.119129 0003 0036 2148 E: 1329930135.119131 0003 0034 0 E: 1329930135.119134 0003 0030 540 E: 1329930135.119137 0003 0031 462 E: 1329930135.119139 0000 0002 0 E: 1329930135.119142 0003 0035 3423 E: 1329930135.119144 0003 0036 4566 E: 1329930135.119147 0003 0034 0 E: 1329930135.119149 0003 0030 360 E: 1329930135.119152 0003 0031 308 E: 1329930135.119154 0000 0002 0 E: 1329930135.119158 0003 0000 4669 E: 1329930135.119161 0003 0001 2092 E: 1329930135.119165 0000 0000 0 E: 1329930135.131069 0003 0035 4873 E: 1329930135.131073 0003 0036 2176 E: 1329930135.131075 0003 0034 1 E: 1329930135.131078 0003 0030 462 E: 1329930135.131080 0003 0031 360 E: 1329930135.131083 0000 0002 0 E: 1329930135.131085 0003 0035 3429 E: 1329930135.131088 0003 0036 4559 E: 1329930135.131090 0003 0034 0 E: 1329930135.131093 0003 0030 360 E: 1329930135.131096 0003 0031 308 E: 1329930135.131098 0000 0002 0 E: 1329930135.131102 0003 0000 4873 E: 1329930135.131105 0003 0001 2134 E: 1329930135.131108 0000 0000 0 E: 1329930135.143071 0003 0035 4922 E: 1329930135.143074 0003 0036 2178 E: 1329930135.143076 0003 0034 0 E: 1329930135.143079 0003 0030 360 E: 1329930135.143081 0003 0031 308 E: 1329930135.143084 0000 0002 0 E: 1329930135.143086 0003 0035 3445 E: 1329930135.143089 0003 0036 4530 E: 1329930135.143091 0003 0034 0 E: 1329930135.143094 0003 0030 540 E: 1329930135.143096 0003 0031 308 E: 1329930135.143099 0000 0002 0 E: 1329930135.143103 0003 0000 4885 E: 1329930135.143105 0003 0001 2145 E: 1329930135.143108 0000 0000 0 E: 1329930135.155057 0003 0035 5053 E: 1329930135.155060 0003 0036 2278 E: 1329930135.155063 0003 0034 0 E: 1329930135.155066 0003 0030 540 E: 1329930135.155068 0003 0031 462 E: 1329930135.155070 0000 0002 0 E: 1329930135.155073 0003 0035 3454 E: 1329930135.155076 0003 0036 4532 E: 1329930135.155078 0003 0034 0 E: 1329930135.155080 0003 0030 360 E: 1329930135.155083 0003 0031 308 E: 1329930135.155086 0000 0002 0 E: 1329930135.155089 0003 0000 5053 E: 1329930135.155092 0003 0001 2211 E: 1329930135.155095 0000 0000 0 E: 1329930135.165091 0003 0035 5173 E: 1329930135.165095 0003 0036 2332 E: 1329930135.165097 0003 0034 1 E: 1329930135.165100 0003 0030 462 E: 1329930135.165102 0003 0031 360 E: 1329930135.165105 0000 0002 0 E: 1329930135.165107 0003 0035 3449 E: 1329930135.165110 0003 0036 4530 E: 1329930135.165112 0003 0034 0 E: 1329930135.165115 0003 0030 360 E: 1329930135.165117 0003 0031 308 E: 1329930135.165120 0000 0002 0 E: 1329930135.165124 0003 0000 5113 E: 1329930135.165126 0003 0001 2271 E: 1329930135.165130 0000 0000 0 E: 1329930135.177084 0003 0035 5250 E: 1329930135.177087 0003 0036 2382 E: 1329930135.177090 0003 0034 0 E: 1329930135.177092 0003 0030 540 E: 1329930135.177095 0003 0031 308 E: 1329930135.177097 0000 0002 0 E: 1329930135.177100 0003 0035 3440 E: 1329930135.177102 0003 0036 4530 E: 1329930135.177105 0003 0034 0 E: 1329930135.177107 0003 0030 360 E: 1329930135.177110 0003 0031 308 E: 1329930135.177113 0000 0002 0 E: 1329930135.177116 0003 0000 5181 E: 1329930135.177119 0003 0001 2326 E: 1329930135.177123 0000 0000 0 E: 1329930135.189089 0003 0035 5279 E: 1329930135.189093 0003 0036 2423 E: 1329930135.189095 0003 0034 0 E: 1329930135.189098 0003 0030 540 E: 1329930135.189100 0003 0031 308 E: 1329930135.189103 0000 0002 0 E: 1329930135.189105 0003 0035 3454 E: 1329930135.189108 0003 0036 4532 E: 1329930135.189110 0003 0034 0 E: 1329930135.189113 0003 0030 360 E: 1329930135.189115 0003 0031 308 E: 1329930135.189118 0000 0002 0 E: 1329930135.189123 0003 0000 5230 E: 1329930135.189126 0003 0001 2374 E: 1329930135.189129 0000 0000 0 E: 1329930135.201083 0003 0035 5365 E: 1329930135.201086 0003 0036 2498 E: 1329930135.201089 0003 0034 0 E: 1329930135.201091 0003 0030 540 E: 1329930135.201093 0003 0031 308 E: 1329930135.201096 0000 0002 0 E: 1329930135.201098 0003 0035 3453 E: 1329930135.201101 0003 0036 4520 E: 1329930135.201103 0003 0034 0 E: 1329930135.201106 0003 0030 360 E: 1329930135.201108 0003 0031 308 E: 1329930135.201111 0000 0002 0 E: 1329930135.201115 0003 0000 5297 E: 1329930135.201117 0003 0001 2436 E: 1329930135.201121 0000 0000 0 E: 1329930135.211076 0003 0035 5388 E: 1329930135.211079 0003 0036 2516 E: 1329930135.211082 0003 0034 1 E: 1329930135.211085 0003 0030 462 E: 1329930135.211087 0003 0031 360 E: 1329930135.211090 0000 0002 0 E: 1329930135.211092 0003 0035 3448 E: 1329930135.211095 0003 0036 4540 E: 1329930135.211097 0003 0034 0 E: 1329930135.211099 0003 0030 360 E: 1329930135.211102 0003 0031 308 E: 1329930135.211104 0000 0002 0 E: 1329930135.211108 0003 0000 5342 E: 1329930135.211111 0003 0001 2476 E: 1329930135.211115 0000 0000 0 E: 1329930135.231085 0003 0035 5480 E: 1329930135.231088 0003 0036 2570 E: 1329930135.231091 0003 0034 1 E: 1329930135.231093 0003 0030 462 E: 1329930135.231096 0003 0031 360 E: 1329930135.231098 0000 0002 0 E: 1329930135.231101 0003 0035 3442 E: 1329930135.231103 0003 0036 4539 E: 1329930135.231106 0003 0034 0 E: 1329930135.231108 0003 0030 360 E: 1329930135.231111 0003 0031 308 E: 1329930135.231113 0000 0002 0 E: 1329930135.231117 0003 0000 5411 E: 1329930135.231120 0003 0001 2523 E: 1329930135.231124 0000 0000 0 E: 1329930135.243093 0003 0035 5565 E: 1329930135.243096 0003 0036 2707 E: 1329930135.243099 0003 0034 1 E: 1329930135.243102 0003 0030 462 E: 1329930135.243104 0003 0031 360 E: 1329930135.243107 0000 0002 0 E: 1329930135.243109 0003 0035 3445 E: 1329930135.243113 0003 0036 4544 E: 1329930135.243115 0003 0034 0 E: 1329930135.243119 0003 0030 540 E: 1329930135.243121 0003 0031 308 E: 1329930135.243124 0000 0002 0 E: 1329930135.243129 0003 0000 5565 E: 1329930135.243132 0003 0001 2707 E: 1329930135.243136 0000 0000 0 E: 1329930135.255090 0003 0035 5633 E: 1329930135.255094 0003 0036 2801 E: 1329930135.255097 0003 0034 0 E: 1329930135.255099 0003 0030 540 E: 1329930135.255102 0003 0031 462 E: 1329930135.255104 0000 0002 0 E: 1329930135.255107 0003 0035 3433 E: 1329930135.255109 0003 0036 4539 E: 1329930135.255112 0003 0034 0 E: 1329930135.255114 0003 0030 360 E: 1329930135.255117 0003 0031 308 E: 1329930135.255119 0000 0002 0 E: 1329930135.255123 0003 0000 5582 E: 1329930135.255126 0003 0001 2754 E: 1329930135.255130 0000 0000 0 E: 1329930135.267065 0003 0035 5690 E: 1329930135.267068 0003 0036 2870 E: 1329930135.267071 0003 0034 0 E: 1329930135.267073 0003 0030 360 E: 1329930135.267076 0003 0031 308 E: 1329930135.267078 0000 0002 0 E: 1329930135.267081 0003 0035 3440 E: 1329930135.267083 0003 0036 4491 E: 1329930135.267086 0003 0034 0 E: 1329930135.267088 0003 0030 540 E: 1329930135.267091 0003 0031 308 E: 1329930135.267093 0000 0002 0 E: 1329930135.267097 0003 0000 5636 E: 1329930135.267100 0003 0001 2812 E: 1329930135.267103 0000 0000 0 E: 1329930135.279058 0003 0035 5718 E: 1329930135.279061 0003 0036 2957 E: 1329930135.279064 0003 0034 0 E: 1329930135.279066 0003 0030 540 E: 1329930135.279069 0003 0031 462 E: 1329930135.279071 0000 0002 0 E: 1329930135.279074 0003 0035 3445 E: 1329930135.279076 0003 0036 4517 E: 1329930135.279079 0003 0034 0 E: 1329930135.279081 0003 0030 360 E: 1329930135.279084 0003 0031 308 E: 1329930135.279086 0000 0002 0 E: 1329930135.279090 0003 0000 5677 E: 1329930135.279093 0003 0001 2884 E: 1329930135.279096 0000 0000 0 E: 1329930135.291090 0003 0035 5788 E: 1329930135.291094 0003 0036 3076 E: 1329930135.291097 0003 0034 1 E: 1329930135.291099 0003 0030 462 E: 1329930135.291102 0003 0031 360 E: 1329930135.291104 0000 0002 0 E: 1329930135.291107 0003 0035 3438 E: 1329930135.291109 0003 0036 4536 E: 1329930135.291112 0003 0034 0 E: 1329930135.291114 0003 0030 360 E: 1329930135.291117 0003 0031 308 E: 1329930135.291119 0000 0002 0 E: 1329930135.291123 0003 0000 5732 E: 1329930135.291126 0003 0001 3076 E: 1329930135.291130 0000 0000 0 E: 1329930135.303077 0003 0035 5847 E: 1329930135.303080 0003 0036 3144 E: 1329930135.303083 0003 0034 0 E: 1329930135.303085 0003 0030 540 E: 1329930135.303087 0003 0031 462 E: 1329930135.303090 0000 0002 0 E: 1329930135.303093 0003 0035 3444 E: 1329930135.303095 0003 0036 4530 E: 1329930135.303098 0003 0034 0 E: 1329930135.303100 0003 0030 540 E: 1329930135.303103 0003 0031 308 E: 1329930135.303105 0000 0002 0 E: 1329930135.303109 0003 0000 5789 E: 1329930135.303112 0003 0001 3093 E: 1329930135.303116 0000 0000 0 E: 1329930135.315074 0003 0035 5869 E: 1329930135.315077 0003 0036 3235 E: 1329930135.315080 0003 0034 0 E: 1329930135.315082 0003 0030 360 E: 1329930135.315085 0003 0031 308 E: 1329930135.315087 0000 0002 0 E: 1329930135.315090 0003 0035 3452 E: 1329930135.315092 0003 0036 4529 E: 1329930135.315095 0003 0034 0 E: 1329930135.315097 0003 0030 360 E: 1329930135.315100 0003 0031 308 E: 1329930135.315102 0000 0002 0 E: 1329930135.315106 0003 0000 5829 E: 1329930135.315109 0003 0001 3164 E: 1329930135.315112 0000 0000 0 E: 1329930135.337091 0003 0035 5904 E: 1329930135.337094 0003 0036 3367 E: 1329930135.337097 0003 0034 0 E: 1329930135.337099 0003 0030 540 E: 1329930135.337102 0003 0031 462 E: 1329930135.337105 0000 0002 0 E: 1329930135.337107 0003 0035 3447 E: 1329930135.337110 0003 0036 4528 E: 1329930135.337112 0003 0034 0 E: 1329930135.337115 0003 0030 360 E: 1329930135.337117 0003 0031 308 E: 1329930135.337120 0000 0002 0 E: 1329930135.337124 0003 0000 5866 E: 1329930135.337126 0003 0001 3367 E: 1329930135.337131 0000 0000 0 E: 1329930135.349077 0003 0035 5869 E: 1329930135.349081 0003 0036 3404 E: 1329930135.349083 0003 0034 0 E: 1329930135.349086 0003 0030 360 E: 1329930135.349088 0003 0031 308 E: 1329930135.349091 0000 0002 0 E: 1329930135.349093 0003 0035 3457 E: 1329930135.349096 0003 0036 4543 E: 1329930135.349098 0003 0034 0 E: 1329930135.349101 0003 0030 540 E: 1329930135.349103 0003 0031 308 E: 1329930135.349106 0000 0002 0 E: 1329930135.349114 0000 0000 0 E: 1329930135.361075 0003 0035 5916 E: 1329930135.361078 0003 0036 3589 E: 1329930135.361080 0003 0034 1 E: 1329930135.361083 0003 0030 462 E: 1329930135.361086 0003 0031 360 E: 1329930135.361088 0000 0002 0 E: 1329930135.361091 0003 0035 3441 E: 1329930135.361093 0003 0036 4541 E: 1329930135.361096 0003 0034 0 E: 1329930135.361098 0003 0030 540 E: 1329930135.361100 0003 0031 308 E: 1329930135.361103 0000 0002 0 E: 1329930135.361107 0003 0000 5878 E: 1329930135.361110 0003 0001 3589 E: 1329930135.361113 0000 0000 0 E: 1329930135.373092 0003 0035 5938 E: 1329930135.373096 0003 0036 3674 E: 1329930135.373098 0003 0034 0 E: 1329930135.373101 0003 0030 540 E: 1329930135.373103 0003 0031 462 E: 1329930135.373106 0000 0002 0 E: 1329930135.373108 0003 0035 3433 E: 1329930135.373111 0003 0036 4543 E: 1329930135.373113 0003 0034 0 E: 1329930135.373116 0003 0030 360 E: 1329930135.373118 0003 0031 308 E: 1329930135.373121 0000 0002 0 E: 1329930135.373125 0003 0000 5893 E: 1329930135.373127 0003 0001 3631 E: 1329930135.373131 0000 0000 0 E: 1329930135.387090 0003 0035 5942 E: 1329930135.387094 0003 0036 3754 E: 1329930135.387096 0003 0034 0 E: 1329930135.387099 0003 0030 540 E: 1329930135.387101 0003 0031 462 E: 1329930135.387104 0000 0002 0 E: 1329930135.387106 0003 0035 3435 E: 1329930135.387109 0003 0036 4561 E: 1329930135.387111 0003 0034 0 E: 1329930135.387114 0003 0030 540 E: 1329930135.387116 0003 0031 308 E: 1329930135.387119 0000 0002 0 E: 1329930135.387123 0003 0000 5905 E: 1329930135.387125 0003 0001 3692 E: 1329930135.387129 0000 0000 0 E: 1329930135.399064 0003 0035 5925 E: 1329930135.399068 0003 0036 3793 E: 1329930135.399070 0003 0034 0 E: 1329930135.399073 0003 0030 360 E: 1329930135.399075 0003 0031 308 E: 1329930135.399078 0000 0002 0 E: 1329930135.399080 0003 0035 3448 E: 1329930135.399083 0003 0036 4547 E: 1329930135.399085 0003 0034 0 E: 1329930135.399088 0003 0030 360 E: 1329930135.399090 0003 0031 308 E: 1329930135.399093 0000 0002 0 E: 1329930135.399098 0003 0001 3742 E: 1329930135.399101 0000 0000 0 E: 1329930135.411071 0003 0035 5946 E: 1329930135.411074 0003 0036 3944 E: 1329930135.411076 0003 0034 1 E: 1329930135.411079 0003 0030 462 E: 1329930135.411081 0003 0031 360 E: 1329930135.411084 0000 0002 0 E: 1329930135.411086 0003 0035 3465 E: 1329930135.411089 0003 0036 4535 E: 1329930135.411091 0003 0034 0 E: 1329930135.411094 0003 0030 540 E: 1329930135.411096 0003 0031 154 E: 1329930135.411099 0000 0002 0 E: 1329930135.411102 0003 0000 5915 E: 1329930135.411105 0003 0001 3944 E: 1329930135.411108 0000 0000 0 E: 1329930135.425091 0003 0035 5945 E: 1329930135.425095 0003 0036 4016 E: 1329930135.425097 0003 0034 0 E: 1329930135.425100 0003 0030 540 E: 1329930135.425102 0003 0031 308 E: 1329930135.425105 0000 0002 0 E: 1329930135.425108 0003 0035 3448 E: 1329930135.425110 0003 0036 4575 E: 1329930135.425112 0003 0034 0 E: 1329930135.425115 0003 0030 540 E: 1329930135.425117 0003 0031 308 E: 1329930135.425120 0000 0002 0 E: 1329930135.425125 0003 0001 3962 E: 1329930135.425129 0000 0000 0 E: 1329930135.445111 0003 0035 5936 E: 1329930135.445115 0003 0036 4081 E: 1329930135.445118 0003 0034 0 E: 1329930135.445120 0003 0030 540 E: 1329930135.445123 0003 0031 462 E: 1329930135.445125 0000 0002 0 E: 1329930135.445128 0003 0035 3414 E: 1329930135.445130 0003 0036 4552 E: 1329930135.445133 0003 0034 0 E: 1329930135.445135 0003 0030 540 E: 1329930135.445138 0003 0031 308 E: 1329930135.445140 0000 0002 0 E: 1329930135.445145 0003 0001 4021 E: 1329930135.445150 0000 0000 0 E: 1329930135.455098 0003 0035 5902 E: 1329930135.455101 0003 0036 4211 E: 1329930135.455104 0003 0034 0 E: 1329930135.455107 0003 0030 540 E: 1329930135.455109 0003 0031 308 E: 1329930135.455112 0000 0002 0 E: 1329930135.455114 0003 0035 3438 E: 1329930135.455117 0003 0036 4555 E: 1329930135.455119 0003 0034 0 E: 1329930135.455121 0003 0030 540 E: 1329930135.455124 0003 0031 308 E: 1329930135.455127 0000 0002 0 E: 1329930135.455132 0003 0001 4211 E: 1329930135.455135 0000 0000 0 E: 1329930135.467086 0003 0035 5893 E: 1329930135.467089 0003 0036 4284 E: 1329930135.467092 0003 0034 0 E: 1329930135.467094 0003 0030 540 E: 1329930135.467097 0003 0031 308 E: 1329930135.467100 0000 0002 0 E: 1329930135.467102 0003 0035 3449 E: 1329930135.467105 0003 0036 4551 E: 1329930135.467107 0003 0034 0 E: 1329930135.467110 0003 0030 540 E: 1329930135.467112 0003 0031 308 E: 1329930135.467115 0000 0002 0 E: 1329930135.467120 0003 0001 4229 E: 1329930135.467124 0000 0000 0 E: 1329930135.477056 0003 0035 5871 E: 1329930135.477059 0003 0036 4321 E: 1329930135.477061 0003 0034 0 E: 1329930135.477064 0003 0030 360 E: 1329930135.477066 0003 0031 308 E: 1329930135.477069 0000 0002 0 E: 1329930135.477071 0003 0035 3439 E: 1329930135.477074 0003 0036 4557 E: 1329930135.477076 0003 0034 0 E: 1329930135.477079 0003 0030 540 E: 1329930135.477081 0003 0031 308 E: 1329930135.477084 0000 0002 0 E: 1329930135.477088 0003 0000 5904 E: 1329930135.477090 0003 0001 4275 E: 1329930135.477094 0000 0000 0 E: 1329930135.489075 0003 0035 5857 E: 1329930135.489079 0003 0036 4376 E: 1329930135.489081 0003 0034 0 E: 1329930135.489083 0003 0030 540 E: 1329930135.489086 0003 0031 308 E: 1329930135.489088 0000 0002 0 E: 1329930135.489091 0003 0035 3446 E: 1329930135.489093 0003 0036 4549 E: 1329930135.489096 0003 0034 0 E: 1329930135.489098 0003 0030 360 E: 1329930135.489101 0003 0031 308 E: 1329930135.489103 0000 0002 0 E: 1329930135.489107 0003 0000 5892 E: 1329930135.489110 0003 0001 4325 E: 1329930135.489113 0000 0000 0 E: 1329930135.499069 0003 0035 5836 E: 1329930135.499072 0003 0036 4479 E: 1329930135.499074 0003 0034 1 E: 1329930135.499077 0003 0030 462 E: 1329930135.499079 0003 0031 360 E: 1329930135.499082 0000 0002 0 E: 1329930135.499084 0003 0035 3432 E: 1329930135.499087 0003 0036 4521 E: 1329930135.499089 0003 0034 0 E: 1329930135.499092 0003 0030 540 E: 1329930135.499094 0003 0031 308 E: 1329930135.499097 0000 0002 0 E: 1329930135.499101 0003 0000 5878 E: 1329930135.499103 0003 0001 4402 E: 1329930135.499107 0000 0000 0 E: 1329930135.509077 0003 0035 5773 E: 1329930135.509080 0003 0036 4498 E: 1329930135.509083 0003 0034 1 E: 1329930135.509085 0003 0030 462 E: 1329930135.509088 0003 0031 360 E: 1329930135.509090 0000 0002 0 E: 1329930135.509093 0003 0035 3443 E: 1329930135.509096 0003 0036 4555 E: 1329930135.509098 0003 0034 0 E: 1329930135.509101 0003 0030 540 E: 1329930135.509103 0003 0031 308 E: 1329930135.509106 0000 0002 0 E: 1329930135.509109 0003 0000 5825 E: 1329930135.509112 0003 0001 4450 E: 1329930135.509116 0000 0000 0 E: 1329930135.519076 0003 0035 5726 E: 1329930135.519079 0003 0036 4557 E: 1329930135.519081 0003 0034 0 E: 1329930135.519084 0003 0030 540 E: 1329930135.519086 0003 0031 462 E: 1329930135.519089 0000 0002 0 E: 1329930135.519091 0003 0035 3443 E: 1329930135.519094 0003 0036 4545 E: 1329930135.519096 0003 0034 0 E: 1329930135.519099 0003 0030 540 E: 1329930135.519101 0003 0031 308 E: 1329930135.519104 0000 0002 0 E: 1329930135.519107 0003 0000 5775 E: 1329930135.519110 0003 0001 4503 E: 1329930135.519114 0000 0000 0 E: 1329930135.529073 0003 0035 5687 E: 1329930135.529076 0003 0036 4653 E: 1329930135.529079 0003 0034 0 E: 1329930135.529081 0003 0030 360 E: 1329930135.529084 0003 0031 308 E: 1329930135.529086 0000 0002 0 E: 1329930135.529089 0003 0035 3443 E: 1329930135.529092 0003 0036 4559 E: 1329930135.529094 0003 0034 0 E: 1329930135.529097 0003 0030 540 E: 1329930135.529099 0003 0031 308 E: 1329930135.529102 0000 0002 0 E: 1329930135.529105 0003 0000 5731 E: 1329930135.529108 0003 0001 4578 E: 1329930135.529111 0000 0000 0 E: 1329930135.537092 0003 0035 5704 E: 1329930135.537096 0003 0036 4635 E: 1329930135.537098 0003 0034 0 E: 1329930135.537101 0003 0030 360 E: 1329930135.537103 0003 0031 308 E: 1329930135.537106 0000 0002 0 E: 1329930135.537109 0003 0035 3437 E: 1329930135.537111 0003 0036 4542 E: 1329930135.537113 0003 0034 0 E: 1329930135.537116 0003 0030 360 E: 1329930135.537118 0003 0031 308 E: 1329930135.537121 0000 0002 0 E: 1329930135.537126 0003 0001 4592 E: 1329930135.537130 0000 0000 0 E: 1329930135.555069 0003 0035 5666 E: 1329930135.555072 0003 0036 4701 E: 1329930135.555075 0003 0034 1 E: 1329930135.555077 0003 0030 462 E: 1329930135.555080 0003 0031 360 E: 1329930135.555082 0000 0002 0 E: 1329930135.555085 0003 0035 3409 E: 1329930135.555087 0003 0036 4637 E: 1329930135.555090 0003 0034 0 E: 1329930135.555092 0003 0030 360 E: 1329930135.555095 0003 0031 308 E: 1329930135.555097 0000 0002 0 E: 1329930135.555101 0003 0000 5714 E: 1329930135.555104 0003 0001 4646 E: 1329930135.555107 0000 0000 0 E: 1329930135.565061 0003 0035 5580 E: 1329930135.565064 0003 0036 4846 E: 1329930135.565066 0003 0034 1 E: 1329930135.565069 0003 0030 462 E: 1329930135.565071 0003 0031 360 E: 1329930135.565074 0000 0002 0 E: 1329930135.565076 0003 0035 3431 E: 1329930135.565079 0003 0036 4527 E: 1329930135.565081 0003 0034 0 E: 1329930135.565084 0003 0030 360 E: 1329930135.565086 0003 0031 308 E: 1329930135.565089 0000 0002 0 E: 1329930135.565093 0003 0000 5647 E: 1329930135.565095 0003 0001 4846 E: 1329930135.565099 0000 0000 0 E: 1329930135.577097 0003 0035 5549 E: 1329930135.577100 0003 0036 4879 E: 1329930135.577103 0003 0034 0 E: 1329930135.577105 0003 0030 540 E: 1329930135.577108 0003 0031 308 E: 1329930135.577110 0000 0002 0 E: 1329930135.577113 0003 0035 3436 E: 1329930135.577115 0003 0036 4537 E: 1329930135.577118 0003 0034 0 E: 1329930135.577120 0003 0030 540 E: 1329930135.577123 0003 0031 308 E: 1329930135.577125 0000 0002 0 E: 1329930135.577129 0003 0000 5598 E: 1329930135.577134 0000 0000 0 E: 1329930135.589062 0003 0035 5550 E: 1329930135.589065 0003 0036 4956 E: 1329930135.589068 0003 0034 0 E: 1329930135.589070 0003 0030 540 E: 1329930135.589073 0003 0031 462 E: 1329930135.589075 0000 0002 0 E: 1329930135.589078 0003 0035 3464 E: 1329930135.589080 0003 0036 4561 E: 1329930135.589083 0003 0034 0 E: 1329930135.589085 0003 0030 540 E: 1329930135.589088 0003 0031 154 E: 1329930135.589090 0000 0002 0 E: 1329930135.589094 0003 0000 5586 E: 1329930135.589097 0003 0001 4901 E: 1329930135.589100 0000 0000 0 E: 1329930135.599075 0003 0035 5515 E: 1329930135.599078 0003 0036 5006 E: 1329930135.599080 0003 0034 0 E: 1329930135.599083 0003 0030 720 E: 1329930135.599085 0003 0031 462 E: 1329930135.599088 0000 0002 0 E: 1329930135.599090 0003 0035 3443 E: 1329930135.599093 0003 0036 4577 E: 1329930135.599096 0003 0034 0 E: 1329930135.599098 0003 0030 540 E: 1329930135.599101 0003 0031 308 E: 1329930135.599103 0000 0002 0 E: 1329930135.599107 0003 0000 5568 E: 1329930135.599109 0003 0001 4953 E: 1329930135.599113 0000 0000 0 E: 1329930135.611072 0003 0035 5483 E: 1329930135.611075 0003 0036 5032 E: 1329930135.611078 0003 0034 1 E: 1329930135.611080 0003 0030 462 E: 1329930135.611083 0003 0031 360 E: 1329930135.611085 0000 0002 0 E: 1329930135.611088 0003 0035 3433 E: 1329930135.611091 0003 0036 4549 E: 1329930135.611093 0003 0034 0 E: 1329930135.611096 0003 0030 540 E: 1329930135.611098 0003 0031 308 E: 1329930135.611101 0000 0002 0 E: 1329930135.611104 0003 0000 5525 E: 1329930135.611107 0003 0001 4992 E: 1329930135.611111 0000 0000 0 E: 1329930135.621101 0003 0035 5457 E: 1329930135.621104 0003 0036 5036 E: 1329930135.621107 0003 0034 1 E: 1329930135.621110 0003 0030 462 E: 1329930135.621112 0003 0031 360 E: 1329930135.621115 0000 0002 0 E: 1329930135.621117 0003 0035 3443 E: 1329930135.621120 0003 0036 4566 E: 1329930135.621122 0003 0034 0 E: 1329930135.621125 0003 0030 540 E: 1329930135.621127 0003 0031 308 E: 1329930135.621130 0000 0002 0 E: 1329930135.621134 0003 0000 5508 E: 1329930135.621136 0003 0001 5003 E: 1329930135.621140 0000 0000 0 E: 1329930135.633079 0003 0035 5467 E: 1329930135.633082 0003 0036 5043 E: 1329930135.633084 0003 0034 1 E: 1329930135.633087 0003 0030 462 E: 1329930135.633089 0003 0031 360 E: 1329930135.633092 0000 0002 0 E: 1329930135.633094 0003 0035 3462 E: 1329930135.633097 0003 0036 4542 E: 1329930135.633099 0003 0034 0 E: 1329930135.633102 0003 0030 360 E: 1329930135.633104 0003 0031 308 E: 1329930135.633107 0000 0002 0 E: 1329930135.633111 0003 0000 5497 E: 1329930135.633113 0003 0001 5013 E: 1329930135.633117 0000 0000 0 E: 1329930135.645072 0003 0035 5462 E: 1329930135.645075 0003 0036 5049 E: 1329930135.645078 0003 0034 1 E: 1329930135.645080 0003 0030 462 E: 1329930135.645083 0003 0031 360 E: 1329930135.645085 0000 0002 0 E: 1329930135.645088 0003 0035 3440 E: 1329930135.645090 0003 0036 4558 E: 1329930135.645093 0003 0034 0 E: 1329930135.645095 0003 0030 540 E: 1329930135.645098 0003 0031 308 E: 1329930135.645100 0000 0002 0 E: 1329930135.645107 0000 0000 0 E: 1329930135.665068 0003 0035 5472 E: 1329930135.665071 0003 0036 5048 E: 1329930135.665074 0003 0034 0 E: 1329930135.665076 0003 0030 540 E: 1329930135.665079 0003 0031 462 E: 1329930135.665081 0000 0002 0 E: 1329930135.665084 0003 0035 3440 E: 1329930135.665086 0003 0036 4523 E: 1329930135.665089 0003 0034 0 E: 1329930135.665091 0003 0030 360 E: 1329930135.665094 0003 0031 308 E: 1329930135.665096 0000 0002 0 E: 1329930135.665103 0000 0000 0 E: 1329930135.675093 0003 0035 5499 E: 1329930135.675097 0003 0036 5004 E: 1329930135.675099 0003 0034 0 E: 1329930135.675101 0003 0030 540 E: 1329930135.675104 0003 0031 462 E: 1329930135.675107 0000 0002 0 E: 1329930135.675109 0003 0035 3431 E: 1329930135.675112 0003 0036 4568 E: 1329930135.675114 0003 0034 0 E: 1329930135.675117 0003 0030 540 E: 1329930135.675119 0003 0031 308 E: 1329930135.675122 0000 0002 0 E: 1329930135.675129 0000 0000 0 E: 1329930135.687065 0003 0035 5539 E: 1329930135.687068 0003 0036 4952 E: 1329930135.687071 0003 0034 0 E: 1329930135.687073 0003 0030 360 E: 1329930135.687076 0003 0031 308 E: 1329930135.687078 0000 0002 0 E: 1329930135.687081 0003 0035 3448 E: 1329930135.687084 0003 0036 4546 E: 1329930135.687086 0003 0034 0 E: 1329930135.687089 0003 0030 540 E: 1329930135.687091 0003 0031 308 E: 1329930135.687094 0000 0002 0 E: 1329930135.687098 0003 0000 5507 E: 1329930135.687100 0003 0001 4997 E: 1329930135.687104 0000 0000 0 E: 1329930135.697106 0003 0035 3452 E: 1329930135.697110 0003 0036 4541 E: 1329930135.697113 0003 0034 0 E: 1329930135.697115 0003 0030 540 E: 1329930135.697117 0003 0031 308 E: 1329930135.697120 0000 0002 0 E: 1329930135.697124 0003 0000 3452 E: 1329930135.697127 0003 0001 4541 E: 1329930135.697130 0000 0000 0 E: 1329930135.709277 0003 0035 3432 E: 1329930135.709280 0003 0036 4570 E: 1329930135.709283 0003 0034 0 E: 1329930135.709286 0003 0030 540 E: 1329930135.709288 0003 0031 308 E: 1329930135.709290 0000 0002 0 E: 1329930135.709298 0000 0000 0 E: 1329930135.721137 0003 0035 3437 E: 1329930135.721141 0003 0036 4574 E: 1329930135.721143 0003 0034 0 E: 1329930135.721146 0003 0030 540 E: 1329930135.721148 0003 0031 308 E: 1329930135.721151 0000 0002 0 E: 1329930135.721159 0000 0000 0 E: 1329930135.733084 0003 0035 3426 E: 1329930135.733087 0003 0036 4543 E: 1329930135.733090 0003 0034 0 E: 1329930135.733092 0003 0030 360 E: 1329930135.733095 0003 0031 308 E: 1329930135.733097 0000 0002 0 E: 1329930135.733105 0000 0000 0 E: 1329930135.747077 0001 014a 0 E: 1329930135.747080 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/drag_2_to_1.record0000644000015600001650000012157412651717544027414 0ustar pbuserpbgroup00000000000000E: 1332952534.708762 0003 0035 1876 E: 1332952534.708764 0003 0036 1676 E: 1332952534.708765 0003 0034 0 E: 1332952534.708766 0003 0030 312 E: 1332952534.708767 0003 0031 204 E: 1332952534.708768 0000 0002 0 E: 1332952534.708895 0000 0000 0 E: 1332952534.718665 0003 0000 3039 E: 1332952534.718667 0003 0001 1638 E: 1332952534.718668 0003 0035 3039 E: 1332952534.718669 0003 0036 1638 E: 1332952534.718670 0003 0034 1 E: 1332952534.718671 0003 0030 306 E: 1332952534.718672 0003 0031 156 E: 1332952534.718673 0000 0002 0 E: 1332952534.718705 0003 0035 1865 E: 1332952534.718706 0003 0036 1703 E: 1332952534.718707 0003 0034 0 E: 1332952534.718708 0003 0030 312 E: 1332952534.718709 0003 0031 204 E: 1332952534.718710 0000 0002 0 E: 1332952534.718833 0001 014d 1 E: 1332952534.718833 0001 014a 1 E: 1332952534.718835 0000 0000 0 E: 1332952534.728724 0003 0000 3031 E: 1332952534.728726 0003 0001 1671 E: 1332952534.728727 0003 0035 3031 E: 1332952534.728728 0003 0036 1671 E: 1332952534.728729 0003 0034 0 E: 1332952534.728730 0003 0030 312 E: 1332952534.728731 0003 0031 306 E: 1332952534.728732 0000 0002 0 E: 1332952534.728764 0003 0035 1864 E: 1332952534.728765 0003 0036 1709 E: 1332952534.728766 0003 0034 0 E: 1332952534.728767 0003 0030 312 E: 1332952534.728768 0003 0031 204 E: 1332952534.728770 0000 0002 0 E: 1332952534.728894 0000 0000 0 E: 1332952534.740725 0003 0000 3041 E: 1332952534.740727 0003 0001 1705 E: 1332952534.740728 0003 0035 3041 E: 1332952534.740729 0003 0036 1705 E: 1332952534.740730 0003 0034 0 E: 1332952534.740731 0003 0030 312 E: 1332952534.740732 0003 0031 306 E: 1332952534.740733 0000 0002 0 E: 1332952534.740765 0003 0035 1870 E: 1332952534.740766 0003 0036 1736 E: 1332952534.740767 0003 0034 0 E: 1332952534.740768 0003 0030 312 E: 1332952534.740769 0003 0031 204 E: 1332952534.740771 0000 0002 0 E: 1332952534.740894 0000 0000 0 E: 1332952534.750726 0003 0000 3047 E: 1332952534.750727 0003 0001 1736 E: 1332952534.750728 0003 0035 3047 E: 1332952534.750729 0003 0036 1736 E: 1332952534.750730 0003 0034 0 E: 1332952534.750731 0003 0030 312 E: 1332952534.750732 0003 0031 306 E: 1332952534.750734 0000 0002 0 E: 1332952534.750766 0003 0035 1856 E: 1332952534.750767 0003 0036 1803 E: 1332952534.750768 0003 0034 0 E: 1332952534.750769 0003 0030 468 E: 1332952534.750770 0003 0031 204 E: 1332952534.750771 0000 0002 0 E: 1332952534.750895 0000 0000 0 E: 1332952534.760669 0003 0000 3029 E: 1332952534.760671 0003 0001 1755 E: 1332952534.760672 0003 0035 3029 E: 1332952534.760673 0003 0036 1755 E: 1332952534.760674 0003 0034 0 E: 1332952534.760675 0003 0030 312 E: 1332952534.760676 0003 0031 306 E: 1332952534.760677 0000 0002 0 E: 1332952534.760709 0003 0035 1868 E: 1332952534.760710 0003 0036 1843 E: 1332952534.760711 0003 0034 0 E: 1332952534.760712 0003 0030 468 E: 1332952534.760713 0003 0031 204 E: 1332952534.760714 0000 0002 0 E: 1332952534.760838 0000 0000 0 E: 1332952534.770670 0003 0000 3024 E: 1332952534.770672 0003 0001 1799 E: 1332952534.770673 0003 0035 3024 E: 1332952534.770674 0003 0036 1799 E: 1332952534.770675 0003 0034 0 E: 1332952534.770676 0003 0030 468 E: 1332952534.770677 0003 0031 306 E: 1332952534.770678 0000 0002 0 E: 1332952534.770710 0003 0035 1860 E: 1332952534.770711 0003 0036 1860 E: 1332952534.770712 0003 0034 0 E: 1332952534.770713 0003 0030 312 E: 1332952534.770714 0003 0031 204 E: 1332952534.770715 0000 0002 0 E: 1332952534.770839 0000 0000 0 E: 1332952534.782672 0003 0000 3031 E: 1332952534.782674 0003 0001 1856 E: 1332952534.782675 0003 0035 3031 E: 1332952534.782676 0003 0036 1856 E: 1332952534.782677 0003 0034 0 E: 1332952534.782678 0003 0030 312 E: 1332952534.782679 0003 0031 306 E: 1332952534.782680 0000 0002 0 E: 1332952534.782712 0003 0035 1865 E: 1332952534.782713 0003 0036 1881 E: 1332952534.782714 0003 0034 0 E: 1332952534.782715 0003 0030 312 E: 1332952534.782716 0003 0031 204 E: 1332952534.782717 0000 0002 0 E: 1332952534.782841 0000 0000 0 E: 1332952534.792670 0003 0000 3030 E: 1332952534.792672 0003 0001 1895 E: 1332952534.792673 0003 0035 3030 E: 1332952534.792674 0003 0036 1895 E: 1332952534.792675 0003 0034 0 E: 1332952534.792676 0003 0030 312 E: 1332952534.792677 0003 0031 306 E: 1332952534.792678 0000 0002 0 E: 1332952534.792710 0003 0035 1858 E: 1332952534.792711 0003 0036 1925 E: 1332952534.792712 0003 0034 0 E: 1332952534.792713 0003 0030 468 E: 1332952534.792714 0003 0031 204 E: 1332952534.792715 0000 0002 0 E: 1332952534.792839 0000 0000 0 E: 1332952534.802677 0003 0000 3022 E: 1332952534.802679 0003 0001 1933 E: 1332952534.802680 0003 0035 3022 E: 1332952534.802681 0003 0036 1933 E: 1332952534.802682 0003 0034 0 E: 1332952534.802683 0003 0030 468 E: 1332952534.802684 0003 0031 306 E: 1332952534.802685 0000 0002 0 E: 1332952534.802717 0003 0035 1842 E: 1332952534.802718 0003 0036 1994 E: 1332952534.802719 0003 0034 0 E: 1332952534.802720 0003 0030 468 E: 1332952534.802721 0003 0031 306 E: 1332952534.802722 0000 0002 0 E: 1332952534.802846 0000 0000 0 E: 1332952534.812674 0003 0000 3015 E: 1332952534.812676 0003 0001 1974 E: 1332952534.812677 0003 0035 3015 E: 1332952534.812678 0003 0036 1974 E: 1332952534.812679 0003 0034 0 E: 1332952534.812680 0003 0030 468 E: 1332952534.812681 0003 0031 306 E: 1332952534.812682 0000 0002 0 E: 1332952534.812714 0003 0035 1855 E: 1332952534.812715 0003 0036 2030 E: 1332952534.812716 0003 0034 0 E: 1332952534.812717 0003 0030 312 E: 1332952534.812718 0003 0031 306 E: 1332952534.812719 0000 0002 0 E: 1332952534.812843 0000 0000 0 E: 1332952534.822670 0003 0000 3019 E: 1332952534.822671 0003 0001 1992 E: 1332952534.822672 0003 0035 3019 E: 1332952534.822673 0003 0036 1992 E: 1332952534.822674 0003 0034 0 E: 1332952534.822675 0003 0030 312 E: 1332952534.822676 0003 0031 306 E: 1332952534.822677 0000 0002 0 E: 1332952534.822709 0003 0035 1851 E: 1332952534.822710 0003 0036 2030 E: 1332952534.822711 0003 0034 0 E: 1332952534.822712 0003 0030 312 E: 1332952534.822713 0003 0031 306 E: 1332952534.822714 0000 0002 0 E: 1332952534.822838 0000 0000 0 E: 1332952534.832725 0003 0001 2032 E: 1332952534.832727 0003 0035 3019 E: 1332952534.832728 0003 0036 2032 E: 1332952534.832729 0003 0034 0 E: 1332952534.832730 0003 0030 312 E: 1332952534.832731 0003 0031 306 E: 1332952534.832732 0000 0002 0 E: 1332952534.832764 0003 0035 1848 E: 1332952534.832765 0003 0036 2076 E: 1332952534.832766 0003 0034 0 E: 1332952534.832767 0003 0030 468 E: 1332952534.832768 0003 0031 306 E: 1332952534.832769 0000 0002 0 E: 1332952534.832893 0000 0000 0 E: 1332952534.842674 0003 0000 3008 E: 1332952534.842676 0003 0001 2057 E: 1332952534.842677 0003 0035 3008 E: 1332952534.842678 0003 0036 2057 E: 1332952534.842679 0003 0034 0 E: 1332952534.842680 0003 0030 312 E: 1332952534.842681 0003 0031 306 E: 1332952534.842682 0000 0002 0 E: 1332952534.842715 0003 0035 1851 E: 1332952534.842716 0003 0036 2136 E: 1332952534.842717 0003 0034 0 E: 1332952534.842718 0003 0030 468 E: 1332952534.842719 0003 0031 306 E: 1332952534.842720 0000 0002 0 E: 1332952534.842843 0000 0000 0 E: 1332952534.852724 0003 0000 3012 E: 1332952534.852725 0003 0001 2060 E: 1332952534.852726 0003 0035 3012 E: 1332952534.852727 0003 0036 2060 E: 1332952534.852728 0003 0034 0 E: 1332952534.852729 0003 0030 312 E: 1332952534.852730 0003 0031 306 E: 1332952534.852732 0000 0002 0 E: 1332952534.852764 0003 0035 1847 E: 1332952534.852765 0003 0036 2169 E: 1332952534.852766 0003 0034 0 E: 1332952534.852767 0003 0030 312 E: 1332952534.852768 0003 0031 306 E: 1332952534.852769 0000 0002 0 E: 1332952534.852893 0000 0000 0 E: 1332952534.862726 0003 0001 2123 E: 1332952534.862727 0003 0035 3012 E: 1332952534.862728 0003 0036 2123 E: 1332952534.862729 0003 0034 0 E: 1332952534.862730 0003 0030 468 E: 1332952534.862731 0003 0031 306 E: 1332952534.862733 0000 0002 0 E: 1332952534.862765 0003 0035 1843 E: 1332952534.862766 0003 0036 2193 E: 1332952534.862767 0003 0034 0 E: 1332952534.862768 0003 0030 312 E: 1332952534.862769 0003 0031 306 E: 1332952534.862770 0000 0002 0 E: 1332952534.862894 0000 0000 0 E: 1332952534.872669 0003 0000 3000 E: 1332952534.872670 0003 0001 2164 E: 1332952534.872671 0003 0035 3000 E: 1332952534.872672 0003 0036 2164 E: 1332952534.872673 0003 0034 0 E: 1332952534.872674 0003 0030 312 E: 1332952534.872675 0003 0031 306 E: 1332952534.872676 0000 0002 0 E: 1332952534.872708 0003 0035 1838 E: 1332952534.872709 0003 0036 2198 E: 1332952534.872710 0003 0034 0 E: 1332952534.872711 0003 0030 312 E: 1332952534.872712 0003 0031 306 E: 1332952534.872713 0000 0002 0 E: 1332952534.872837 0000 0000 0 E: 1332952534.882676 0003 0000 2999 E: 1332952534.882678 0003 0001 2182 E: 1332952534.882679 0003 0035 2999 E: 1332952534.882680 0003 0036 2182 E: 1332952534.882681 0003 0034 0 E: 1332952534.882682 0003 0030 312 E: 1332952534.882683 0003 0031 306 E: 1332952534.882684 0000 0002 0 E: 1332952534.882717 0003 0035 1828 E: 1332952534.882718 0003 0036 2243 E: 1332952534.882719 0003 0034 0 E: 1332952534.882720 0003 0030 468 E: 1332952534.882721 0003 0031 306 E: 1332952534.882722 0000 0002 0 E: 1332952534.882845 0000 0000 0 E: 1332952534.892676 0003 0000 2996 E: 1332952534.892678 0003 0001 2206 E: 1332952534.892679 0003 0035 2996 E: 1332952534.892680 0003 0036 2206 E: 1332952534.892681 0003 0034 0 E: 1332952534.892682 0003 0030 312 E: 1332952534.892683 0003 0031 306 E: 1332952534.892684 0000 0002 0 E: 1332952534.892716 0003 0035 1836 E: 1332952534.892717 0003 0036 2306 E: 1332952534.892718 0003 0034 0 E: 1332952534.892719 0003 0030 312 E: 1332952534.892720 0003 0031 306 E: 1332952534.892721 0000 0002 0 E: 1332952534.892845 0000 0000 0 E: 1332952534.902723 0003 0000 3001 E: 1332952534.902724 0003 0001 2261 E: 1332952534.902725 0003 0035 3001 E: 1332952534.902726 0003 0036 2261 E: 1332952534.902728 0003 0034 0 E: 1332952534.902729 0003 0030 468 E: 1332952534.902730 0003 0031 306 E: 1332952534.902731 0000 0002 0 E: 1332952534.902763 0003 0035 1827 E: 1332952534.902764 0003 0036 2329 E: 1332952534.902765 0003 0034 0 E: 1332952534.902766 0003 0030 312 E: 1332952534.902767 0003 0031 306 E: 1332952534.902768 0000 0002 0 E: 1332952534.902892 0000 0000 0 E: 1332952534.912676 0003 0000 3000 E: 1332952534.912677 0003 0001 2314 E: 1332952534.912679 0003 0035 3000 E: 1332952534.912680 0003 0036 2314 E: 1332952534.912681 0003 0034 0 E: 1332952534.912682 0003 0030 312 E: 1332952534.912683 0003 0031 306 E: 1332952534.912684 0000 0002 0 E: 1332952534.912716 0003 0035 1833 E: 1332952534.912717 0003 0036 2355 E: 1332952534.912718 0003 0034 0 E: 1332952534.912719 0003 0030 312 E: 1332952534.912720 0003 0031 306 E: 1332952534.912721 0000 0002 0 E: 1332952534.912845 0000 0000 0 E: 1332952534.922725 0003 0000 3002 E: 1332952534.922727 0003 0001 2344 E: 1332952534.922728 0003 0035 3002 E: 1332952534.922729 0003 0036 2344 E: 1332952534.922730 0003 0034 0 E: 1332952534.922731 0003 0030 312 E: 1332952534.922732 0003 0031 306 E: 1332952534.922733 0000 0002 0 E: 1332952534.922765 0003 0035 1832 E: 1332952534.922766 0003 0036 2397 E: 1332952534.922767 0003 0034 0 E: 1332952534.922768 0003 0030 468 E: 1332952534.922769 0003 0031 306 E: 1332952534.922770 0000 0002 0 E: 1332952534.922894 0000 0000 0 E: 1332952534.932725 0003 0000 2988 E: 1332952534.932726 0003 0001 2362 E: 1332952534.932728 0003 0035 2988 E: 1332952534.932729 0003 0036 2362 E: 1332952534.932730 0003 0034 0 E: 1332952534.932731 0003 0030 312 E: 1332952534.932732 0003 0031 306 E: 1332952534.932733 0000 0002 0 E: 1332952534.932765 0003 0035 1818 E: 1332952534.932766 0003 0036 2429 E: 1332952534.932767 0003 0034 0 E: 1332952534.932768 0003 0030 468 E: 1332952534.932769 0003 0031 306 E: 1332952534.932770 0000 0002 0 E: 1332952534.932894 0000 0000 0 E: 1332952534.942671 0003 0000 2996 E: 1332952534.942673 0003 0001 2380 E: 1332952534.942674 0003 0035 2996 E: 1332952534.942675 0003 0036 2380 E: 1332952534.942676 0003 0034 0 E: 1332952534.942677 0003 0030 468 E: 1332952534.942678 0003 0031 306 E: 1332952534.942679 0000 0002 0 E: 1332952534.942711 0003 0035 1830 E: 1332952534.942712 0003 0036 2470 E: 1332952534.942713 0003 0034 0 E: 1332952534.942714 0003 0030 468 E: 1332952534.942715 0003 0031 306 E: 1332952534.942716 0000 0002 0 E: 1332952534.942840 0000 0000 0 E: 1332952534.952755 0003 0000 2984 E: 1332952534.952756 0003 0001 2439 E: 1332952534.952757 0003 0035 2984 E: 1332952534.952758 0003 0036 2439 E: 1332952534.952759 0003 0034 0 E: 1332952534.952760 0003 0030 468 E: 1332952534.952761 0003 0031 204 E: 1332952534.952762 0000 0002 0 E: 1332952534.952795 0003 0035 1830 E: 1332952534.952796 0003 0036 2510 E: 1332952534.952797 0003 0034 0 E: 1332952534.952798 0003 0030 312 E: 1332952534.952799 0003 0031 306 E: 1332952534.952800 0000 0002 0 E: 1332952534.952923 0000 0000 0 E: 1332952534.964725 0003 0000 2995 E: 1332952534.964727 0003 0001 2472 E: 1332952534.964728 0003 0035 2995 E: 1332952534.964729 0003 0036 2472 E: 1332952534.964730 0003 0034 0 E: 1332952534.964731 0003 0030 468 E: 1332952534.964732 0003 0031 306 E: 1332952534.964733 0000 0002 0 E: 1332952534.964766 0003 0035 1825 E: 1332952534.964767 0003 0036 2520 E: 1332952534.964768 0003 0034 0 E: 1332952534.964769 0003 0030 312 E: 1332952534.964770 0003 0031 306 E: 1332952534.964771 0000 0002 0 E: 1332952534.964894 0000 0000 0 E: 1332952534.974675 0003 0000 2981 E: 1332952534.974676 0003 0001 2487 E: 1332952534.974677 0003 0035 2981 E: 1332952534.974678 0003 0036 2487 E: 1332952534.974679 0003 0034 0 E: 1332952534.974680 0003 0030 312 E: 1332952534.974681 0003 0031 306 E: 1332952534.974682 0000 0002 0 E: 1332952534.974715 0003 0035 1824 E: 1332952534.974716 0003 0036 2557 E: 1332952534.974717 0003 0034 0 E: 1332952534.974718 0003 0030 468 E: 1332952534.974719 0003 0031 306 E: 1332952534.974720 0000 0002 0 E: 1332952534.974844 0000 0000 0 E: 1332952534.984677 0003 0000 2991 E: 1332952534.984679 0003 0001 2509 E: 1332952534.984680 0003 0035 2991 E: 1332952534.984681 0003 0036 2509 E: 1332952534.984682 0003 0034 0 E: 1332952534.984683 0003 0030 312 E: 1332952534.984684 0003 0031 306 E: 1332952534.984685 0000 0002 0 E: 1332952534.984717 0003 0035 1817 E: 1332952534.984718 0003 0036 2591 E: 1332952534.984719 0003 0034 0 E: 1332952534.984720 0003 0030 468 E: 1332952534.984721 0003 0031 306 E: 1332952534.984723 0000 0002 0 E: 1332952534.984846 0000 0000 0 E: 1332952534.994725 0003 0000 2997 E: 1332952534.994726 0003 0001 2529 E: 1332952534.994727 0003 0035 2997 E: 1332952534.994728 0003 0036 2529 E: 1332952534.994729 0003 0034 0 E: 1332952534.994730 0003 0030 312 E: 1332952534.994731 0003 0031 306 E: 1332952534.994732 0000 0002 0 E: 1332952534.994765 0003 0035 1820 E: 1332952534.994766 0003 0036 2630 E: 1332952534.994767 0003 0034 0 E: 1332952534.994768 0003 0030 312 E: 1332952534.994769 0003 0031 306 E: 1332952534.994770 0000 0002 0 E: 1332952534.994894 0000 0000 0 E: 1332952535.004728 0003 0000 2992 E: 1332952535.004730 0003 0001 2574 E: 1332952535.004731 0003 0035 2992 E: 1332952535.004732 0003 0036 2574 E: 1332952535.004733 0003 0034 0 E: 1332952535.004734 0003 0030 468 E: 1332952535.004735 0003 0031 306 E: 1332952535.004736 0000 0002 0 E: 1332952535.004768 0003 0035 1822 E: 1332952535.004769 0003 0036 2651 E: 1332952535.004770 0003 0034 0 E: 1332952535.004771 0003 0030 312 E: 1332952535.004772 0003 0031 306 E: 1332952535.004773 0000 0002 0 E: 1332952535.004897 0000 0000 0 E: 1332952535.016674 0003 0000 2996 E: 1332952535.016676 0003 0001 2621 E: 1332952535.016677 0003 0035 2996 E: 1332952535.016678 0003 0036 2621 E: 1332952535.016679 0003 0034 0 E: 1332952535.016680 0003 0030 312 E: 1332952535.016681 0003 0031 306 E: 1332952535.016682 0000 0002 0 E: 1332952535.016714 0003 0035 1824 E: 1332952535.016715 0003 0036 2672 E: 1332952535.016716 0003 0034 0 E: 1332952535.016717 0003 0030 468 E: 1332952535.016718 0003 0031 306 E: 1332952535.016719 0000 0002 0 E: 1332952535.016843 0000 0000 0 E: 1332952535.026675 0003 0000 3004 E: 1332952535.026677 0003 0001 2650 E: 1332952535.026678 0003 0035 3004 E: 1332952535.026679 0003 0036 2650 E: 1332952535.026680 0003 0034 0 E: 1332952535.026681 0003 0030 312 E: 1332952535.026682 0003 0031 306 E: 1332952535.026683 0000 0002 0 E: 1332952535.026715 0003 0035 1820 E: 1332952535.026716 0003 0036 2719 E: 1332952535.026717 0003 0034 0 E: 1332952535.026718 0003 0030 468 E: 1332952535.026719 0003 0031 306 E: 1332952535.026720 0000 0002 0 E: 1332952535.026844 0000 0000 0 E: 1332952535.036709 0003 0000 2996 E: 1332952535.036711 0003 0001 2687 E: 1332952535.036712 0003 0035 2996 E: 1332952535.036713 0003 0036 2687 E: 1332952535.036714 0003 0034 0 E: 1332952535.036715 0003 0030 312 E: 1332952535.036716 0003 0031 306 E: 1332952535.036717 0000 0002 0 E: 1332952535.036749 0003 0035 1825 E: 1332952535.036750 0003 0036 2770 E: 1332952535.036751 0003 0034 0 E: 1332952535.036752 0003 0030 468 E: 1332952535.036753 0003 0031 306 E: 1332952535.036755 0000 0002 0 E: 1332952535.036878 0000 0000 0 E: 1332952535.046675 0003 0000 3009 E: 1332952535.046677 0003 0001 2738 E: 1332952535.046678 0003 0035 3009 E: 1332952535.046679 0003 0036 2738 E: 1332952535.046680 0003 0034 0 E: 1332952535.046681 0003 0030 468 E: 1332952535.046682 0003 0031 306 E: 1332952535.046683 0000 0002 0 E: 1332952535.046715 0003 0035 1821 E: 1332952535.046716 0003 0036 2810 E: 1332952535.046717 0003 0034 0 E: 1332952535.046718 0003 0030 312 E: 1332952535.046719 0003 0031 306 E: 1332952535.046720 0000 0002 0 E: 1332952535.046844 0000 0000 0 E: 1332952535.058725 0003 0000 2999 E: 1332952535.058726 0003 0001 2788 E: 1332952535.058728 0003 0035 2999 E: 1332952535.058729 0003 0036 2788 E: 1332952535.058730 0003 0034 0 E: 1332952535.058731 0003 0030 312 E: 1332952535.058732 0003 0031 306 E: 1332952535.058733 0000 0002 0 E: 1332952535.058765 0003 0035 1829 E: 1332952535.058766 0003 0036 2833 E: 1332952535.058767 0003 0034 0 E: 1332952535.058768 0003 0030 468 E: 1332952535.058769 0003 0031 306 E: 1332952535.058770 0000 0002 0 E: 1332952535.058894 0000 0000 0 E: 1332952535.066676 0003 0001 2822 E: 1332952535.066677 0003 0035 2999 E: 1332952535.066678 0003 0036 2822 E: 1332952535.066679 0003 0034 0 E: 1332952535.066680 0003 0030 312 E: 1332952535.066681 0003 0031 306 E: 1332952535.066682 0000 0002 0 E: 1332952535.066715 0003 0035 1824 E: 1332952535.066716 0003 0036 2900 E: 1332952535.066717 0003 0034 0 E: 1332952535.066718 0003 0030 468 E: 1332952535.066719 0003 0031 306 E: 1332952535.066720 0000 0002 0 E: 1332952535.066844 0000 0000 0 E: 1332952535.076723 0003 0000 2997 E: 1332952535.076724 0003 0001 2864 E: 1332952535.076725 0003 0035 2997 E: 1332952535.076726 0003 0036 2864 E: 1332952535.076727 0003 0034 0 E: 1332952535.076728 0003 0030 468 E: 1332952535.076729 0003 0031 306 E: 1332952535.076731 0000 0002 0 E: 1332952535.076763 0003 0035 1822 E: 1332952535.076764 0003 0036 2947 E: 1332952535.076765 0003 0034 0 E: 1332952535.076766 0003 0030 468 E: 1332952535.076767 0003 0031 306 E: 1332952535.076768 0000 0002 0 E: 1332952535.076892 0000 0000 0 E: 1332952535.086670 0003 0000 2992 E: 1332952535.086671 0003 0001 2940 E: 1332952535.086672 0003 0035 2992 E: 1332952535.086673 0003 0036 2940 E: 1332952535.086674 0003 0034 0 E: 1332952535.086675 0003 0030 468 E: 1332952535.086676 0003 0031 306 E: 1332952535.086678 0000 0002 0 E: 1332952535.086709 0003 0035 1829 E: 1332952535.086710 0003 0036 2997 E: 1332952535.086711 0003 0034 0 E: 1332952535.086712 0003 0030 312 E: 1332952535.086713 0003 0031 306 E: 1332952535.086714 0000 0002 0 E: 1332952535.086838 0000 0000 0 E: 1332952535.098706 0003 0000 2989 E: 1332952535.098708 0003 0001 2982 E: 1332952535.098709 0003 0035 2989 E: 1332952535.098710 0003 0036 2982 E: 1332952535.098711 0003 0034 0 E: 1332952535.098712 0003 0030 312 E: 1332952535.098713 0003 0031 306 E: 1332952535.098714 0000 0002 0 E: 1332952535.098746 0003 0035 1817 E: 1332952535.098747 0003 0036 3045 E: 1332952535.098748 0003 0034 0 E: 1332952535.098749 0003 0030 468 E: 1332952535.098750 0003 0031 306 E: 1332952535.098752 0000 0002 0 E: 1332952535.098877 0000 0000 0 E: 1332952535.110741 0003 0000 2993 E: 1332952535.110743 0003 0001 3009 E: 1332952535.110744 0003 0035 2993 E: 1332952535.110745 0003 0036 3009 E: 1332952535.110746 0003 0034 0 E: 1332952535.110747 0003 0030 468 E: 1332952535.110748 0003 0031 306 E: 1332952535.110749 0000 0002 0 E: 1332952535.110783 0003 0035 1822 E: 1332952535.110784 0003 0036 3094 E: 1332952535.110785 0003 0034 0 E: 1332952535.110786 0003 0030 312 E: 1332952535.110787 0003 0031 306 E: 1332952535.110788 0000 0002 0 E: 1332952535.110914 0000 0000 0 E: 1332952535.120634 0003 0001 3061 E: 1332952535.120636 0003 0035 2993 E: 1332952535.120637 0003 0036 3061 E: 1332952535.120638 0003 0034 0 E: 1332952535.120639 0003 0030 468 E: 1332952535.120640 0003 0031 408 E: 1332952535.120641 0000 0002 0 E: 1332952535.120674 0003 0035 1818 E: 1332952535.120675 0003 0036 3128 E: 1332952535.120676 0003 0034 0 E: 1332952535.120677 0003 0030 312 E: 1332952535.120678 0003 0031 306 E: 1332952535.120679 0000 0002 0 E: 1332952535.120803 0000 0000 0 E: 1332952535.132622 0003 0000 2988 E: 1332952535.132622 0003 0001 3126 E: 1332952535.132623 0003 0035 2988 E: 1332952535.132623 0003 0036 3126 E: 1332952535.132624 0003 0034 0 E: 1332952535.132624 0003 0030 312 E: 1332952535.132625 0003 0031 306 E: 1332952535.132625 0000 0002 0 E: 1332952535.132638 0003 0035 1813 E: 1332952535.132638 0003 0036 3175 E: 1332952535.132639 0003 0034 0 E: 1332952535.132639 0003 0030 468 E: 1332952535.132640 0003 0031 306 E: 1332952535.132640 0000 0002 0 E: 1332952535.132689 0000 0000 0 E: 1332952535.142756 0003 0000 2996 E: 1332952535.142758 0003 0001 3152 E: 1332952535.142759 0003 0035 2996 E: 1332952535.142761 0003 0036 3152 E: 1332952535.142763 0003 0034 0 E: 1332952535.142764 0003 0030 468 E: 1332952535.142765 0003 0031 306 E: 1332952535.142766 0000 0002 0 E: 1332952535.142799 0003 0035 1820 E: 1332952535.142800 0003 0036 3242 E: 1332952535.142801 0003 0034 0 E: 1332952535.142802 0003 0030 312 E: 1332952535.142803 0003 0031 306 E: 1332952535.142804 0000 0002 0 E: 1332952535.142938 0000 0000 0 E: 1332952535.152724 0003 0001 3227 E: 1332952535.152726 0003 0035 2996 E: 1332952535.152727 0003 0036 3227 E: 1332952535.152728 0003 0034 0 E: 1332952535.152729 0003 0030 468 E: 1332952535.152730 0003 0031 306 E: 1332952535.152731 0000 0002 0 E: 1332952535.152763 0003 0035 1817 E: 1332952535.152764 0003 0036 3276 E: 1332952535.152765 0003 0034 0 E: 1332952535.152766 0003 0030 312 E: 1332952535.152767 0003 0031 306 E: 1332952535.152768 0000 0002 0 E: 1332952535.152892 0000 0000 0 E: 1332952535.162671 0003 0000 2983 E: 1332952535.162673 0003 0001 3260 E: 1332952535.162674 0003 0035 2983 E: 1332952535.162675 0003 0036 3260 E: 1332952535.162676 0003 0034 0 E: 1332952535.162677 0003 0030 312 E: 1332952535.162678 0003 0031 306 E: 1332952535.162679 0000 0002 0 E: 1332952535.162713 0003 0035 1810 E: 1332952535.162714 0003 0036 3297 E: 1332952535.162715 0003 0034 0 E: 1332952535.162716 0003 0030 312 E: 1332952535.162717 0003 0031 306 E: 1332952535.162718 0000 0002 0 E: 1332952535.162842 0000 0000 0 E: 1332952535.172723 0003 0000 2986 E: 1332952535.172725 0003 0001 3285 E: 1332952535.172726 0003 0035 2986 E: 1332952535.172727 0003 0036 3285 E: 1332952535.172728 0003 0034 0 E: 1332952535.172729 0003 0030 312 E: 1332952535.172730 0003 0031 306 E: 1332952535.172731 0000 0002 0 E: 1332952535.172763 0003 0035 1805 E: 1332952535.172764 0003 0036 3376 E: 1332952535.172765 0003 0034 0 E: 1332952535.172766 0003 0030 468 E: 1332952535.172767 0003 0031 306 E: 1332952535.172768 0000 0002 0 E: 1332952535.172892 0000 0000 0 E: 1332952535.184726 0003 0000 2985 E: 1332952535.184728 0003 0001 3319 E: 1332952535.184729 0003 0035 2985 E: 1332952535.184730 0003 0036 3319 E: 1332952535.184731 0003 0034 0 E: 1332952535.184732 0003 0030 468 E: 1332952535.184733 0003 0031 306 E: 1332952535.184734 0000 0002 0 E: 1332952535.184766 0003 0035 1812 E: 1332952535.184767 0003 0036 3408 E: 1332952535.184768 0003 0034 0 E: 1332952535.184769 0003 0030 312 E: 1332952535.184770 0003 0031 306 E: 1332952535.184771 0000 0002 0 E: 1332952535.184895 0000 0000 0 E: 1332952535.194682 0003 0000 2979 E: 1332952535.194683 0003 0001 3375 E: 1332952535.194684 0003 0035 2979 E: 1332952535.194685 0003 0036 3375 E: 1332952535.194686 0003 0034 0 E: 1332952535.194687 0003 0030 468 E: 1332952535.194688 0003 0031 408 E: 1332952535.194689 0000 0002 0 E: 1332952535.194722 0003 0035 1803 E: 1332952535.194723 0003 0036 3437 E: 1332952535.194724 0003 0034 0 E: 1332952535.194725 0003 0030 312 E: 1332952535.194726 0003 0031 306 E: 1332952535.194727 0000 0002 0 E: 1332952535.194851 0000 0000 0 E: 1332952535.206634 0003 0000 2987 E: 1332952535.206635 0003 0001 3417 E: 1332952535.206637 0003 0035 2987 E: 1332952535.206637 0003 0036 3417 E: 1332952535.206639 0003 0034 0 E: 1332952535.206640 0003 0030 312 E: 1332952535.206641 0003 0031 306 E: 1332952535.206642 0000 0002 0 E: 1332952535.206674 0003 0035 1818 E: 1332952535.206675 0003 0036 3479 E: 1332952535.206676 0003 0034 0 E: 1332952535.206677 0003 0030 468 E: 1332952535.206678 0003 0031 306 E: 1332952535.206679 0000 0002 0 E: 1332952535.206803 0000 0000 0 E: 1332952535.216724 0003 0000 2967 E: 1332952535.216725 0003 0001 3447 E: 1332952535.216727 0003 0035 2967 E: 1332952535.216728 0003 0036 3447 E: 1332952535.216728 0003 0034 1 E: 1332952535.216730 0003 0030 408 E: 1332952535.216731 0003 0031 312 E: 1332952535.216732 0000 0002 0 E: 1332952535.216764 0003 0035 1821 E: 1332952535.216765 0003 0036 3529 E: 1332952535.216766 0003 0034 0 E: 1332952535.216767 0003 0030 468 E: 1332952535.216768 0003 0031 306 E: 1332952535.216769 0000 0002 0 E: 1332952535.216893 0000 0000 0 E: 1332952535.226647 0003 0000 2978 E: 1332952535.226648 0003 0001 3483 E: 1332952535.226649 0003 0035 2978 E: 1332952535.226650 0003 0036 3483 E: 1332952535.226651 0003 0034 0 E: 1332952535.226652 0003 0030 468 E: 1332952535.226653 0003 0031 306 E: 1332952535.226655 0000 0002 0 E: 1332952535.226687 0003 0035 1812 E: 1332952535.226688 0003 0036 3567 E: 1332952535.226689 0003 0034 0 E: 1332952535.226690 0003 0030 312 E: 1332952535.226691 0003 0031 306 E: 1332952535.226692 0000 0002 0 E: 1332952535.226816 0000 0000 0 E: 1332952535.236718 0003 0001 3559 E: 1332952535.236720 0003 0035 2978 E: 1332952535.236721 0003 0036 3559 E: 1332952535.236722 0003 0034 0 E: 1332952535.236723 0003 0030 468 E: 1332952535.236724 0003 0031 204 E: 1332952535.236725 0000 0002 0 E: 1332952535.236757 0003 0035 1832 E: 1332952535.236758 0003 0036 3592 E: 1332952535.236759 0003 0034 0 E: 1332952535.236760 0003 0030 468 E: 1332952535.236761 0003 0031 306 E: 1332952535.236762 0000 0002 0 E: 1332952535.236886 0000 0000 0 E: 1332952535.248724 0003 0000 2972 E: 1332952535.248725 0003 0001 3583 E: 1332952535.248726 0003 0035 2972 E: 1332952535.248727 0003 0036 3583 E: 1332952535.248728 0003 0034 0 E: 1332952535.248729 0003 0030 312 E: 1332952535.248730 0003 0031 306 E: 1332952535.248731 0000 0002 0 E: 1332952535.248764 0003 0035 1828 E: 1332952535.248765 0003 0036 3605 E: 1332952535.248766 0003 0034 0 E: 1332952535.248767 0003 0030 468 E: 1332952535.248768 0003 0031 306 E: 1332952535.248769 0000 0002 0 E: 1332952535.248893 0000 0000 0 E: 1332952535.258634 0003 0000 2970 E: 1332952535.258635 0003 0001 3626 E: 1332952535.258636 0003 0035 2970 E: 1332952535.258637 0003 0036 3626 E: 1332952535.258638 0003 0034 0 E: 1332952535.258639 0003 0030 312 E: 1332952535.258640 0003 0031 204 E: 1332952535.258642 0000 0002 0 E: 1332952535.258674 0003 0035 1831 E: 1332952535.258675 0003 0036 3649 E: 1332952535.258676 0003 0034 0 E: 1332952535.258677 0003 0030 468 E: 1332952535.258678 0003 0031 306 E: 1332952535.258679 0000 0002 0 E: 1332952535.258803 0000 0000 0 E: 1332952535.268724 0003 0000 1835 E: 1332952535.268725 0003 0001 3709 E: 1332952535.268726 0003 0035 1835 E: 1332952535.268727 0003 0036 3709 E: 1332952535.268728 0003 0034 0 E: 1332952535.268729 0003 0030 468 E: 1332952535.268730 0003 0031 306 E: 1332952535.268731 0000 0002 0 E: 1332952535.268886 0000 0000 0 E: 1332952535.278710 0003 0000 1816 E: 1332952535.278712 0003 0001 3743 E: 1332952535.278713 0003 0035 1816 E: 1332952535.278714 0003 0036 3743 E: 1332952535.278715 0003 0034 0 E: 1332952535.278716 0003 0030 312 E: 1332952535.278717 0003 0031 306 E: 1332952535.278718 0000 0002 0 E: 1332952535.278873 0000 0000 0 E: 1332952535.288723 0003 0000 1831 E: 1332952535.288724 0003 0001 3768 E: 1332952535.288725 0003 0035 1831 E: 1332952535.288726 0003 0036 3768 E: 1332952535.288728 0003 0034 0 E: 1332952535.288729 0003 0030 468 E: 1332952535.288730 0003 0031 306 E: 1332952535.288731 0000 0002 0 E: 1332952535.288885 0000 0000 0 E: 1332952535.298644 0003 0000 1828 E: 1332952535.298645 0003 0001 3823 E: 1332952535.298646 0003 0035 1828 E: 1332952535.298647 0003 0036 3823 E: 1332952535.298648 0003 0034 0 E: 1332952535.298649 0003 0030 468 E: 1332952535.298650 0003 0031 306 E: 1332952535.298651 0000 0002 0 E: 1332952535.298806 0000 0000 0 E: 1332952535.308723 0003 0000 1847 E: 1332952535.308725 0003 0001 3851 E: 1332952535.308726 0003 0035 1847 E: 1332952535.308727 0003 0036 3851 E: 1332952535.308728 0003 0034 0 E: 1332952535.308729 0003 0030 468 E: 1332952535.308730 0003 0031 204 E: 1332952535.308731 0000 0002 0 E: 1332952535.308885 0000 0000 0 E: 1332952535.318707 0003 0000 1853 E: 1332952535.318709 0003 0001 3895 E: 1332952535.318710 0003 0035 1853 E: 1332952535.318711 0003 0036 3895 E: 1332952535.318712 0003 0034 0 E: 1332952535.318713 0003 0030 312 E: 1332952535.318714 0003 0031 204 E: 1332952535.318715 0000 0002 0 E: 1332952535.318869 0000 0000 0 E: 1332952535.330700 0003 0000 1837 E: 1332952535.330701 0003 0001 3934 E: 1332952535.330702 0003 0035 1837 E: 1332952535.330703 0003 0036 3934 E: 1332952535.330704 0003 0034 0 E: 1332952535.330705 0003 0030 468 E: 1332952535.330706 0003 0031 306 E: 1332952535.330708 0000 0002 0 E: 1332952535.330862 0000 0000 0 E: 1332952535.340724 0003 0000 1818 E: 1332952535.340725 0003 0001 3990 E: 1332952535.340726 0003 0035 1818 E: 1332952535.340727 0003 0036 3990 E: 1332952535.340728 0003 0034 0 E: 1332952535.340729 0003 0030 468 E: 1332952535.340730 0003 0031 306 E: 1332952535.340731 0000 0002 0 E: 1332952535.340886 0000 0000 0 E: 1332952535.350723 0003 0000 1816 E: 1332952535.350725 0003 0001 4007 E: 1332952535.350726 0003 0035 1816 E: 1332952535.350727 0003 0036 4007 E: 1332952535.350728 0003 0034 0 E: 1332952535.350729 0003 0030 468 E: 1332952535.350730 0003 0031 306 E: 1332952535.350731 0000 0002 0 E: 1332952535.350885 0000 0000 0 E: 1332952535.362723 0003 0000 1821 E: 1332952535.362725 0003 0001 4049 E: 1332952535.362726 0003 0035 1821 E: 1332952535.362727 0003 0036 4049 E: 1332952535.362728 0003 0034 0 E: 1332952535.362729 0003 0030 312 E: 1332952535.362730 0003 0031 306 E: 1332952535.362731 0000 0002 0 E: 1332952535.362885 0000 0000 0 E: 1332952535.370724 0003 0000 1849 E: 1332952535.370725 0003 0001 4066 E: 1332952535.370726 0003 0035 1849 E: 1332952535.370727 0003 0036 4066 E: 1332952535.370728 0003 0034 0 E: 1332952535.370729 0003 0030 312 E: 1332952535.370730 0003 0031 204 E: 1332952535.370732 0000 0002 0 E: 1332952535.370886 0000 0000 0 E: 1332952535.386725 0003 0000 1819 E: 1332952535.386726 0003 0001 4114 E: 1332952535.386727 0003 0035 1819 E: 1332952535.386728 0003 0036 4114 E: 1332952535.386729 0003 0034 0 E: 1332952535.386730 0003 0030 468 E: 1332952535.386731 0003 0031 306 E: 1332952535.386732 0000 0002 0 E: 1332952535.386887 0000 0000 0 E: 1332952535.394707 0003 0000 1804 E: 1332952535.394708 0003 0001 4106 E: 1332952535.394709 0003 0035 1804 E: 1332952535.394710 0003 0036 4106 E: 1332952535.394711 0003 0034 0 E: 1332952535.394712 0003 0030 468 E: 1332952535.394713 0003 0031 306 E: 1332952535.394715 0000 0002 0 E: 1332952535.394869 0000 0000 0 E: 1332952535.404725 0003 0001 4197 E: 1332952535.404726 0003 0035 1804 E: 1332952535.404727 0003 0036 4197 E: 1332952535.404728 0003 0034 0 E: 1332952535.404729 0003 0030 312 E: 1332952535.404730 0003 0031 306 E: 1332952535.404732 0000 0002 0 E: 1332952535.404886 0000 0000 0 E: 1332952535.418707 0003 0000 1810 E: 1332952535.418709 0003 0001 4191 E: 1332952535.418710 0003 0035 1810 E: 1332952535.418711 0003 0036 4191 E: 1332952535.418712 0003 0034 0 E: 1332952535.418713 0003 0030 312 E: 1332952535.418714 0003 0031 306 E: 1332952535.418715 0000 0002 0 E: 1332952535.418869 0000 0000 0 E: 1332952535.426633 0003 0000 1801 E: 1332952535.426634 0003 0001 4219 E: 1332952535.426635 0003 0035 1801 E: 1332952535.426636 0003 0036 4219 E: 1332952535.426637 0003 0034 0 E: 1332952535.426638 0003 0030 312 E: 1332952535.426639 0003 0031 306 E: 1332952535.426641 0000 0002 0 E: 1332952535.426796 0000 0000 0 E: 1332952535.436709 0003 0000 1814 E: 1332952535.436710 0003 0001 4264 E: 1332952535.436711 0003 0035 1814 E: 1332952535.436712 0003 0036 4264 E: 1332952535.436713 0003 0034 0 E: 1332952535.436714 0003 0030 468 E: 1332952535.436715 0003 0031 306 E: 1332952535.436717 0000 0002 0 E: 1332952535.436871 0000 0000 0 E: 1332952535.446648 0003 0000 1805 E: 1332952535.446649 0003 0001 4319 E: 1332952535.446650 0003 0035 1805 E: 1332952535.446651 0003 0036 4319 E: 1332952535.446653 0003 0034 0 E: 1332952535.446654 0003 0030 468 E: 1332952535.446655 0003 0031 306 E: 1332952535.446656 0000 0002 0 E: 1332952535.446810 0000 0000 0 E: 1332952535.456724 0003 0000 1825 E: 1332952535.456725 0003 0001 4329 E: 1332952535.456726 0003 0035 1825 E: 1332952535.456727 0003 0036 4329 E: 1332952535.456728 0003 0034 0 E: 1332952535.456729 0003 0030 468 E: 1332952535.456730 0003 0031 306 E: 1332952535.456731 0000 0002 0 E: 1332952535.456886 0000 0000 0 E: 1332952535.468724 0003 0000 1814 E: 1332952535.468725 0003 0001 4350 E: 1332952535.468726 0003 0035 1814 E: 1332952535.468727 0003 0036 4350 E: 1332952535.468728 0003 0034 0 E: 1332952535.468729 0003 0030 312 E: 1332952535.468730 0003 0031 306 E: 1332952535.468732 0000 0002 0 E: 1332952535.468886 0000 0000 0 E: 1332952535.478659 0003 0000 1804 E: 1332952535.478660 0003 0001 4374 E: 1332952535.478662 0003 0035 1804 E: 1332952535.478663 0003 0036 4374 E: 1332952535.478664 0003 0034 0 E: 1332952535.478665 0003 0030 312 E: 1332952535.478666 0003 0031 306 E: 1332952535.478667 0000 0002 0 E: 1332952535.478821 0000 0000 0 E: 1332952535.490658 0003 0000 1811 E: 1332952535.490659 0003 0001 4429 E: 1332952535.490660 0003 0035 1811 E: 1332952535.490661 0003 0036 4429 E: 1332952535.490662 0003 0034 0 E: 1332952535.490663 0003 0030 468 E: 1332952535.490664 0003 0031 306 E: 1332952535.490666 0000 0002 0 E: 1332952535.490820 0000 0000 0 E: 1332952535.498660 0003 0000 1826 E: 1332952535.498661 0003 0001 4448 E: 1332952535.498662 0003 0035 1826 E: 1332952535.498663 0003 0036 4448 E: 1332952535.498665 0003 0034 0 E: 1332952535.498666 0003 0030 468 E: 1332952535.498667 0003 0031 306 E: 1332952535.498668 0000 0002 0 E: 1332952535.498822 0000 0000 0 E: 1332952535.508726 0003 0000 1809 E: 1332952535.508727 0003 0001 4489 E: 1332952535.508729 0003 0035 1809 E: 1332952535.508730 0003 0036 4489 E: 1332952535.508731 0003 0034 0 E: 1332952535.508732 0003 0030 468 E: 1332952535.508733 0003 0031 306 E: 1332952535.508734 0000 0002 0 E: 1332952535.508888 0000 0000 0 E: 1332952535.518654 0003 0000 1810 E: 1332952535.518655 0003 0001 4511 E: 1332952535.518657 0003 0035 1810 E: 1332952535.518658 0003 0036 4511 E: 1332952535.518659 0003 0034 0 E: 1332952535.518660 0003 0030 312 E: 1332952535.518661 0003 0031 306 E: 1332952535.518662 0000 0002 0 E: 1332952535.518816 0000 0000 0 E: 1332952535.528724 0003 0000 1809 E: 1332952535.528726 0003 0001 4523 E: 1332952535.528727 0003 0035 1809 E: 1332952535.528728 0003 0036 4523 E: 1332952535.528729 0003 0034 0 E: 1332952535.528730 0003 0030 312 E: 1332952535.528731 0003 0031 306 E: 1332952535.528732 0000 0002 0 E: 1332952535.528886 0000 0000 0 E: 1332952535.544723 0003 0000 1823 E: 1332952535.544725 0003 0001 4555 E: 1332952535.544726 0003 0035 1823 E: 1332952535.544727 0003 0036 4555 E: 1332952535.544728 0003 0034 0 E: 1332952535.544729 0003 0030 312 E: 1332952535.544730 0003 0031 306 E: 1332952535.544731 0000 0002 0 E: 1332952535.544886 0000 0000 0 E: 1332952535.554653 0003 0000 1829 E: 1332952535.554655 0003 0001 4591 E: 1332952535.554656 0003 0035 1829 E: 1332952535.554657 0003 0036 4591 E: 1332952535.554658 0003 0034 0 E: 1332952535.554659 0003 0030 468 E: 1332952535.554660 0003 0031 306 E: 1332952535.554661 0000 0002 0 E: 1332952535.554815 0000 0000 0 E: 1332952535.564724 0003 0000 1814 E: 1332952535.564726 0003 0001 4621 E: 1332952535.564727 0003 0035 1814 E: 1332952535.564728 0003 0036 4621 E: 1332952535.564729 0003 0034 0 E: 1332952535.564730 0003 0030 468 E: 1332952535.564731 0003 0031 306 E: 1332952535.564732 0000 0002 0 E: 1332952535.564886 0000 0000 0 E: 1332952535.574725 0003 0000 1818 E: 1332952535.574727 0003 0001 4631 E: 1332952535.574728 0003 0035 1818 E: 1332952535.574729 0003 0036 4631 E: 1332952535.574730 0003 0034 0 E: 1332952535.574731 0003 0030 468 E: 1332952535.574732 0003 0031 306 E: 1332952535.574733 0000 0002 0 E: 1332952535.574887 0000 0000 0 E: 1332952535.584723 0003 0000 1826 E: 1332952535.584725 0003 0001 4655 E: 1332952535.584726 0003 0035 1826 E: 1332952535.584727 0003 0036 4655 E: 1332952535.584728 0003 0034 0 E: 1332952535.584729 0003 0030 312 E: 1332952535.584730 0003 0031 306 E: 1332952535.584731 0000 0002 0 E: 1332952535.584885 0000 0000 0 E: 1332952535.594727 0003 0000 1815 E: 1332952535.594729 0003 0001 4681 E: 1332952535.594730 0003 0035 1815 E: 1332952535.594731 0003 0036 4681 E: 1332952535.594732 0003 0034 0 E: 1332952535.594733 0003 0030 312 E: 1332952535.594734 0003 0031 306 E: 1332952535.594735 0000 0002 0 E: 1332952535.594889 0000 0000 0 E: 1332952535.604725 0003 0000 1809 E: 1332952535.604726 0003 0001 4710 E: 1332952535.604727 0003 0035 1809 E: 1332952535.604728 0003 0036 4710 E: 1332952535.604729 0003 0034 0 E: 1332952535.604730 0003 0030 468 E: 1332952535.604731 0003 0031 306 E: 1332952535.604732 0000 0002 0 E: 1332952535.604887 0000 0000 0 E: 1332952535.614728 0003 0000 1829 E: 1332952535.614729 0003 0001 4753 E: 1332952535.614731 0003 0035 1829 E: 1332952535.614732 0003 0036 4753 E: 1332952535.614733 0003 0034 0 E: 1332952535.614734 0003 0030 468 E: 1332952535.614735 0003 0031 306 E: 1332952535.614736 0000 0002 0 E: 1332952535.614890 0000 0000 0 E: 1332952535.624726 0003 0000 1825 E: 1332952535.624727 0003 0001 4781 E: 1332952535.624728 0003 0035 1825 E: 1332952535.624729 0003 0036 4781 E: 1332952535.624730 0003 0034 0 E: 1332952535.624731 0003 0030 468 E: 1332952535.624732 0003 0031 306 E: 1332952535.624733 0000 0002 0 E: 1332952535.624888 0000 0000 0 E: 1332952535.634723 0003 0000 1850 E: 1332952535.634725 0003 0001 4820 E: 1332952535.634726 0003 0035 1850 E: 1332952535.634727 0003 0036 4820 E: 1332952535.634728 0003 0034 0 E: 1332952535.634729 0003 0030 312 E: 1332952535.634730 0003 0031 204 E: 1332952535.634731 0000 0002 0 E: 1332952535.634885 0000 0000 0 E: 1332952535.644727 0003 0000 1816 E: 1332952535.644728 0003 0001 4826 E: 1332952535.644729 0003 0035 1816 E: 1332952535.644730 0003 0036 4826 E: 1332952535.644731 0003 0034 0 E: 1332952535.644732 0003 0030 312 E: 1332952535.644733 0003 0031 306 E: 1332952535.644734 0000 0002 0 E: 1332952535.644889 0000 0000 0 E: 1332952535.654787 0003 0000 1850 E: 1332952535.654789 0003 0001 4833 E: 1332952535.654790 0003 0035 1850 E: 1332952535.654791 0003 0036 4833 E: 1332952535.654792 0003 0034 0 E: 1332952535.654793 0003 0030 312 E: 1332952535.654794 0003 0031 204 E: 1332952535.654795 0000 0002 0 E: 1332952535.654949 0000 0000 0 E: 1332952535.664725 0003 0000 1827 E: 1332952535.664727 0003 0001 4849 E: 1332952535.664728 0003 0035 1827 E: 1332952535.664729 0003 0036 4849 E: 1332952535.664730 0003 0034 0 E: 1332952535.664731 0003 0030 312 E: 1332952535.664732 0003 0031 306 E: 1332952535.664733 0000 0002 0 E: 1332952535.664887 0000 0000 0 E: 1332952535.674725 0003 0000 1862 E: 1332952535.674726 0003 0001 4889 E: 1332952535.674728 0003 0035 1862 E: 1332952535.674729 0003 0036 4889 E: 1332952535.674730 0003 0034 0 E: 1332952535.674731 0003 0030 468 E: 1332952535.674732 0003 0031 204 E: 1332952535.674733 0000 0002 0 E: 1332952535.674887 0000 0000 0 E: 1332952535.684723 0003 0000 1831 E: 1332952535.684725 0003 0001 4922 E: 1332952535.684726 0003 0035 1831 E: 1332952535.684727 0003 0036 4922 E: 1332952535.684728 0003 0034 0 E: 1332952535.684729 0003 0030 468 E: 1332952535.684730 0003 0031 306 E: 1332952535.684731 0000 0002 0 E: 1332952535.684885 0000 0000 0 E: 1332952535.694723 0003 0000 1828 E: 1332952535.694724 0003 0001 4937 E: 1332952535.694726 0003 0035 1828 E: 1332952535.694727 0003 0036 4937 E: 1332952535.694728 0003 0034 0 E: 1332952535.694729 0003 0030 468 E: 1332952535.694730 0003 0031 306 E: 1332952535.694731 0000 0002 0 E: 1332952535.694885 0000 0000 0 E: 1332952535.704725 0003 0000 1854 E: 1332952535.704726 0003 0001 4980 E: 1332952535.704727 0003 0035 1854 E: 1332952535.704728 0003 0036 4980 E: 1332952535.704729 0003 0034 0 E: 1332952535.704730 0003 0030 312 E: 1332952535.704731 0003 0031 204 E: 1332952535.704733 0000 0002 0 E: 1332952535.704887 0000 0000 0 E: 1332952535.714728 0003 0000 1850 E: 1332952535.714729 0003 0001 4985 E: 1332952535.714731 0003 0035 1850 E: 1332952535.714732 0003 0036 4985 E: 1332952535.714733 0003 0034 0 E: 1332952535.714734 0003 0030 312 E: 1332952535.714735 0003 0031 204 E: 1332952535.714736 0000 0002 0 E: 1332952535.714890 0000 0000 0 E: 1332952535.724723 0003 0000 1852 E: 1332952535.724725 0003 0001 4990 E: 1332952535.724726 0003 0035 1852 E: 1332952535.724727 0003 0036 4990 E: 1332952535.724728 0003 0034 0 E: 1332952535.724729 0003 0030 312 E: 1332952535.724730 0003 0031 204 E: 1332952535.724731 0000 0002 0 E: 1332952535.724886 0000 0000 0 E: 1332952535.734876 0001 014d 0 E: 1332952535.734877 0001 014a 0 E: 1332952535.734878 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/drag_2.record0000644000015600001650000004242312651717544026465 0ustar pbuserpbgroup00000000000000E: 1334596954.223117 0003 0035 2951 E: 1334596954.223119 0003 0036 4161 E: 1334596954.223122 0003 0034 1 E: 1334596954.223124 0003 0030 616 E: 1334596954.223126 0003 0031 540 E: 1334596954.223129 0000 0002 0 E: 1334596954.223131 0003 0035 3187 E: 1334596954.223134 0003 0036 3194 E: 1334596954.223136 0003 0034 0 E: 1334596954.223139 0003 0030 720 E: 1334596954.223141 0003 0031 462 E: 1334596954.223143 0000 0002 0 E: 1334596954.223147 0003 0000 2904 E: 1334596954.223150 0003 0001 4188 E: 1334596954.223151 0001 014a 1 E: 1334596954.223152 0000 0000 0 E: 1334596954.237124 0003 0035 3045 E: 1334596954.237127 0003 0036 4196 E: 1334596954.237129 0003 0034 1 E: 1334596954.237132 0003 0030 616 E: 1334596954.237134 0003 0031 540 E: 1334596954.237137 0000 0002 0 E: 1334596954.237139 0003 0035 3224 E: 1334596954.237141 0003 0036 3195 E: 1334596954.237144 0003 0034 1 E: 1334596954.237146 0003 0030 616 E: 1334596954.237149 0003 0031 540 E: 1334596954.237151 0000 0002 0 E: 1334596954.237155 0003 0000 2974 E: 1334596954.237159 0000 0000 0 E: 1334596954.249121 0003 0035 3098 E: 1334596954.249123 0003 0036 4167 E: 1334596954.249126 0003 0034 0 E: 1334596954.249128 0003 0030 540 E: 1334596954.249130 0003 0031 308 E: 1334596954.249133 0000 0002 0 E: 1334596954.249135 0003 0035 3375 E: 1334596954.249138 0003 0036 3250 E: 1334596954.249140 0003 0034 0 E: 1334596954.249142 0003 0030 720 E: 1334596954.249145 0003 0031 462 E: 1334596954.249147 0000 0002 0 E: 1334596954.249151 0003 0000 3036 E: 1334596954.249155 0000 0000 0 E: 1334596954.263123 0003 0035 3185 E: 1334596954.263126 0003 0036 4154 E: 1334596954.263128 0003 0034 0 E: 1334596954.263130 0003 0030 540 E: 1334596954.263133 0003 0031 462 E: 1334596954.263135 0000 0002 0 E: 1334596954.263138 0003 0035 3402 E: 1334596954.263140 0003 0036 3297 E: 1334596954.263142 0003 0034 0 E: 1334596954.263145 0003 0030 720 E: 1334596954.263147 0003 0031 308 E: 1334596954.263150 0000 0002 0 E: 1334596954.263153 0003 0000 3110 E: 1334596954.263158 0000 0000 0 E: 1334596954.277121 0003 0035 3282 E: 1334596954.277124 0003 0036 4132 E: 1334596954.277126 0003 0034 0 E: 1334596954.277128 0003 0030 540 E: 1334596954.277131 0003 0031 462 E: 1334596954.277133 0000 0002 0 E: 1334596954.277136 0003 0035 3465 E: 1334596954.277138 0003 0036 3235 E: 1334596954.277140 0003 0034 0 E: 1334596954.277143 0003 0030 720 E: 1334596954.277145 0003 0031 154 E: 1334596954.277147 0000 0002 0 E: 1334596954.277151 0003 0000 3282 E: 1334596954.277154 0003 0001 4174 E: 1334596954.277157 0000 0000 0 E: 1334596954.289105 0003 0035 3393 E: 1334596954.289108 0003 0036 4193 E: 1334596954.289110 0003 0034 0 E: 1334596954.289113 0003 0030 540 E: 1334596954.289115 0003 0031 308 E: 1334596954.289117 0000 0002 0 E: 1334596954.289120 0003 0035 3583 E: 1334596954.289122 0003 0036 3206 E: 1334596954.289125 0003 0034 0 E: 1334596954.289127 0003 0030 720 E: 1334596954.289130 0003 0031 462 E: 1334596954.289132 0000 0002 0 E: 1334596954.289136 0003 0000 3337 E: 1334596954.289140 0000 0000 0 E: 1334596954.311152 0003 0035 3465 E: 1334596954.311155 0003 0036 4200 E: 1334596954.311158 0003 0034 0 E: 1334596954.311160 0003 0030 540 E: 1334596954.311162 0003 0031 154 E: 1334596954.311165 0000 0002 0 E: 1334596954.311167 0003 0035 3810 E: 1334596954.311170 0003 0036 3265 E: 1334596954.311172 0003 0034 0 E: 1334596954.311175 0003 0030 720 E: 1334596954.311177 0003 0031 462 E: 1334596954.311179 0000 0002 0 E: 1334596954.311183 0003 0000 3401 E: 1334596954.311188 0000 0000 0 E: 1334596954.325136 0003 0035 3828 E: 1334596954.325139 0003 0036 4132 E: 1334596954.325142 0003 0034 1 E: 1334596954.325144 0003 0030 770 E: 1334596954.325146 0003 0031 540 E: 1334596954.325149 0000 0002 0 E: 1334596954.325151 0003 0035 3910 E: 1334596954.325154 0003 0036 3282 E: 1334596954.325156 0003 0034 1 E: 1334596954.325158 0003 0030 770 E: 1334596954.325161 0003 0031 720 E: 1334596954.325163 0000 0002 0 E: 1334596954.325167 0003 0000 3828 E: 1334596954.325170 0003 0001 4163 E: 1334596954.325173 0000 0000 0 E: 1334596954.337127 0003 0035 3875 E: 1334596954.337130 0003 0036 4235 E: 1334596954.337133 0003 0034 0 E: 1334596954.337135 0003 0030 540 E: 1334596954.337137 0003 0031 462 E: 1334596954.337140 0000 0002 0 E: 1334596954.337142 0003 0035 4139 E: 1334596954.337145 0003 0036 3311 E: 1334596954.337147 0003 0034 0 E: 1334596954.337149 0003 0030 540 E: 1334596954.337152 0003 0031 462 E: 1334596954.337154 0000 0002 0 E: 1334596954.337158 0003 0000 3839 E: 1334596954.337160 0003 0001 4181 E: 1334596954.337163 0000 0000 0 E: 1334596954.351124 0003 0035 4045 E: 1334596954.351126 0003 0036 4245 E: 1334596954.351129 0003 0034 1 E: 1334596954.351131 0003 0030 616 E: 1334596954.351133 0003 0031 540 E: 1334596954.351136 0000 0002 0 E: 1334596954.351138 0003 0035 4257 E: 1334596954.351141 0003 0036 3347 E: 1334596954.351143 0003 0034 0 E: 1334596954.351146 0003 0030 720 E: 1334596954.351148 0003 0031 462 E: 1334596954.351150 0000 0002 0 E: 1334596954.351154 0003 0000 4045 E: 1334596954.351156 0003 0001 4197 E: 1334596954.351160 0000 0000 0 E: 1334596954.363121 0003 0035 4177 E: 1334596954.363124 0003 0036 4254 E: 1334596954.363126 0003 0034 0 E: 1334596954.363129 0003 0030 540 E: 1334596954.363131 0003 0031 308 E: 1334596954.363134 0000 0002 0 E: 1334596954.363136 0003 0035 4413 E: 1334596954.363138 0003 0036 3274 E: 1334596954.363141 0003 0034 0 E: 1334596954.363143 0003 0030 720 E: 1334596954.363146 0003 0031 462 E: 1334596954.363148 0000 0002 0 E: 1334596954.363152 0003 0000 4111 E: 1334596954.363155 0003 0001 4211 E: 1334596954.363158 0000 0000 0 E: 1334596954.374349 0003 0035 4328 E: 1334596954.374352 0003 0036 4266 E: 1334596954.374354 0003 0034 0 E: 1334596954.374357 0003 0030 540 E: 1334596954.374359 0003 0031 462 E: 1334596954.374362 0000 0002 0 E: 1334596954.374364 0003 0035 4646 E: 1334596954.374367 0003 0036 3330 E: 1334596954.374369 0003 0034 0 E: 1334596954.374371 0003 0030 540 E: 1334596954.374374 0003 0031 308 E: 1334596954.374376 0000 0002 0 E: 1334596954.374380 0003 0000 4328 E: 1334596954.374383 0003 0001 4224 E: 1334596954.374386 0000 0000 0 E: 1334596954.387113 0003 0035 4528 E: 1334596954.387115 0003 0036 4292 E: 1334596954.387118 0003 0034 0 E: 1334596954.387120 0003 0030 540 E: 1334596954.387122 0003 0031 462 E: 1334596954.387125 0000 0002 0 E: 1334596954.387127 0003 0035 4804 E: 1334596954.387130 0003 0036 3333 E: 1334596954.387132 0003 0034 0 E: 1334596954.387134 0003 0030 540 E: 1334596954.387137 0003 0031 462 E: 1334596954.387139 0000 0002 0 E: 1334596954.387143 0003 0000 4528 E: 1334596954.387145 0003 0001 4241 E: 1334596954.387149 0000 0000 0 E: 1334596954.399103 0003 0035 4701 E: 1334596954.399106 0003 0036 4268 E: 1334596954.399109 0003 0034 0 E: 1334596954.399111 0003 0030 540 E: 1334596954.399113 0003 0031 462 E: 1334596954.399116 0000 0002 0 E: 1334596954.399118 0003 0035 4915 E: 1334596954.399121 0003 0036 3347 E: 1334596954.399123 0003 0034 0 E: 1334596954.399126 0003 0030 540 E: 1334596954.399128 0003 0031 308 E: 1334596954.399130 0000 0002 0 E: 1334596954.399134 0003 0000 4701 E: 1334596954.399138 0000 0000 0 E: 1334596954.419131 0003 0035 4859 E: 1334596954.419134 0003 0036 4276 E: 1334596954.419136 0003 0034 0 E: 1334596954.419139 0003 0030 540 E: 1334596954.419141 0003 0031 462 E: 1334596954.419144 0000 0002 0 E: 1334596954.419146 0003 0035 5167 E: 1334596954.419149 0003 0036 3311 E: 1334596954.419151 0003 0034 0 E: 1334596954.419153 0003 0030 540 E: 1334596954.419156 0003 0031 462 E: 1334596954.419158 0000 0002 0 E: 1334596954.419162 0003 0000 4859 E: 1334596954.419166 0000 0000 0 E: 1334596954.433145 0003 0035 5228 E: 1334596954.433148 0003 0036 4255 E: 1334596954.433151 0003 0034 0 E: 1334596954.433153 0003 0030 540 E: 1334596954.433155 0003 0031 462 E: 1334596954.433158 0000 0002 0 E: 1334596954.433160 0003 0035 5439 E: 1334596954.433163 0003 0036 3388 E: 1334596954.433165 0003 0034 0 E: 1334596954.433167 0003 0030 540 E: 1334596954.433170 0003 0031 462 E: 1334596954.433172 0000 0002 0 E: 1334596954.433176 0003 0000 5228 E: 1334596954.433181 0000 0000 0 E: 1334596954.447141 0003 0035 5343 E: 1334596954.447144 0003 0036 4315 E: 1334596954.447148 0003 0034 0 E: 1334596954.447151 0003 0030 720 E: 1334596954.447153 0003 0031 462 E: 1334596954.447155 0000 0002 0 E: 1334596954.447158 0003 0035 5665 E: 1334596954.447160 0003 0036 3331 E: 1334596954.447163 0003 0034 0 E: 1334596954.447165 0003 0030 540 E: 1334596954.447167 0003 0031 462 E: 1334596954.447170 0000 0002 0 E: 1334596954.447174 0003 0000 5285 E: 1334596954.447176 0003 0001 4259 E: 1334596954.447180 0000 0000 0 E: 1334596954.461133 0003 0035 5552 E: 1334596954.461135 0003 0036 4317 E: 1334596954.461138 0003 0034 0 E: 1334596954.461140 0003 0030 720 E: 1334596954.461142 0003 0031 462 E: 1334596954.461145 0000 0002 0 E: 1334596954.461147 0003 0035 5869 E: 1334596954.461150 0003 0036 3395 E: 1334596954.461152 0003 0034 0 E: 1334596954.461154 0003 0030 720 E: 1334596954.461157 0003 0031 308 E: 1334596954.461159 0000 0002 0 E: 1334596954.461163 0003 0000 5552 E: 1334596954.461166 0003 0001 4273 E: 1334596954.461169 0000 0000 0 E: 1334596954.475133 0003 0035 5743 E: 1334596954.475136 0003 0036 4303 E: 1334596954.475138 0003 0034 0 E: 1334596954.475140 0003 0030 720 E: 1334596954.475143 0003 0031 462 E: 1334596954.475145 0000 0002 0 E: 1334596954.475148 0003 0035 5978 E: 1334596954.475150 0003 0036 3373 E: 1334596954.475152 0003 0034 0 E: 1334596954.475155 0003 0030 720 E: 1334596954.475157 0003 0031 308 E: 1334596954.475160 0000 0002 0 E: 1334596954.475163 0003 0000 5743 E: 1334596954.475168 0000 0000 0 E: 1334596954.489110 0003 0035 5882 E: 1334596954.489112 0003 0036 4340 E: 1334596954.489114 0003 0034 0 E: 1334596954.489117 0003 0030 720 E: 1334596954.489119 0003 0031 308 E: 1334596954.489122 0000 0002 0 E: 1334596954.489124 0003 0035 6264 E: 1334596954.489127 0003 0036 3460 E: 1334596954.489129 0003 0034 0 E: 1334596954.489131 0003 0030 720 E: 1334596954.489134 0003 0031 616 E: 1334596954.489136 0000 0002 0 E: 1334596954.489140 0003 0000 5812 E: 1334596954.489142 0003 0001 4289 E: 1334596954.489145 0000 0000 0 E: 1334596954.503135 0003 0035 5991 E: 1334596954.503138 0003 0036 4330 E: 1334596954.503140 0003 0034 1 E: 1334596954.503142 0003 0030 462 E: 1334596954.503145 0003 0031 360 E: 1334596954.503147 0000 0002 0 E: 1334596954.503150 0003 0035 6372 E: 1334596954.503152 0003 0036 3355 E: 1334596954.503155 0003 0034 0 E: 1334596954.503157 0003 0030 720 E: 1334596954.503159 0003 0031 462 E: 1334596954.503162 0000 0002 0 E: 1334596954.503165 0003 0000 5991 E: 1334596954.503168 0003 0001 4299 E: 1334596954.503171 0000 0000 0 E: 1334596954.525223 0003 0035 6208 E: 1334596954.525226 0003 0036 4290 E: 1334596954.525229 0003 0034 0 E: 1334596954.525231 0003 0030 720 E: 1334596954.525234 0003 0031 462 E: 1334596954.525236 0000 0002 0 E: 1334596954.525239 0003 0035 6518 E: 1334596954.525241 0003 0036 3422 E: 1334596954.525243 0003 0034 0 E: 1334596954.525246 0003 0030 720 E: 1334596954.525248 0003 0031 462 E: 1334596954.525250 0000 0002 0 E: 1334596954.525255 0003 0000 6208 E: 1334596954.525260 0000 0000 0 E: 1334596954.539143 0003 0035 6324 E: 1334596954.539146 0003 0036 4303 E: 1334596954.539148 0003 0034 0 E: 1334596954.539151 0003 0030 720 E: 1334596954.539153 0003 0031 308 E: 1334596954.539156 0000 0002 0 E: 1334596954.539158 0003 0035 6675 E: 1334596954.539160 0003 0036 3409 E: 1334596954.539163 0003 0034 0 E: 1334596954.539165 0003 0030 720 E: 1334596954.539168 0003 0031 462 E: 1334596954.539170 0000 0002 0 E: 1334596954.539174 0003 0000 6266 E: 1334596954.539179 0000 0000 0 E: 1334596954.553146 0003 0035 6397 E: 1334596954.553149 0003 0036 4361 E: 1334596954.553151 0003 0034 0 E: 1334596954.553153 0003 0030 720 E: 1334596954.553156 0003 0031 616 E: 1334596954.553158 0000 0002 0 E: 1334596954.553161 0003 0035 6704 E: 1334596954.553163 0003 0036 3339 E: 1334596954.553165 0003 0034 0 E: 1334596954.553168 0003 0030 720 E: 1334596954.553170 0003 0031 462 E: 1334596954.553173 0000 0002 0 E: 1334596954.553177 0003 0000 6331 E: 1334596954.553179 0003 0001 4314 E: 1334596954.553182 0000 0000 0 E: 1334596954.569136 0003 0035 6577 E: 1334596954.569139 0003 0036 4162 E: 1334596954.569141 0003 0034 0 E: 1334596954.569144 0003 0030 720 E: 1334596954.569146 0003 0031 616 E: 1334596954.569149 0000 0002 0 E: 1334596954.569151 0003 0035 6762 E: 1334596954.569153 0003 0036 3371 E: 1334596954.569156 0003 0034 0 E: 1334596954.569158 0003 0030 720 E: 1334596954.569161 0003 0031 616 E: 1334596954.569163 0000 0002 0 E: 1334596954.569167 0003 0000 6577 E: 1334596954.569169 0003 0001 4238 E: 1334596954.569173 0000 0000 0 E: 1334596954.581134 0003 0035 6454 E: 1334596954.581136 0003 0036 4354 E: 1334596954.581139 0003 0034 0 E: 1334596954.581141 0003 0030 540 E: 1334596954.581144 0003 0031 462 E: 1334596954.581146 0000 0002 0 E: 1334596954.581149 0003 0035 6770 E: 1334596954.581151 0003 0036 3407 E: 1334596954.581153 0003 0034 0 E: 1334596954.581156 0003 0030 720 E: 1334596954.581158 0003 0031 616 E: 1334596954.581160 0000 0002 0 E: 1334596954.581164 0003 0000 6515 E: 1334596954.581167 0003 0001 4296 E: 1334596954.581170 0000 0000 0 E: 1334596954.597124 0003 0035 6473 E: 1334596954.597127 0003 0036 4379 E: 1334596954.597129 0003 0034 0 E: 1334596954.597131 0003 0030 720 E: 1334596954.597134 0003 0031 616 E: 1334596954.597136 0000 0002 0 E: 1334596954.597139 0003 0035 6762 E: 1334596954.597141 0003 0036 3379 E: 1334596954.597143 0003 0034 0 E: 1334596954.597146 0003 0030 720 E: 1334596954.597148 0003 0031 308 E: 1334596954.597151 0000 0002 0 E: 1334596954.597154 0003 0000 6504 E: 1334596954.597157 0003 0001 4337 E: 1334596954.597160 0000 0000 0 E: 1334596954.611122 0003 0035 6478 E: 1334596954.611125 0003 0036 4354 E: 1334596954.611127 0003 0034 0 E: 1334596954.611130 0003 0030 720 E: 1334596954.611132 0003 0031 616 E: 1334596954.611134 0000 0002 0 E: 1334596954.611137 0003 0035 6762 E: 1334596954.611139 0003 0036 3395 E: 1334596954.611142 0003 0034 0 E: 1334596954.611144 0003 0030 720 E: 1334596954.611146 0003 0031 616 E: 1334596954.611149 0000 0002 0 E: 1334596954.611156 0000 0000 0 E: 1334596954.633157 0003 0035 6459 E: 1334596954.633160 0003 0036 4310 E: 1334596954.633162 0003 0034 1 E: 1334596954.633165 0003 0030 770 E: 1334596954.633167 0003 0031 540 E: 1334596954.633170 0000 0002 0 E: 1334596954.633172 0003 0035 6748 E: 1334596954.633174 0003 0036 3368 E: 1334596954.633177 0003 0034 0 E: 1334596954.633179 0003 0030 720 E: 1334596954.633182 0003 0031 616 E: 1334596954.633184 0000 0002 0 E: 1334596954.633188 0003 0000 6492 E: 1334596954.633193 0000 0000 0 E: 1334596954.647151 0003 0035 6428 E: 1334596954.647154 0003 0036 4310 E: 1334596954.647156 0003 0034 0 E: 1334596954.647158 0003 0030 540 E: 1334596954.647161 0003 0031 462 E: 1334596954.647163 0000 0002 0 E: 1334596954.647166 0003 0035 6743 E: 1334596954.647168 0003 0036 3356 E: 1334596954.647170 0003 0034 0 E: 1334596954.647173 0003 0030 720 E: 1334596954.647175 0003 0031 462 E: 1334596954.647177 0000 0002 0 E: 1334596954.647181 0003 0000 6476 E: 1334596954.647186 0000 0000 0 E: 1334596954.661141 0003 0035 6436 E: 1334596954.661144 0003 0036 4327 E: 1334596954.661146 0003 0034 1 E: 1334596954.661149 0003 0030 616 E: 1334596954.661151 0003 0031 540 E: 1334596954.661153 0000 0002 0 E: 1334596954.661156 0003 0035 6735 E: 1334596954.661158 0003 0036 3400 E: 1334596954.661161 0003 0034 0 E: 1334596954.661163 0003 0030 720 E: 1334596954.661166 0003 0031 462 E: 1334596954.661168 0000 0002 0 E: 1334596954.661172 0003 0000 6466 E: 1334596954.661176 0000 0000 0 E: 1334596954.675133 0003 0035 6440 E: 1334596954.675136 0003 0036 4289 E: 1334596954.675138 0003 0034 0 E: 1334596954.675141 0003 0030 540 E: 1334596954.675143 0003 0031 462 E: 1334596954.675146 0000 0002 0 E: 1334596954.675148 0003 0035 6714 E: 1334596954.675150 0003 0036 3433 E: 1334596954.675153 0003 0034 0 E: 1334596954.675155 0003 0030 720 E: 1334596954.675158 0003 0031 616 E: 1334596954.675160 0000 0002 0 E: 1334596954.675165 0003 0001 4325 E: 1334596954.675168 0000 0000 0 E: 1334596954.689123 0003 0035 6402 E: 1334596954.689126 0003 0036 4302 E: 1334596954.689129 0003 0034 0 E: 1334596954.689131 0003 0030 540 E: 1334596954.689133 0003 0031 462 E: 1334596954.689136 0000 0002 0 E: 1334596954.689138 0003 0035 6733 E: 1334596954.689141 0003 0036 3331 E: 1334596954.689143 0003 0034 0 E: 1334596954.689145 0003 0030 720 E: 1334596954.689148 0003 0031 462 E: 1334596954.689150 0000 0002 0 E: 1334596954.689154 0003 0000 6450 E: 1334596954.689158 0000 0000 0 E: 1334596954.703125 0003 0035 6386 E: 1334596954.703128 0003 0036 4362 E: 1334596954.703130 0003 0034 1 E: 1334596954.703133 0003 0030 616 E: 1334596954.703135 0003 0031 540 E: 1334596954.703137 0000 0002 0 E: 1334596954.703140 0003 0035 6735 E: 1334596954.703142 0003 0036 3340 E: 1334596954.703145 0003 0034 0 E: 1334596954.703147 0003 0030 720 E: 1334596954.703150 0003 0031 462 E: 1334596954.703152 0000 0002 0 E: 1334596954.703156 0003 0000 6434 E: 1334596954.703160 0000 0000 0 E: 1334596954.717119 0003 0035 6734 E: 1334596954.717122 0003 0036 3366 E: 1334596954.717124 0003 0034 0 E: 1334596954.717127 0003 0030 540 E: 1334596954.717129 0003 0031 462 E: 1334596954.717131 0000 0002 0 E: 1334596954.717135 0003 0000 6734 E: 1334596954.717137 0003 0001 3366 E: 1334596954.717141 0000 0000 0 E: 1334596954.735127 0003 0035 6708 E: 1334596954.735129 0003 0036 3330 E: 1334596954.735132 0003 0034 1 E: 1334596954.735134 0003 0030 308 E: 1334596954.735137 0003 0031 180 E: 1334596954.735139 0000 0002 0 E: 1334596954.735146 0000 0000 0 E: 1334596954.749127 0001 014a 0 E: 1334596954.749130 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/touchscreen_a/drag_with_3s_pause.record0000644000015600001650000022414512651717544031104 0ustar pbuserpbgroup00000000000000E: 1334596952.475336 0003 0035 2849 E: 1334596952.475339 0003 0036 4167 E: 1334596952.475341 0003 0034 0 E: 1334596952.475344 0003 0030 360 E: 1334596952.475346 0003 0031 154 E: 1334596952.475349 0000 0002 0 E: 1334596952.475351 0003 0035 3081 E: 1334596952.475353 0003 0036 3196 E: 1334596952.475356 0003 0034 0 E: 1334596952.475358 0003 0030 540 E: 1334596952.475360 0003 0031 308 E: 1334596952.475363 0000 0002 0 E: 1334596952.475365 0001 014a 1 E: 1334596952.475368 0003 0000 2849 E: 1334596952.475370 0003 0001 4167 E: 1334596952.475374 0000 0000 0 E: 1334596952.485147 0003 0035 2851 E: 1334596952.485150 0003 0036 4149 E: 1334596952.485153 0003 0034 1 E: 1334596952.485155 0003 0030 462 E: 1334596952.485157 0003 0031 360 E: 1334596952.485160 0000 0002 0 E: 1334596952.485162 0003 0035 3062 E: 1334596952.485165 0003 0036 3143 E: 1334596952.485167 0003 0034 0 E: 1334596952.485169 0003 0030 540 E: 1334596952.485172 0003 0031 462 E: 1334596952.485174 0000 0002 0 E: 1334596952.485182 0000 0000 0 E: 1334596952.497130 0003 0035 2838 E: 1334596952.497133 0003 0036 4147 E: 1334596952.497135 0003 0034 1 E: 1334596952.497138 0003 0030 462 E: 1334596952.497140 0003 0031 360 E: 1334596952.497143 0000 0002 0 E: 1334596952.497145 0003 0035 3101 E: 1334596952.497147 0003 0036 3137 E: 1334596952.497150 0003 0034 0 E: 1334596952.497152 0003 0030 540 E: 1334596952.497154 0003 0031 462 E: 1334596952.497157 0000 0002 0 E: 1334596952.497164 0000 0000 0 E: 1334596952.507125 0003 0035 2883 E: 1334596952.507128 0003 0036 4154 E: 1334596952.507130 0003 0034 1 E: 1334596952.507133 0003 0030 462 E: 1334596952.507135 0003 0031 360 E: 1334596952.507137 0000 0002 0 E: 1334596952.507140 0003 0035 3091 E: 1334596952.507142 0003 0036 3146 E: 1334596952.507145 0003 0034 0 E: 1334596952.507147 0003 0030 540 E: 1334596952.507149 0003 0031 462 E: 1334596952.507152 0000 0002 0 E: 1334596952.507158 0000 0000 0 E: 1334596952.519120 0003 0035 2851 E: 1334596952.519123 0003 0036 4151 E: 1334596952.519125 0003 0034 1 E: 1334596952.519128 0003 0030 462 E: 1334596952.519130 0003 0031 360 E: 1334596952.519133 0000 0002 0 E: 1334596952.519135 0003 0035 3065 E: 1334596952.519137 0003 0036 3160 E: 1334596952.519140 0003 0034 0 E: 1334596952.519142 0003 0030 540 E: 1334596952.519145 0003 0031 308 E: 1334596952.519147 0000 0002 0 E: 1334596952.519154 0000 0000 0 E: 1334596952.529125 0003 0035 2855 E: 1334596952.529127 0003 0036 4143 E: 1334596952.529130 0003 0034 1 E: 1334596952.529132 0003 0030 462 E: 1334596952.529134 0003 0031 360 E: 1334596952.529137 0000 0002 0 E: 1334596952.529139 0003 0035 3062 E: 1334596952.529142 0003 0036 3161 E: 1334596952.529144 0003 0034 0 E: 1334596952.529146 0003 0030 540 E: 1334596952.529149 0003 0031 308 E: 1334596952.529151 0000 0002 0 E: 1334596952.529158 0000 0000 0 E: 1334596952.543119 0003 0035 2850 E: 1334596952.543122 0003 0036 4163 E: 1334596952.543124 0003 0034 1 E: 1334596952.543126 0003 0030 462 E: 1334596952.543129 0003 0031 360 E: 1334596952.543131 0000 0002 0 E: 1334596952.543134 0003 0035 3087 E: 1334596952.543136 0003 0036 3160 E: 1334596952.543138 0003 0034 0 E: 1334596952.543141 0003 0030 540 E: 1334596952.543143 0003 0031 308 E: 1334596952.543146 0000 0002 0 E: 1334596952.543152 0000 0000 0 E: 1334596952.555122 0003 0035 2860 E: 1334596952.555125 0003 0036 4160 E: 1334596952.555127 0003 0034 0 E: 1334596952.555130 0003 0030 540 E: 1334596952.555132 0003 0031 462 E: 1334596952.555135 0000 0002 0 E: 1334596952.555137 0003 0035 3092 E: 1334596952.555139 0003 0036 3133 E: 1334596952.555142 0003 0034 0 E: 1334596952.555144 0003 0030 540 E: 1334596952.555147 0003 0031 462 E: 1334596952.555149 0000 0002 0 E: 1334596952.555155 0000 0000 0 E: 1334596952.575127 0003 0035 2883 E: 1334596952.575129 0003 0036 4246 E: 1334596952.575132 0003 0034 0 E: 1334596952.575134 0003 0030 540 E: 1334596952.575136 0003 0031 462 E: 1334596952.575139 0000 0002 0 E: 1334596952.575141 0003 0035 3089 E: 1334596952.575144 0003 0036 3143 E: 1334596952.575146 0003 0034 0 E: 1334596952.575148 0003 0030 540 E: 1334596952.575151 0003 0031 462 E: 1334596952.575153 0000 0002 0 E: 1334596952.575158 0003 0001 4206 E: 1334596952.575161 0000 0000 0 E: 1334596952.587139 0003 0035 2840 E: 1334596952.587142 0003 0036 4175 E: 1334596952.587144 0003 0034 0 E: 1334596952.587146 0003 0030 540 E: 1334596952.587149 0003 0031 462 E: 1334596952.587151 0000 0002 0 E: 1334596952.587154 0003 0035 3052 E: 1334596952.587156 0003 0036 3135 E: 1334596952.587158 0003 0034 1 E: 1334596952.587161 0003 0030 616 E: 1334596952.587163 0003 0031 540 E: 1334596952.587166 0000 0002 0 E: 1334596952.587173 0000 0000 0 E: 1334596952.599133 0003 0035 2853 E: 1334596952.599135 0003 0036 4148 E: 1334596952.599138 0003 0034 1 E: 1334596952.599140 0003 0030 616 E: 1334596952.599143 0003 0031 540 E: 1334596952.599145 0000 0002 0 E: 1334596952.599147 0003 0035 3098 E: 1334596952.599150 0003 0036 3151 E: 1334596952.599152 0003 0034 0 E: 1334596952.599154 0003 0030 540 E: 1334596952.599157 0003 0031 462 E: 1334596952.599159 0000 0002 0 E: 1334596952.599164 0003 0001 4191 E: 1334596952.599168 0000 0000 0 E: 1334596952.611128 0003 0035 2830 E: 1334596952.611130 0003 0036 4179 E: 1334596952.611133 0003 0034 0 E: 1334596952.611135 0003 0030 540 E: 1334596952.611138 0003 0031 462 E: 1334596952.611140 0000 0002 0 E: 1334596952.611143 0003 0035 3000 E: 1334596952.611145 0003 0036 3001 E: 1334596952.611147 0003 0034 1 E: 1334596952.611150 0003 0030 616 E: 1334596952.611152 0003 0031 540 E: 1334596952.611155 0000 0002 0 E: 1334596952.611161 0000 0000 0 E: 1334596952.623128 0003 0035 2873 E: 1334596952.623131 0003 0036 4168 E: 1334596952.623133 0003 0034 0 E: 1334596952.623136 0003 0030 540 E: 1334596952.623138 0003 0031 462 E: 1334596952.623141 0000 0002 0 E: 1334596952.623143 0003 0035 3069 E: 1334596952.623145 0003 0036 3143 E: 1334596952.623148 0003 0034 0 E: 1334596952.623150 0003 0030 540 E: 1334596952.623153 0003 0031 462 E: 1334596952.623155 0000 0002 0 E: 1334596952.623162 0000 0000 0 E: 1334596952.635121 0003 0035 2845 E: 1334596952.635124 0003 0036 4161 E: 1334596952.635126 0003 0034 0 E: 1334596952.635129 0003 0030 540 E: 1334596952.635131 0003 0031 462 E: 1334596952.635134 0000 0002 0 E: 1334596952.635136 0003 0035 3038 E: 1334596952.635138 0003 0036 3119 E: 1334596952.635141 0003 0034 0 E: 1334596952.635143 0003 0030 540 E: 1334596952.635146 0003 0031 462 E: 1334596952.635148 0000 0002 0 E: 1334596952.635155 0000 0000 0 E: 1334596952.647139 0003 0035 2842 E: 1334596952.647141 0003 0036 4159 E: 1334596952.647144 0003 0034 0 E: 1334596952.647146 0003 0030 540 E: 1334596952.647149 0003 0031 462 E: 1334596952.647151 0000 0002 0 E: 1334596952.647153 0003 0035 3069 E: 1334596952.647156 0003 0036 3171 E: 1334596952.647158 0003 0034 1 E: 1334596952.647160 0003 0030 616 E: 1334596952.647163 0003 0031 540 E: 1334596952.647165 0000 0002 0 E: 1334596952.647172 0000 0000 0 E: 1334596952.659136 0003 0035 2825 E: 1334596952.659139 0003 0036 4169 E: 1334596952.659141 0003 0034 0 E: 1334596952.659145 0003 0030 540 E: 1334596952.659147 0003 0031 308 E: 1334596952.659150 0000 0002 0 E: 1334596952.659152 0003 0035 3068 E: 1334596952.659154 0003 0036 3152 E: 1334596952.659157 0003 0034 0 E: 1334596952.659159 0003 0030 540 E: 1334596952.659162 0003 0031 462 E: 1334596952.659164 0000 0002 0 E: 1334596952.659171 0000 0000 0 E: 1334596952.681138 0003 0035 2857 E: 1334596952.681141 0003 0036 4180 E: 1334596952.681143 0003 0034 0 E: 1334596952.681146 0003 0030 540 E: 1334596952.681148 0003 0031 462 E: 1334596952.681151 0000 0002 0 E: 1334596952.681153 0003 0035 3045 E: 1334596952.681155 0003 0036 3204 E: 1334596952.681158 0003 0034 0 E: 1334596952.681160 0003 0030 540 E: 1334596952.681162 0003 0031 462 E: 1334596952.681165 0000 0002 0 E: 1334596952.681172 0000 0000 0 E: 1334596952.693136 0003 0035 2860 E: 1334596952.693139 0003 0036 4196 E: 1334596952.693141 0003 0034 0 E: 1334596952.693143 0003 0030 540 E: 1334596952.693146 0003 0031 462 E: 1334596952.693148 0000 0002 0 E: 1334596952.693151 0003 0035 3060 E: 1334596952.693153 0003 0036 3144 E: 1334596952.693155 0003 0034 0 E: 1334596952.693158 0003 0030 540 E: 1334596952.693160 0003 0031 462 E: 1334596952.693163 0000 0002 0 E: 1334596952.693170 0000 0000 0 E: 1334596952.705140 0003 0035 2844 E: 1334596952.705143 0003 0036 4137 E: 1334596952.705145 0003 0034 1 E: 1334596952.705148 0003 0030 462 E: 1334596952.705150 0003 0031 360 E: 1334596952.705153 0000 0002 0 E: 1334596952.705155 0003 0035 3063 E: 1334596952.705157 0003 0036 3136 E: 1334596952.705160 0003 0034 0 E: 1334596952.705162 0003 0030 540 E: 1334596952.705164 0003 0031 462 E: 1334596952.705167 0000 0002 0 E: 1334596952.705172 0003 0001 4177 E: 1334596952.705175 0000 0000 0 E: 1334596952.717135 0003 0035 2856 E: 1334596952.717138 0003 0036 4191 E: 1334596952.717140 0003 0034 0 E: 1334596952.717143 0003 0030 540 E: 1334596952.717145 0003 0031 462 E: 1334596952.717148 0000 0002 0 E: 1334596952.717150 0003 0035 3067 E: 1334596952.717152 0003 0036 3162 E: 1334596952.717155 0003 0034 0 E: 1334596952.717157 0003 0030 540 E: 1334596952.717160 0003 0031 462 E: 1334596952.717162 0000 0002 0 E: 1334596952.717169 0000 0000 0 E: 1334596952.729126 0003 0035 2841 E: 1334596952.729129 0003 0036 4172 E: 1334596952.729131 0003 0034 0 E: 1334596952.729134 0003 0030 540 E: 1334596952.729136 0003 0031 462 E: 1334596952.729138 0000 0002 0 E: 1334596952.729141 0003 0035 3059 E: 1334596952.729143 0003 0036 3127 E: 1334596952.729146 0003 0034 1 E: 1334596952.729148 0003 0030 616 E: 1334596952.729150 0003 0031 540 E: 1334596952.729153 0000 0002 0 E: 1334596952.729159 0000 0000 0 E: 1334596952.741119 0003 0035 2873 E: 1334596952.741122 0003 0036 4211 E: 1334596952.741124 0003 0034 0 E: 1334596952.741127 0003 0030 540 E: 1334596952.741129 0003 0031 462 E: 1334596952.741131 0000 0002 0 E: 1334596952.741134 0003 0035 3085 E: 1334596952.741136 0003 0036 3119 E: 1334596952.741138 0003 0034 0 E: 1334596952.741141 0003 0030 540 E: 1334596952.741143 0003 0031 462 E: 1334596952.741146 0000 0002 0 E: 1334596952.741152 0000 0000 0 E: 1334596952.753115 0003 0035 2867 E: 1334596952.753118 0003 0036 4188 E: 1334596952.753120 0003 0034 0 E: 1334596952.753122 0003 0030 540 E: 1334596952.753125 0003 0031 462 E: 1334596952.753127 0000 0002 0 E: 1334596952.753130 0003 0035 3031 E: 1334596952.753132 0003 0036 3114 E: 1334596952.753134 0003 0034 0 E: 1334596952.753137 0003 0030 540 E: 1334596952.753139 0003 0031 462 E: 1334596952.753142 0000 0002 0 E: 1334596952.753148 0000 0000 0 E: 1334596952.765113 0003 0035 2851 E: 1334596952.765116 0003 0036 4187 E: 1334596952.765118 0003 0034 0 E: 1334596952.765120 0003 0030 540 E: 1334596952.765123 0003 0031 462 E: 1334596952.765125 0000 0002 0 E: 1334596952.765128 0003 0035 3075 E: 1334596952.765130 0003 0036 3160 E: 1334596952.765132 0003 0034 0 E: 1334596952.765135 0003 0030 540 E: 1334596952.765137 0003 0031 308 E: 1334596952.765140 0000 0002 0 E: 1334596952.765146 0000 0000 0 E: 1334596952.785347 0003 0035 2871 E: 1334596952.785350 0003 0036 4199 E: 1334596952.785352 0003 0034 0 E: 1334596952.785355 0003 0030 540 E: 1334596952.785357 0003 0031 462 E: 1334596952.785360 0000 0002 0 E: 1334596952.785362 0003 0035 3067 E: 1334596952.785365 0003 0036 3177 E: 1334596952.785367 0003 0034 0 E: 1334596952.785369 0003 0030 540 E: 1334596952.785372 0003 0031 462 E: 1334596952.785374 0000 0002 0 E: 1334596952.785382 0000 0000 0 E: 1334596952.797140 0003 0035 2849 E: 1334596952.797142 0003 0036 4170 E: 1334596952.797145 0003 0034 0 E: 1334596952.797147 0003 0030 540 E: 1334596952.797150 0003 0031 462 E: 1334596952.797152 0000 0002 0 E: 1334596952.797154 0003 0035 3051 E: 1334596952.797157 0003 0036 3150 E: 1334596952.797159 0003 0034 1 E: 1334596952.797162 0003 0030 616 E: 1334596952.797164 0003 0031 540 E: 1334596952.797167 0000 0002 0 E: 1334596952.797173 0000 0000 0 E: 1334596952.809131 0003 0035 2853 E: 1334596952.809134 0003 0036 4175 E: 1334596952.809137 0003 0034 0 E: 1334596952.809139 0003 0030 540 E: 1334596952.809141 0003 0031 462 E: 1334596952.809144 0000 0002 0 E: 1334596952.809146 0003 0035 3071 E: 1334596952.809149 0003 0036 3155 E: 1334596952.809151 0003 0034 0 E: 1334596952.809153 0003 0030 540 E: 1334596952.809156 0003 0031 462 E: 1334596952.809158 0000 0002 0 E: 1334596952.809165 0000 0000 0 E: 1334596952.823131 0003 0035 2845 E: 1334596952.823134 0003 0036 4163 E: 1334596952.823136 0003 0034 0 E: 1334596952.823139 0003 0030 540 E: 1334596952.823141 0003 0031 462 E: 1334596952.823144 0000 0002 0 E: 1334596952.823146 0003 0035 3032 E: 1334596952.823148 0003 0036 3169 E: 1334596952.823151 0003 0034 1 E: 1334596952.823153 0003 0030 616 E: 1334596952.823156 0003 0031 540 E: 1334596952.823158 0000 0002 0 E: 1334596952.823164 0000 0000 0 E: 1334596952.835125 0003 0035 2834 E: 1334596952.835128 0003 0036 4149 E: 1334596952.835131 0003 0034 0 E: 1334596952.835133 0003 0030 540 E: 1334596952.835135 0003 0031 462 E: 1334596952.835138 0000 0002 0 E: 1334596952.835140 0003 0035 3034 E: 1334596952.835143 0003 0036 3194 E: 1334596952.835145 0003 0034 0 E: 1334596952.835147 0003 0030 540 E: 1334596952.835150 0003 0031 462 E: 1334596952.835152 0000 0002 0 E: 1334596952.835159 0000 0000 0 E: 1334596952.847124 0003 0035 2844 E: 1334596952.847127 0003 0036 4180 E: 1334596952.847129 0003 0034 0 E: 1334596952.847131 0003 0030 540 E: 1334596952.847134 0003 0031 462 E: 1334596952.847136 0000 0002 0 E: 1334596952.847139 0003 0035 3076 E: 1334596952.847141 0003 0036 3148 E: 1334596952.847143 0003 0034 0 E: 1334596952.847146 0003 0030 540 E: 1334596952.847148 0003 0031 462 E: 1334596952.847151 0000 0002 0 E: 1334596952.847157 0000 0000 0 E: 1334596952.859121 0003 0035 2871 E: 1334596952.859123 0003 0036 4177 E: 1334596952.859126 0003 0034 1 E: 1334596952.859128 0003 0030 616 E: 1334596952.859131 0003 0031 540 E: 1334596952.859133 0000 0002 0 E: 1334596952.859135 0003 0035 3075 E: 1334596952.859138 0003 0036 3154 E: 1334596952.859140 0003 0034 0 E: 1334596952.859143 0003 0030 540 E: 1334596952.859145 0003 0031 462 E: 1334596952.859148 0000 0002 0 E: 1334596952.859156 0000 0000 0 E: 1334596952.871120 0003 0035 2852 E: 1334596952.871123 0003 0036 4168 E: 1334596952.871125 0003 0034 0 E: 1334596952.871128 0003 0030 540 E: 1334596952.871130 0003 0031 462 E: 1334596952.871132 0000 0002 0 E: 1334596952.871135 0003 0035 3040 E: 1334596952.871137 0003 0036 3167 E: 1334596952.871139 0003 0034 0 E: 1334596952.871142 0003 0030 540 E: 1334596952.871144 0003 0031 462 E: 1334596952.871147 0000 0002 0 E: 1334596952.871153 0000 0000 0 E: 1334596952.891334 0003 0035 2879 E: 1334596952.891337 0003 0036 4247 E: 1334596952.891339 0003 0034 0 E: 1334596952.891342 0003 0030 540 E: 1334596952.891344 0003 0031 462 E: 1334596952.891347 0000 0002 0 E: 1334596952.891349 0003 0035 3061 E: 1334596952.891352 0003 0036 3153 E: 1334596952.891354 0003 0034 1 E: 1334596952.891356 0003 0030 616 E: 1334596952.891359 0003 0031 540 E: 1334596952.891361 0000 0002 0 E: 1334596952.891366 0003 0001 4194 E: 1334596952.891370 0000 0000 0 E: 1334596952.903145 0003 0035 2845 E: 1334596952.903148 0003 0036 4207 E: 1334596952.903151 0003 0034 0 E: 1334596952.903153 0003 0030 540 E: 1334596952.903156 0003 0031 462 E: 1334596952.903158 0000 0002 0 E: 1334596952.903161 0003 0035 3048 E: 1334596952.903163 0003 0036 3122 E: 1334596952.903165 0003 0034 1 E: 1334596952.903168 0003 0030 616 E: 1334596952.903170 0003 0031 540 E: 1334596952.903172 0000 0002 0 E: 1334596952.903180 0000 0000 0 E: 1334596952.915109 0003 0035 2843 E: 1334596952.915112 0003 0036 4180 E: 1334596952.915114 0003 0034 0 E: 1334596952.915116 0003 0030 540 E: 1334596952.915119 0003 0031 462 E: 1334596952.915121 0000 0002 0 E: 1334596952.915124 0003 0035 3073 E: 1334596952.915126 0003 0036 3133 E: 1334596952.915128 0003 0034 0 E: 1334596952.915131 0003 0030 540 E: 1334596952.915133 0003 0031 462 E: 1334596952.915136 0000 0002 0 E: 1334596952.915142 0000 0000 0 E: 1334596952.927106 0003 0035 2876 E: 1334596952.927109 0003 0036 4253 E: 1334596952.927111 0003 0034 0 E: 1334596952.927113 0003 0030 540 E: 1334596952.927116 0003 0031 462 E: 1334596952.927118 0000 0002 0 E: 1334596952.927121 0003 0035 3082 E: 1334596952.927123 0003 0036 3137 E: 1334596952.927125 0003 0034 0 E: 1334596952.927128 0003 0030 540 E: 1334596952.927130 0003 0031 462 E: 1334596952.927133 0000 0002 0 E: 1334596952.927137 0003 0001 4208 E: 1334596952.927141 0000 0000 0 E: 1334596952.939104 0003 0035 2848 E: 1334596952.939107 0003 0036 4174 E: 1334596952.939109 0003 0034 0 E: 1334596952.939112 0003 0030 540 E: 1334596952.939114 0003 0031 462 E: 1334596952.939116 0000 0002 0 E: 1334596952.939119 0003 0035 3057 E: 1334596952.939121 0003 0036 3136 E: 1334596952.939124 0003 0034 0 E: 1334596952.939126 0003 0030 540 E: 1334596952.939128 0003 0031 462 E: 1334596952.939131 0000 0002 0 E: 1334596952.939137 0000 0000 0 E: 1334596952.951104 0003 0035 2846 E: 1334596952.951107 0003 0036 4167 E: 1334596952.951109 0003 0034 0 E: 1334596952.951112 0003 0030 540 E: 1334596952.951114 0003 0031 462 E: 1334596952.951116 0000 0002 0 E: 1334596952.951119 0003 0035 3020 E: 1334596952.951121 0003 0036 3166 E: 1334596952.951124 0003 0034 0 E: 1334596952.951126 0003 0030 540 E: 1334596952.951128 0003 0031 462 E: 1334596952.951131 0000 0002 0 E: 1334596952.951136 0003 0001 4197 E: 1334596952.951139 0000 0000 0 E: 1334596952.963102 0003 0035 2849 E: 1334596952.963104 0003 0036 4139 E: 1334596952.963107 0003 0034 0 E: 1334596952.963109 0003 0030 540 E: 1334596952.963112 0003 0031 462 E: 1334596952.963114 0000 0002 0 E: 1334596952.963116 0003 0035 3014 E: 1334596952.963119 0003 0036 3138 E: 1334596952.963121 0003 0034 0 E: 1334596952.963124 0003 0030 540 E: 1334596952.963126 0003 0031 462 E: 1334596952.963129 0000 0002 0 E: 1334596952.963133 0003 0001 4182 E: 1334596952.963136 0000 0000 0 E: 1334596952.975103 0003 0035 2845 E: 1334596952.975106 0003 0036 4182 E: 1334596952.975108 0003 0034 0 E: 1334596952.975110 0003 0030 540 E: 1334596952.975113 0003 0031 462 E: 1334596952.975115 0000 0002 0 E: 1334596952.975118 0003 0035 3084 E: 1334596952.975120 0003 0036 3157 E: 1334596952.975122 0003 0034 0 E: 1334596952.975125 0003 0030 540 E: 1334596952.975127 0003 0031 462 E: 1334596952.975130 0000 0002 0 E: 1334596952.975136 0000 0000 0 E: 1334596952.997135 0003 0035 2828 E: 1334596952.997138 0003 0036 4177 E: 1334596952.997140 0003 0034 0 E: 1334596952.997142 0003 0030 540 E: 1334596952.997145 0003 0031 462 E: 1334596952.997147 0000 0002 0 E: 1334596952.997150 0003 0035 3056 E: 1334596952.997152 0003 0036 3177 E: 1334596952.997154 0003 0034 1 E: 1334596952.997157 0003 0030 616 E: 1334596952.997159 0003 0031 540 E: 1334596952.997162 0000 0002 0 E: 1334596952.997169 0000 0000 0 E: 1334596953.009113 0003 0035 2862 E: 1334596953.009116 0003 0036 4185 E: 1334596953.009118 0003 0034 0 E: 1334596953.009120 0003 0030 540 E: 1334596953.009123 0003 0031 462 E: 1334596953.009125 0000 0002 0 E: 1334596953.009128 0003 0035 3074 E: 1334596953.009130 0003 0036 3144 E: 1334596953.009132 0003 0034 1 E: 1334596953.009135 0003 0030 616 E: 1334596953.009137 0003 0031 540 E: 1334596953.009140 0000 0002 0 E: 1334596953.009146 0000 0000 0 E: 1334596953.021114 0003 0035 2849 E: 1334596953.021117 0003 0036 4220 E: 1334596953.021119 0003 0034 0 E: 1334596953.021121 0003 0030 540 E: 1334596953.021124 0003 0031 154 E: 1334596953.021126 0000 0002 0 E: 1334596953.021129 0003 0035 3157 E: 1334596953.021131 0003 0036 3130 E: 1334596953.021133 0003 0034 0 E: 1334596953.021136 0003 0030 540 E: 1334596953.021138 0003 0031 154 E: 1334596953.021141 0000 0002 0 E: 1334596953.021147 0000 0000 0 E: 1334596953.033113 0003 0035 2873 E: 1334596953.033116 0003 0036 4203 E: 1334596953.033118 0003 0034 0 E: 1334596953.033121 0003 0030 540 E: 1334596953.033123 0003 0031 462 E: 1334596953.033125 0000 0002 0 E: 1334596953.033128 0003 0035 3078 E: 1334596953.033130 0003 0036 3140 E: 1334596953.033133 0003 0034 1 E: 1334596953.033135 0003 0030 616 E: 1334596953.033137 0003 0031 540 E: 1334596953.033140 0000 0002 0 E: 1334596953.033146 0000 0000 0 E: 1334596953.045105 0003 0035 2845 E: 1334596953.045108 0003 0036 4173 E: 1334596953.045110 0003 0034 0 E: 1334596953.045113 0003 0030 540 E: 1334596953.045115 0003 0031 462 E: 1334596953.045117 0000 0002 0 E: 1334596953.045120 0003 0035 3083 E: 1334596953.045122 0003 0036 3131 E: 1334596953.045125 0003 0034 1 E: 1334596953.045127 0003 0030 616 E: 1334596953.045130 0003 0031 540 E: 1334596953.045132 0000 0002 0 E: 1334596953.045139 0000 0000 0 E: 1334596953.059106 0003 0035 2863 E: 1334596953.059108 0003 0036 4160 E: 1334596953.059111 0003 0034 0 E: 1334596953.059113 0003 0030 540 E: 1334596953.059115 0003 0031 462 E: 1334596953.059118 0000 0002 0 E: 1334596953.059120 0003 0035 3091 E: 1334596953.059123 0003 0036 3128 E: 1334596953.059125 0003 0034 0 E: 1334596953.059127 0003 0030 540 E: 1334596953.059130 0003 0031 462 E: 1334596953.059132 0000 0002 0 E: 1334596953.059139 0000 0000 0 E: 1334596953.071107 0003 0035 2861 E: 1334596953.071109 0003 0036 4148 E: 1334596953.071112 0003 0034 0 E: 1334596953.071114 0003 0030 540 E: 1334596953.071116 0003 0031 462 E: 1334596953.071119 0000 0002 0 E: 1334596953.071121 0003 0035 3046 E: 1334596953.071124 0003 0036 3135 E: 1334596953.071126 0003 0034 0 E: 1334596953.071128 0003 0030 720 E: 1334596953.071131 0003 0031 616 E: 1334596953.071133 0000 0002 0 E: 1334596953.071139 0000 0000 0 E: 1334596953.085106 0003 0035 2851 E: 1334596953.085109 0003 0036 4226 E: 1334596953.085111 0003 0034 0 E: 1334596953.085113 0003 0030 540 E: 1334596953.085116 0003 0031 462 E: 1334596953.085118 0000 0002 0 E: 1334596953.085121 0003 0035 3058 E: 1334596953.085123 0003 0036 3149 E: 1334596953.085125 0003 0034 0 E: 1334596953.085128 0003 0030 720 E: 1334596953.085130 0003 0031 616 E: 1334596953.085133 0000 0002 0 E: 1334596953.085138 0003 0001 4193 E: 1334596953.085141 0000 0000 0 E: 1334596953.105136 0003 0035 2846 E: 1334596953.105139 0003 0036 4176 E: 1334596953.105141 0003 0034 0 E: 1334596953.105144 0003 0030 540 E: 1334596953.105146 0003 0031 462 E: 1334596953.105149 0000 0002 0 E: 1334596953.105151 0003 0035 3071 E: 1334596953.105153 0003 0036 3188 E: 1334596953.105156 0003 0034 0 E: 1334596953.105158 0003 0030 720 E: 1334596953.105161 0003 0031 616 E: 1334596953.105163 0000 0002 0 E: 1334596953.105170 0000 0000 0 E: 1334596953.119116 0003 0035 2849 E: 1334596953.119119 0003 0036 4172 E: 1334596953.119121 0003 0034 0 E: 1334596953.119124 0003 0030 540 E: 1334596953.119126 0003 0031 462 E: 1334596953.119128 0000 0002 0 E: 1334596953.119131 0003 0035 3058 E: 1334596953.119133 0003 0036 3200 E: 1334596953.119136 0003 0034 1 E: 1334596953.119138 0003 0030 616 E: 1334596953.119141 0003 0031 540 E: 1334596953.119143 0000 0002 0 E: 1334596953.119149 0000 0000 0 E: 1334596953.131115 0003 0035 2855 E: 1334596953.131118 0003 0036 4173 E: 1334596953.131120 0003 0034 0 E: 1334596953.131123 0003 0030 540 E: 1334596953.131125 0003 0031 462 E: 1334596953.131127 0000 0002 0 E: 1334596953.131130 0003 0035 3048 E: 1334596953.131132 0003 0036 3167 E: 1334596953.131135 0003 0034 0 E: 1334596953.131137 0003 0030 540 E: 1334596953.131140 0003 0031 462 E: 1334596953.131142 0000 0002 0 E: 1334596953.131148 0000 0000 0 E: 1334596953.145119 0003 0035 2849 E: 1334596953.145122 0003 0036 4208 E: 1334596953.145124 0003 0034 0 E: 1334596953.145127 0003 0030 540 E: 1334596953.145129 0003 0031 462 E: 1334596953.145132 0000 0002 0 E: 1334596953.145134 0003 0035 3076 E: 1334596953.145137 0003 0036 3125 E: 1334596953.145139 0003 0034 0 E: 1334596953.145141 0003 0030 540 E: 1334596953.145144 0003 0031 462 E: 1334596953.145146 0000 0002 0 E: 1334596953.145153 0000 0000 0 E: 1334596953.159106 0003 0035 2878 E: 1334596953.159108 0003 0036 4186 E: 1334596953.159111 0003 0034 0 E: 1334596953.159113 0003 0030 540 E: 1334596953.159116 0003 0031 462 E: 1334596953.159118 0000 0002 0 E: 1334596953.159120 0003 0035 3089 E: 1334596953.159123 0003 0036 3168 E: 1334596953.159125 0003 0034 1 E: 1334596953.159128 0003 0030 616 E: 1334596953.159130 0003 0031 540 E: 1334596953.159132 0000 0002 0 E: 1334596953.159139 0000 0000 0 E: 1334596953.171105 0003 0035 2849 E: 1334596953.171107 0003 0036 4171 E: 1334596953.171109 0003 0034 0 E: 1334596953.171112 0003 0030 540 E: 1334596953.171114 0003 0031 462 E: 1334596953.171117 0000 0002 0 E: 1334596953.171119 0003 0035 3084 E: 1334596953.171121 0003 0036 3137 E: 1334596953.171124 0003 0034 1 E: 1334596953.171126 0003 0030 616 E: 1334596953.171129 0003 0031 540 E: 1334596953.171131 0000 0002 0 E: 1334596953.171137 0000 0000 0 E: 1334596953.185108 0003 0035 2833 E: 1334596953.185110 0003 0036 4193 E: 1334596953.185113 0003 0034 0 E: 1334596953.185115 0003 0030 540 E: 1334596953.185117 0003 0031 462 E: 1334596953.185120 0000 0002 0 E: 1334596953.185122 0003 0035 3031 E: 1334596953.185125 0003 0036 3128 E: 1334596953.185127 0003 0034 1 E: 1334596953.185130 0003 0030 616 E: 1334596953.185132 0003 0031 540 E: 1334596953.185134 0000 0002 0 E: 1334596953.185141 0000 0000 0 E: 1334596953.205105 0003 0035 2844 E: 1334596953.205108 0003 0036 4176 E: 1334596953.205110 0003 0034 0 E: 1334596953.205113 0003 0030 540 E: 1334596953.205115 0003 0031 462 E: 1334596953.205118 0000 0002 0 E: 1334596953.205120 0003 0035 3118 E: 1334596953.205122 0003 0036 3164 E: 1334596953.205125 0003 0034 1 E: 1334596953.205127 0003 0030 616 E: 1334596953.205130 0003 0031 540 E: 1334596953.205132 0000 0002 0 E: 1334596953.205139 0000 0000 0 E: 1334596953.219105 0003 0035 2868 E: 1334596953.219108 0003 0036 4223 E: 1334596953.219110 0003 0034 0 E: 1334596953.219113 0003 0030 540 E: 1334596953.219115 0003 0031 462 E: 1334596953.219117 0000 0002 0 E: 1334596953.219120 0003 0035 3042 E: 1334596953.219122 0003 0036 3187 E: 1334596953.219125 0003 0034 1 E: 1334596953.219127 0003 0030 616 E: 1334596953.219130 0003 0031 540 E: 1334596953.219132 0000 0002 0 E: 1334596953.219138 0000 0000 0 E: 1334596953.233105 0003 0035 2842 E: 1334596953.233107 0003 0036 4198 E: 1334596953.233109 0003 0034 0 E: 1334596953.233112 0003 0030 540 E: 1334596953.233114 0003 0031 462 E: 1334596953.233117 0000 0002 0 E: 1334596953.233119 0003 0035 3079 E: 1334596953.233121 0003 0036 3198 E: 1334596953.233124 0003 0034 0 E: 1334596953.233126 0003 0030 720 E: 1334596953.233129 0003 0031 616 E: 1334596953.233131 0000 0002 0 E: 1334596953.233138 0000 0000 0 E: 1334596953.245101 0003 0035 2847 E: 1334596953.245104 0003 0036 4190 E: 1334596953.245106 0003 0034 0 E: 1334596953.245108 0003 0030 540 E: 1334596953.245111 0003 0031 462 E: 1334596953.245113 0000 0002 0 E: 1334596953.245116 0003 0035 3056 E: 1334596953.245118 0003 0036 3129 E: 1334596953.245120 0003 0034 1 E: 1334596953.245123 0003 0030 616 E: 1334596953.245125 0003 0031 540 E: 1334596953.245128 0000 0002 0 E: 1334596953.245134 0000 0000 0 E: 1334596953.259103 0003 0035 2877 E: 1334596953.259106 0003 0036 4185 E: 1334596953.259108 0003 0034 0 E: 1334596953.259111 0003 0030 540 E: 1334596953.259113 0003 0031 462 E: 1334596953.259115 0000 0002 0 E: 1334596953.259118 0003 0035 3072 E: 1334596953.259120 0003 0036 3264 E: 1334596953.259123 0003 0034 0 E: 1334596953.259125 0003 0030 720 E: 1334596953.259127 0003 0031 616 E: 1334596953.259130 0000 0002 0 E: 1334596953.259136 0000 0000 0 E: 1334596953.275105 0003 0035 2950 E: 1334596953.275108 0003 0036 3954 E: 1334596953.275110 0003 0034 0 E: 1334596953.275113 0003 0030 720 E: 1334596953.275115 0003 0031 616 E: 1334596953.275117 0000 0002 0 E: 1334596953.275120 0003 0035 3054 E: 1334596953.275122 0003 0036 3327 E: 1334596953.275125 0003 0034 0 E: 1334596953.275127 0003 0030 720 E: 1334596953.275130 0003 0031 616 E: 1334596953.275132 0000 0002 0 E: 1334596953.275136 0003 0000 2899 E: 1334596953.275138 0003 0001 3954 E: 1334596953.275141 0000 0000 0 E: 1334596953.287119 0003 0035 2834 E: 1334596953.287131 0003 0036 4153 E: 1334596953.287133 0003 0034 0 E: 1334596953.287136 0003 0030 540 E: 1334596953.287138 0003 0031 462 E: 1334596953.287141 0000 0002 0 E: 1334596953.287143 0003 0035 3071 E: 1334596953.287146 0003 0036 3170 E: 1334596953.287148 0003 0034 0 E: 1334596953.287150 0003 0030 720 E: 1334596953.287153 0003 0031 616 E: 1334596953.287155 0000 0002 0 E: 1334596953.287159 0003 0000 2882 E: 1334596953.287162 0003 0001 4153 E: 1334596953.287165 0000 0000 0 E: 1334596953.309122 0003 0035 2854 E: 1334596953.309125 0003 0036 4229 E: 1334596953.309127 0003 0034 0 E: 1334596953.309129 0003 0030 540 E: 1334596953.309132 0003 0031 462 E: 1334596953.309134 0000 0002 0 E: 1334596953.309136 0003 0035 3062 E: 1334596953.309139 0003 0036 3174 E: 1334596953.309141 0003 0034 0 E: 1334596953.309144 0003 0030 720 E: 1334596953.309146 0003 0031 616 E: 1334596953.309148 0000 0002 0 E: 1334596953.309153 0003 0001 4172 E: 1334596953.309157 0000 0000 0 E: 1334596953.323106 0003 0035 2855 E: 1334596953.323109 0003 0036 4164 E: 1334596953.323111 0003 0034 0 E: 1334596953.323113 0003 0030 540 E: 1334596953.323116 0003 0031 462 E: 1334596953.323118 0000 0002 0 E: 1334596953.323121 0003 0035 3070 E: 1334596953.323123 0003 0036 3258 E: 1334596953.323126 0003 0034 0 E: 1334596953.323128 0003 0030 720 E: 1334596953.323130 0003 0031 616 E: 1334596953.323133 0000 0002 0 E: 1334596953.323140 0000 0000 0 E: 1334596953.335103 0003 0035 2879 E: 1334596953.335106 0003 0036 4231 E: 1334596953.335108 0003 0034 0 E: 1334596953.335111 0003 0030 540 E: 1334596953.335113 0003 0031 462 E: 1334596953.335115 0000 0002 0 E: 1334596953.335118 0003 0035 3082 E: 1334596953.335120 0003 0036 3125 E: 1334596953.335123 0003 0034 0 E: 1334596953.335125 0003 0030 720 E: 1334596953.335127 0003 0031 616 E: 1334596953.335130 0000 0002 0 E: 1334596953.335135 0003 0001 4186 E: 1334596953.335138 0000 0000 0 E: 1334596953.349104 0003 0035 2844 E: 1334596953.349107 0003 0036 4181 E: 1334596953.349109 0003 0034 0 E: 1334596953.349112 0003 0030 540 E: 1334596953.349114 0003 0031 462 E: 1334596953.349116 0000 0002 0 E: 1334596953.349119 0003 0035 3063 E: 1334596953.349121 0003 0036 3223 E: 1334596953.349124 0003 0034 0 E: 1334596953.349126 0003 0030 720 E: 1334596953.349129 0003 0031 616 E: 1334596953.349131 0000 0002 0 E: 1334596953.349135 0003 0000 2872 E: 1334596953.349139 0000 0000 0 E: 1334596953.361129 0003 0035 2871 E: 1334596953.361132 0003 0036 4199 E: 1334596953.361135 0003 0034 0 E: 1334596953.361137 0003 0030 540 E: 1334596953.361139 0003 0031 462 E: 1334596953.361142 0000 0002 0 E: 1334596953.361144 0003 0035 3065 E: 1334596953.361147 0003 0036 3111 E: 1334596953.361149 0003 0034 0 E: 1334596953.361151 0003 0030 720 E: 1334596953.361154 0003 0031 616 E: 1334596953.361156 0000 0002 0 E: 1334596953.361163 0000 0000 0 E: 1334596953.375121 0003 0035 2847 E: 1334596953.375124 0003 0036 4171 E: 1334596953.375126 0003 0034 0 E: 1334596953.375129 0003 0030 540 E: 1334596953.375131 0003 0031 462 E: 1334596953.375133 0000 0002 0 E: 1334596953.375136 0003 0035 3071 E: 1334596953.375138 0003 0036 3216 E: 1334596953.375141 0003 0034 0 E: 1334596953.375143 0003 0030 720 E: 1334596953.375146 0003 0031 616 E: 1334596953.375148 0000 0002 0 E: 1334596953.375155 0000 0000 0 E: 1334596953.389152 0003 0035 2890 E: 1334596953.389155 0003 0036 4199 E: 1334596953.389158 0003 0034 0 E: 1334596953.389160 0003 0030 540 E: 1334596953.389162 0003 0031 462 E: 1334596953.389165 0000 0002 0 E: 1334596953.389167 0003 0035 3069 E: 1334596953.389170 0003 0036 3168 E: 1334596953.389172 0003 0034 0 E: 1334596953.389175 0003 0030 720 E: 1334596953.389177 0003 0031 616 E: 1334596953.389179 0000 0002 0 E: 1334596953.389187 0000 0000 0 E: 1334596953.409137 0003 0035 2862 E: 1334596953.409140 0003 0036 4215 E: 1334596953.409143 0003 0034 0 E: 1334596953.409145 0003 0030 540 E: 1334596953.409147 0003 0031 462 E: 1334596953.409150 0000 0002 0 E: 1334596953.409152 0003 0035 3048 E: 1334596953.409155 0003 0036 3179 E: 1334596953.409157 0003 0034 0 E: 1334596953.409159 0003 0030 720 E: 1334596953.409162 0003 0031 616 E: 1334596953.409164 0000 0002 0 E: 1334596953.409171 0000 0000 0 E: 1334596953.423122 0003 0035 2855 E: 1334596953.423125 0003 0036 4138 E: 1334596953.423127 0003 0034 0 E: 1334596953.423130 0003 0030 540 E: 1334596953.423132 0003 0031 462 E: 1334596953.423134 0000 0002 0 E: 1334596953.423137 0003 0035 3067 E: 1334596953.423139 0003 0036 3142 E: 1334596953.423142 0003 0034 0 E: 1334596953.423144 0003 0030 720 E: 1334596953.423147 0003 0031 616 E: 1334596953.423149 0000 0002 0 E: 1334596953.423154 0003 0001 4174 E: 1334596953.423157 0000 0000 0 E: 1334596953.435116 0003 0035 2873 E: 1334596953.435119 0003 0036 4215 E: 1334596953.435121 0003 0034 0 E: 1334596953.435123 0003 0030 540 E: 1334596953.435126 0003 0031 462 E: 1334596953.435128 0000 0002 0 E: 1334596953.435131 0003 0035 3062 E: 1334596953.435133 0003 0036 3122 E: 1334596953.435135 0003 0034 0 E: 1334596953.435138 0003 0030 720 E: 1334596953.435140 0003 0031 616 E: 1334596953.435143 0000 0002 0 E: 1334596953.435148 0003 0001 4184 E: 1334596953.435151 0000 0000 0 E: 1334596953.449128 0003 0035 2846 E: 1334596953.449131 0003 0036 4212 E: 1334596953.449133 0003 0034 0 E: 1334596953.449136 0003 0030 540 E: 1334596953.449138 0003 0031 462 E: 1334596953.449140 0000 0002 0 E: 1334596953.449143 0003 0035 3039 E: 1334596953.449145 0003 0036 3158 E: 1334596953.449148 0003 0034 0 E: 1334596953.449150 0003 0030 540 E: 1334596953.449153 0003 0031 462 E: 1334596953.449155 0000 0002 0 E: 1334596953.449162 0000 0000 0 E: 1334596953.463116 0003 0035 2848 E: 1334596953.463119 0003 0036 4194 E: 1334596953.463121 0003 0034 0 E: 1334596953.463124 0003 0030 540 E: 1334596953.463126 0003 0031 462 E: 1334596953.463128 0000 0002 0 E: 1334596953.463131 0003 0035 3075 E: 1334596953.463133 0003 0036 3116 E: 1334596953.463135 0003 0034 0 E: 1334596953.463138 0003 0030 720 E: 1334596953.463140 0003 0031 616 E: 1334596953.463143 0000 0002 0 E: 1334596953.463149 0000 0000 0 E: 1334596953.475116 0003 0035 2878 E: 1334596953.475118 0003 0036 4227 E: 1334596953.475121 0003 0034 1 E: 1334596953.475123 0003 0030 616 E: 1334596953.475125 0003 0031 540 E: 1334596953.475128 0000 0002 0 E: 1334596953.475130 0003 0035 3102 E: 1334596953.475133 0003 0036 3130 E: 1334596953.475135 0003 0034 1 E: 1334596953.475138 0003 0030 616 E: 1334596953.475140 0003 0031 540 E: 1334596953.475142 0000 0002 0 E: 1334596953.475147 0003 0001 4194 E: 1334596953.475150 0000 0000 0 E: 1334596953.489118 0003 0035 2841 E: 1334596953.489121 0003 0036 4196 E: 1334596953.489123 0003 0034 0 E: 1334596953.489125 0003 0030 540 E: 1334596953.489128 0003 0031 462 E: 1334596953.489130 0000 0002 0 E: 1334596953.489133 0003 0035 3100 E: 1334596953.489135 0003 0036 3174 E: 1334596953.489137 0003 0034 0 E: 1334596953.489140 0003 0030 720 E: 1334596953.489142 0003 0031 616 E: 1334596953.489145 0000 0002 0 E: 1334596953.489151 0000 0000 0 E: 1334596953.509337 0003 0035 2850 E: 1334596953.509340 0003 0036 4165 E: 1334596953.509343 0003 0034 1 E: 1334596953.509345 0003 0030 462 E: 1334596953.509348 0003 0031 360 E: 1334596953.509350 0000 0002 0 E: 1334596953.509353 0003 0035 3064 E: 1334596953.509355 0003 0036 3179 E: 1334596953.509357 0003 0034 0 E: 1334596953.509359 0003 0030 720 E: 1334596953.509362 0003 0031 616 E: 1334596953.509365 0000 0002 0 E: 1334596953.509373 0000 0000 0 E: 1334596953.523149 0003 0035 2847 E: 1334596953.523152 0003 0036 4152 E: 1334596953.523154 0003 0034 1 E: 1334596953.523157 0003 0030 462 E: 1334596953.523159 0003 0031 360 E: 1334596953.523162 0000 0002 0 E: 1334596953.523164 0003 0035 3039 E: 1334596953.523167 0003 0036 3160 E: 1334596953.523169 0003 0034 1 E: 1334596953.523171 0003 0030 616 E: 1334596953.523174 0003 0031 540 E: 1334596953.523176 0000 0002 0 E: 1334596953.523181 0003 0001 4183 E: 1334596953.523185 0000 0000 0 E: 1334596953.535107 0003 0035 2849 E: 1334596953.535110 0003 0036 4166 E: 1334596953.535112 0003 0034 0 E: 1334596953.535115 0003 0030 540 E: 1334596953.535117 0003 0031 462 E: 1334596953.535119 0000 0002 0 E: 1334596953.535122 0003 0035 3043 E: 1334596953.535124 0003 0036 3135 E: 1334596953.535127 0003 0034 1 E: 1334596953.535129 0003 0030 616 E: 1334596953.535132 0003 0031 540 E: 1334596953.535134 0000 0002 0 E: 1334596953.535141 0000 0000 0 E: 1334596953.549103 0003 0035 2847 E: 1334596953.549106 0003 0036 4176 E: 1334596953.549108 0003 0034 0 E: 1334596953.549111 0003 0030 540 E: 1334596953.549113 0003 0031 462 E: 1334596953.549116 0000 0002 0 E: 1334596953.549118 0003 0035 3056 E: 1334596953.549120 0003 0036 3175 E: 1334596953.549123 0003 0034 1 E: 1334596953.549125 0003 0030 616 E: 1334596953.549128 0003 0031 540 E: 1334596953.549130 0000 0002 0 E: 1334596953.549136 0000 0000 0 E: 1334596953.563107 0003 0035 2850 E: 1334596953.563110 0003 0036 4168 E: 1334596953.563112 0003 0034 0 E: 1334596953.563115 0003 0030 540 E: 1334596953.563117 0003 0031 462 E: 1334596953.563119 0000 0002 0 E: 1334596953.563122 0003 0035 3070 E: 1334596953.563124 0003 0036 3122 E: 1334596953.563127 0003 0034 1 E: 1334596953.563129 0003 0030 616 E: 1334596953.563132 0003 0031 540 E: 1334596953.563134 0000 0002 0 E: 1334596953.563140 0000 0000 0 E: 1334596953.575103 0003 0035 2858 E: 1334596953.575106 0003 0036 4184 E: 1334596953.575108 0003 0034 0 E: 1334596953.575111 0003 0030 540 E: 1334596953.575113 0003 0031 462 E: 1334596953.575115 0000 0002 0 E: 1334596953.575118 0003 0035 3077 E: 1334596953.575120 0003 0036 3166 E: 1334596953.575123 0003 0034 1 E: 1334596953.575125 0003 0030 616 E: 1334596953.575128 0003 0031 540 E: 1334596953.575130 0000 0002 0 E: 1334596953.575136 0000 0000 0 E: 1334596953.589105 0003 0035 2847 E: 1334596953.589108 0003 0036 4174 E: 1334596953.589110 0003 0034 0 E: 1334596953.589113 0003 0030 540 E: 1334596953.589115 0003 0031 462 E: 1334596953.589117 0000 0002 0 E: 1334596953.589120 0003 0035 3052 E: 1334596953.589122 0003 0036 3128 E: 1334596953.589125 0003 0034 0 E: 1334596953.589127 0003 0030 720 E: 1334596953.589130 0003 0031 616 E: 1334596953.589132 0000 0002 0 E: 1334596953.589139 0000 0000 0 E: 1334596953.609136 0003 0035 2848 E: 1334596953.609139 0003 0036 4201 E: 1334596953.609141 0003 0034 0 E: 1334596953.609144 0003 0030 540 E: 1334596953.609146 0003 0031 462 E: 1334596953.609149 0000 0002 0 E: 1334596953.609151 0003 0035 3042 E: 1334596953.609153 0003 0036 3134 E: 1334596953.609156 0003 0034 0 E: 1334596953.609158 0003 0030 720 E: 1334596953.609161 0003 0031 616 E: 1334596953.609163 0000 0002 0 E: 1334596953.609170 0000 0000 0 E: 1334596953.623114 0003 0035 2844 E: 1334596953.623117 0003 0036 4192 E: 1334596953.623119 0003 0034 0 E: 1334596953.623121 0003 0030 540 E: 1334596953.623124 0003 0031 462 E: 1334596953.623126 0000 0002 0 E: 1334596953.623129 0003 0035 3048 E: 1334596953.623131 0003 0036 3165 E: 1334596953.623133 0003 0034 0 E: 1334596953.623136 0003 0030 720 E: 1334596953.623138 0003 0031 616 E: 1334596953.623141 0000 0002 0 E: 1334596953.623147 0000 0000 0 E: 1334596953.637117 0003 0035 2851 E: 1334596953.637119 0003 0036 4208 E: 1334596953.637122 0003 0034 0 E: 1334596953.637124 0003 0030 540 E: 1334596953.637126 0003 0031 462 E: 1334596953.637129 0000 0002 0 E: 1334596953.637131 0003 0035 3049 E: 1334596953.637134 0003 0036 3147 E: 1334596953.637136 0003 0034 0 E: 1334596953.637139 0003 0030 720 E: 1334596953.637141 0003 0031 616 E: 1334596953.637143 0000 0002 0 E: 1334596953.637150 0000 0000 0 E: 1334596953.649115 0003 0035 2852 E: 1334596953.649117 0003 0036 4164 E: 1334596953.649120 0003 0034 0 E: 1334596953.649122 0003 0030 540 E: 1334596953.649124 0003 0031 462 E: 1334596953.649127 0000 0002 0 E: 1334596953.649129 0003 0035 3088 E: 1334596953.649132 0003 0036 3153 E: 1334596953.649134 0003 0034 1 E: 1334596953.649137 0003 0030 616 E: 1334596953.649139 0003 0031 540 E: 1334596953.649141 0000 0002 0 E: 1334596953.649148 0000 0000 0 E: 1334596953.663115 0003 0035 2860 E: 1334596953.663118 0003 0036 4185 E: 1334596953.663120 0003 0034 0 E: 1334596953.663123 0003 0030 540 E: 1334596953.663125 0003 0031 462 E: 1334596953.663127 0000 0002 0 E: 1334596953.663130 0003 0035 3030 E: 1334596953.663132 0003 0036 3099 E: 1334596953.663135 0003 0034 1 E: 1334596953.663137 0003 0030 616 E: 1334596953.663140 0003 0031 540 E: 1334596953.663142 0000 0002 0 E: 1334596953.663148 0000 0000 0 E: 1334596953.675116 0003 0035 2982 E: 1334596953.675118 0003 0036 4139 E: 1334596953.675121 0003 0034 1 E: 1334596953.675123 0003 0030 616 E: 1334596953.675125 0003 0031 540 E: 1334596953.675128 0000 0002 0 E: 1334596953.675130 0003 0035 3086 E: 1334596953.675133 0003 0036 3190 E: 1334596953.675135 0003 0034 0 E: 1334596953.675137 0003 0030 720 E: 1334596953.675140 0003 0031 616 E: 1334596953.675142 0000 0002 0 E: 1334596953.675146 0003 0000 2927 E: 1334596953.675148 0003 0001 4172 E: 1334596953.675152 0000 0000 0 E: 1334596953.689130 0003 0035 2865 E: 1334596953.689133 0003 0036 4194 E: 1334596953.689136 0003 0034 0 E: 1334596953.689138 0003 0030 540 E: 1334596953.689140 0003 0031 462 E: 1334596953.689143 0000 0002 0 E: 1334596953.689145 0003 0035 3074 E: 1334596953.689148 0003 0036 3247 E: 1334596953.689150 0003 0034 0 E: 1334596953.689152 0003 0030 720 E: 1334596953.689155 0003 0031 616 E: 1334596953.689157 0000 0002 0 E: 1334596953.689161 0003 0000 2911 E: 1334596953.689166 0000 0000 0 E: 1334596953.709337 0003 0035 2865 E: 1334596953.709340 0003 0036 4172 E: 1334596953.709342 0003 0034 0 E: 1334596953.709345 0003 0030 540 E: 1334596953.709347 0003 0031 462 E: 1334596953.709350 0000 0002 0 E: 1334596953.709352 0003 0035 3065 E: 1334596953.709355 0003 0036 3193 E: 1334596953.709357 0003 0034 1 E: 1334596953.709359 0003 0030 616 E: 1334596953.709362 0003 0031 540 E: 1334596953.709364 0000 0002 0 E: 1334596953.709368 0003 0000 2899 E: 1334596953.709374 0000 0000 0 E: 1334596953.723154 0003 0035 2877 E: 1334596953.723157 0003 0036 4126 E: 1334596953.723159 0003 0034 1 E: 1334596953.723162 0003 0030 462 E: 1334596953.723164 0003 0031 360 E: 1334596953.723167 0000 0002 0 E: 1334596953.723169 0003 0035 3069 E: 1334596953.723171 0003 0036 3228 E: 1334596953.723174 0003 0034 0 E: 1334596953.723176 0003 0030 540 E: 1334596953.723178 0003 0031 462 E: 1334596953.723181 0000 0002 0 E: 1334596953.723186 0003 0001 4160 E: 1334596953.723190 0000 0000 0 E: 1334596953.737141 0003 0035 2940 E: 1334596953.737144 0003 0036 4323 E: 1334596953.737146 0003 0034 1 E: 1334596953.737149 0003 0030 616 E: 1334596953.737151 0003 0031 540 E: 1334596953.737154 0000 0002 0 E: 1334596953.737156 0003 0035 3059 E: 1334596953.737158 0003 0036 3140 E: 1334596953.737161 0003 0034 0 E: 1334596953.737163 0003 0030 720 E: 1334596953.737166 0003 0031 616 E: 1334596953.737168 0000 0002 0 E: 1334596953.737172 0003 0000 2909 E: 1334596953.737174 0003 0001 4323 E: 1334596953.737178 0000 0000 0 E: 1334596953.749132 0003 0035 2847 E: 1334596953.749134 0003 0036 4161 E: 1334596953.749137 0003 0034 0 E: 1334596953.749139 0003 0030 540 E: 1334596953.749141 0003 0031 462 E: 1334596953.749144 0000 0002 0 E: 1334596953.749146 0003 0035 3085 E: 1334596953.749149 0003 0036 3194 E: 1334596953.749151 0003 0034 0 E: 1334596953.749153 0003 0030 720 E: 1334596953.749156 0003 0031 308 E: 1334596953.749158 0000 0002 0 E: 1334596953.749162 0003 0000 2893 E: 1334596953.749165 0003 0001 4161 E: 1334596953.749168 0000 0000 0 E: 1334596953.763134 0003 0035 2855 E: 1334596953.763137 0003 0036 4203 E: 1334596953.763139 0003 0034 0 E: 1334596953.763141 0003 0030 540 E: 1334596953.763144 0003 0031 462 E: 1334596953.763146 0000 0002 0 E: 1334596953.763149 0003 0035 3047 E: 1334596953.763151 0003 0036 3131 E: 1334596953.763153 0003 0034 0 E: 1334596953.763156 0003 0030 720 E: 1334596953.763158 0003 0031 616 E: 1334596953.763161 0000 0002 0 E: 1334596953.763165 0003 0000 2883 E: 1334596953.763167 0003 0001 4171 E: 1334596953.763170 0000 0000 0 E: 1334596953.775106 0003 0035 2853 E: 1334596953.775109 0003 0036 4191 E: 1334596953.775111 0003 0034 0 E: 1334596953.775114 0003 0030 540 E: 1334596953.775116 0003 0031 462 E: 1334596953.775119 0000 0002 0 E: 1334596953.775121 0003 0035 3075 E: 1334596953.775123 0003 0036 3189 E: 1334596953.775126 0003 0034 0 E: 1334596953.775128 0003 0030 720 E: 1334596953.775131 0003 0031 462 E: 1334596953.775133 0000 0002 0 E: 1334596953.775140 0000 0000 0 E: 1334596953.789128 0003 0035 2842 E: 1334596953.789131 0003 0036 4185 E: 1334596953.789134 0003 0034 0 E: 1334596953.789136 0003 0030 540 E: 1334596953.789138 0003 0031 462 E: 1334596953.789141 0000 0002 0 E: 1334596953.789143 0003 0035 3071 E: 1334596953.789146 0003 0036 3195 E: 1334596953.789148 0003 0034 0 E: 1334596953.789150 0003 0030 720 E: 1334596953.789153 0003 0031 616 E: 1334596953.789156 0000 0002 0 E: 1334596953.789159 0003 0000 2872 E: 1334596953.789164 0000 0000 0 E: 1334596953.811137 0003 0035 2880 E: 1334596953.811140 0003 0036 4272 E: 1334596953.811142 0003 0034 0 E: 1334596953.811145 0003 0030 540 E: 1334596953.811147 0003 0031 462 E: 1334596953.811149 0000 0002 0 E: 1334596953.811152 0003 0035 3047 E: 1334596953.811154 0003 0036 3128 E: 1334596953.811157 0003 0034 1 E: 1334596953.811159 0003 0030 616 E: 1334596953.811161 0003 0031 540 E: 1334596953.811164 0000 0002 0 E: 1334596953.811169 0003 0001 4221 E: 1334596953.811172 0000 0000 0 E: 1334596953.823129 0003 0035 2864 E: 1334596953.823132 0003 0036 4165 E: 1334596953.823134 0003 0034 0 E: 1334596953.823137 0003 0030 540 E: 1334596953.823139 0003 0031 462 E: 1334596953.823141 0000 0002 0 E: 1334596953.823144 0003 0035 3093 E: 1334596953.823146 0003 0036 3253 E: 1334596953.823149 0003 0034 0 E: 1334596953.823151 0003 0030 720 E: 1334596953.823154 0003 0031 616 E: 1334596953.823156 0000 0002 0 E: 1334596953.823161 0003 0001 4207 E: 1334596953.823164 0000 0000 0 E: 1334596953.837126 0003 0035 2832 E: 1334596953.837128 0003 0036 4197 E: 1334596953.837131 0003 0034 0 E: 1334596953.837133 0003 0030 540 E: 1334596953.837135 0003 0031 462 E: 1334596953.837138 0000 0002 0 E: 1334596953.837140 0003 0035 3035 E: 1334596953.837143 0003 0036 3176 E: 1334596953.837145 0003 0034 1 E: 1334596953.837147 0003 0030 616 E: 1334596953.837150 0003 0031 540 E: 1334596953.837152 0000 0002 0 E: 1334596953.837156 0003 0000 2862 E: 1334596953.837160 0000 0000 0 E: 1334596953.849124 0003 0035 2875 E: 1334596953.849126 0003 0036 4192 E: 1334596953.849129 0003 0034 1 E: 1334596953.849131 0003 0030 616 E: 1334596953.849133 0003 0031 540 E: 1334596953.849136 0000 0002 0 E: 1334596953.849138 0003 0035 3068 E: 1334596953.849140 0003 0036 3174 E: 1334596953.849143 0003 0034 1 E: 1334596953.849145 0003 0030 616 E: 1334596953.849148 0003 0031 540 E: 1334596953.849150 0000 0002 0 E: 1334596953.849157 0000 0000 0 E: 1334596953.863122 0003 0035 2859 E: 1334596953.863125 0003 0036 4209 E: 1334596953.863127 0003 0034 0 E: 1334596953.863129 0003 0030 540 E: 1334596953.863132 0003 0031 462 E: 1334596953.863134 0000 0002 0 E: 1334596953.863137 0003 0035 3047 E: 1334596953.863139 0003 0036 3154 E: 1334596953.863141 0003 0034 0 E: 1334596953.863144 0003 0030 720 E: 1334596953.863146 0003 0031 616 E: 1334596953.863149 0000 0002 0 E: 1334596953.863155 0000 0000 0 E: 1334596953.877121 0003 0035 2888 E: 1334596953.877124 0003 0036 4162 E: 1334596953.877126 0003 0034 1 E: 1334596953.877129 0003 0030 616 E: 1334596953.877131 0003 0031 540 E: 1334596953.877133 0000 0002 0 E: 1334596953.877136 0003 0035 3064 E: 1334596953.877138 0003 0036 3258 E: 1334596953.877140 0003 0034 0 E: 1334596953.877143 0003 0030 720 E: 1334596953.877145 0003 0031 616 E: 1334596953.877148 0000 0002 0 E: 1334596953.877153 0003 0001 4195 E: 1334596953.877156 0000 0000 0 E: 1334596953.889130 0003 0035 2881 E: 1334596953.889133 0003 0036 4156 E: 1334596953.889135 0003 0034 0 E: 1334596953.889137 0003 0030 540 E: 1334596953.889140 0003 0031 462 E: 1334596953.889142 0000 0002 0 E: 1334596953.889145 0003 0035 3053 E: 1334596953.889147 0003 0036 3249 E: 1334596953.889149 0003 0034 0 E: 1334596953.889152 0003 0030 720 E: 1334596953.889154 0003 0031 616 E: 1334596953.889157 0000 0002 0 E: 1334596953.889162 0003 0001 4185 E: 1334596953.889165 0000 0000 0 E: 1334596953.911138 0003 0035 2845 E: 1334596953.911141 0003 0036 4170 E: 1334596953.911143 0003 0034 1 E: 1334596953.911145 0003 0030 462 E: 1334596953.911148 0003 0031 360 E: 1334596953.911150 0000 0002 0 E: 1334596953.911153 0003 0035 3052 E: 1334596953.911155 0003 0036 3124 E: 1334596953.911157 0003 0034 0 E: 1334596953.911160 0003 0030 720 E: 1334596953.911162 0003 0031 462 E: 1334596953.911165 0000 0002 0 E: 1334596953.911172 0000 0000 0 E: 1334596953.923127 0003 0035 2845 E: 1334596953.923130 0003 0036 4138 E: 1334596953.923132 0003 0034 0 E: 1334596953.923135 0003 0030 540 E: 1334596953.923137 0003 0031 462 E: 1334596953.923139 0000 0002 0 E: 1334596953.923142 0003 0035 3026 E: 1334596953.923144 0003 0036 3282 E: 1334596953.923147 0003 0034 0 E: 1334596953.923149 0003 0030 720 E: 1334596953.923152 0003 0031 616 E: 1334596953.923154 0000 0002 0 E: 1334596953.923159 0003 0001 4173 E: 1334596953.923162 0000 0000 0 E: 1334596953.937123 0003 0035 2877 E: 1334596953.937126 0003 0036 4220 E: 1334596953.937128 0003 0034 0 E: 1334596953.937131 0003 0030 540 E: 1334596953.937133 0003 0031 462 E: 1334596953.937136 0000 0002 0 E: 1334596953.937138 0003 0035 3034 E: 1334596953.937140 0003 0036 3193 E: 1334596953.937143 0003 0034 0 E: 1334596953.937145 0003 0030 720 E: 1334596953.937148 0003 0031 462 E: 1334596953.937150 0000 0002 0 E: 1334596953.937155 0003 0001 4184 E: 1334596953.937158 0000 0000 0 E: 1334596953.949117 0003 0035 2862 E: 1334596953.949119 0003 0036 4144 E: 1334596953.949122 0003 0034 0 E: 1334596953.949124 0003 0030 540 E: 1334596953.949127 0003 0031 462 E: 1334596953.949129 0000 0002 0 E: 1334596953.949131 0003 0035 3080 E: 1334596953.949134 0003 0036 3168 E: 1334596953.949136 0003 0034 1 E: 1334596953.949139 0003 0030 616 E: 1334596953.949141 0003 0031 540 E: 1334596953.949143 0000 0002 0 E: 1334596953.949148 0003 0001 4174 E: 1334596953.949151 0000 0000 0 E: 1334596953.963116 0003 0035 2851 E: 1334596953.963119 0003 0036 4202 E: 1334596953.963121 0003 0034 0 E: 1334596953.963124 0003 0030 540 E: 1334596953.963126 0003 0031 462 E: 1334596953.963128 0000 0002 0 E: 1334596953.963131 0003 0035 3042 E: 1334596953.963133 0003 0036 3142 E: 1334596953.963136 0003 0034 0 E: 1334596953.963138 0003 0030 720 E: 1334596953.963141 0003 0031 616 E: 1334596953.963143 0000 0002 0 E: 1334596953.963149 0000 0000 0 E: 1334596953.977115 0003 0035 2847 E: 1334596953.977117 0003 0036 4195 E: 1334596953.977120 0003 0034 0 E: 1334596953.977122 0003 0030 540 E: 1334596953.977124 0003 0031 462 E: 1334596953.977127 0000 0002 0 E: 1334596953.977129 0003 0035 3103 E: 1334596953.977132 0003 0036 3164 E: 1334596953.977134 0003 0034 0 E: 1334596953.977136 0003 0030 720 E: 1334596953.977139 0003 0031 462 E: 1334596953.977141 0000 0002 0 E: 1334596953.977147 0000 0000 0 E: 1334596953.989113 0003 0035 2848 E: 1334596953.989115 0003 0036 4182 E: 1334596953.989118 0003 0034 0 E: 1334596953.989120 0003 0030 540 E: 1334596953.989122 0003 0031 462 E: 1334596953.989125 0000 0002 0 E: 1334596953.989127 0003 0035 3063 E: 1334596953.989129 0003 0036 3172 E: 1334596953.989132 0003 0034 0 E: 1334596953.989135 0003 0030 720 E: 1334596953.989137 0003 0031 462 E: 1334596953.989139 0000 0002 0 E: 1334596953.989146 0000 0000 0 E: 1334596954.011146 0003 0035 2843 E: 1334596954.011148 0003 0036 4219 E: 1334596954.011151 0003 0034 0 E: 1334596954.011153 0003 0030 540 E: 1334596954.011155 0003 0031 462 E: 1334596954.011158 0000 0002 0 E: 1334596954.011160 0003 0035 3104 E: 1334596954.011162 0003 0036 3163 E: 1334596954.011165 0003 0034 0 E: 1334596954.011167 0003 0030 720 E: 1334596954.011170 0003 0031 616 E: 1334596954.011172 0000 0002 0 E: 1334596954.011177 0003 0001 4185 E: 1334596954.011180 0000 0000 0 E: 1334596954.023141 0003 0035 2854 E: 1334596954.023145 0003 0036 4200 E: 1334596954.023147 0003 0034 0 E: 1334596954.023150 0003 0030 540 E: 1334596954.023152 0003 0031 462 E: 1334596954.023155 0000 0002 0 E: 1334596954.023157 0003 0035 3049 E: 1334596954.023159 0003 0036 3178 E: 1334596954.023162 0003 0034 0 E: 1334596954.023164 0003 0030 720 E: 1334596954.023167 0003 0031 616 E: 1334596954.023169 0000 0002 0 E: 1334596954.023176 0000 0000 0 E: 1334596954.037138 0003 0035 2853 E: 1334596954.037141 0003 0036 4184 E: 1334596954.037143 0003 0034 0 E: 1334596954.037146 0003 0030 540 E: 1334596954.037148 0003 0031 462 E: 1334596954.037150 0000 0002 0 E: 1334596954.037153 0003 0035 3065 E: 1334596954.037155 0003 0036 3199 E: 1334596954.037158 0003 0034 0 E: 1334596954.037160 0003 0030 720 E: 1334596954.037163 0003 0031 616 E: 1334596954.037165 0000 0002 0 E: 1334596954.037172 0000 0000 0 E: 1334596954.051132 0003 0035 2860 E: 1334596954.051135 0003 0036 4162 E: 1334596954.051137 0003 0034 0 E: 1334596954.051140 0003 0030 540 E: 1334596954.051142 0003 0031 462 E: 1334596954.051145 0000 0002 0 E: 1334596954.051147 0003 0035 3080 E: 1334596954.051149 0003 0036 3247 E: 1334596954.051152 0003 0034 0 E: 1334596954.051154 0003 0030 720 E: 1334596954.051157 0003 0031 616 E: 1334596954.051159 0000 0002 0 E: 1334596954.051166 0000 0000 0 E: 1334596954.063130 0003 0035 2838 E: 1334596954.063133 0003 0036 4177 E: 1334596954.063135 0003 0034 0 E: 1334596954.063138 0003 0030 540 E: 1334596954.063140 0003 0031 462 E: 1334596954.063143 0000 0002 0 E: 1334596954.063145 0003 0035 3065 E: 1334596954.063147 0003 0036 3161 E: 1334596954.063150 0003 0034 1 E: 1334596954.063152 0003 0030 616 E: 1334596954.063155 0003 0031 540 E: 1334596954.063157 0000 0002 0 E: 1334596954.063164 0000 0000 0 E: 1334596954.077128 0003 0035 2867 E: 1334596954.077131 0003 0036 4182 E: 1334596954.077133 0003 0034 0 E: 1334596954.077136 0003 0030 540 E: 1334596954.077138 0003 0031 462 E: 1334596954.077140 0000 0002 0 E: 1334596954.077143 0003 0035 3073 E: 1334596954.077145 0003 0036 3148 E: 1334596954.077148 0003 0034 0 E: 1334596954.077150 0003 0030 720 E: 1334596954.077152 0003 0031 616 E: 1334596954.077155 0000 0002 0 E: 1334596954.077161 0000 0000 0 E: 1334596954.089120 0003 0035 2857 E: 1334596954.089123 0003 0036 4168 E: 1334596954.089125 0003 0034 0 E: 1334596954.089127 0003 0030 540 E: 1334596954.089130 0003 0031 462 E: 1334596954.089132 0000 0002 0 E: 1334596954.089135 0003 0035 3063 E: 1334596954.089137 0003 0036 3202 E: 1334596954.089139 0003 0034 0 E: 1334596954.089142 0003 0030 720 E: 1334596954.089144 0003 0031 616 E: 1334596954.089147 0000 0002 0 E: 1334596954.089153 0000 0000 0 E: 1334596954.111144 0003 0035 2869 E: 1334596954.111146 0003 0036 4198 E: 1334596954.111149 0003 0034 0 E: 1334596954.111151 0003 0030 540 E: 1334596954.111154 0003 0031 462 E: 1334596954.111156 0000 0002 0 E: 1334596954.111159 0003 0035 3064 E: 1334596954.111161 0003 0036 3138 E: 1334596954.111163 0003 0034 0 E: 1334596954.111166 0003 0030 720 E: 1334596954.111168 0003 0031 616 E: 1334596954.111171 0000 0002 0 E: 1334596954.111178 0000 0000 0 E: 1334596954.123135 0003 0035 2899 E: 1334596954.123138 0003 0036 4199 E: 1334596954.123140 0003 0034 1 E: 1334596954.123142 0003 0030 616 E: 1334596954.123145 0003 0031 540 E: 1334596954.123147 0000 0002 0 E: 1334596954.123150 0003 0035 3112 E: 1334596954.123152 0003 0036 3112 E: 1334596954.123155 0003 0034 1 E: 1334596954.123157 0003 0030 616 E: 1334596954.123159 0003 0031 540 E: 1334596954.123162 0000 0002 0 E: 1334596954.123166 0003 0000 2871 E: 1334596954.123170 0000 0000 0 E: 1334596954.137134 0003 0035 2897 E: 1334596954.137137 0003 0036 4244 E: 1334596954.137139 0003 0034 0 E: 1334596954.137141 0003 0030 540 E: 1334596954.137144 0003 0031 462 E: 1334596954.137146 0000 0002 0 E: 1334596954.137149 0003 0035 3084 E: 1334596954.137151 0003 0036 3169 E: 1334596954.137153 0003 0034 0 E: 1334596954.137156 0003 0030 720 E: 1334596954.137158 0003 0031 616 E: 1334596954.137161 0000 0002 0 E: 1334596954.137166 0003 0001 4199 E: 1334596954.137169 0000 0000 0 E: 1334596954.151135 0003 0035 2878 E: 1334596954.151138 0003 0036 4158 E: 1334596954.151140 0003 0034 0 E: 1334596954.151143 0003 0030 540 E: 1334596954.151145 0003 0031 462 E: 1334596954.151147 0000 0002 0 E: 1334596954.151150 0003 0035 3081 E: 1334596954.151152 0003 0036 3244 E: 1334596954.151155 0003 0034 0 E: 1334596954.151157 0003 0030 720 E: 1334596954.151160 0003 0031 616 E: 1334596954.151162 0000 0002 0 E: 1334596954.151167 0003 0001 4188 E: 1334596954.151170 0000 0000 0 E: 1334596954.163117 0003 0035 2868 E: 1334596954.163119 0003 0036 4174 E: 1334596954.163121 0003 0034 0 E: 1334596954.163124 0003 0030 540 E: 1334596954.163126 0003 0031 462 E: 1334596954.163129 0000 0002 0 E: 1334596954.163131 0003 0035 3076 E: 1334596954.163133 0003 0036 3122 E: 1334596954.163136 0003 0034 0 E: 1334596954.163138 0003 0030 720 E: 1334596954.163141 0003 0031 616 E: 1334596954.163143 0000 0002 0 E: 1334596954.163149 0000 0000 0 E: 1334596954.177114 0003 0035 2900 E: 1334596954.177117 0003 0036 4178 E: 1334596954.177119 0003 0034 0 E: 1334596954.177122 0003 0030 540 E: 1334596954.177124 0003 0031 462 E: 1334596954.177126 0000 0002 0 E: 1334596954.177129 0003 0035 3093 E: 1334596954.177131 0003 0036 3145 E: 1334596954.177134 0003 0034 0 E: 1334596954.177136 0003 0030 540 E: 1334596954.177139 0003 0031 462 E: 1334596954.177141 0000 0002 0 E: 1334596954.177147 0000 0000 0 E: 1334596954.189124 0003 0035 2885 E: 1334596954.189127 0003 0036 4193 E: 1334596954.189129 0003 0034 0 E: 1334596954.189132 0003 0030 540 E: 1334596954.189134 0003 0031 308 E: 1334596954.189136 0000 0002 0 E: 1334596954.189139 0003 0035 3102 E: 1334596954.189141 0003 0036 3142 E: 1334596954.189144 0003 0034 0 E: 1334596954.189146 0003 0030 720 E: 1334596954.189148 0003 0031 616 E: 1334596954.189151 0000 0002 0 E: 1334596954.189158 0000 0000 0 E: 1334596954.211138 0003 0035 2943 E: 1334596954.211140 0003 0036 4205 E: 1334596954.211143 0003 0034 0 E: 1334596954.211145 0003 0030 540 E: 1334596954.211148 0003 0031 462 E: 1334596954.211150 0000 0002 0 E: 1334596954.211152 0003 0035 3095 E: 1334596954.211155 0003 0036 3181 E: 1334596954.211157 0003 0034 0 E: 1334596954.211160 0003 0030 540 E: 1334596954.211162 0003 0031 462 E: 1334596954.211165 0000 0002 0 E: 1334596954.211168 0003 0000 2889 E: 1334596954.211173 0000 0000 0 E: 1334596954.223117 0003 0035 2951 E: 1334596954.223119 0003 0036 4161 E: 1334596954.223122 0003 0034 1 E: 1334596954.223124 0003 0030 616 E: 1334596954.223126 0003 0031 540 E: 1334596954.223129 0000 0002 0 E: 1334596954.223131 0003 0035 3187 E: 1334596954.223134 0003 0036 3194 E: 1334596954.223136 0003 0034 0 E: 1334596954.223139 0003 0030 720 E: 1334596954.223141 0003 0031 462 E: 1334596954.223143 0000 0002 0 E: 1334596954.223147 0003 0000 2904 E: 1334596954.223152 0000 0000 0 E: 1334596954.237124 0003 0035 3045 E: 1334596954.237127 0003 0036 4196 E: 1334596954.237129 0003 0034 1 E: 1334596954.237132 0003 0030 616 E: 1334596954.237134 0003 0031 540 E: 1334596954.237137 0000 0002 0 E: 1334596954.237139 0003 0035 3224 E: 1334596954.237141 0003 0036 3195 E: 1334596954.237144 0003 0034 1 E: 1334596954.237146 0003 0030 616 E: 1334596954.237149 0003 0031 540 E: 1334596954.237151 0000 0002 0 E: 1334596954.237155 0003 0000 2974 E: 1334596954.237159 0000 0000 0 E: 1334596954.249121 0003 0035 3098 E: 1334596954.249123 0003 0036 4167 E: 1334596954.249126 0003 0034 0 E: 1334596954.249128 0003 0030 540 E: 1334596954.249130 0003 0031 308 E: 1334596954.249133 0000 0002 0 E: 1334596954.249135 0003 0035 3375 E: 1334596954.249138 0003 0036 3250 E: 1334596954.249140 0003 0034 0 E: 1334596954.249142 0003 0030 720 E: 1334596954.249145 0003 0031 462 E: 1334596954.249147 0000 0002 0 E: 1334596954.249151 0003 0000 3036 E: 1334596954.249155 0000 0000 0 E: 1334596954.263123 0003 0035 3185 E: 1334596954.263126 0003 0036 4154 E: 1334596954.263128 0003 0034 0 E: 1334596954.263130 0003 0030 540 E: 1334596954.263133 0003 0031 462 E: 1334596954.263135 0000 0002 0 E: 1334596954.263138 0003 0035 3402 E: 1334596954.263140 0003 0036 3297 E: 1334596954.263142 0003 0034 0 E: 1334596954.263145 0003 0030 720 E: 1334596954.263147 0003 0031 308 E: 1334596954.263150 0000 0002 0 E: 1334596954.263153 0003 0000 3110 E: 1334596954.263158 0000 0000 0 E: 1334596954.277121 0003 0035 3282 E: 1334596954.277124 0003 0036 4132 E: 1334596954.277126 0003 0034 0 E: 1334596954.277128 0003 0030 540 E: 1334596954.277131 0003 0031 462 E: 1334596954.277133 0000 0002 0 E: 1334596954.277136 0003 0035 3465 E: 1334596954.277138 0003 0036 3235 E: 1334596954.277140 0003 0034 0 E: 1334596954.277143 0003 0030 720 E: 1334596954.277145 0003 0031 154 E: 1334596954.277147 0000 0002 0 E: 1334596954.277151 0003 0000 3282 E: 1334596954.277154 0003 0001 4174 E: 1334596954.277157 0000 0000 0 E: 1334596954.289105 0003 0035 3393 E: 1334596954.289108 0003 0036 4193 E: 1334596954.289110 0003 0034 0 E: 1334596954.289113 0003 0030 540 E: 1334596954.289115 0003 0031 308 E: 1334596954.289117 0000 0002 0 E: 1334596954.289120 0003 0035 3583 E: 1334596954.289122 0003 0036 3206 E: 1334596954.289125 0003 0034 0 E: 1334596954.289127 0003 0030 720 E: 1334596954.289130 0003 0031 462 E: 1334596954.289132 0000 0002 0 E: 1334596954.289136 0003 0000 3337 E: 1334596954.289140 0000 0000 0 E: 1334596954.311152 0003 0035 3465 E: 1334596954.311155 0003 0036 4200 E: 1334596954.311158 0003 0034 0 E: 1334596954.311160 0003 0030 540 E: 1334596954.311162 0003 0031 154 E: 1334596954.311165 0000 0002 0 E: 1334596954.311167 0003 0035 3810 E: 1334596954.311170 0003 0036 3265 E: 1334596954.311172 0003 0034 0 E: 1334596954.311175 0003 0030 720 E: 1334596954.311177 0003 0031 462 E: 1334596954.311179 0000 0002 0 E: 1334596954.311183 0003 0000 3401 E: 1334596954.311188 0000 0000 0 E: 1334596954.325136 0003 0035 3828 E: 1334596954.325139 0003 0036 4132 E: 1334596954.325142 0003 0034 1 E: 1334596954.325144 0003 0030 770 E: 1334596954.325146 0003 0031 540 E: 1334596954.325149 0000 0002 0 E: 1334596954.325151 0003 0035 3910 E: 1334596954.325154 0003 0036 3282 E: 1334596954.325156 0003 0034 1 E: 1334596954.325158 0003 0030 770 E: 1334596954.325161 0003 0031 720 E: 1334596954.325163 0000 0002 0 E: 1334596954.325167 0003 0000 3828 E: 1334596954.325170 0003 0001 4163 E: 1334596954.325173 0000 0000 0 E: 1334596954.337127 0003 0035 3875 E: 1334596954.337130 0003 0036 4235 E: 1334596954.337133 0003 0034 0 E: 1334596954.337135 0003 0030 540 E: 1334596954.337137 0003 0031 462 E: 1334596954.337140 0000 0002 0 E: 1334596954.337142 0003 0035 4139 E: 1334596954.337145 0003 0036 3311 E: 1334596954.337147 0003 0034 0 E: 1334596954.337149 0003 0030 540 E: 1334596954.337152 0003 0031 462 E: 1334596954.337154 0000 0002 0 E: 1334596954.337158 0003 0000 3839 E: 1334596954.337160 0003 0001 4181 E: 1334596954.337163 0000 0000 0 E: 1334596954.351124 0003 0035 4045 E: 1334596954.351126 0003 0036 4245 E: 1334596954.351129 0003 0034 1 E: 1334596954.351131 0003 0030 616 E: 1334596954.351133 0003 0031 540 E: 1334596954.351136 0000 0002 0 E: 1334596954.351138 0003 0035 4257 E: 1334596954.351141 0003 0036 3347 E: 1334596954.351143 0003 0034 0 E: 1334596954.351146 0003 0030 720 E: 1334596954.351148 0003 0031 462 E: 1334596954.351150 0000 0002 0 E: 1334596954.351154 0003 0000 4045 E: 1334596954.351156 0003 0001 4197 E: 1334596954.351160 0000 0000 0 E: 1334596954.363121 0003 0035 4177 E: 1334596954.363124 0003 0036 4254 E: 1334596954.363126 0003 0034 0 E: 1334596954.363129 0003 0030 540 E: 1334596954.363131 0003 0031 308 E: 1334596954.363134 0000 0002 0 E: 1334596954.363136 0003 0035 4413 E: 1334596954.363138 0003 0036 3274 E: 1334596954.363141 0003 0034 0 E: 1334596954.363143 0003 0030 720 E: 1334596954.363146 0003 0031 462 E: 1334596954.363148 0000 0002 0 E: 1334596954.363152 0003 0000 4111 E: 1334596954.363155 0003 0001 4211 E: 1334596954.363158 0000 0000 0 E: 1334596954.374349 0003 0035 4328 E: 1334596954.374352 0003 0036 4266 E: 1334596954.374354 0003 0034 0 E: 1334596954.374357 0003 0030 540 E: 1334596954.374359 0003 0031 462 E: 1334596954.374362 0000 0002 0 E: 1334596954.374364 0003 0035 4646 E: 1334596954.374367 0003 0036 3330 E: 1334596954.374369 0003 0034 0 E: 1334596954.374371 0003 0030 540 E: 1334596954.374374 0003 0031 308 E: 1334596954.374376 0000 0002 0 E: 1334596954.374380 0003 0000 4328 E: 1334596954.374383 0003 0001 4224 E: 1334596954.374386 0000 0000 0 E: 1334596954.387113 0003 0035 4528 E: 1334596954.387115 0003 0036 4292 E: 1334596954.387118 0003 0034 0 E: 1334596954.387120 0003 0030 540 E: 1334596954.387122 0003 0031 462 E: 1334596954.387125 0000 0002 0 E: 1334596954.387127 0003 0035 4804 E: 1334596954.387130 0003 0036 3333 E: 1334596954.387132 0003 0034 0 E: 1334596954.387134 0003 0030 540 E: 1334596954.387137 0003 0031 462 E: 1334596954.387139 0000 0002 0 E: 1334596954.387143 0003 0000 4528 E: 1334596954.387145 0003 0001 4241 E: 1334596954.387149 0000 0000 0 E: 1334596954.399103 0003 0035 4701 E: 1334596954.399106 0003 0036 4268 E: 1334596954.399109 0003 0034 0 E: 1334596954.399111 0003 0030 540 E: 1334596954.399113 0003 0031 462 E: 1334596954.399116 0000 0002 0 E: 1334596954.399118 0003 0035 4915 E: 1334596954.399121 0003 0036 3347 E: 1334596954.399123 0003 0034 0 E: 1334596954.399126 0003 0030 540 E: 1334596954.399128 0003 0031 308 E: 1334596954.399130 0000 0002 0 E: 1334596954.399134 0003 0000 4701 E: 1334596954.399138 0000 0000 0 E: 1334596954.419131 0003 0035 4859 E: 1334596954.419134 0003 0036 4276 E: 1334596954.419136 0003 0034 0 E: 1334596954.419139 0003 0030 540 E: 1334596954.419141 0003 0031 462 E: 1334596954.419144 0000 0002 0 E: 1334596954.419146 0003 0035 5167 E: 1334596954.419149 0003 0036 3311 E: 1334596954.419151 0003 0034 0 E: 1334596954.419153 0003 0030 540 E: 1334596954.419156 0003 0031 462 E: 1334596954.419158 0000 0002 0 E: 1334596954.419162 0003 0000 4859 E: 1334596954.419166 0000 0000 0 E: 1334596954.433145 0003 0035 5228 E: 1334596954.433148 0003 0036 4255 E: 1334596954.433151 0003 0034 0 E: 1334596954.433153 0003 0030 540 E: 1334596954.433155 0003 0031 462 E: 1334596954.433158 0000 0002 0 E: 1334596954.433160 0003 0035 5439 E: 1334596954.433163 0003 0036 3388 E: 1334596954.433165 0003 0034 0 E: 1334596954.433167 0003 0030 540 E: 1334596954.433170 0003 0031 462 E: 1334596954.433172 0000 0002 0 E: 1334596954.433176 0003 0000 5228 E: 1334596954.433181 0000 0000 0 E: 1334596954.447141 0003 0035 5343 E: 1334596954.447144 0003 0036 4315 E: 1334596954.447148 0003 0034 0 E: 1334596954.447151 0003 0030 720 E: 1334596954.447153 0003 0031 462 E: 1334596954.447155 0000 0002 0 E: 1334596954.447158 0003 0035 5665 E: 1334596954.447160 0003 0036 3331 E: 1334596954.447163 0003 0034 0 E: 1334596954.447165 0003 0030 540 E: 1334596954.447167 0003 0031 462 E: 1334596954.447170 0000 0002 0 E: 1334596954.447174 0003 0000 5285 E: 1334596954.447176 0003 0001 4259 E: 1334596954.447180 0000 0000 0 E: 1334596954.461133 0003 0035 5552 E: 1334596954.461135 0003 0036 4317 E: 1334596954.461138 0003 0034 0 E: 1334596954.461140 0003 0030 720 E: 1334596954.461142 0003 0031 462 E: 1334596954.461145 0000 0002 0 E: 1334596954.461147 0003 0035 5869 E: 1334596954.461150 0003 0036 3395 E: 1334596954.461152 0003 0034 0 E: 1334596954.461154 0003 0030 720 E: 1334596954.461157 0003 0031 308 E: 1334596954.461159 0000 0002 0 E: 1334596954.461163 0003 0000 5552 E: 1334596954.461166 0003 0001 4273 E: 1334596954.461169 0000 0000 0 E: 1334596954.475133 0003 0035 5743 E: 1334596954.475136 0003 0036 4303 E: 1334596954.475138 0003 0034 0 E: 1334596954.475140 0003 0030 720 E: 1334596954.475143 0003 0031 462 E: 1334596954.475145 0000 0002 0 E: 1334596954.475148 0003 0035 5978 E: 1334596954.475150 0003 0036 3373 E: 1334596954.475152 0003 0034 0 E: 1334596954.475155 0003 0030 720 E: 1334596954.475157 0003 0031 308 E: 1334596954.475160 0000 0002 0 E: 1334596954.475163 0003 0000 5743 E: 1334596954.475168 0000 0000 0 E: 1334596954.489110 0003 0035 5882 E: 1334596954.489112 0003 0036 4340 E: 1334596954.489114 0003 0034 0 E: 1334596954.489117 0003 0030 720 E: 1334596954.489119 0003 0031 308 E: 1334596954.489122 0000 0002 0 E: 1334596954.489124 0003 0035 6264 E: 1334596954.489127 0003 0036 3460 E: 1334596954.489129 0003 0034 0 E: 1334596954.489131 0003 0030 720 E: 1334596954.489134 0003 0031 616 E: 1334596954.489136 0000 0002 0 E: 1334596954.489140 0003 0000 5812 E: 1334596954.489142 0003 0001 4289 E: 1334596954.489145 0000 0000 0 E: 1334596954.503135 0003 0035 5991 E: 1334596954.503138 0003 0036 4330 E: 1334596954.503140 0003 0034 1 E: 1334596954.503142 0003 0030 462 E: 1334596954.503145 0003 0031 360 E: 1334596954.503147 0000 0002 0 E: 1334596954.503150 0003 0035 6372 E: 1334596954.503152 0003 0036 3355 E: 1334596954.503155 0003 0034 0 E: 1334596954.503157 0003 0030 720 E: 1334596954.503159 0003 0031 462 E: 1334596954.503162 0000 0002 0 E: 1334596954.503165 0003 0000 5991 E: 1334596954.503168 0003 0001 4299 E: 1334596954.503171 0000 0000 0 E: 1334596954.525223 0003 0035 6208 E: 1334596954.525226 0003 0036 4290 E: 1334596954.525229 0003 0034 0 E: 1334596954.525231 0003 0030 720 E: 1334596954.525234 0003 0031 462 E: 1334596954.525236 0000 0002 0 E: 1334596954.525239 0003 0035 6518 E: 1334596954.525241 0003 0036 3422 E: 1334596954.525243 0003 0034 0 E: 1334596954.525246 0003 0030 720 E: 1334596954.525248 0003 0031 462 E: 1334596954.525250 0000 0002 0 E: 1334596954.525255 0003 0000 6208 E: 1334596954.525260 0000 0000 0 E: 1334596954.539143 0003 0035 6324 E: 1334596954.539146 0003 0036 4303 E: 1334596954.539148 0003 0034 0 E: 1334596954.539151 0003 0030 720 E: 1334596954.539153 0003 0031 308 E: 1334596954.539156 0000 0002 0 E: 1334596954.539158 0003 0035 6675 E: 1334596954.539160 0003 0036 3409 E: 1334596954.539163 0003 0034 0 E: 1334596954.539165 0003 0030 720 E: 1334596954.539168 0003 0031 462 E: 1334596954.539170 0000 0002 0 E: 1334596954.539174 0003 0000 6266 E: 1334596954.539179 0000 0000 0 E: 1334596954.553146 0003 0035 6397 E: 1334596954.553149 0003 0036 4361 E: 1334596954.553151 0003 0034 0 E: 1334596954.553153 0003 0030 720 E: 1334596954.553156 0003 0031 616 E: 1334596954.553158 0000 0002 0 E: 1334596954.553161 0003 0035 6704 E: 1334596954.553163 0003 0036 3339 E: 1334596954.553165 0003 0034 0 E: 1334596954.553168 0003 0030 720 E: 1334596954.553170 0003 0031 462 E: 1334596954.553173 0000 0002 0 E: 1334596954.553177 0003 0000 6331 E: 1334596954.553179 0003 0001 4314 E: 1334596954.553182 0000 0000 0 E: 1334596954.569136 0003 0035 6577 E: 1334596954.569139 0003 0036 4162 E: 1334596954.569141 0003 0034 0 E: 1334596954.569144 0003 0030 720 E: 1334596954.569146 0003 0031 616 E: 1334596954.569149 0000 0002 0 E: 1334596954.569151 0003 0035 6762 E: 1334596954.569153 0003 0036 3371 E: 1334596954.569156 0003 0034 0 E: 1334596954.569158 0003 0030 720 E: 1334596954.569161 0003 0031 616 E: 1334596954.569163 0000 0002 0 E: 1334596954.569167 0003 0000 6577 E: 1334596954.569169 0003 0001 4238 E: 1334596954.569173 0000 0000 0 E: 1334596954.581134 0003 0035 6454 E: 1334596954.581136 0003 0036 4354 E: 1334596954.581139 0003 0034 0 E: 1334596954.581141 0003 0030 540 E: 1334596954.581144 0003 0031 462 E: 1334596954.581146 0000 0002 0 E: 1334596954.581149 0003 0035 6770 E: 1334596954.581151 0003 0036 3407 E: 1334596954.581153 0003 0034 0 E: 1334596954.581156 0003 0030 720 E: 1334596954.581158 0003 0031 616 E: 1334596954.581160 0000 0002 0 E: 1334596954.581164 0003 0000 6515 E: 1334596954.581167 0003 0001 4296 E: 1334596954.581170 0000 0000 0 E: 1334596954.597124 0003 0035 6473 E: 1334596954.597127 0003 0036 4379 E: 1334596954.597129 0003 0034 0 E: 1334596954.597131 0003 0030 720 E: 1334596954.597134 0003 0031 616 E: 1334596954.597136 0000 0002 0 E: 1334596954.597139 0003 0035 6762 E: 1334596954.597141 0003 0036 3379 E: 1334596954.597143 0003 0034 0 E: 1334596954.597146 0003 0030 720 E: 1334596954.597148 0003 0031 308 E: 1334596954.597151 0000 0002 0 E: 1334596954.597154 0003 0000 6504 E: 1334596954.597157 0003 0001 4337 E: 1334596954.597160 0000 0000 0 E: 1334596954.611122 0003 0035 6478 E: 1334596954.611125 0003 0036 4354 E: 1334596954.611127 0003 0034 0 E: 1334596954.611130 0003 0030 720 E: 1334596954.611132 0003 0031 616 E: 1334596954.611134 0000 0002 0 E: 1334596954.611137 0003 0035 6762 E: 1334596954.611139 0003 0036 3395 E: 1334596954.611142 0003 0034 0 E: 1334596954.611144 0003 0030 720 E: 1334596954.611146 0003 0031 616 E: 1334596954.611149 0000 0002 0 E: 1334596954.611156 0000 0000 0 E: 1334596954.633157 0003 0035 6459 E: 1334596954.633160 0003 0036 4310 E: 1334596954.633162 0003 0034 1 E: 1334596954.633165 0003 0030 770 E: 1334596954.633167 0003 0031 540 E: 1334596954.633170 0000 0002 0 E: 1334596954.633172 0003 0035 6748 E: 1334596954.633174 0003 0036 3368 E: 1334596954.633177 0003 0034 0 E: 1334596954.633179 0003 0030 720 E: 1334596954.633182 0003 0031 616 E: 1334596954.633184 0000 0002 0 E: 1334596954.633188 0003 0000 6492 E: 1334596954.633193 0000 0000 0 E: 1334596954.647151 0003 0035 6428 E: 1334596954.647154 0003 0036 4310 E: 1334596954.647156 0003 0034 0 E: 1334596954.647158 0003 0030 540 E: 1334596954.647161 0003 0031 462 E: 1334596954.647163 0000 0002 0 E: 1334596954.647166 0003 0035 6743 E: 1334596954.647168 0003 0036 3356 E: 1334596954.647170 0003 0034 0 E: 1334596954.647173 0003 0030 720 E: 1334596954.647175 0003 0031 462 E: 1334596954.647177 0000 0002 0 E: 1334596954.647181 0003 0000 6476 E: 1334596954.647186 0000 0000 0 E: 1334596954.661141 0003 0035 6436 E: 1334596954.661144 0003 0036 4327 E: 1334596954.661146 0003 0034 1 E: 1334596954.661149 0003 0030 616 E: 1334596954.661151 0003 0031 540 E: 1334596954.661153 0000 0002 0 E: 1334596954.661156 0003 0035 6735 E: 1334596954.661158 0003 0036 3400 E: 1334596954.661161 0003 0034 0 E: 1334596954.661163 0003 0030 720 E: 1334596954.661166 0003 0031 462 E: 1334596954.661168 0000 0002 0 E: 1334596954.661172 0003 0000 6466 E: 1334596954.661176 0000 0000 0 E: 1334596954.675133 0003 0035 6440 E: 1334596954.675136 0003 0036 4289 E: 1334596954.675138 0003 0034 0 E: 1334596954.675141 0003 0030 540 E: 1334596954.675143 0003 0031 462 E: 1334596954.675146 0000 0002 0 E: 1334596954.675148 0003 0035 6714 E: 1334596954.675150 0003 0036 3433 E: 1334596954.675153 0003 0034 0 E: 1334596954.675155 0003 0030 720 E: 1334596954.675158 0003 0031 616 E: 1334596954.675160 0000 0002 0 E: 1334596954.675165 0003 0001 4325 E: 1334596954.675168 0000 0000 0 E: 1334596954.689123 0003 0035 6402 E: 1334596954.689126 0003 0036 4302 E: 1334596954.689129 0003 0034 0 E: 1334596954.689131 0003 0030 540 E: 1334596954.689133 0003 0031 462 E: 1334596954.689136 0000 0002 0 E: 1334596954.689138 0003 0035 6733 E: 1334596954.689141 0003 0036 3331 E: 1334596954.689143 0003 0034 0 E: 1334596954.689145 0003 0030 720 E: 1334596954.689148 0003 0031 462 E: 1334596954.689150 0000 0002 0 E: 1334596954.689154 0003 0000 6450 E: 1334596954.689158 0000 0000 0 E: 1334596954.703125 0003 0035 6386 E: 1334596954.703128 0003 0036 4362 E: 1334596954.703130 0003 0034 1 E: 1334596954.703133 0003 0030 616 E: 1334596954.703135 0003 0031 540 E: 1334596954.703137 0000 0002 0 E: 1334596954.703140 0003 0035 6735 E: 1334596954.703142 0003 0036 3340 E: 1334596954.703145 0003 0034 0 E: 1334596954.703147 0003 0030 720 E: 1334596954.703150 0003 0031 462 E: 1334596954.703152 0000 0002 0 E: 1334596954.703156 0003 0000 6434 E: 1334596954.703160 0000 0000 0 E: 1334596954.717119 0003 0035 6734 E: 1334596954.717122 0003 0036 3366 E: 1334596954.717124 0003 0034 0 E: 1334596954.717127 0003 0030 540 E: 1334596954.717129 0003 0031 462 E: 1334596954.717131 0000 0002 0 E: 1334596954.717135 0003 0000 6734 E: 1334596954.717137 0003 0001 3366 E: 1334596954.717141 0000 0000 0 E: 1334596954.735127 0003 0035 6708 E: 1334596954.735129 0003 0036 3330 E: 1334596954.735132 0003 0034 1 E: 1334596954.735134 0003 0030 308 E: 1334596954.735137 0003 0031 180 E: 1334596954.735139 0000 0002 0 E: 1334596954.735146 0000 0000 0 E: 1334596954.749127 0001 014a 0 E: 1334596954.749130 0000 0000 0 geis-2.2.17+16.04.20160126/testsuite/recordings/test_device2/0000755000015600001650000000000012651717732023657 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/testsuite/recordings/test_device2/device.prop0000644000015600001650000000150712651717544026024 0ustar pbuserpbgroup00000000000000N: Test Device2 I: 0011 0002 0007 01b1 P: 09 00 00 00 00 00 00 00 B: 00 0b 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 03 00 00 00 00 00 B: 01 20 64 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 01 00 00 00 00 00 00 00 00 B: 02 00 00 00 00 00 00 00 00 B: 03 03 00 00 11 00 80 60 02 B: 04 00 00 00 00 00 00 00 00 B: 05 00 00 00 00 00 00 00 00 B: 11 00 00 00 00 00 00 00 00 B: 12 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 B: 15 00 00 00 00 00 00 00 00 A: 00 1472 5888 0 0 A: 01 1408 4820 0 0 A: 18 0 255 0 0 A: 1c 0 15 0 0 A: 2f 0 1 0 0 A: 35 1472 5888 0 0 A: 36 1408 4820 0 0 A: 39 0 65535 0 0 geis-2.2.17+16.04.20160126/examples/0000755000015600001650000000000012651717732016725 5ustar pbuserpbgroup00000000000000geis-2.2.17+16.04.20160126/examples/geis2.c0000644000015600001650000001225612651717544020111 0ustar pbuserpbgroup00000000000000/** * @file geis2.c * @brief A simple example using the GEIS v2 API. * * Copyright 2011 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of version 3 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "geis_config.h" #include #include #include #include #include void print_attr(GeisAttr attr) { GeisString attr_name = geis_attr_name(attr); switch (geis_attr_type(attr)) { case GEIS_ATTR_TYPE_BOOLEAN: printf(" \"%s\": %s\n", attr_name, geis_attr_value_to_boolean(attr) ? "true" : "false"); break; case GEIS_ATTR_TYPE_FLOAT: printf(" \"%s\": %g\n", attr_name, geis_attr_value_to_float(attr)); break; case GEIS_ATTR_TYPE_INTEGER: printf(" \"%s\": %d\n", attr_name, geis_attr_value_to_integer(attr)); break; case GEIS_ATTR_TYPE_STRING: printf(" \"%s\": %s\n", attr_name, geis_attr_value_to_string(attr)); break; default: break; } } void dump_device_event(GeisEvent event) { GeisDevice device; GeisAttr attr; GeisSize i; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); device = geis_attr_value_to_pointer(attr); printf("device %02d \"%s\"\n", geis_device_id(device), geis_device_name(device)); for (i = 0; i < geis_device_attr_count(device); ++i) { print_attr(geis_device_attr(device, i)); } } void dump_gesture_event(GeisEvent event) { GeisSize i; GeisTouchSet touchset; GeisGroupSet groupset; GeisAttr attr; attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); touchset = geis_attr_value_to_pointer(attr); attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); groupset = geis_attr_value_to_pointer(attr); printf("gesture\n"); for (i= 0; i < geis_groupset_group_count(groupset); ++i) { GeisSize j; GeisGroup group = geis_groupset_group(groupset, i); printf("+group %u\n", geis_group_id(group)); for (j=0; j < geis_group_frame_count(group); ++j) { GeisSize k; GeisFrame frame = geis_group_frame(group, j); GeisSize attr_count = geis_frame_attr_count(frame); printf("+frame %u\n", geis_frame_id(frame)); for (k = 0; k < attr_count; ++k) { print_attr(geis_frame_attr(frame, k)); } for (k = 0; k < geis_frame_touchid_count(frame); ++k) { GeisSize touchid = geis_frame_touchid(frame, k); GeisTouch touch = geis_touchset_touch_by_id(touchset, touchid); GeisSize n; printf("+touch %u\n", (unsigned)k); for (n = 0; n < geis_touch_attr_count(touch); ++n) { print_attr(geis_touch_attr(touch, n)); } } } } } void target_subscription(Geis geis, GeisSubscription subscription) { GeisStatus status; GeisFilter filter = geis_filter_new(geis, "filter"); geis_filter_add_term(filter, GEIS_FILTER_CLASS, GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 2, NULL); status = geis_subscription_add_filter(subscription, filter); if (status != GEIS_STATUS_SUCCESS) { fprintf(stderr, "error adding filter\n"); } } int main(int argc GEIS_UNUSED, char* argv[] GEIS_UNUSED) { GeisStatus status; Geis geis; GeisSubscription subscription; int fd; geis = geis_new(GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL); geis_get_configuration(geis, GEIS_CONFIGURATION_FD, &fd); subscription = geis_subscription_new(geis, "example", GEIS_SUBSCRIPTION_CONT); while(1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(0, &read_fds); FD_SET(fd, &read_fds); int sstat = select(fd+1, &read_fds, NULL, NULL, NULL); if (sstat < 0) { fprintf(stderr, "error %d in select(): %s\n", errno, strerror(errno)); break; } if (FD_ISSET(fd, &read_fds)) { GeisEvent event; status = geis_dispatch_events(geis); status = geis_next_event(geis, &event); while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS) { switch (geis_event_type(event)) { case GEIS_EVENT_INIT_COMPLETE: target_subscription(geis, subscription); status = geis_subscription_activate(subscription); break; case GEIS_EVENT_DEVICE_AVAILABLE: case GEIS_EVENT_DEVICE_UNAVAILABLE: dump_device_event(event); break; case GEIS_EVENT_GESTURE_BEGIN: case GEIS_EVENT_GESTURE_UPDATE: case GEIS_EVENT_GESTURE_END: dump_gesture_event(event); break; default: break; } geis_event_delete(event); status = geis_next_event(geis, &event); } } if (FD_ISSET(0, &read_fds)) { break; } } geis_subscription_delete(subscription); geis_delete(geis); } geis-2.2.17+16.04.20160126/examples/Makefile.am0000644000015600001650000000171412651717544020765 0ustar pbuserpbgroup00000000000000# # @file examples/Makefile.am # @brief automake recipe for the GEIS examples # # Copyright 2011 Canonical, Ltd. # # This file is part of the geis library. 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 3 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 General Public License # along with this program. If not, see . # noinst_PROGRAMS = geis2 geis2_SOURCES = geis2.c geis2_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libgeis geis2_LDADD = $(top_builddir)/libgeis/libgeis.la geis-2.2.17+16.04.20160126/ChangeLog0000644000015600001650000020466112651717544016673 0ustar pbuserpbgroup000000000000002011-03-31 Stephen M. Webb Add initial python bindings. * python/Makefile.am: new file * python/_geis_bindings/_geis_bindings.c: new file * python/geis/__init__.py: new file * python/geis/geis_v2.py: new file * python/pygeis: new script * Makefile.am (SUBDIRS): added python * configure.ac (AC_CONFIG_FILES): added new generated files 2011-04-10 Stephen M. Webb Repaired a callback persistence problem (LP: #754135). * testsuite/geis1/check_subscription.c: new test suite * libgeis/geis_v1.c: saved a copy of the callback tables * testsuite/geis1/Makefile.am: included new test suite * testsuite/geis1/check_geis1_api.c: ran new test suite 2011-04-12 Stephen M. Webb Made direct use of XI2.1 optional at build time (LP: #741404). * m4/ax_enable_xi2.m4: new autoconf macro * configure.ac: invoked the new macro * libgeis/backend/xcb/geis_xcb_backend.c: optioned XI2.1 code 2011-04-05 Stephen M. Webb Fixed invalid pointer dereference on XI initialization failure in XCB back end (LP: #730899). * libgeis/backend/xcb/geis_xcb_backend.c (geis_xcb_backend_new): cleared properly to indicate a failure. 2011-03-28 Stephen M. Webb Changes the list of attrs received from grail for the Touch gesture. * libgeis/backend/xcb/grail_gestures.c: change Touch attrs 2011-03-25 Stephen M. Webb Added new TOUCH gesture types (LP: #742555). * include/geis/geis.h: added new TOUCH gesture types * libgeis/backend/xcb/geis_xcb_backend.c: tweaked gesture mask size * libgeis/backend/xcb/grail_gestures.c: added new TOUCH gesture types added proper handling of a variable-size gesture mask * libgeis/geis_v1.c: mapped new TOUCH gesture types to grail TOUCH gesture types * testsuite/geis1/check_gesture_types.c: new testsuite * testsuite/geis1/Makefile.am: added new testsuite * testsuite/geis1/check_geis1_api.c: invoked new testsuite * testsuite/geistest/geistest.c: added new gesture types 2011-03-24 Stephen M. Webb Fixed a bad index when translating grail touches (LP: #742002). * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): fixed offset calculation for grail touch properties 2011-03-22 Stephen M. Webb Added a default back end (LP: #740311). * examples/geis2.c (dump_gesture_event): dumped more info (main): removed GEIS_INIT_XCB from geis_new call * libgeis/geis.c (geis_new): added GEIS_INIT_XCB as default 2011-03-22 Stephen M. Webb Passed the correct gesture_id to GEIS v1 callbacks (LP: #740284). * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): Used the grail gesture_id as the frame_id. * testsuite/geistest/geistest.c (gesture_update): reported the gesture_id (gesture_start): reported the gesture_id (gesture_finish): reported the gesture_id 2011-03-22 Stephen M. Webb Corrected the number of touches on a gesture event (LP: #737745). * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): replaced geis_xcb_backend_touch_count() call with a calculation based on the number of touch properties passed from grail * libgeis/backend/xcb/grail_gestures.c (geis_xcb_backend_touch_count): removed * libgeis/backend/xcb/grail_gestures.h (geis_xcb_backend_touch_count): removed 2011-03-17 Stephen M. Webb Added definitions for GEIS v1 gesture primitive types (LP: #737230). * include/geis/geis.h (GEIS_GESTURE_PRIMITIVE_DRAG): new symbol (GEIS_GESTURE_PRIMITIVE_PINCH): new symbol (GEIS_GESTURE_PRIMITIVE_ROTATE): new symbol (GEIS_GESTURE_PRIMITIVE_TAP): new symbol * libgeis/backend/xcb/grail_gestures.c (s_grail_class_map): replaced grail symbolic constants with the new GEIS symbolic constants 2011-03-16 Stephen M. Webb Refined the API documentation and added an examples directory. * doc/api.dox: new documentation file * doc/logo_x64.png: new logo image * doc/using_geis_v2.dox: new documentation file * examples/Makefile.am: examples subdirectory Makefile * examples/geis2.c: new example program * Makefile.am: added examples subdirectory * configure.ac: added examples subdirectory * doc/Doxyfile: tweaked Doxygen settings * include/geis/geis.h: complete API docs refinement 2011-03-16 Stephen M. Webb Replaced device class with explicit attributes. * include/geis/geis.h (GEIS_DEVICE_CLASS_*) removed (GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH): added (GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH): added * libgeis/backend/xcb/geis_xcb_backend.c: (_map_xi2_mode_to_geis_device_attrs): replaced function _map_xi2_mode_to_geis_device_class * testsuite/geis2/check_device.c: added checks for new attributes 2011-03-16 Stephen M. Webb Refinement of input device class handling. * include/geis/geis.h (GEIS_DEVICE_CLASS_UNKNOWN): new device class (GEIS_DEVICE_CLASS_TOUCH_MULTIFINGER): new device class * libgeis/backend/xcb/geis_xcb_backend.c (_map_xi2_mode_to_geis_device_class): new function (_report_an_xcb_device): used it 2011-03-13 Stephen M. Webb Initialized an uninitialized variable. * libgeis/geis_v1.c (_v1_input_callback): initialized device_id 2011-03-12 Stephen M. Webb Added spcifying devices to geistest. * libgeis/backend/xcb/geis_xcb_backend.c: added -d swicth * doc/geistest.1: documented its use 2011-03-12 Stephen M. Webb Added proper device ID filtering for GEIS v1. * libgeis/geis_v1.c (_subscribe_device): Added filter for device ID. 2011-03-11 Stephen M. Webb Implement device enumeration (LP: #733296) * libgeis/backend/xcb/geis_xcb_backend.c (_report_an_xcb_device): new (_report_xcb_devices): imlemented * libgeis/geis_device.c (geis_device_new): made "id" an attr (geis_device_id): same (geis_device_add_attr): implemented missing function * libgeis/geis_v1.c (_v1_input_callback): new function (geis_input_devices): implemented * testsuite/geis1/check_gesture_attrs.c: removed debug message * testsuite/geistest/geistest.c (input_device_added): added a dump 2011-03-11 Stephen M. Webb Fix a lifetime issue with string attrs. * libgeis/geis_attr.c (geis_attr_new): dup all strings (geis_attr_delete): free strings 2011-03-11 Stephen M. Webb Added new device symbolic constants due to a change in the GEIS spec. * include/geis/geis.h (GEIS_DEVICE_ATTRIBUTE_CLASS): new constant (GEIS_DEVICE_ATTRIBUTE_TOUCHES): new constant (GEIS_DEVICE_CLASS_TOUCH_DIRECT): new constant (GEIS_DEVICE_CLASS_TOUCH_DEPENDENT): new constant (GEIS_DEVICE_CLASS_TOUCH_INDEPENDENT): new constant (GEIS_DEVICE_CLASS_TOUCH_PARTIAL): new constant * testsuite/geis2/check_device.c: added tests for the above 2011-03-11 Stephen M. Webb Added a required symbolic constant for device events. * include/geis/geis.h (GEIS_EVENT_ATTRIBUTE_DEVICE): new symbol (GEIS_DEVICE_ATTRIBUTE_ID): new symbol * libgeis/backend/test_fixture/geis_backend_test_fixture.c: used them * libgeis/geis.c: used them * testsuite/geis2/check_device.c (geis_device_types): checked them * testsuite/geis2/check_subscription.c: used them 2011-03-08 Stephen M. Webb Released geis v2.0.3. * configure.ac (AC_INIT): bumped version to 2.0.3 2011-03-08 Stephen M. Webb Added fix for LP: #732104: re-order class event pump in v1 emulation. * libgeis/geis_v1.c (_subscribe_device): added more diagnostic messages (geis_subscribe): re-ordered event pump to prime the class table 2011-03-08 Stephen M. Webb Added a unit test and related infrastructure in the mock objects to reproduce LP: #732104. * libgeis/backend/test_fixture/geis_backend_test_fixture.c: moved generation of gesture events to after subscription creation, added support for TOUCH filters * testsuite/geis1/check_gesture_attrs.c: added check for touch count, changed subscription from GEIS_ALL_GESTURES to an explicit list * testsuite/geis2/check_frame.c: activated subscription 2011-03-07 Stephen M. Webb Released GEIS v2.0.2. * configure.ac (AC_INIT): bumped version to 2.0.2 2011-03-07 Stephen M. Webb Renamed test case for LP: #728606 * testsuite/geis1/check_gesture_attrs.c: renamed from testsuite/geis1/check_lp728606.c * testsuite/geis1/Makefile.am: renamed source file added -Werror to CFLAGS * testsuite/geis1/check_geis1_api.c: renamed test 2011-03-07 Stephen M. Webb Added regression test for LP: #728606 * testsuite/geis1/check_lp728606.c: new test suite * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_gesture_events): add some basic gesture attrs to mock events * libgeis/geis_v1.c (geis_init): tweaked mock object creation (geis_finish): reset global Geis object (geis_subscribe): relocated class event pump * testsuite/geis1/Makefile.am: added new test suite source * testsuite/geis1/check_geis1_api.c: ran new test suite 2011-03-07 Stephen M. Webb Enabled GEIS v1 for basic API unit testing. * testsuite/geis1/check_instance.c: new test suite * libgeis/geis_v1.c (_generate_subscription_name): handled NULL XCB info (geis_init): handled request for mock back end * testsuite/geis1/Makefile.am: added new source file * testsuite/geis1/check_geis1_api.c: ran new test suite 2011-03-07 Stephen M. Webb Re-added GEIS v1 API testing. * testsuite/geis1/check_geis_internals.c: removed * testsuite/geis1/check_instance_table.c: removed * testsuite/geis1/check_geis1_api.c: new file * configure.ac (AC_CONFIG_FILES): added testsuite.geis1/Makefile * testsuite/Makefile.am (SUBDIRS): added geis1 * testsuite/geis1/Makefile.am: Removed old unit tests, added check_geis1_api 2011-03-03 Stephen M. Webb Fixed incorrect data conversion in GEIS v1 implementation (LP: #728606) * libgeis/geis_v1 (_map_frame_to_attrs): put float value in the float member of the attr union to avoid unwanted coercion. 2011-02-28 Stephen M. Webb Added a graceful exit to the geistest tool. * testsuite/geistest/geistest.c (main): added watch on stdin for exit * doc/geistest.1: mentioned how to exit gracefully 2011-02-28 Stephen M. Webb Fixed logic in a string-to-boolean conversion. * libgeis/geis_attr.c (geis_attr_value_to_boolean): fixed logic 2011-02-27 Stephen M. Webb Fixed memory leaks in GEIS v2 subscriptions. * libgeis/backend/xcb/geis_xcb_backend.c (_finalize): closed X display * libgeis/geis.c (geis_new): reffed the new geis object (geis_delete): invalidated all outstanding subscriptions * libgeis/geis_backend.c: fixed debug message to avoid a bad dereference * libgeis/geis_filter.c: only unref ther geis object on destruction * libgeis/geis_filter_term.c: free the bag store on deletion * libgeis/geis_subscription.h (geis_subscription_bag_invalidate): new (geis_subscription_invalidate): new * libgeis/geis_subscription.c: imlemented new functions (_subscription_destroy): handled destruction in invalided state * libgeis/geis_v1.c (geis_finish): deleted window filter 2011-02-23 Stephen M. Webb Fixed memory leaks in GEIS v2 group and touch sets. * libgeis/geis_frame.c (geis_frameset_delete): fixed loop condition (geis_frame_delete): freed touches * libgeis/geis_group.c (geis_groupset_delete): fixed loop condition * libgeis/geis_touch.c (geis_touchset_delete): fixed loop condition 2011-02-23 Stephen M. Webb Fixed a memory leak in GEIS v2 gesture events. * libgeis/geis_attr.h (GeisAttrDestructor): new type (geis_attr_set_destructor): new function * libgeis/geis_attr.c (geis_attr_set_destructor): implemented it (attr_value): named union for ISO C compatibility * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): added destructors to groupset and touchset attrs 2011-02-22 Stephen M. Webb Released version 2.0.1. * configure.ac (AC_INIT): bumped package version to 2.0.1 2011-02-22 Stephen M. Webb Used standardized LGPL-v3 license text. * COPYING: refreshed with standardized text. 2011-02-22 Stephen M. Webb Restored missing GEIS v1 symbols and fixed a segfault in libgrip. * libgeis/geis_v1.c (struct _GeisInstance): added window_filter field (geis_init): initialized window_filter field (_subscribe_device): used window_filter field from instance (geis_configuration_set_value): added missing GEIS v1 function (geis_unsubscribe): added missing GEIS v1 function 2011-02-22 Stephen M. Webb Release version 2.0.0 * configure.ac (AC_INIT): bumped package version to 2.0.0 * libgeis/Makefile.am (libgeis_la_LDFLAGS): bumped version-info to 3:0:2 (gives .so version 1.2.0) to reflect the addition of a new interface 2011-02-21 Stephen M. Webb Added support for setting the XCB sysflg through the GEIS v1 interface. * include/geis/geis.h (GEIS_GESTURE_TYPE_SYSTEM): new gesture type * libgeis/geis_subscription.h (geis_subscription_set_flags): new function * libgeis/geis_subscription.c: implemented it * libgeis/geis_v1.c (geis_subscribe): used it 2011-02-20 Stephen M. Webb Cranked up warning level on testsuite and fixed (most of) the consequent warnings. * testsuite/geis2/check_attr.c: fxied compile-time warnings * testsuite/geis2/check_class.c: same * testsuite/geis2/check_device.c: same * testsuite/geis2/check_event.c: same * testsuite/geis2/check_filter.c: ditto * testsuite/geis2/check_frame.c: same * testsuite/geis2/check_geis2_api.c: same * testsuite/geis2/check_geis_new.c: same * testsuite/geis2/check_general_types.c: same * testsuite/geis2/check_region.c: same * testsuite/libgeis/check_attr.c: same * testsuite/libgeis/check_backend_multiplexor.c: same * testsuite/libgeis/check_class.c: same * testsuite/libgeis/check_device.c: idem * testsuite/libgeis/check_error_reporting.c: same * testsuite/libgeis/check_filter.c: yep * testsuite/libgeis/check_geis2_internals.c: you guessed it * testsuite/libgeis/check_geis_private.c: uh-huh 2011-02-19 Stephen M. Webb Fixed failed "make distcheck". * libgeis/Makefile.am: added geis_atomic.h * libgeis/server/Makefile.am: added geis_dbus.h 2011-02-19 Stephen M. Webb Removed old crufty unused source code. * libgeis-dbus: removed directory * libgeis-xcb: removed directory 2011-02-17 Stephen M. Webb Added proper support for region filters in XCB. * libgeis/backend/xcb/geis_xcb_backend.c (XcbGestureSub): added windows and window_count fields (_translate_device_term_to_xcb): eliminated duplicates (_translate_region_term_to_xcb): new function (_subscribe): used new fields/function * libgeis/geis_v1.c (geis_init): added region filter for window 2011-02-17 Stephen M. Webb Added a check for the maximum number of device terms. * libgeis/backend/xcb/geis_xcb_backend.c (_translate_device_term_to_xcb): Added MAX_NUM_DEVICES and checked it. 2011-02-17 Stephen M. Webb Added proper support for continuations and system gestures. * libgeis/backend/xcb/geis_xcb_backend.c (_translate_class_term_to_xcb): fixed min/max logic (_translate_filter_to_xcb): added subscription parameter, called new functions, ORed masks from different filters on same subscription (_subscribe): removed special case for no class filters * libgeis/backend/xcb/grail_gestures.h (geis_xcb_backend_create_gesture_bitmask): removed and replaced with... (geis_xcb_backend_gesture_bitmask_filter_class): new function (geis_xcb_backend_gesture_bitmask_filter_touches): new function (geis_xcb_backend_gesture_bitmask_init): new function * libgeis/backend/xcb/grail_gestures.c: implemented the above new * functions * libgeis/geis_subscription.h (geis_subscription_flags): new function * libgeis/geis_subscription.c: implemented it * testsuite/geistest/geistest.c: switched from 'all' to a set of gestures 2011-02-17 Stephen M. Webb Added the ability to fetch a filter from a subscription and clone it. * include/geis/geis.h (geis_filter_clone): new function (geis_subscription_filter_by_name): new function * libgeis/geis_filter.h (geis_filter_bag_filter_by_name): new function * libgeis/geis_filter.c (geis_filter_bag_filter_by_name): implemented (_filter_new_empty): new function (geis_filter_new): used it (geis_filter_clone): implemented it (geis_filter_delete): unreffed geis * libgeis/geis_filter_term.h (geis_filter_term_bag_clone): new function * libgeis/geis_filter_term.c (geis_filter_term_bag_clone): implemented * libgeis/geis_subscription.c (geis_subscription_filter_by_name): impl * libgeis/geis_v1.c (_subscribe): used new functions * libgeis/libgeis.ver (geis_filter_clone): new exported symbol (geis_subscription_filter_by_name): new exported symbol * testsuite/geis2/Makefile.am: added -Wall -Wextra CFLAGS * testsuite/geis2/check_filter.c: new test case, silenced warnings * testsuite/geis2/check_subscription.c: new test case, silenced warnings * testsuite/libgeis/Makefile.am: added -Wall -Wextra CFLAGS 2011-02-17 Stephen M. Webb Reference counting fixes: added geis_atomic functions, added reference counting semantics to Geis and GeisFilterTerm modules. * libgeis/geis_atomic.h: new file * libgeis/geis.c (_geis_destroy): new function (geis_ref): new function (geis_unref): new function (geis_delete): used new functions * libgeis/geis_class.c (geis_gesture_class_ref): used new atomics (geis_gesture_class_unref): same * libgeis/geis_device.c (geis_device_ref): used new atomics (geis_device_unref): same * libgeis/geis_filter.c (geis_filter_ref): used new atomics (geis_filter_unref): same (geis_filter_bag_insert): moved ref call to after all possible errors * libgeis/geis_filter.h (geis_filter_ref): changed return type * libgeis/geis_filter_term.c (struct _GeisFilterTerm): added refcount (geis_filter_term_ref): new function (geis_filter_term_unref): new function (geis_filter_term_new): called geis_filter_term_ref (geis_filter_term_delete): made static and renamed _filter_term_destroy * libgeis/geis_filter_term.h: prototyped new functions * libgeis/geis_private.h: prototyped new functions * libgeis/geis_region.c: used new atomics * libgeis/geis_subscription.c (_subscription_ref): new static function (_subscription_unref): new static function (geis_subscription_bag_empty): new function (geis_subscription_bag_new): used new function (geis_subscription_bag_delete): used new function (geis_subscription_bag_remov): used new function * libgeis/geis_subscription.h: prototyped new functions 2011-02-11 Stephen M. Webb Implemented class and device filters properly. * libgeis/backend/xcb/geis_xcb_backend.c (struct _XcbGestureSub): added new fields (_translate_class_filter_to_xcb): removed function (_translate_device_term_to_xcb): new function (_translate_class_term_to_xcb): new function (_translate_filter_to_xcb): new function (_subscribe): replaced old functions with new, restructired filter loop * libgeis/backend/xcb/grail_gestures.c: silenced compiler warnings * libgeis/geis_filter.c: replace by_facility functions * libgeis/geis_filter.h: same * libgeis/geis_filter_term.c: same * libgeis/geis_filter_term.h: same * libgeis/backend/test_fixture/geis_backend_test_fixture.c: replaced filter by_facility calls. 2011-02-09 Stephen M. Webb Fixed a memory allocation problem during error reporting. * libgeis/geis_error.c (geis_error_stack_push): fixed realloc size 2011-02-05 Stephen M. Webb Fixed a memory leak in the XCB back end. * libgeis/backend/xcb/geis_xcb_backend.c (_xcb_dispatch): freed XCB event 2011-02-04 Stephen M. Webb Reimplement GEIS v1.0 on top of GEIS v2.0, Part III (touch attrs). * include/geis/geis.h (GEIS_TOUCH_ATTRIBUTE_ID): new symbol (GEIS_TOUCH_ATTRIBUTE_X): new symbol (GEIS_TOUCH_ATTRIBUTE_Y): new symbol * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): added touch mapping * libgeis/geis_v1.c (_map_frame_to_attrs): mapped touches into gesture attrs 2011-02-02 Stephen M. Webb Reimplement GEIS v1.0 on top of GEIS v2.0, Part II (gesture attrs). * libgeis/backend/xcb/grail_gestures.h (geis_xcb_backend_map_grail_attrs): new function * libgeis/backend/xcb/grail_gestures.c: implemented it * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): called it * libgeis/geis_attr.c: fixed a memory leak * libgeis/geis_v1.c (_map_frame_to_attrs): new function (_v1_event_callback): called it 2011-01-31 Stephen M. Webb Reimplement GEIS v1.0 on top of GEIS v2.0, Part I (basic gesture events). * libgeis/geis_v1.c: new file * configure.ac: removed refs to libgeis-xcb and testsuite/geis1 * libgeis/Makefile.am: removed refs to libgeis-xcb * libgeis/backend/xcb/geis_xcb_backend.c (_dispatch_gesture): added basic group, frame, and touch attrs to gesture events * testsuite/Makefile.am: removed refs to testsuite/geis1 2011-01-28 Stephen M. Webb Implemented basic gesture subscriptions through the XCB back end. * libgeis/backend/xcb/geis_xcb_backend.c (struct _XcbGestureSub): new (_dispatch_gesture): new function (_xcb_dispatch): called it (_subscribe): initialized XcbGestureSub (_unsubscribe): destroyed XcbGestureSub * libgeis/backend/xcb/grail_gestures.h (geis_xcb_backend_primitive_class): new function (geis_xcb_backend_touch_count): implemented new functions * libgeis/geis_subscription.h (geis_subscription_pdata): new function (geis_subscription_set_pdata): new function * libgeis/geis_subscription.c: implemented new functions 2011-01-27 Stephen M. Webb Added GEIS v2.0 gesture module, part V (refined frame-touch interaction) * include/geis/geis.h (GeisTouchId) new type (geis_touchset_touch_by_id(): new function (geis_frame_touchid_count(): renamed from geis_frame_touch_count (geis_frame_touchid): renamed from geis_frame_touch * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_gesture_events): called geis_frame_add_touchid * libgeis/geis_frame.c (struct _GeisFrame): added touch fields (geis_frame_new): initialized touch fields (geis_frame_delete): destroyed touch fields * libgeis/geis_frame.h (geis_frame_add_touchid): new fucntion * libgeis/geis_touch.c: implemented new function * libgeis/geis_touch.h (geis_touch_new): changed parameter type * libgeis/libgeis.ver: added/renamed symbols * testsuite/geis2/check_frame.c: expanded test case to include frame-touch 2011-01-27 Stephen M. Webb Added GEIS v2.0 gesture module, part IV (frame implementation) * libgeis/geis_frame.c: new file * libgeis/geis_frame.h: new file * libgeis/Makefile.am: added new files * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_gesture_events): added frame to injected event * libgeis/geis_group.c (struct _GeisGroup): added frameset field (geis_groupset_delete): cleaned out container (geis_group_new): initialized frameset member (geis_group_delete): destroyed frameset member (geis_group_insert_frame): added function implementation (geis_group_frame_count): added function implementation (geis_group_frame): added function implementation (geis_group_reject): added function stub * libgeis/geis_group.h (geis_group_insert_frame): new function * libgeis/geis_touch.c (geis_touchset_delete): cleaned out container (geis_touch_new): initialized attr_bag member (geis_touch_delete): destroyed attr_bag member * testsuite/geis2/check_frame.c: added new checks for frames 2011-01-27 Stephen M. Webb Added missing callback registration function. * libgeis/geis.c (geis_register_device_callback): implemented function 2011-01-27 Stephen M. Webb Added GEIS v2.0 gesture module, part III (touch/touchset implementation) * libgeis/geis_touch.c: new file * libgeis/geis_touch.h: new file * libgeis/Makefile.am: added new files * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_gesture_events): added touch set to injected event * testsuite/geis2/check_frame.c: added test case 2011-01-26 Stephen M. Webb Added GEIS v2.0 gesture module, part II (group/groupset implementation) * libgeis/geis_group.c: new file * libgeis/geis_group.h: new file * libgeis/Makefile.am: added new files * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_gesture_events): new function (geis_backend_new_test_fixture): called it * testsuite/geis2/check_class.c(receive_events): allowed for multiple events * testsuite/geis2/check_device.c(receive_events): allowed for multiple events * testsuite/geis2/check_frame.c (receive_events): new test case * testsuite/geis2/check_subscription.c (receive_events): fixed leak 2011-01-25 Stephen M. Webb Added GEIS v2.0 gesture module, part I (public API). * testsuite/geis2/check_frame.c: new test suite * include/geis/geis.h (GeisGroup): new type (GeisGroupSet): new type (GeisTouch): new type (GeisTouchSet): new type (GeisFrame): new type (GEIS_EVENT_ATTRIBUTE_GROUPSET): new symbol (GEIS_EVENT_ATTRIBUTE_TOUCHSET): new symbol (geis_groupset_group_count): new function (geis_groupset_group): new function (geis_group_id): new function (geis_group_frame_count): new function (geis_group_frame): new function (geis_group_reject): new function (geis_touchset_touch_count): new function (geis_touchset_touch): new function (geis_touch_id): new function (geis_touch_attr_count): new function (geis_touch_attr): new function (geis_touch_attr_by_name): new function (geis_frame_id): new function (geis_frame_is_class): new function (geis_frame_attr_count): new function (geis_frame_attr): new function (geis_frame_attr_by_name): new function (geis_frame_matrix): new function (geis_frame_touch_count): new function (geis_frame_touch): new function (geis_gesture_reject): new function * libgeis/libgeis.ver: added new symbols * testsuite/geis2/Makefile.am: added new test suite file * testsuite/geis2/check_geis2_api.c: referenced new test suite 2011-01-10 Stephen M. Webb Added gesture class events to XCB back end. * libgeis/backend/xcb/grail_gestures.c: new file * libgeis/backend/xcb/grail_gestures.h: new file * libgeis/backend/xcb/Makefile.am: added new files * libgeis/backend/xcb/geis_xcb_backend.c (_report_xcb_devices): new (_report_grail_glasses): new (geis_xcb_backend_new: called new functions 2011-01-07 Stephen M. Webb Added XCB back end convenience library. * libgeis/backend/xcb/geis_xcb_backend.c: new file * libgeis/backend/xcb/geis_xcb_backend.h: new file * libgeis/backend/xcb/Makefile.am: added rules for new library * include/geis/geis.h (GEIS_INIT_XCB): new init arg symbol * libgeis/geis.c: used it * libgeis/Makefile.am: added XCB protocol library * libgeis-xcb/Makefile.am: removed XCB protocol library * testsuite/libgeis/Makefile.am: added XCB runtime libraries 2011-01-07 Stephen M. Webb Refactored XCB protocol library into a separate convenience lib. * libs/Makefile.am: new directory * libs/xcb/Makefile.am: new subproject * libs/xcb/c-client.xsl: renamed from libgeis-xcb/c-client.xsl * libs/xcb/c_client.py: renamed from libgeis-xcb/c_client.py * libs/xcb/xcb_gesture.xml.in: was libgeis-xcb/xcb_gesture.xml.in * Makefile.am: added new subproject * configure.ac: added new subproject * libgeis-xcb/Makefile.am: moved XCB protocol to libs/xcb subproject 2011-01-07 Stephen M. Webb Added XCB back end subproject to libgeis. * libgeis/backend/xcb: new subproject * libgeis/backend/xcb/Makefile.am: new file. * Makefile.am: updated copyright * configure.ac: added new subproject * libgeis/backend/Makefile.am: added new subproject 2011-01-06 Stephen M. Webb Added Geis v2.0 gesture class implementation (part 2, oif internals) * testsuite/libgeis/check_class.c: new test suite * include/geis/geis.h: fixed GEIS_FILTER_CLASS * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_test_classes): new function * libgeis/backend/test_fixture/geis_backend_test_fixture.h (geis_backend_new_test_fixture): added track_classes parameter * libgeis/geis.c (struct _Geis): added new fields (_class_event_handler): implemented event handling (geis_new_empty): initialized new fields (_set_valist): handled GEIS_INIT_TRACK_GESTURE_CLASSES (geis_get_class_attr_type): new function * libgeis/geis_class.h (GeisGestureClassBag): new data structure (geis_gesture_class_bag_new): new function (geis_gesture_class_bag_delete): new function (geis_gesture_class_bag_count): new function (geis_gesture_class_bag_gesture_class): new function (geis_gesture_class_bag_insert): new function (geis_gesture_class_bag_remove): new function * libgeis/geis_class.c: implemented above new functions * libgeis/geis_filter.c (_facility_is_valid): fixed facility name * libgeis/geis_private.h (geis_get_class_attr_type): new function * testsuite/geis2/check_filter.c: fixed facility name * testsuite/geis2/check_subscription.c: added check for class subscription * testsuite/libgeis/Makefile.am: added new test suite file * testsuite/libgeis/check_geis2_internals.c: called new test suite 2011-01-06 Stephen M. Webb Added Geis v2.0 gesture class implementation (part 1, basic API) * libgeis/geis_class.c: new file * libgeis/geis_class.h: new file * libgeis/Makefile.am: added new source files * libgeis/geis.c (struct _Geis): added new class callback fields (_class_event_handler): new function (_input_event_handler): added case for gesture class events (geis_register_class_callback): implemented function * include/geis/geis.h (geis_gesture_class_ref): adjusted return type (geis_gesture_class_unref): same 2011-01-06 Stephen M. Webb Added GEIS v2.0 gesture class API * testsuite/geis2/check_class.c: new test suite * include/geis/geis.h (GEIS_INIT_TRACK_GESTURE_CLASSES): new init ath (GEIS_EVENT_CLASS_AVAILABLE): new event type (GEIS_EVENT_CLASS_CHANGED): new event type (GEIS_EVENT_CLASS_UNAVAILABLE): new event type (GeisGestureClass): new opaque type (GEIS_CLASS_ATTRIBUTE_NAME): new attribute name (GEIS_CLASS_ATTRIBUTE_ID): new attribute name (GEIS_EVENT_ATTRIBUTE_CLASS): new attribute name (geis_register_class_callback): new function (geis_gesture_class_ref): new function (geis_gesture_class_unref): new function (geis_gesture_class_name): new function (geis_gesture_class_id): new function (geis_gesture_class_attr_count): new function (geis_gesture_class_attr): new function * libgeis/libgeis.ver: added new exported symbols * testsuite/geis2/Makefile.am: build new test suite * testsuite/geis2/check_event.c: changed event type names * testsuite/geis2/check_geis2_api.c: used new test suite * testsuite/geis2/check_geis_new.c: changed init constant names 2011-01-05 Stephen M. Webb Minor tweaks. * include/geis/geis.h: fixed typos in comments (GEIS_DEVICE_ATTRIBUTE_NAME): new constant * libgeis/geis_device.c: used new constant instead of hard-coded string * testsuite/geis2/check_subscription.c: same 2011-01-05 Stephen M. Webb Added GEIS v2.0 filter implementation (part 4, device subscription) * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_subscription): add debug output to the test fixture * libgeis/geis_device.c: made name an attr for filtering on * libgeis/geis_filter.h (geis_filter_term_by_facility_count): new function (geis_filter_term_by_facility): new function * libgeis/geis_filter.c: implemented the above new functions * libgeis/geis_subscription.h (geis_subscription_filter_count): new function (geis_subscription_filter): new function * libgeis/geis_subscription.c: implemented the above new functions * testsuite/geis2/check_subscription.c (device_filter): new test case 2011-01-05 Stephen M. Webb Added group test for back end device creation. * libgeis/backend/test_fixture/geis_backend_test_fixture.c (_create_test_devices): new function (geis_backend_new_test_fixture): used it * libgeis/backend/test_fixture/geis_backend_test_fixture.h (geis_backend_new_test_fixture): added track_devices parameter * libgeis/geis.c (_set_valist): refactored to propagate init args * testsuite/geis2/check_device.c: new test case 2011-01-05 Stephen M. Webb Marked missing geis_event_* symbols as exported. * libgeis/libgeis.ver (geis_event_attr): exported (geis_event_attr_by_name): exported (geis_event_attr_count): exported (geis_event_delete): exported (geis_event_type): exported 2011-01-05 Stephen M. Webb Moved back end test fixture into a subproject. * libgeis/backend/test_fixture: new subproject * libgeis/backend/test_fixture/Makefile.am: new file * libgeis/backend/test_fixture/geis_backend_test_fixture.c: renamed from libgeis/geis_backend_test_fixture.c * libgeis/backend/test_fixture/geis_backend_test_fixture.h: renamed from libgeis/geis_backend_test_fixture.h * configure.ac (AC_OUTPUT): added libgeis/backend/test_fixture/Makefile * libgeis/Makefile.am: linked in new subproject * libgeis/backend/Makefile.am: added new subproject * libgeis/geis.c: changed header qualification 2011-01-05 Stephen M. Webb Added device cacheing. * libgeis/geis_private.h (geis_get_device_attr_type): new function * libgeis/geis.c (struct _Geis): added devices field (_device_event_handler): new function (_input_event_handler): dispatched BE device events (geis_new_empty): initialized devices field (geis_new_delete): destroyed devices field * libgeis/geis_filter.c (_get_attr_type_for_facility): implemented for the device facility 2011-01-05 Stephen M. Webb Fixed failure-mode return value from geis_filter_term_bag_new * libgeis/geis_filter_term.c (geis_filter_term_bag_new): returned NULL on failure 2011-01-05 Stephen M. Webb Added missing geis_attr_value_to_pointer. * libgeis/geis_attr.c (geis_attr_value_to_pointer): new function (geis_attr_value_to_string): added case to handle GEIS_ATTR_TYPE_POINTER 2011-01-03 Stephen M. Webb Added GEIS v2.0 filter implementation (part 3, filter terms) * libgeis/geis_filter_term.c: new file * libgeis/geis_filter_term.h: new file * include/geis/geis.h (GeisFilterOperation): fixed typo * libgeis/Makefile.am: added new files * libgeis/geis_filter.c (geis_filter_add_term): implemented function (_facility_is_valid): new function (_operation_is_valid): new function (_get_attr_for_facility): new function 2011-01-01 Stephen M. Webb Added GEIS v2.0 filter implementation (part 2) * libgeis/geis_filter.c: fixed refcounting on bag insertion * libgeis/geis_subscription.c (geis_subscription_add_filter): implemented stubbed-out function (geis_subscription_remove_filter): implemented stubbed-out function * testsuite/geis2/check_subscription.c: new test case 2010-12-20 Stephen M. Webb Added GEIS v2.0 filter implementation (part 1) * testsuite/libgeis/check_filter.c: new test suite * libgeis/geis_filter.h (GeisFilterBag): new data structure (geis_filter_bag_new): new function (geis_filter_bag_delete): new function (geis_filter_bag_count): new function (geis_filter_bag_filter): new function (geis_filter_bag_insert): new function (geis_filter_bag_remove): new function (geis_filter_ref): new function (geis_filter_unref): new function * libgeis/geis_filter.c: implemented new functions * testsuite/libgeis/Makefile.am: added new test suite * testsuite/libgeis/check_geis2_internals.c: added new test suite 2010-12-29 Stephen M. Webb Added GEIS v2.0 filter API * libgeis/geis_filter.c: new file * libgeis/geis_filter.h: new file * testsuite/geis2/check_filter.c: new test suite * include/geis/geis.h (GeisFilter): new type (GeisFilterFacility): new enumeration (GeisFilterOperation): new enumeration (gei_filter_new): new function (geis_filter_delete): new function (geis_filter_name): new function (geis_filter_add_term): new function * libgeis/Makefile.am: added new files * libgeis/libgeis.ver: added new symbols * testsuite/geis2/Makefile.am: added new test suite * testsuite/geis2/check_geis2_api.c: added new test suite 2010-12-29 Stephen M. Webb Added backend subdirectory to libgeis. * libgeis/backend/Makefile.am: new file * configure.ac (AC_OUTPUT): added libgeis/backend/Makefile * libgeis/Makefile.am (SUBDORS): added backend 2010-12-29 Stephen M. Webb Moved geis/geisimpl.h into GEIS v2.0 sources. * libgeis/geis/geisimple.h: renamed from libgeis-xcb/geis * libgeis-xcb/Makefile.am: changed header search path * libgeis/Makefile.am: changed header search path * testsuite/geis1/Makefile.am: changed header search path * testsuite/geis2/Makefile.am: changed header search path * testsuite/geistest/Makefile.am: changed header search path * testsuite/libgeis/Makefile.am: changed header search path 2010-12-20 Stephen M. Webb Added GEIS v2.0 input device implementation. * libgeis/geis_device.h (GeisDeviceBag): new type (geis_device_bag_new): new function (geis_device_bag_delete): new function (geis_device_bag_count): new function (geis_device_bag_device): new function (geis_device_bag_insert): new function (geis_device_bag_remove): new function * libgeis/geis_device.c: implemented new functions * testsuite/libgeis/check_device.c: new test suite * testsuite/libgeis/Makefile.am: added new test suite * testsuite/libgeis/check_geis2_internals.c: added new test suite 2010-12-20 Stephen M. Webb Added GEIS v2.0 input device API * libgeis/geis_device.c: new file * libgeis/geis_device.h: new file * testsuite/geis2/check_device.c: new test suite * include/geis/geis.h (GeisDevice): new type (geis_register_device_callback): new function (geis_device_ref): new function (geis_device_unref): new function (geis_device_name): new function (geis_device_id): new function (geis_device_attr_count): new function (geis_device_attr): new function * libgeis/Makefile.am: added new files * libgeis/libgeis.ver: added new API symbols * testsuite/geis2/Makefile.am: added new test suite * testsuite/geis2/check_geis2_api.c: added new test suite 2010-12-20 Stephen M. Webb Updates to match new GEIS v2.0 spec release of 2010.12.20. - added a pointer type to the GEIS attr module - added additional required GEIS initialization arguments - event type enumarant name changes * testsuite/geis2/check_attr.c: new test suite * testsuite/geis2/check_event.c: new test suite * include/geis/geis.h (GEIS_INIT_TRACK_DEVICES): new init arg (GEIS_INIT_TRACK_GESTURE_TYPES): new init arg (GeisAttrType): added GEIS_ATTR_TYPE_POINTER enumerant (geis_attr_value_to_pointer): new function (GeisEventType): added new enumerants * libgeis-xcb/geis/geisimpl.h: added GeisPointer type * libgeis/Makefile.am: added libgeis-xcb to header search path * libgeis/libgeis.ver (geis_attr_value_to_pointer): new symbol * testsuite/geis2/Makefile.am: added new test suites * testsuite/geis2/check_geis2_api.c: added new test suites * testsuite/geis2/check_geis_new.c: added new test case for init args * testsuite/geis2/check_general_types.c: added new test case fo GeisPointer * testsuite/geistest/Makefile.am: added libgeis-xcb to header search path * testsuite/libgeis/Makefile.am: same * testsuite/libgeis/check_event_queue.c: changed name of event types * testsuite/libgeis/check_geis_private.c: changed name of event types 2010-12-15 Stephen M. Webb Added GEIS v2.0 region module. * libgeis/geis_region.c: new file * libgeis/geis_region.h: new file * testsuite/geis2/check_region.c: new test suite * testsuite/libgeis/check_region.c: new test suite * include/geis/geis.h (GeisRegion): new typedef (GEIS_REGION_X11_ROOT): new region initialization constant (GEIS_REGION_X11_WINDOWID): new region initialization constant (geis_region_new): new function (geis_region_delete): new function (geis_region_name): new function * libgeis/Makefile.am: added new files * libgeis/libgeis.ver: added new symbols * testsuite/geis2/Makefile.am: added new test suite files * testsuite/geis2/check_geis2_api.c: added new test suite * testsuite/libgeis/Makefile.am: added new test suite files * testsuite/libgeis/check_geis2_internals.c: added new test suite 2010-12-12 Stephen M. Webb Fixed some container expansion errors. * libgeis/geis_attr.c (geis_attr_bag_insert): fixed realloc size * libgeis/geis_subscription.c (geis_subscription_bag_insert): fixed realloc size, cleared newly realloc'd memory * testsuite/libgeis/check_attr.c (expansion): new check * testsuite/libgeis/check_subscription.c (expansion): new check 2010-12-12 Stephen M. Webb Added GEIS v2.0 subscription activation calls. * include/geis/geis.h (geis_subscription_activate): new function (geis_subscription_deactivate): new function * libgeis/geis_subscription.c: implemented above new functions * libgeis/geis_backend.h (geis_backend_subscribe) new function (geis_backend_unsubscribe): new function * libgeis/geis_backend.c: implemented above new functions * libgeis/geis_backend_protected.h (GeisBackendVtable): added new subscribe and unsubscribe function pointers * libgeis/geis_backend_test_fixture.c (_subscribe): new vfunction (_unsubscribe): new vfunction * libgeis/geis_private.h (geis_activate_subscription): new function (geis_deactivate_subscription): new function * libgeis/geis.c: implemented above new functions * libgeis/geis_subscription.h: fixed a typo in a prototype * libgeis/libgeis.ver: added new GEIS v2.0 symbols * testsuite/geis2/check_subscription.c: new test cases 2010-12-12 Stephen M. Webb Added forwarding functions so back ends can multiplex file descriptors through the API. * libgeis/geis_private.h (geis_multiplex_fd): new function (geis_demultiplex_fd): new function * libgeis/geis.c: implemented above new functions * testsuite/libgeis/check_geis_private.c: renamed from check_backend_event_posting.c (multiplex_fd): new test case * testsuite/libgeis/Makefile.am: renamed above file * testsuite/libgeis/check_backend_multiplexor.c: removed debug message silenced build warnings 2010-12-08 Stephen M. Webb Refactored event queue style. * libgeis/geis_event_queue.h (geis_event_queue_enqueue): renamed from geis_event_queue_push (geis_event_queue_dequeue): renamed from geis_event_queue_pop changed event output parameter to return value * libgeis/geis_event_queue.c: refactored for above * libgeis/geis.c: refactored for above * testsuite/libgeis/check_event_queue.c: refactored for above 2010-12-08 Stephen M. Webb Added an event queue. * libgeis/geis_event.c: new file * libgeis/geis_event.h: new file * libgeis/geis_event_queue.c: new file * libgeis/geis_event_queue.h: new file * testsuite/libgeis/check_backend_event_posting.c: new test case * testsuite/libgeis/check_event_queue.c: new test case * include/geis/geis.h (GeisEventType): new enum type (geis_event_delete): new function (geis_event_type): new function (geis_event_attr_count): new function (geis_event_attr): new function (geis_event_attr_by_name): new function * libgeis/Makefile.am: added new files * libgeis/geis.c (struct _Geis): added input_event_queue, output_event_queue, and input_signal_pipe members (_default_output_event_callback): new function (_input_event_handler): new function (geis_new_empty): initialized new members (geis_register_event_callback): used _default_output_event_callback (geis_next_event): implemented stubbed-out function * testsuite/libgeis/Makefile.am: added new test cases * testsuite/libgeis/check_geis2_internals.c: added new test cases 2010-12-02 Stephen M. Webb Added GEIS v2.0 event control functions. * include/geis/geis.h (GeisEvent): new type (GeisEventCallback): new type (GEIS_DEFAULT_EVENT_CALLBACK): new constant (geis_register_event_callback): new function (geis_dispatch_events): new function (geis_next_event): new function * libgeis/geis_private.h (geis_post_event): new function * libgeis/geis.c: implemented new functions * libgeis/libgeis.ver: added new symbols 2010-12-02 Stephen M. Webb Added a back end base and test fixture. * libgeis/geis_backend.c: new file * libgeis/geis_backend.h: new file * libgeis/geis_backend_protected.h: new file * libgeis/geis_backend_test_fixture.c: new file * libgeis/geis_backend_test_fixture.h: new file * include/geis/geis.h (GEIS_INIT_SERVICE_PROVIDER): changed constant value (GEIS_INIT_MOCK_ENGINE): added new constant * libgeis/Makefile.am: added new files * libgeis/geis.c (struct _Geis): replaced is_test_fixture with backend (geis_set_valist): created new test fixture backend (geis_delete): destroyed backend * testsuite/geis2/check_config.c: used new name for test fixture back end * testsuite/geis2/check_geis_new.c: same * testsuite/geis2/check_subscription.c: idem * testsuite/libgeis/check_subscription.c: ditto 2010-12-02 Stephen M. Webb Added a back end multiplexor. * libgeis/geis_backend_multiplexor.c: new file * libgeis/geis_backend_multiplexor.h: new file * testsuite/libgeis/check_backend_multiplexor.c: new testsuite * include/geis/geis.h (GeisStatus): added new status codes GEIS_STATUS_CONTINUE and GEIS_STATUS_EMPTY (GEIS_CONFIG_MAX_EVENTS): new configuration item * libgeis/Makefile.am: added new files * libgeis/geis.c (struct _Geis): added backend_multiplexor field (geis_new_empty): initialized it (geis_delete): destroyed it (geis_get_configuration): retrieved its file descriptor and config value (geis_set_configuration): set its configuration value * testsuite/geis2/check_error_codes.c: checked new status codes * testsuite/libgeis/Makefile.am * testsuite/libgeis/check_geis2_internals.c 2010-11-29 Stephen M. Webb Refactored geis_private.h to provide improved data encapsulation. * libgeis/geis_private.h (struct _Geis): moved to geis.c (geis_error_stack): new function * libgeis/geis.c: implemented new function * libgeis/geis_error.c: used new function 2010-11-29 Stephen M. Webb Fixed a typo in the Doxygen comments in geis.h. * include/geis/geis.h: fixed typo in documentation 2010-11-28 Stephen M. Webb Added Geis Subscription creation and accessors. * libgeis/geis_subscription.c: new file * libgeis/geis_subscription.h: new file * testsuite/geis2/check_subscription.c: new API test suite * testsuite/libgeis/check_subscription.c: new internals test suite * include/geis/geis.h (GeisFilter): new type (GeisSubscription): new type (GeisSubscriptionFlags): new type (geis_subscription_new): new function (geis_subscription_delete): new function (geis_subscription_name): new function (geis_subscription_id): new function (geis_subscription_add_filter): new function (geis_subscription_remove_filter): new function * libgeis/Makefile.am: added new files * libgeis/geis_private.h (geis_subscription_bag): new function (struct _Geis): added subscription_bag field * libgeis/geis.c (geis_subscription_bag): implemented it (geis_new_empty): created an empty subscription bag * libgeis/libgeis.ver: added new geis_subscription_* symbols * testsuite/geis2/Makefile.am: added new test suite source * testsuite/geis2/check_geis2_api.c: added new test suite * testsuite/libgeis/Makefile.am: added new test suite source * testsuite/libgeis/check_geis2_internals.c: added new test suite 2010-11-26 Stephen M. Webb Added Geis Attr functions. * libgeis/geis_attr.c: new file * libgeis/geis_attr.h: new file * testsuite/libgeis/check_attr.c: new unit test suite * include/geis/geis.h (GeisAttr): new type (geis_attr_name): new function (geis_attr_type): new function (geis_attr_value_to_boolean): new function (geis_attr_value_to_float): new function (geis_attr_value_to_integer): new function (geis_attr_value_to_string): new function * libgeis/Makefile.am: added new files * libgeis/libgeis.ver: added new symbols * testsuite/libgeis/Makefile.am: added new test suite * testsuite/libgeis/check_error_reporting.c: renamed test suite * testsuite/libgeis/check_geis2_internals.c: added new test suite 2010-11-24 Stephen M. Webb Added Geis configuration functions. * include/geis/geis.h (geis_get_config): new function (geis_set_config): new function * libgeis/geis.c: added stubs for new functions * libgeis/libgeis.ver: added symbols for new functions * testsuite/geis2/check_config.c: new test suite for new functions * testsuite/geis2/Makefile.am: added above new file 2010-11-24 Stephen M. Webb Added silent rules to build. * configure.ac (AM_INIT_AUTOMAKE): required minimum version 1.11 (AM_SILENT_RULES): new macros to set silent build rules on by default 2010-11-24 Stephen M. Webb Fixed a "make distcheck" problem. * testsuite/libgeis/Makefile.am (check_geis2_internals_CFLAGS): added $(top_srcdir) to the header search path 2010-11-24 Stephen M. Webb Added unit testing for GEIS v2.0 internals. * testsuite/libgeis: new subdirectory * testsuite/libgeis/Makefile.am: new file * testsuite/libgeis/check_error_reporting.c: new file * testsuite/libgeis/check_geis2_internals.c: new file * configure.ac (AC_OUTPUT): added new Makefile * testsuite/Makefile.am (SUBDIRS): added new subdirectory * testsuite/geis1/check_geis_internals.c: renamed test suite * testsuite/geis2/check_geis2_api.c: renamed test suite 2010-11-23 Stephen M. Webb Added Error Reporting functions. * libgeis/geis_error.c: new file * libgeis/geis_error.h: new file * libgeis/geis_private.h: new file * include/geis/geis.h (geis_error_count): new function (geis_error_code): new function (geis_error_message): new function * libgeis/Makefile.am: added new files * libgeis/geis.c: used new functions * libgeis/libgeis.ver: added new function symbols 2010-11-23 Stephen M. Webb Added diagnostics to geis_new(). * libgeis/geis.c (geis_error): reported calloc failure (geis_set_valist): added debug diagnostics for init args 2010-11-23 Stephen M. Webb Moved diagnostic logging from GEIS v1.0 to GEIS v2.0 libraries. * libgeis/geis_logging.h: renamed from libgeis-xcb/geis_logging.h * libgeis/geis_logging.c: renamed from libgeis-xcb/geis_logging.c * libgeis-xcb/Makefile.am: removed above renamed files * libgeis/Makefile.am: added above renamed files * testsuite/geis1/Makefile.am: changed library path * testsuite/geistest/Makefile.am: changed library path 2010-11-23 Stephen M. Webb Merged GEIS v1.0 into GEIS v2.0 library for backwards compatibility. * libgeis-xcb/libgeis-xcb.ver: removed * libgeis-xcb/Makefile.am: converted to build a convenience lib * libgeis/Makefile.am: added libgeis-xcb as a conveniemnce lib * libgeis/libgeis.ver: Added GEIS v1.0 symbols * testsuite/geis2/Makefile.am: fixed path to shared library in build tree 2010-11-22 Stephen M. Webb Refactored API initialization to use variadic arguments a la spec change. * include/geis/geis.h (geis_new): changed function prototype * libgeis/geis.c (geis_new_empty): new function (geis_set_valist): new function (geis_new): changed parameters, used new functions * testsuite/geis2/check_geis_new.c (geis_new_and_delete): changed geis_new() arguments 2010-11-22 Stephen M. Webb Fixed visibility of new GEIS 2.0 symbols. * include/geis/geis.h (geis_new): fixed visibility (geis_delete): same 2010-11-22 Stephen M. Webb Made geis2_geis_new test case pass. * libgeis/geis.c (geis_hints_find_by_id): new static function (geis_hints_append): new static function (geis_new): used them, malloc'd struct _Geis (geis_delete): free'd struct _Geis 2010-11-22 Stephen M. Webb Added test case for GEIS v2.0 geis_new() and geis_delete() functions, together with a skeletal implementation of the libgeis v2.0 library. * libgeis: new source directory * libgeis/Makefile.am: new build recipe for libgeis v2.0 * libgeis/geis.c: new source file * libgeis/libgeis.ver: new library version map * testsuite/geis2/check_geis_new.c: new test suite * Makefile.am (SUBDIRS): added libgeis * configure.ac (AC_OUTPUT): added libgeis/Makefile * include/geis/geis.h (GeisHints): new data structure (Geis): new opaque data structure (geis_new): new function (geis_delete): new function * testsuite/geis2/Makefile.am (check_geis2_api_SOURCES): added check_geis_new * testsuite/geis2/check_geis2_api.c (main): added geis_new_suite 2010-11-21 Stephen M. Webb Added test case for geis v2.0 error codes. * include/geis/geis.h: added required v2.0 error codes * testsuite/geis2/check_error_codes.c: new test case * testsuite/geis2/Makefile.am: added new test case * testsuite/geis2/check_geis2_api.c: same 2010-11-20 Stephen M. Webb Added test case for geis v2.0 basic types. * testsuite/geis2/check_general_types.c: new file * testsuite/geis2/Makefile.am: added above new file * testsuite/geis2/check_geis2_api.c (geis2_general_types_suite_new): added new unit test 2010-11-19 Stephen M. Webb Added geis v2.0 test hardness and version macro test. * include/geis/geis.h (GEIS_VERSION_2_0): added macro * testsuite/geis2/check_geis_api.c: new testsuite. * testsuite/geis2/check_version_macro.c: added unit test for geis 2.0 version macro * testsuite/geis2/Makefile: new file * configure.ac (AC_OUTPUT): added above enw file * testsuite/Makefile: added new testsuite directory geis2 2010-11-12 Stephen M. Webb Made existing unit test directory specific to geis v1.0. * testsuite/geis1: renamed from testsuite/check * configure.ac: renamed testsuite/check * testsuite/Makefile.am: same * testsuite/geis1/Makefile.am: same 2010-10-20 Stephen M. Webb Added unit tests for internal geis_instance_table. * testsuite/check/check_instance_table.c: new file * testsuite/check/Makefile.am (check_geis_internals_SOURCES): added it (MOSTLYCLEANFILES): new target to clean up unit test logs * testsuite/check/check_geis_internals.c (main): added unit test suite 2010-10-20 Stephen M. Webb Added unit test infrastructure based on 'check'. * testsuite/check/Makefile.am: new file * testsuite/check/check_geis_internals.c: new file * testsuite/Makefile.am (SUBDIRS): added check target * configure.ac: added new stanza for detecting check package (AC_CONFIG_FILES): added testsuite/check/Makefile 2010-10-18 Stephen M. Webb Added configury check for xcb-proto package >= 1.6 (LP: #661946). * configure.ac: added PKG_CHECK_MODULES for xcb-proto >= 1.6 2010-10-14 Stephen M. Webb Release version 1.0.13. * configure.ac (AC_INIT): bumped package version to 1.0.13 2010-10-12 Stephen M. Webb Removed extra newlines from diagnostic messages * libgeis-xcb/geis_xcb.c: removed newline from several diagnostic messages. 2010-10-07 Stephen M. Webb Fixed LP: #656503 - event dispatch can hang under some circumstances * libgeis-xcb/geis_xcb.c (geis_xcb_dispatch): changed loop condition * libgeis-xcb/Makefile.am (libgeis_la_LDFLAGS): bumped library revision 2010-09-28 Stephen M. Webb Version bump to 1.0.12. * configure.ac (AC_INIT): bumped package version to 1.0.12 2010-09-28 Stephen M. Webb Made lib compatible with C++. * geis/geis.h: forced C linkage 2010-09-14 Stephen M. Webb Version bump tp 1.0.11 * configure.ac: bumped package version to 1.0.11 * libgeis-xcb/Makefile.am: bumped shlib version to reflect changes 2010-09-01 Stephen M. Webb Fixed typos in manpage. * doc/geistest.1: fixed several typographical errors 2010-09-01 Stephen M. Webb Fixed a memory leak when logging messages. * libgeis-xcb/geis_logging.c (_geis_message): fixed memory leak 2010-08-31 Stephen M. Webb Fixed prefix string used in diagnostics. * libgeis-xcb/geis_logging.c (_geis_message): fixed which prefix string gets used for which diagnostic level 2010-08-31 Stephen M. Webb Removed input device enumeration handling until later. * libgeis-xcb/geis.c (geis_input_devices): removed #if 0 block * libgeis-xcb/geis_instance.h (geis_instance_input_devices): removed * libgeis-xcb/geis_instance.c (geis_instance_input_devices): removed * libgeis-xcb/geis_xcb.h (geis_xcb_input_devices): added funcs and cookie parameters * libgeis-xcb/geis_xcb.c (_GeisXcb): added input_funcs and input_cookie (geis_xcb_new): removed #if 0 blocks (geis_xcb_input_devices): removed XInput handling until later 2010-08-30 Stephen M. Webb Removed some debug code and fixed pasto. * libgeis-xcb/geis_instance.c: fixed a pasto * testsuite/geistest/geistest.c: removed debug code 2010-08-30 Stephen M. Webb Fixed so multiple windows will work. Altered geistest to work with a single window or all windows, had to fix geis implementation so this was possible. * libgeis-xcb/geis_instance_table.c: new file * libgeis-xcb/geis_instance_table.h: new file * configure.ac: added package checks for x11-xcb and xi * doc/geistest.1: documented new CLI switches * geis/geis.h (geis_input_devices): fixed argument type * libgeis-xcb/Makefile.am (libgeis_la_SOURCES): added new files (libgeis_la_CFLAGS): aded X11XCB_CFLAGS and XI2_CFLAGS (libgeis_la_LIBADD): aded X11XCB_LIBS and XI2LIBS_ * libgeis-xcb/geis.c (s_geis_xcb): new static global (geis_init): used it * libgeis-xcb/geis_instance.h (_GeisInstance): added window_id (geis_instance_new): renamed from geis_instance_get (geis_instance_input_devices): new function (geis_instance_subscribe): added GeisXcb parameter (geis_instance_get_window_id): new function (geis_instance_fd): removed function (geis_instance_event_dispatch): removed function * libgeis-xcb/geis_instance.c: implemented new functions * libgeis-xcb/geis_xcb.h (geis_xcb_new): renamed from geis_xcb_get (geis_xcb_create_instance): new function (geis_xcb_input_devices): new function (geis_xcb_subscribe): added GeisInstance parameter (geis_xcb_dispatch): changed parameter type to GeisXcb * libgeis-xcb/geis_xcb.c: Implemeneted new functions * testsuite/geistest/geistest.c (parse_opts): added -w switch (subscribe_window): new function (subscribe_windows_preorder): new function (subscribe_all_windows): new function (main): used the new functions 2010-08-30 Stephen M. Webb Added runtime diagnostic facility. * libgeis-xcb/geis_debug.h: replaced with * libgeis-xcb/geis_logging.h: mew file * libgeis-xcb/geis_logging.c: new file * libgeis-xcb/Makefile.am: replaced above files * libgeis-xcb/geis_xcb.c: replaced geis_debug calls with geis_warning or geis_error as appropriate 2010-08-27 Stephen M. Webb Fixed checking of gesture masks for multiple input devices. * libgeis-xcb/geis_instance.c (geis_instance_subscribe): added missing index increment * libgeis-xcb/geis_xcb.c (geis_xcb_verify_event_selection): added logic for iterating through multiple input devices 2010-08-27 Stephen M. Webb Move gesture-type-added callback until later in the subscription sequence. * libgeis-xcb/geis_xcb.c (geis_xcb_subscribe): move call to geis_xcb_dispatch_gesture_type until later in sequence 2010-08-27 Stephen M. Webb Removed "Grab" gestire entirely from the list of known gestures. * libgeis-xcb/geis_xcb.c (s_grail_type_map): removed GRAIL_TYPE_SYSFLAG1 (geis_xcb_dispatch_gesture_type): removed references to GRAIL_TYPE_SYSFLAG1 2010-08-26 Stephen M. Webb Prevented "Grab" gesture from being propagated. * libgeis-xcb/geis_xcb.c (geis_xcb_dispatch_gesture_type): skipped notification of the availability of the "Grab" gesture type. 2010-08-26 Stephen M. Webb Fixed an allocation size issue. * libgeis-xcb/geis_instance.c (geis_instance_get): fixed allocation size issue 2010-08-26 Stephen M. Webb Minor style adjustments. Adjusted whitespace for consistency. * libgeis-xcb/geis_xcb.c (geis_xcb_verify_event_selection): renamed function from geis_xcb_select_events (geis_xcb_determine_primitive_type): renamed from geis_xcb_determine_fundamental_gesture_type (geis_xcb_get_gesture_type_primitive_name): renamed form geis_xcb_get_gesture_type_fundamental_name 2010-08-25 Stephen M. Webb Reverted version bump. * configure,.ac (AC_INIT): reverted to version 1.0.10 2010-08-23 Stephen M. Webb Implemented gesture and input device selection. * geis/geis.h: new gesture definitions * libgeis-xcb/geis_xcb.h (geis_xcb_subscribe): added device_id parameter * libgeis-xcb/geis_xcb.c (s_grail_type_map): new gesture definitions (geis_xcb_map_gestures_to_mask): new function (geis_xcb_select_events): new function (geis_xcb_subscribe): used them added device_id parameter (geis_xcb_determine_gesture_type): renamed to geis_xcb_determine_fundamental_gesture_type (geis_xcb_get_gesture_type_fundamental_name): new function (geis_xcb_dispatch_gesture_type): mapped public gesture definitions to fundamental gesture types * libgeis-xcb/geis_instance.c (geis_instance_subscribe): handled input_list argument * testsuite/geistest/geistest.c: included an example of selecting gestures 2010-08-22 Chase Douglas Bumped to version 1.0.10 for various fixes * geisimple.h: Define the correct number of attributes for each gesture * geis.h: Sync up with latest grail ABI for gesture attributes * geis_xcb.c: Sync up with latest grail ABI for gesture attributes * geisspec-1.0.asc: Sync up with latest grail ABI for gesture attributes * geis_instance.h: Fix header include macro typo * geisimple.h: Use int32_t instead of long for integer values * geis.h: Make win_type unsigned to match usage in code * geis_xcb.c: Fix missing initializer value issue * geis_xcb.c: Fix unused variable warning 2010-08-20 Stephen M. Webb Removed spec build from packaged files. * doc/Makefile.am (doc-html): removed doc-html-asciidoc 2010-08-16 Stephen M. Webb Conformed to GNU strictness for consistency. * AUTHORS: New file. * COPYING: new file renamed from COPYING.LGPL. * INSTALL: New file. * NEWS: New file. * README: New file. * Makefile.am: distributed the new files. * configure.ac: Swicthed from foreign to gnu conformance level. * libgeis-xcb/Makefile.am: Fixed relative paths. 2010-08-16 Stephen M. Webb Bumped version to 1.0.9 to replect API change. * configure.ac: bumped package version. 2010-08-16 Stephen M. Webb Added standard fundamental gesture constants. * doc/geisspec-1.0.asc: Added section on fundamental gestures. * geis/geis.h: Added fundamental gestures and attributes. * libgeis-xcb/geis_xcb.c: Used them.