/**
 * @file xklavier.h
 */

#ifndef __XKLAVIER_H__
#define __XKLAVIER_H__

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * XKB state. Can be global or per-window
 */
  typedef struct
  {
/** selected group */
    int group;
/** set of active indicators */
    unsigned indicators;
  }
  XklState;

/**
 * @defgroup initterm Library initialization and termination
 * @{
 */

/**
 * Initializes internal structures. Does not start actual listening though.
 * Some apps can use Xklavier for information retrieval but not for actual
 * processing.
 * @param dpy is an open display, will be tested for XKB extension
 * @return 0 if OK, otherwise last X error
 */
  extern int XklInit( Display * dpy );

/**
 * Terminates everything...
 */
  extern int XklTerm( void );

/** @} */

/**
 * @defgroup xkbevents XKB event handling and management
 * @{
 */

/**
 * Starts listening for XKB-related events
 * @return 0
 */
  extern int XklStartListen( void );

/**
 * Stops listening for XKB-related events
 * @return 0
 */
  extern int XklStopListen( void );

/**
 * Temporary pauses listening for XKB-related events
 * @return 0
 */
  extern int XklPauseListen( void );

/**
 * Resumes listening for XKB-related events
 * @return 0
 */
  extern int XklResumeListen( void );

/**
 * Grabs some key
 * @param key is a keysym
 * @param modifiers is a bitmask of modifiers
 * @return True on success
 */
  extern Bool XklGrabKey( int key, unsigned modifiers );

/**
 * Ungrabs some key
 * @param key is a keysym
 * @param modifiers is a bitmask of modifiers
 * @return True on success
 */
  extern Bool XklUngrabKey( int key, unsigned modifiers );

/**
 * Processes X events. Should be included into the main event cycle of an
 * application. One of the most important functions. 
 * @param evt is delivered X event
 * @return 0
 * @see XklStartListen
 */
  extern int XklFilterEvents( XEvent * evt );

/** @} */

/**
 * @defgroup currents Current state of the library
 * @{
 */

/**
 * @return currently focused window
 */
  extern Window XklGetCurrentWindow( void );

/**
 * @return current state of the keyboard (in XKB terms). 
 * Returned value is a statically allocated buffer, should not be freed.
 */
  extern XklState *XklGetCurrentState( void );

/** @} */

/**
 * @defgroup wininfo Per-window information
 * @{
 */

/**
 * @return the window title of some window or NULL. 
 * If not NULL, it should be freed with XFree
 */
  extern char *XklGetWindowTitle( Window w );

/** 
 * Finds the state for a given window (for its "App window").
 * @param win is a target window
 * @param state_return is a structure to store the state
 * @return True on success, otherwise False 
 * (the error message can be obtained using XklGetLastError).
 */
  extern Bool XklGetState( Window win, XklState * state_return );

/**
 * Drops the state of a given window (of its "App window").
 * @param win is a target window
 */
  extern void XklDelState( Window win );

/** 
 * Stores ths state for a given window
 * @param win is a target window
 * @param state is a new state of the window
 */
  extern void XklSaveState( Window win, XklState * state );

/**
 * Checks whether 2 windows have the same App Window
 * @param win1 is first window
 * @param win2 is second window
 * @return True is windows are in the same application
 */
  extern Bool XklIsSameApp( Window win1, Window win2 );

/** @} */

/**
 * @defgroup xkbinfo Various XKB configuration info
 * @{
 */

/**
 * @return the total number of groups in the current XKB configuration 
 * (keyboard)
 */
  extern unsigned XklGetNumGroups( void );

/**
 * @return the array of group names for the current XKB configuration 
 * (keyboard).
 * This array is static, should not be freed
 */
  extern const char **XklGetGroupNames( void );

/**
 * @return the array of indicator names for the current XKB configuration 
 * (keyboard).
 * This array is static, should not be freed
 */
  extern const char **XklGetIndicatorNames( void );

/** @} */

/**
 * @defgroup xkbgroup XKB group calculation and change
 * @{
 */

/**
 * Calculates next group id. Does not change the state of anything.
 * @return next group id
 */
  extern int XklGetNextGroup( void );

/**
 * Calculates prev group id. Does not change the state of anything.
 * @return prev group id
 */
  extern int XklGetPrevGroup( void );

/**
 * @return saved group id of the current client. 
 * Does not change the state of anything.
 */
  extern int XklGetRestoreGroup( void );

/**
 * Locks the group. Can be used after XklGetXXXGroup functions
 * @param group is a group number for locking
 * @see XklGetNextGroup
 * @see XklGetPrevGroup
 * @see XklGetRestoreGroup
 */
  extern void XklLockGroup( int group );

/** @} */

/**
 * @defgroup callbacks Application callbacks support
 * @{
 */

/**
 * Used for notifying application of the XKB configuration change.
 * @param userData is anything which can be stored into the pointer
 * @see XklRegisterConfigCallback
 */
  typedef void ( *ConfigCallback ) ( void *userData );

/**
 * Registers user callback. Only one callback can be registered at a time
 * @param fun is the function to call
 * @param userData is the data to pass
 * @see ConfigCallback
 */
  extern int XklRegisterConfigCallback( ConfigCallback fun, void *userData );

/**
 * Used for notifying application of new window creation (actually, 
 * registration).
 * @param win is a new window
 * @param parent is a new window's parent
 * @param userData is anything which can be stored into the pointer
 * @see XklRegisterConfigCallback
 */
  typedef void ( *WinCallback ) ( Window win, Window parent, void *userData );

/**
 * Registers user callback. Only one callback can be registered at a time
 * @param fun is the function to call
 * @param userData is the data to pass
 * @see WindowCallback
 */
  extern int XklRegisterWindowCallback( WinCallback fun, void *userData );

/**
 * Used for notifying application of the window state change.
 * @param win is a window
 * @param restore is indicator of whether this state is restored from
 * saved state of set as new.
 * @param userData is anything which can be stored into the pointer
 * @see XklRegisterConfigCallback
 */
  typedef void ( *StateCallback ) ( int group, Bool restore, void *userData );

/**
 * Registers user callback. Only one callback can be registered at a time
 * @param fun is the function to call
 * @param userData is the data to pass
 * @see StateCallback
 */
  extern int XklRegisterStateCallback( StateCallback fun, void *userData );

/** @} */

/**
 * @defgroup settings Settings for event processing
 * @{
 */

/**
 * Sets the configuration parameter: layout per application
 * @param isGlobal is a new parameter value
 */
  extern void XklSetLayoutPerApp( Bool isGlobal );

/**
 *  @return the value of the parameter: layout per application
 */
  extern Bool XklIsLayoutPerApp( void );

/**
 * Sets the configuration parameter: perform indicators handling
 * @param whetherHandle is a new parameter value
 */
  extern void XklSetIndicatorsHandling( Bool whetherHandle );

/**
 *  @return the value of the parameter: perform indicator handling
 */
  extern Bool XklGetIndicatorsHandling( void );

/** @} */

/**
 * @defgroup debugerr Debugging, error processing 
 * @{
 */

/**
 * @return the text message (statically allocated) of the last error
 */
  extern const char *XklGetLastError( void );

/**
 * Output (optionally) some debug info
 * @param file is the name of the source file. 
 * Preprocessor symbol__FILE__ should be used here
 * @param function is a name of the function
 * Preprocessor symbol__func__ should be used here
 * @param level is a level of the message
 * @param format is a format (like in printf)
 * @see XklDebug
 */
  extern void _XklDebug( const char file[], const char function[], int level,
                         const char format[], ... );

/**
 * Sets maximum debug level. 
 * Message of the level more than the one set here - will be ignored
 * @param level is a new debug level
 */
  extern void XklSetDebugLevel( int level );

/**
 * Output (optionally) some debug info
 * @param level is a level of the message
 * @param format is a format (like in printf)
 * @see _XklDebug
 */
#define XklDebug( level, format, args... ) \
  _XklDebug( __FILE__, __func__, level, format, ## args )

/** @} */

#ifdef __cplusplus
}
#endif                          /* __cplusplus */

#endif
