summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Udaltsov <svu@gnome.org>2006-03-27 23:54:22 +0000
committerSergey Udaltsov <svu@gnome.org>2006-03-27 23:54:22 +0000
commitd8339126d5036eb7751b97207afed1eabbd5114c (patch)
treed0962fd9ff1f3fdfb30ce4c1bd505e239caa4102
parent07e9909c131b67bc72db39411c29a268a15d9699 (diff)
downloadlibxklavier-d8339126d5036eb7751b97207afed1eabbd5114c.tar.gz
making xkb config load more robust
-rw-r--r--ChangeLog5
-rw-r--r--libxklavier/xklavier.c1404
-rw-r--r--libxklavier/xklavier_config_xkb.c796
-rw-r--r--libxklavier/xklavier_evt.c957
-rw-r--r--libxklavier/xklavier_private.h644
5 files changed, 1769 insertions, 2037 deletions
diff --git a/ChangeLog b/ChangeLog
index 1231054..7156654 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-02-28 svu
+
+ * libxklavier/xklavier_config_xkb.c: libxklavier/xklavier_evt.c:
+ making XKB configuration loading more robust (ignoring ALL xkb errors)
+
2006-02-16 svu
* libxklavier/xklavier_evt_xmm.c: fixing GCC 2.95 compilation,
diff --git a/libxklavier/xklavier.c b/libxklavier/xklavier.c
index d20c873..033b0a1 100644
--- a/libxklavier/xklavier.c
+++ b/libxklavier/xklavier.c
@@ -1,880 +1,862 @@
-#include <string.h>
#include <time.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/Xmd.h>
+#include <X11/Xlibint.h>
#include "xklavier_private.h"
-#include "xkl_engine_marshal.h"
-static GObjectClass *parent_class = NULL;
+Display *_xklDpy;
-static XklEngine *the_engine = NULL;
+XklState _xklCurState;
-gint xkl_debug_level = 0;
+Window _xklCurClient;
-static XklLogAppender log_appender = xkl_default_log_appender;
+Status _xklLastErrorCode;
-const gchar *xkl_last_error_message;
+const char *_xklLastErrorMsg;
-enum {
- PROP_0,
- PROP_DISPLAY,
- PROP_BACKEND_NAME,
- PROP_FEATURES,
- PROP_MAX_NUM_GROUPS,
- PROP_NUM_GROUPS,
- PROP_DEFAULT_GROUP,
- PROP_SECONDARY_GROUPS_MASK,
- PROP_INDICATORS_HANDLING,
-};
+XErrorHandler _xklDefaultErrHandler;
-void
-xkl_engine_set_indicators_handling(XklEngine * engine,
- gboolean whether_handle)
+Atom _xklAtoms[TOTAL_ATOMS];
+
+Window _xklRootWindow;
+
+int _xklDefaultGroup;
+
+Bool _xklSkipOneRestore;
+
+int _xklSecondaryGroupsMask;
+
+int _xklDebugLevel = 0;
+
+Window _xklPrevAppWindow;
+
+int _xklListenerType = 0;
+
+XklVTable *xklVTable = NULL;
+
+XklConfigCallback _xklConfigCallback = NULL;
+void *_xklConfigCallbackData;
+
+Bool _xklCriticalSection = False;
+
+static XklStateCallback stateCallback = NULL;
+static void *stateCallbackData;
+
+static XklWinCallback winCallback = NULL;
+static void *winCallbackData;
+
+static XklLogAppender logAppender = XklDefaultLogAppender;
+
+static Bool groupPerApp = True;
+
+static Bool handleIndicators = False;
+
+
+void XklSetIndicatorsHandling( Bool whetherHandle )
{
- xkl_engine_priv(engine, handle_indicators) = whether_handle;
+ handleIndicators = whetherHandle;
}
-gboolean
-xkl_engine_get_indicators_handling(XklEngine * engine)
+Bool XklGetIndicatorsHandling( void )
{
- return xkl_engine_priv(engine, handle_indicators);
+ return handleIndicators;
}
-void
-xkl_set_debug_level(int level)
+void XklSetDebugLevel( int level )
{
- xkl_debug_level = level;
+ _xklDebugLevel = level;
}
-void
-xkl_engine_set_group_per_toplevel_window(XklEngine * engine,
- gboolean is_set)
+void XklSetGroupPerApp( Bool isSet )
{
- xkl_engine_priv(engine, group_per_toplevel_window) = is_set;
+ groupPerApp = isSet;
}
-gboolean
-xkl_engine_is_group_per_toplevel_window(XklEngine * engine)
+Bool XklIsGroupPerApp( void )
{
- return xkl_engine_priv(engine, group_per_toplevel_window);
+ return groupPerApp;
}
-static void
-xkl_engine_set_switch_to_secondary_group(XklEngine * engine, gboolean val)
+static void _XklSetSwitchToSecondaryGroup( Bool val )
{
- CARD32 propval = (CARD32) val;
- Display *dpy = xkl_engine_get_display(engine);
- XChangeProperty(dpy,
- xkl_engine_priv(engine, root_window),
- xkl_engine_priv(engine,
- atoms)[XKLAVIER_ALLOW_SECONDARY],
- XA_INTEGER, 32, PropModeReplace,
- (unsigned char *) &propval, 1);
- XSync(dpy, False);
+ CARD32 propval = (CARD32)val;
+ XChangeProperty( _xklDpy, _xklRootWindow, _xklAtoms[XKLAVIER_ALLOW_SECONDARY],
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char*)&propval, 1 );
+ XSync( _xklDpy, False );
}
-void
-xkl_engine_allow_one_switch_to_secondary_group(XklEngine * engine)
+void XklAllowOneSwitchToSecondaryGroup( void )
{
- xkl_debug(150,
- "Setting allow_one_switch_to_secondary_group flag\n");
- xkl_engine_set_switch_to_secondary_group(engine, TRUE);
+ XklDebug( 150, "Setting allowOneSwitchToSecondaryGroup flag\n" );
+ _XklSetSwitchToSecondaryGroup( True );
}
-gboolean
-xkl_engine_is_one_switch_to_secondary_group_allowed(XklEngine * engine)
+Bool _XklIsOneSwitchToSecondaryGroupAllowed( void )
{
- gboolean rv = FALSE;
- unsigned char *propval = NULL;
- Atom actual_type;
- int actual_format;
- unsigned long bytes_remaining;
- unsigned long actual_items;
- int result;
+ Bool rv = False;
+ unsigned char *propval = NULL;
+ Atom actualType;
+ int actualFormat;
+ unsigned long bytesRemaining;
+ unsigned long actualItems;
+ int result;
- result =
- XGetWindowProperty(xkl_engine_get_display(engine),
- xkl_engine_priv(engine, root_window),
- xkl_engine_priv(engine, atoms)
- [XKLAVIER_ALLOW_SECONDARY], 0L, 1L, False,
- XA_INTEGER, &actual_type, &actual_format,
- &actual_items, &bytes_remaining, &propval);
+ result = XGetWindowProperty( _xklDpy, _xklRootWindow,
+ _xklAtoms[XKLAVIER_ALLOW_SECONDARY], 0L, 1L,
+ False, XA_INTEGER, &actualType, &actualFormat,
+ &actualItems, &bytesRemaining,
+ &propval );
- if (Success == result) {
- if (actual_format == 32 && actual_items == 1) {
- rv = (gboolean) * (Bool *) propval;
- }
- XFree(propval);
- }
+ if( Success == result )
+ {
+ if( actualFormat == 32 && actualItems == 1 )
+ {
+ rv = *(Bool*)propval;
+ }
+ XFree( propval );
+ }
- return rv;
+ return rv;
}
-void
-xkl_engine_one_switch_to_secondary_group_performed(XklEngine * engine)
+void _XklOneSwitchToSecondaryGroupPerformed( void )
{
- xkl_debug(150,
- "Resetting allow_one_switch_to_secondary_group flag\n");
- xkl_engine_set_switch_to_secondary_group(engine, FALSE);
+ XklDebug( 150, "Resetting allowOneSwitchToSecondaryGroup flag\n" );
+ _XklSetSwitchToSecondaryGroup( False );
}
-void
-xkl_engine_set_default_group(XklEngine * engine, gint group)
+void XklSetDefaultGroup( int group )
{
- xkl_engine_priv(engine, default_group) = group;
+ _xklDefaultGroup = group;
}
-gint
-xkl_engine_get_default_group(XklEngine * engine)
+int XklGetDefaultGroup( void )
{
- return xkl_engine_priv(engine, default_group);
+ return _xklDefaultGroup;
}
-void
-xkl_engine_set_secondary_groups_mask(XklEngine * engine, guint mask)
+void XklSetSecondaryGroupsMask( int mask )
{
- xkl_engine_priv(engine, secondary_groups_mask) = mask;
+ _xklSecondaryGroupsMask = mask;
}
-guint
-xkl_engine_get_secondary_groups_mask(XklEngine * engine)
+int XklGetSecondaryGroupsMask( void )
{
- return xkl_engine_priv(engine, secondary_groups_mask);
+ return _xklSecondaryGroupsMask;
}
-void
-xkl_set_log_appender(XklLogAppender func)
+int XklRegisterConfigCallback( XklConfigCallback fun, void *data )
{
- log_appender = func;
+ _xklConfigCallback = fun;
+ _xklConfigCallbackData = data;
+ return 0;
}
-gint
-xkl_engine_start_listen(XklEngine * engine, guint what)
+int XklRegisterStateCallback( XklStateCallback fun, void *data )
{
- xkl_engine_priv(engine, listener_type) = what;
+ stateCallback = fun;
+ stateCallbackData = data;
+ return 0;
+}
- if (!
- (xkl_engine_priv(engine, features) &
- XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT)
-&& (what & XKLL_MANAGE_LAYOUTS))
- xkl_debug(0,
- "The backend does not require manual layout management - "
- "but it is provided by the application");
+int XklRegisterWindowCallback( XklWinCallback fun, void *data )
+{
+ winCallback = fun;
+ winCallbackData = data;
+ return 0;
+}
- xkl_engine_resume_listen(engine);
- xkl_engine_load_window_tree(engine);
- XFlush(xkl_engine_get_display(engine));
- return 0;
+void XklSetLogAppender( XklLogAppender fun )
+{
+ logAppender = fun;
}
-gint
-xkl_engine_stop_listen(XklEngine * engine)
+int XklStartListen( int what )
{
- xkl_engine_pause_listen(engine);
- return 0;
+ _xklListenerType = what;
+
+ if( !( xklVTable->features & XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT ) &&
+ ( what & XKLL_MANAGE_LAYOUTS ) )
+ XklDebug( 0, "The backend does not require manual layout management - "
+ "but it is provided by the application" );
+
+ XklResumeListen( );
+ _XklLoadWindowTree( );
+ XFlush( _xklDpy );
+ return 0;
}
-XklEngine *
-xkl_engine_get_instance(Display * display)
+int XklStopListen( void )
{
- if (the_engine != NULL) {
- g_object_ref(G_OBJECT(the_engine));
- return the_engine;
- }
+ XklPauseListen( );
+ return 0;
+}
- if (!display) {
- xkl_debug(10, "xkl_init : display is NULL ?\n");
- return NULL;
- }
+int XklInit( Display * a_dpy )
+{
+ int scr;
+ char *sdl;
+ int rv;
- the_engine =
- XKL_ENGINE(g_object_new
- (xkl_engine_get_type(), "display", display, NULL));
+ sdl = getenv( "XKL_DEBUG" );
+ if( sdl != NULL )
+ {
+ XklSetDebugLevel( atoi( sdl ) );
+ }
- return the_engine;
+ if( !a_dpy )
+ {
+ XklDebug( 10, "XklInit : display is NULL ?\n");
+ return -1;
+ }
+
+ _xklDefaultErrHandler =
+ XSetErrorHandler( ( XErrorHandler ) _XklErrHandler );
+
+ _xklDpy = a_dpy;
+ scr = DefaultScreen( _xklDpy );
+ _xklRootWindow = RootWindow( _xklDpy, scr );
+
+ _xklSkipOneRestore = False;
+ _xklDefaultGroup = -1;
+ _xklSecondaryGroupsMask = 0L;
+ _xklPrevAppWindow = 0;
+
+ _xklAtoms[WM_NAME] = XInternAtom( _xklDpy, "WM_NAME", False );
+ _xklAtoms[WM_STATE] = XInternAtom( _xklDpy, "WM_STATE", False );
+ _xklAtoms[XKLAVIER_STATE] = XInternAtom( _xklDpy, "XKLAVIER_STATE", False );
+ _xklAtoms[XKLAVIER_TRANSPARENT] =
+ XInternAtom( _xklDpy, "XKLAVIER_TRANSPARENT", False );
+ _xklAtoms[XKLAVIER_ALLOW_SECONDARY] =
+ XInternAtom( _xklDpy, "XKLAVIER_ALLOW_SECONDARY", False );
+
+ _XklOneSwitchToSecondaryGroupPerformed();
+
+ rv = -1;
+ XklDebug( 150, "Trying all backends:\n" );
+#ifdef ENABLE_XKB_SUPPORT
+ XklDebug( 150, "Trying XKB backend\n" );
+ rv = _XklXkbInit();
+#endif
+#ifdef ENABLE_XMM_SUPPORT
+ if( rv != 0 )
+ {
+ XklDebug( 150, "Trying XMM backend\n" );
+ rv = _XklXmmInit();
+ }
+#endif
+ if( rv == 0 )
+ {
+ XklDebug( 150, "Actual backend: %s\n",
+ XklGetBackendName() );
+ }
+ else
+ {
+ XklDebug( 0, "All backends failed, last result: %d\n", rv );
+ _xklDpy = NULL;
+ }
+
+ return ( rv == 0 ) ?
+ ( _XklLoadAllInfo() ? 0 : _xklLastErrorCode ) : -1;
}
-gboolean
-xkl_engine_grab_key(XklEngine * engine, gint keycode, guint modifiers)
+int XklTerm( void )
{
- gboolean ret_code;
- gchar *keyname;
- Display *dpy = xkl_engine_get_display(engine);
+ XSetErrorHandler( ( XErrorHandler ) _xklDefaultErrHandler );
+ _xklConfigCallback = NULL;
+ stateCallback = NULL;
+ winCallback = NULL;
- if (xkl_debug_level >= 100) {
- keyname =
- XKeysymToString(XKeycodeToKeysym(dpy, keycode, 0));
- xkl_debug(100, "Listen to the key %d/(%s)/%d\n", keycode,
- keyname, modifiers);
- }
+ logAppender = XklDefaultLogAppender;
+ _XklFreeAllInfo( );
+
+ return 0;
+}
+
+Bool XklGrabKey( int keycode, unsigned modifiers )
+{
+ Bool retCode;
+ char *keyName;
- if (0 == keycode)
- return FALSE;
+ if( _xklDebugLevel >= 100 )
+ {
+ keyName = XKeysymToString( XKeycodeToKeysym( _xklDpy, keycode, 0 ) );
+ XklDebug( 100, "Listen to the key %d/(%s)/%d\n",
+ keycode, keyName, modifiers );
+ }
- xkl_engine_priv(engine, last_error_code) = Success;
+ if( ( KeyCode ) NULL == keycode )
+ return False;
- ret_code =
- XGrabKey(dpy, keycode, modifiers,
- xkl_engine_priv(engine, root_window), TRUE,
- GrabModeAsync, GrabModeAsync);
- XSync(dpy, False);
+ _xklLastErrorCode = Success;
- xkl_debug(100, "XGrabKey recode %d/error %d\n",
- ret_code, xkl_engine_priv(engine, last_error_code));
+ retCode = XGrabKey( _xklDpy, keycode, modifiers, _xklRootWindow,
+ True, GrabModeAsync, GrabModeAsync );
+ XSync( _xklDpy, False );
- ret_code = (xkl_engine_priv(engine, last_error_code) == Success);
+ XklDebug( 100, "XGrabKey recode %d/error %d\n", retCode, _xklLastErrorCode );
- if (!ret_code)
- xkl_last_error_message = "Could not grab the key";
+ retCode = ( _xklLastErrorCode == Success );
- return ret_code;
+ if( !retCode )
+ _xklLastErrorMsg = "Could not grab the key";
+
+ return retCode;
}
-gboolean
-xkl_engine_ungrab_key(XklEngine * engine, gint keycode, guint modifiers)
+Bool XklUngrabKey( int keycode, unsigned modifiers )
{
- if (0 == keycode)
- return FALSE;
+ if( ( KeyCode ) NULL == keycode )
+ return False;
- return Success == XUngrabKey(xkl_engine_get_display(engine),
- keycode, 0,
- xkl_engine_priv(engine, root_window));
+ return Success == XUngrabKey( _xklDpy, keycode, 0, _xklRootWindow );
}
-gint
-xkl_engine_get_next_group(XklEngine * engine)
+int XklGetNextGroup( void )
{
- gint n = xkl_engine_get_num_groups(engine);
- return (xkl_engine_priv(engine, curr_state).group + 1) % n;
+ return ( _xklCurState.group + 1 ) % XklGetNumGroups( );
}
-
-gint
-xkl_engine_get_prev_group(XklEngine * engine)
+
+int XklGetPrevGroup( void )
{
- gint n = xkl_engine_get_num_groups(engine);
- return (xkl_engine_priv(engine, curr_state).group + n - 1) % n;
+ int n = XklGetNumGroups( );
+ return ( _xklCurState.group + n - 1 ) % n;
}
-gint
-xkl_engine_get_current_window_group(XklEngine * engine)
+int XklGetRestoreGroup( void )
{
- XklState state;
- if (xkl_engine_priv(engine, curr_toplvl_win) == (Window) NULL) {
- xkl_debug(150, "cannot restore without current client\n");
- } else
- if (xkl_engine_get_toplevel_window_state
- (engine, xkl_engine_priv(engine, curr_toplvl_win),
- &state)) {
- return state.group;
- } else
- xkl_debug(150,
- "Unbelievable: current client " WINID_FORMAT
- ", '%s' has no group\n",
- xkl_engine_priv(engine, curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)));
- return 0;
+ XklState state;
+ if( _xklCurClient == ( Window ) NULL )
+ {
+ XklDebug( 150, "cannot restore without current client\n" );
+ } else if( XklGetState( _xklCurClient, &state ) )
+ {
+ return state.group;
+ } else
+ XklDebug( 150,
+ "Unbelievable: current client " WINID_FORMAT
+ ", '%s' has no group\n", _xklCurClient,
+ _XklGetDebugWindowTitle( _xklCurClient ) );
+ return 0;
}
-void
-xkl_engine_set_transparent(XklEngine * engine, Window win,
- gboolean transparent)
+void XklSetTransparent( Window win, Bool transparent )
{
- Window toplevel_win;
- xkl_debug(150,
- "setting transparent flag %d for " WINID_FORMAT "\n",
- transparent, win);
+ Window appWin;
+ Bool wasTransparent;
+ XklDebug( 150, "setting transparent flag %d for " WINID_FORMAT "\n",
+ transparent, win );
- if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) {
- xkl_debug(150, "No toplevel window!\n");
- /* toplevel_win = win; */
- return;
- }
+ if( !_XklGetAppWindow( win, &appWin ) )
+ {
+ XklDebug( 150, "No app window!\n" );
+ /* appWin = win; */
+ return;
+ }
- xkl_engine_set_toplevel_window_transparent(engine, toplevel_win,
- transparent);
+ wasTransparent = XklIsTransparent( appWin );
+ XklDebug( 150, "appwin " WINID_FORMAT " was %stransparent\n", appWin,
+ wasTransparent ? "" : "not " );
+ if( transparent && !wasTransparent )
+ {
+ CARD32 prop = 1;
+ XChangeProperty( _xklDpy, appWin, _xklAtoms[XKLAVIER_TRANSPARENT],
+ XA_INTEGER, 32, PropModeReplace,
+ ( const unsigned char * ) &prop, 1 );
+ } else if( !transparent && wasTransparent )
+ {
+ XDeleteProperty( _xklDpy, appWin, _xklAtoms[XKLAVIER_TRANSPARENT] );
+ }
}
-gboolean
-xkl_engine_is_window_transparent(XklEngine * engine, Window win)
+Bool XklIsTransparent( Window win )
{
- Window toplevel_win;
+ Window appWin;
- if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win))
- return FALSE;
- return xkl_engine_is_toplevel_window_transparent(engine,
- toplevel_win);
-}
+ if( !_XklGetAppWindow( win, &appWin ) )
+ return False;
+ return _XklIsTransparentAppWindow( appWin );
-/**
- * Loads the tree recursively.
- */
-gboolean
-xkl_engine_load_window_tree(XklEngine * engine)
-{
- Window focused;
- int revert;
- gboolean retval = TRUE, have_toplevel_win;
-
- if (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES)
- retval =
- xkl_engine_load_subtree(engine,
- xkl_engine_priv(engine,
- root_window),
- 0, &xkl_engine_priv(engine,
- curr_state));
-
- XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert);
-
- xkl_debug(160, "initially focused: " WINID_FORMAT ", '%s'\n",
- focused, xkl_get_debug_window_title(engine, focused));
-
- have_toplevel_win =
- xkl_engine_find_toplevel_window(engine, focused,
- &xkl_engine_priv(engine,
- curr_toplvl_win));
-
- if (have_toplevel_win) {
- gboolean have_state =
- xkl_engine_get_toplevel_window_state(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- &xkl_engine_priv
- (engine,
- curr_state));
- xkl_debug(160,
- "initial toplevel: " WINID_FORMAT
- ", '%s' %s state %d/%X\n",
- xkl_engine_priv(engine, curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)),
- (have_state ? "with" : "without"),
- (have_state ?
- xkl_engine_priv(engine, curr_state).group : -1),
- (have_state ?
- xkl_engine_priv(engine,
- curr_state).indicators : -1));
- } else {
- xkl_debug(160,
- "Could not find initial app. "
- "Probably, focus belongs to some WM service window. "
- "Will try to survive:)");
- }
-
- return retval;
-}
-
-void
-_xkl_debug(const gchar file[], const gchar function[], gint level,
- const gchar format[], ...)
-{
- va_list lst;
-
- if (level > xkl_debug_level)
- return;
-
- va_start(lst, format);
- if (log_appender != NULL)
- (*log_appender) (file, function, level, format, lst);
- va_end(lst);
-}
-
-void
-xkl_default_log_appender(const gchar file[], const gchar function[],
- gint level, const gchar format[], va_list args)
-{
- time_t now = time(NULL);
- fprintf(stdout, "[%08ld,%03d,%s:%s/] \t", now, level, file,
- function);
- vfprintf(stdout, format, args);
}
/**
- * Just selects some events from the window.
+ * "Adds" app window to the set of managed windows.
+ * Actually, no data structures involved. The only thing we do is save app state
+ * and register ourselves us listeners.
+ * Note: User's callback is called
*/
-void
-xkl_engine_select_input(XklEngine * engine, Window win, gulong mask)
+void _XklAddAppWindow( Window appWin, Window parent, Bool ignoreExistingState,
+ XklState * initState )
{
- if (xkl_engine_priv(engine, root_window) == win)
- xkl_debug(160,
- "Someone is looking for %lx on root window ***\n",
- mask);
+ XklState state = *initState;
+ int defGroupToUse = -1;
- XSelectInput(xkl_engine_get_display(engine), win, mask);
-}
+ if( appWin == _xklRootWindow )
+ XklDebug( 150, "??? root app win ???\n" );
-void
-xkl_engine_select_input_merging(XklEngine * engine, Window win,
- gulong mask)
-{
- XWindowAttributes attrs;
- gulong oldmask = 0L, newmask;
- memset(&attrs, 0, sizeof(attrs));
- if (XGetWindowAttributes
- (xkl_engine_get_display(engine), win, &attrs))
- oldmask = attrs.your_event_mask;
+ XklDebug( 150, "Trying to add window " WINID_FORMAT "/%s with group %d\n",
+ appWin, _XklGetDebugWindowTitle( appWin ), initState->group );
+
+ if( !ignoreExistingState )
+ {
+ Bool have_state = _XklGetAppState( appWin, &state );
+
+ if( have_state )
+ {
+ XklDebug( 150,
+ "The window " WINID_FORMAT
+ " does not require to be added, it already has the xklavier state \n",
+ appWin );
+ return;
+ }
+ }
+
+ if( winCallback != NULL )
+ defGroupToUse = ( *winCallback ) ( appWin, parent, winCallbackData );
+
+ if( defGroupToUse == -1 )
+ defGroupToUse = _xklDefaultGroup;
+
+ if( defGroupToUse != -1 )
+ state.group = defGroupToUse;
- newmask = oldmask | mask;
- if (newmask != oldmask)
- xkl_engine_select_input(engine, win, newmask);
+ _XklSaveAppState( appWin, &state );
+ _XklSelectInputMerging( appWin, FocusChangeMask | PropertyChangeMask );
+
+ if( defGroupToUse != -1 )
+ {
+ if( _xklCurClient == appWin )
+ {
+ if( ( _xklSecondaryGroupsMask & ( 1 << defGroupToUse ) ) != 0 )
+ XklAllowOneSwitchToSecondaryGroup();
+ XklLockGroup( defGroupToUse );
+ }
+ }
+
+ if( parent == ( Window ) NULL )
+ parent = _XklGetRegisteredParent( appWin );
+
+ XklDebug( 150, "done\n" );
}
-void
-xkl_engine_try_call_state_func(XklEngine * engine,
- XklEngineStateChange change_type,
- XklState * old_state)
+/**
+ * Checks the window and goes up
+ */
+Bool _XklGetAppWindowBottomToTop( Window win, Window * appWin_return )
{
- gint group = xkl_engine_priv(engine, curr_state).group;
- gboolean restore = old_state->group == group;
+ Window parent = ( Window ) NULL, rwin = ( Window ) NULL, *children = NULL;
+ unsigned int num = 0;
+
+ if( win == ( Window ) NULL || win == _xklRootWindow )
+ {
+ *appWin_return = win;
+ _xklLastErrorMsg = "The window is either 0 or root";
+ return False;
+ }
+
+ if( _XklHasWmState( win ) )
+ {
+ *appWin_return = win;
+ return True;
+ }
- xkl_debug(150,
- "change_type: %d, group: %d, secondary_group_mask: %X, allowsecondary: %d\n",
- change_type, group, xkl_engine_priv(engine,
- secondary_groups_mask),
- xkl_engine_is_one_switch_to_secondary_group_allowed
- (engine));
+ _xklLastErrorCode =
+ _XklStatusQueryTree( _xklDpy, win, &rwin, &parent, &children, &num );
- if (change_type == GROUP_CHANGED) {
- if (!restore) {
- if ((xkl_engine_priv(engine, secondary_groups_mask)
- & (1 << group)) != 0
- &&
- !xkl_engine_is_one_switch_to_secondary_group_allowed
- (engine)) {
- xkl_debug(150, "secondary -> go next\n");
- group = xkl_engine_get_next_group(engine);
- xkl_engine_lock_group(engine, group);
- return; /* we do not need to revalidate */
- }
- }
- xkl_engine_one_switch_to_secondary_group_performed(engine);
- }
+ if( _xklLastErrorCode != Success )
+ {
+ *appWin_return = ( Window ) NULL;
+ return False;
+ }
- g_signal_emit_by_name(engine, "X-state-changed", change_type,
- xkl_engine_priv(engine, curr_state).group,
- restore);
+ if( children != NULL )
+ XFree( children );
+ return _XklGetAppWindowBottomToTop( parent, appWin_return );
}
-void
-xkl_engine_ensure_vtable_inited(XklEngine * engine)
-{
- char *p;
- if (xkl_engine_priv(engine, backend_id) == NULL) {
- xkl_debug(0, "ERROR: XKL VTable is NOT initialized.\n");
- /* force the crash! */
- p = NULL;
- *p = '\0';
- }
+/**
+ * Recursively finds "App window" (window with WM_STATE) for given window.
+ * First, checks the window itself
+ * Then, for first level of recursion, checks childen,
+ * Then, goes to parent.
+ * NOTE: root window cannot be "App window" under normal circumstances
+ */
+Bool _XklGetAppWindow( Window win, Window * appWin_return )
+{
+ Window parent = ( Window ) NULL,
+ rwin = ( Window ) NULL, *children = NULL, *child;
+ unsigned int num = 0;
+ Bool rv;
+
+ if( win == ( Window ) NULL || win == _xklRootWindow )
+ {
+ *appWin_return = ( Window ) NULL;
+ _xklLastErrorMsg = "The window is either 0 or root";
+ XklDebug( 150,
+ "Window " WINID_FORMAT
+ " is either 0 or root so could not get the app window for it\n",
+ win );
+ return False;
+ }
+
+ if( _XklHasWmState( win ) )
+ {
+ *appWin_return = win;
+ return True;
+ }
+
+ _xklLastErrorCode =
+ _XklStatusQueryTree( _xklDpy, win, &rwin, &parent, &children, &num );
+
+ if( _xklLastErrorCode != Success )
+ {
+ *appWin_return = ( Window ) NULL;
+ XklDebug( 150,
+ "Could not get tree for window " WINID_FORMAT
+ " so could not get the app window for it\n", win );
+ return False;
+ }
+
+ /**
+ * Here we first check the children (in case win is just above some "App Window")
+ * and then go upstairs
+ */
+ child = children;
+ while( num )
+ {
+ if( _XklHasWmState( *child ) )
+ {
+ *appWin_return = *child;
+ if( children != NULL )
+ XFree( children );
+ return True;
+ }
+ child++;
+ num--;
+ }
+
+ if( children != NULL )
+ XFree( children );
+
+ rv = _XklGetAppWindowBottomToTop( parent, appWin_return );
+
+ if( !rv )
+ XklDebug( 200, "Could not get the app window for " WINID_FORMAT "/%s\n",
+ win, _XklGetDebugWindowTitle( win ) );
+
+ return rv;
}
-const gchar *
-xkl_engine_get_backend_name(XklEngine * engine)
+/**
+ * Loads the tree recursively.
+ */
+Bool _XklLoadWindowTree( void )
{
- return xkl_engine_priv(engine, backend_id);
+ Window focused;
+ int revert;
+ Bool retval = True, haveAppWindow;
+
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ retval = _XklLoadSubtree( _xklRootWindow, 0, &_xklCurState );
+
+ XGetInputFocus( _xklDpy, &focused, &revert );
+
+ XklDebug( 160, "initially focused: " WINID_FORMAT ", '%s'\n",
+ focused, _XklGetDebugWindowTitle( focused ) );
+
+ haveAppWindow = _XklGetAppWindow( focused, &_xklCurClient );
+
+ if( haveAppWindow )
+ {
+ Bool haveState = _XklGetAppState( _xklCurClient, &_xklCurState );
+ XklDebug( 160,
+ "initial _xklCurClient: " WINID_FORMAT
+ ", '%s' %s state %d/%X\n", _xklCurClient,
+ _XklGetDebugWindowTitle( _xklCurClient ),
+ ( haveState ? "with" : "without" ),
+ ( haveState ? _xklCurState.group : -1 ),
+ ( haveState ? _xklCurState.indicators : -1 ) );
+ } else
+ {
+ XklDebug( 160,
+ "could not find initial app. Probably, focus belongs to some WM service window. Will try to survive:)" );
+ }
+
+ return retval;
}
-guint
-xkl_engine_get_features(XklEngine * engine)
+void _XklDebug( const char file[], const char function[], int level,
+ const char format[], ... )
{
- return xkl_engine_priv(engine, features);
+ va_list lst;
+
+ if( level > _xklDebugLevel )
+ return;
+
+ va_start( lst, format );
+ if( logAppender != NULL )
+ ( *logAppender ) ( file, function, level, format, lst );
+ va_end( lst );
}
-void
-xkl_engine_reset_all_info(XklEngine * engine, const gchar reason[])
+void XklDefaultLogAppender( const char file[], const char function[],
+ int level, const char format[], va_list args )
{
- xkl_debug(150, "Resetting all the cached info, reason: [%s]\n",
- reason);
- xkl_engine_ensure_vtable_inited(engine);
- if (!xkl_engine_vcall(engine, if_cached_info_equals_actual)
- (engine)) {
- xkl_engine_vcall(engine, free_all_info) (engine);
- xkl_engine_vcall(engine, load_all_info) (engine);
- } else
- xkl_debug(100,
- "NOT Resetting the cache: same configuration\n");
+ time_t now = time( NULL );
+ fprintf( stdout, "[%08ld,%03d,%s:%s/] \t", now, level, file, function );
+ vfprintf( stdout, format, args );
}
/**
- * Calling through vtable
+ * Gets the state from the window property
*/
-const gchar **
-xkl_engine_groups_get_names(XklEngine * engine)
+Bool _XklGetAppState( Window appWin, XklState * state_return )
+{
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems, rest;
+ CARD32 *prop = NULL;
+ Bool ret = False;
+
+ int grp = -1;
+ unsigned inds = 0;
+
+ if( ( XGetWindowProperty
+ ( _xklDpy, appWin, _xklAtoms[XKLAVIER_STATE], 0L,
+ XKLAVIER_STATE_PROP_LENGTH, False,
+ XA_INTEGER, &type_ret, &format_ret, &nitems, &rest,
+ ( unsigned char ** ) ( void * ) &prop ) == Success )
+ && ( type_ret == XA_INTEGER ) && ( format_ret == 32 ) )
+ {
+ grp = prop[0];
+ if( grp >= XklGetNumGroups( ) || grp < 0 )
+ grp = 0;
+
+ inds = prop[1];
+
+ if( state_return != NULL )
+ {
+ state_return->group = grp;
+ state_return->indicators = inds;
+ }
+ if( prop != NULL )
+ XFree( prop );
+
+ ret = True;
+ }
+
+ if( ret )
+ XklDebug( 150,
+ "Appwin " WINID_FORMAT
+ ", '%s' has the group %d, indicators %X\n", appWin,
+ _XklGetDebugWindowTitle( appWin ), grp, inds );
+ else
+ XklDebug( 150, "Appwin " WINID_FORMAT ", '%s' does not have state\n",
+ appWin, _XklGetDebugWindowTitle( appWin ) );
+
+ return ret;
+}
+
+/**
+ * Deletes the state from the window properties
+ */
+void _XklDelAppState( Window appWin )
{
- xkl_engine_ensure_vtable_inited(engine);
- return xkl_engine_vcall(engine, get_groups_names) (engine);
+ XDeleteProperty( _xklDpy, appWin, _xklAtoms[XKLAVIER_STATE] );
}
-guint
-xkl_engine_get_num_groups(XklEngine * engine)
+/**
+ * Saves the state into the window properties
+ */
+void _XklSaveAppState( Window appWin, XklState * state )
{
- xkl_engine_ensure_vtable_inited(engine);
- return xkl_engine_vcall(engine, get_num_groups) (engine);
+ CARD32 prop[XKLAVIER_STATE_PROP_LENGTH];
+
+ prop[0] = state->group;
+ prop[1] = state->indicators;
+
+ XChangeProperty( _xklDpy, appWin, _xklAtoms[XKLAVIER_STATE], XA_INTEGER,
+ 32, PropModeReplace, ( const unsigned char * ) prop,
+ XKLAVIER_STATE_PROP_LENGTH );
+
+ XklDebug( 160,
+ "Saved the group %d, indicators %X for appwin " WINID_FORMAT "\n",
+ state->group, state->indicators, appWin );
}
-void
-xkl_engine_lock_group(XklEngine * engine, int group)
+/**
+ * Just selects some events from the window.
+ */
+void _XklSelectInput( Window win, long mask )
{
- xkl_engine_ensure_vtable_inited(engine);
- xkl_engine_vcall(engine, lock_group) (engine, group);
+ if( _xklRootWindow == win )
+ XklDebug( 160,
+ "Someone is looking for %lx on root window ***\n",
+ mask );
+
+ XSelectInput( _xklDpy, win, mask );
}
-gint
-xkl_engine_pause_listen(XklEngine * engine)
+void _XklSelectInputMerging( Window win, long mask )
{
- xkl_engine_ensure_vtable_inited(engine);
- return xkl_engine_vcall(engine, pause_listen) (engine);
+ XWindowAttributes attrs;
+ long oldmask = 0L, newmask;
+ memset( &attrs, 0, sizeof( attrs ) );
+ if( XGetWindowAttributes( _xklDpy, win, &attrs ) )
+ oldmask = attrs.your_event_mask;
+
+ newmask = oldmask | mask;
+ if( newmask != oldmask )
+ _XklSelectInput( win, newmask );
}
-gint
-xkl_engine_resume_listen(XklEngine * engine)
+void _XklTryCallStateCallback( XklStateChange changeType,
+ XklState * oldState )
{
- xkl_engine_ensure_vtable_inited(engine);
- xkl_debug(150, "listenerType: %x\n",
- xkl_engine_priv(engine, listener_type));
- if (xkl_engine_vcall(engine, resume_listen) (engine))
- return 1;
+ int group = _xklCurState.group;
+ Bool restore = oldState->group == group;
+
+ XklDebug( 150,
+ "changeType: %d, group: %d, secondaryGroupMask: %X, allowsecondary: %d\n",
+ changeType, group, _xklSecondaryGroupsMask,
+ _XklIsOneSwitchToSecondaryGroupAllowed() );
- xkl_engine_select_input_merging(engine,
- xkl_engine_priv(engine,
- root_window),
- SubstructureNotifyMask |
- PropertyChangeMask);
+ if( changeType == GROUP_CHANGED )
+ {
+ if( !restore )
+ {
+ if( ( _xklSecondaryGroupsMask & ( 1 << group ) ) != 0 &&
+ !_XklIsOneSwitchToSecondaryGroupAllowed() )
+ {
+ XklDebug( 150, "secondary -> go next\n" );
+ group = XklGetNextGroup( );
+ XklLockGroup( group );
+ return; /* we do not need to revalidate */
+ }
+ }
+ _XklOneSwitchToSecondaryGroupPerformed();
+ }
+ if( stateCallback != NULL )
+ {
- xkl_engine_vcall(engine,
- get_server_state) (engine,
- &xkl_engine_priv(engine,
- curr_state));
- return 0;
+ ( *stateCallback ) ( changeType, _xklCurState.group,
+ restore, stateCallbackData );
+ }
}
-guint
-xkl_engine_get_max_num_groups(XklEngine * engine)
+Bool _XklIsTransparentAppWindow( Window appWin )
{
- xkl_engine_ensure_vtable_inited(engine);
- return xkl_engine_vcall(engine, get_max_num_groups) (engine);
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems, rest;
+ CARD32 *prop = NULL;
+ if( ( XGetWindowProperty
+ ( _xklDpy, appWin, _xklAtoms[XKLAVIER_TRANSPARENT], 0L, 1, False,
+ XA_INTEGER, &type_ret, &format_ret, &nitems, &rest,
+ ( unsigned char ** ) ( void * ) &prop ) == Success )
+ && ( type_ret == XA_INTEGER ) && ( format_ret == 32 ) )
+ {
+ if( prop != NULL )
+ XFree( prop );
+ return True;
+ }
+ return False;
}
-XklEngine *
-xkl_get_the_engine()
+void _XklEnsureVTableInited( void )
{
- return the_engine;
+ char *p;
+ if ( xklVTable == NULL )
+ {
+ XklDebug( 0, "ERROR: XKL VTable is NOT initialized.\n" );
+ /* force the crash! */
+ p = NULL; *p = '\0';
+ }
}
-G_DEFINE_TYPE(XklEngine, xkl_engine, G_TYPE_OBJECT)
-
-static GObject *
-xkl_engine_constructor(GType type,
- guint n_construct_properties,
- GObjectConstructParam * construct_properties)
+const char *XklGetBackendName( void )
{
- GObject *obj;
-
- {
- /* Invoke parent constructor. */
- XklEngineClass *klass;
- klass =
- XKL_ENGINE_CLASS(g_type_class_peek(XKL_TYPE_ENGINE));
- obj =
- parent_class->constructor(type, n_construct_properties,
- construct_properties);
- }
+ return xklVTable->id;
+}
- XklEngine *engine = XKL_ENGINE(obj);
+int XklGetBackendFeatures( void )
+{
+ return xklVTable->features;
+}
- Display *display =
- (Display *) g_value_peek_pointer(construct_properties[0].
- value);
+void _XklResetAllInfo( const char reason[] )
+{
+ XklDebug( 150, "Resetting all the cached info, reason: [%s]\n", reason );
+ _XklEnsureVTableInited();
+ if( !(*xklVTable->xklIfCachedInfoEqualsActualHandler)() )
+ {
+ (*xklVTable->xklFreeAllInfoHandler)();
+ (*xklVTable->xklLoadAllInfoHandler)();
+ } else
+ XklDebug( 100, "NOT Resetting the cache: same configuration\n" );
+}
- xkl_engine_priv(engine, display) = display;
+/**
+ * Calling through vtable
+ */
+const char **XklGetGroupNames( void )
+{
+ _XklEnsureVTableInited();
+ return (*xklVTable->xklGetGroupNamesHandler)();
+}
- int scr;
+unsigned XklGetNumGroups( void )
+{
+ _XklEnsureVTableInited();
+ return (*xklVTable->xklGetNumGroupsHandler)();
+}
- xkl_engine_priv(engine, default_error_handler) =
- XSetErrorHandler((XErrorHandler) xkl_process_error);
+void XklLockGroup( int group )
+{
+ _XklEnsureVTableInited();
+ (*xklVTable->xklLockGroupHandler)( group );
+}
- scr = DefaultScreen(display);
- xkl_engine_priv(engine, root_window) = RootWindow(display, scr);
+int XklPauseListen( void )
+{
+ _XklEnsureVTableInited();
+ return (*xklVTable->xklPauseListenHandler)();
+}
- xkl_engine_priv(engine, skip_one_restore) = FALSE;
- xkl_engine_priv(engine, default_group) = -1;
- xkl_engine_priv(engine, secondary_groups_mask) = 0L;
- xkl_engine_priv(engine, prev_toplvl_win) = 0;
+int XklResumeListen( void )
+{
+ _XklEnsureVTableInited();
+ XklDebug( 150, "listenerType: %x\n", _xklListenerType );
+ if( (*xklVTable->xklResumeListenHandler)() )
+ return 1;
+
+ _XklSelectInputMerging( _xklRootWindow,
+ SubstructureNotifyMask | PropertyChangeMask );
+ _XklEnsureVTableInited();
+ (*xklVTable->xklGetRealStateHandler)( &_xklCurState );
+ return 0;
+}
- xkl_engine_priv(engine, atoms)[WM_NAME] =
- XInternAtom(display, "WM_NAME", False);
- xkl_engine_priv(engine, atoms)[WM_STATE] =
- XInternAtom(display, "WM_STATE", False);
- xkl_engine_priv(engine, atoms)[XKLAVIER_STATE] =
- XInternAtom(display, "XKLAVIER_STATE", False);
- xkl_engine_priv(engine, atoms)[XKLAVIER_TRANSPARENT] =
- XInternAtom(display, "XKLAVIER_TRANSPARENT", False);
- xkl_engine_priv(engine, atoms)[XKLAVIER_ALLOW_SECONDARY] =
- XInternAtom(display, "XKLAVIER_ALLOW_SECONDARY", False);
+Bool _XklLoadAllInfo( void )
+{
+ _XklEnsureVTableInited();
+ return (*xklVTable->xklLoadAllInfoHandler)();
+}
- xkl_engine_one_switch_to_secondary_group_performed(engine);
+void _XklFreeAllInfo( void )
+{
+ _XklEnsureVTableInited();
+ (*xklVTable->xklFreeAllInfoHandler)();
+}
- gint rv = -1;
- xkl_debug(150, "Trying all backends:\n");
-#ifdef ENABLE_XKB_SUPPORT
- xkl_debug(150, "Trying XKB backend\n");
- rv = xkl_xkb_init(engine);
-#endif
-#ifdef ENABLE_XMM_SUPPORT
- if (rv != 0) {
- xkl_debug(150, "Trying XMM backend\n");
- rv = xkl_xmm_init(engine);
- }
-#endif
- if (rv == 0) {
- xkl_debug(150, "Actual backend: %s\n",
- xkl_engine_get_backend_name(engine));
- } else {
- xkl_debug(0, "All backends failed, last result: %d\n", rv);
- xkl_engine_priv(engine, display) = NULL;
- g_object_unref(G_OBJECT(engine));
- return NULL;
- }
-
- xkl_engine_ensure_vtable_inited(engine);
- if (!xkl_engine_vcall(engine, load_all_info) (engine)) {
- g_object_unref(G_OBJECT(engine));
- return NULL;
- }
-
- return obj;
-}
-
-static void
-xkl_engine_init(XklEngine * engine)
-{
- engine->priv = g_new0(XklEnginePrivate, 1);
-}
-
-static void
-xkl_engine_set_property(GObject * object,
- guint property_id,
- const GValue * value, GParamSpec * pspec)
-{
-}
-
-static void
-xkl_engine_get_property(GObject * object,
- guint property_id,
- GValue * value, GParamSpec * pspec)
-{
- XklEngine *engine = XKL_ENGINE(object);
-
- switch (property_id) {
- case PROP_DISPLAY:
- g_value_set_pointer(value, xkl_engine_get_display(engine));
- break;
- case PROP_BACKEND_NAME:
- g_value_set_string(value,
- xkl_engine_priv(engine, backend_id));
- break;
- case PROP_FEATURES:
- g_value_set_flags(value,
- xkl_engine_priv(engine, features));
- break;
- case PROP_MAX_NUM_GROUPS:
- g_value_set_uint(value,
- xkl_engine_vcall(engine,
- get_max_num_groups)
- (engine));
- break;
- case PROP_NUM_GROUPS:
- g_value_set_uint(value,
- xkl_engine_vcall(engine, get_num_groups)
- (engine));
- break;
- case PROP_DEFAULT_GROUP:
- g_value_set_uint(value,
- xkl_engine_priv(engine, default_group));
- break;
- case PROP_SECONDARY_GROUPS_MASK:
- g_value_set_uint(value,
- xkl_engine_priv(engine,
- secondary_groups_mask));
- break;
- case PROP_INDICATORS_HANDLING:
- g_value_set_boolean(value,
- xkl_engine_priv(engine,
- handle_indicators));
- break;
- }
-}
-
-static void
-xkl_engine_finalize(GObject * obj)
-{
- XklEngine *engine = (XklEngine *) obj;
-
- XSetErrorHandler((XErrorHandler)
- xkl_engine_priv(engine, default_error_handler));
-
- xkl_engine_ensure_vtable_inited(engine);
- xkl_engine_vcall(engine, free_all_info) (engine);
-
- xkl_engine_vcall(engine, finalize) (engine);
-
- gpointer backend = xkl_engine_priv(engine, backend);
- if (backend != NULL)
- g_free(backend);
- g_free(engine->priv);
-
- G_OBJECT_CLASS(parent_class)->finalize(obj);
-}
-
-static void
-xkl_engine_class_init(XklEngineClass * klass)
-{
- static GFlagsValue feature_flags[] = {
- {XKLF_CAN_TOGGLE_INDICATORS, "XKLF_CAN_TOGGLE_INDICATORS",
- NULL},
- {XKLF_CAN_OUTPUT_CONFIG_AS_ASCII,
- "XKLF_CAN_OUTPUT_CONFIG_AS_ASCII", NULL},
- {XKLF_CAN_OUTPUT_CONFIG_AS_BINARY,
- "XKLF_CAN_OUTPUT_CONFIG_AS_BINARY", NULL},
- {XKLF_MULTIPLE_LAYOUTS_SUPPORTED,
- "XKLF_MULTIPLE_LAYOUTS_SUPPORTED", NULL},
- {XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT,
- "XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT", NULL},
- {0, NULL, NULL}
- };
- static GEnumValue state_change_values[] = {
- {GROUP_CHANGED, "GROUP_CHANGED", NULL},
- {INDICATORS_CHANGED, "INDICATORS_CHANGED", NULL},
- {0, NULL, NULL}
- };
-
- GObjectClass *object_class;
-
- object_class = (GObjectClass *) klass;
- parent_class = g_type_class_peek_parent(object_class);
-
- object_class->constructor = xkl_engine_constructor;
- object_class->finalize = xkl_engine_finalize;
- object_class->set_property = xkl_engine_set_property;
- object_class->get_property = xkl_engine_get_property;
-
- GParamSpec *display_param_spec = g_param_spec_pointer("display",
- "Display",
- "X Display pointer",
- G_PARAM_CONSTRUCT_ONLY
- |
- G_PARAM_READWRITE);
-
- GParamSpec *backend_name_param_spec =
- g_param_spec_string("backendName",
- "backendName",
- "Backend name",
- NULL,
- G_PARAM_READABLE);
-
- GType features_type = g_flags_register_static("XklEngineFeatures",
- feature_flags);
-
- GType state_change_type =
- g_enum_register_static("XklEngineStateChangeType",
- state_change_values);
-
- GParamSpec *features_param_spec = g_param_spec_flags("features",
- "Features",
- "Backend features",
- features_type,
- 0,
- G_PARAM_READABLE);
- GParamSpec *max_num_groups_param_spec =
- g_param_spec_uint("max-num-groups",
- "maxNumGroups",
- "Max number of groups",
- 0, 0x100, 0,
- G_PARAM_READABLE);
-
- GParamSpec *num_groups_param_spec = g_param_spec_uint("num-groups",
- "numGroups",
- "Current number of groups",
- 0, 0x100, 0,
- G_PARAM_READABLE);
-
- GParamSpec *default_group_param_spec =
- g_param_spec_uint("default-group",
- "defaultGroup",
- "Default group",
- 0, 0x100, 0,
- G_PARAM_READABLE);
-
- GParamSpec *secondary_groups_mask_param_spec =
- g_param_spec_uint("secondary-groups-mask",
- "secondaryGroupsMask",
- "Secondary groups mask",
- 0, 0x100, 0,
- G_PARAM_READABLE);
-
- GParamSpec *indicators_handling_param_spec =
- g_param_spec_boolean("indicators-handling",
- "indicatorsHandling",
- "Whether engine should handle indicators",
- FALSE,
- G_PARAM_READABLE);
-
- g_object_class_install_property(object_class,
- PROP_DISPLAY, display_param_spec);
- g_object_class_install_property(object_class,
- PROP_BACKEND_NAME,
- backend_name_param_spec);
- g_object_class_install_property(object_class, PROP_FEATURES,
- features_param_spec);
- g_object_class_install_property(object_class, PROP_MAX_NUM_GROUPS,
- max_num_groups_param_spec);
- g_object_class_install_property(object_class, PROP_NUM_GROUPS,
- num_groups_param_spec);
- g_object_class_install_property(object_class, PROP_DEFAULT_GROUP,
- default_group_param_spec);
- g_object_class_install_property(object_class,
- PROP_SECONDARY_GROUPS_MASK,
- secondary_groups_mask_param_spec);
- g_object_class_install_property(object_class,
- PROP_INDICATORS_HANDLING,
- indicators_handling_param_spec);
-
-
- g_signal_new("X-config-changed", XKL_TYPE_ENGINE,
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass,
- config_notify),
- NULL, NULL, xkl_engine_VOID__VOID, G_TYPE_NONE, 0);
-
- g_signal_new("new-toplevel-window", XKL_TYPE_ENGINE,
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass,
- new_window_notify),
- NULL, NULL, xkl_engine_INT__LONG_LONG,
- G_TYPE_INT, 2, G_TYPE_LONG, G_TYPE_LONG);
-
- g_signal_new("X-state-changed", XKL_TYPE_ENGINE,
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass,
- state_notify),
- NULL, NULL,
- xkl_engine_VOID__FLAGS_INT_BOOLEAN,
- G_TYPE_NONE, 3, state_change_type, G_TYPE_INT,
- G_TYPE_BOOLEAN);
-
- /* 2 Windows passed */
- /* static stuff initialized */
-
- const gchar *sdl = g_getenv("XKL_DEBUG");
-
- if (sdl != NULL) {
- xkl_set_debug_level(atoi(sdl));
- }
+unsigned XklGetMaxNumGroups( void )
+{
+ _XklEnsureVTableInited();
+ return (*xklVTable->xklGetMaxNumGroupsHandler)();
}
+
diff --git a/libxklavier/xklavier_config_xkb.c b/libxklavier/xklavier_config_xkb.c
index 39b74e8..9334a4b 100644
--- a/libxklavier/xklavier_config_xkb.c
+++ b/libxklavier/xklavier_config_xkb.c
@@ -1,6 +1,6 @@
#include <errno.h>
-#include <locale.h>
#include <string.h>
+#include <locale.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/param.h>
@@ -30,504 +30,426 @@
#include <X11/keysymdef.h>
#ifdef XKB_HEADERS_PRESENT
-static XkbRF_RulesPtr xkl_rules;
+static XkbRF_RulesPtr _xklRules;
-static XkbRF_RulesPtr
-xkl_rules_set_load(XklEngine * engine)
+static XkbRF_RulesPtr _XklLoadRulesSet( void )
{
- XkbRF_RulesPtr rules_set = NULL;
- char file_name[MAXPATHLEN] = "";
- char *rf =
- xkl_engine_get_ruleset_name(engine, XKB_DEFAULT_RULESET);
- char *locale = NULL;
-
- if (rf == NULL) {
- xkl_last_error_message =
- "Could not find the XKB rules set";
- return NULL;
- }
-
- locale = setlocale(LC_ALL, NULL);
-
- snprintf(file_name, sizeof file_name, XKB_BASE "/rules/%s", rf);
- xkl_debug(160, "Loading rules from [%s]\n", file_name);
-
- rules_set = XkbRF_Load(file_name, locale, True, True);
-
- if (rules_set == NULL) {
- xkl_last_error_message = "Could not load rules";
- return NULL;
- }
- return rules_set;
+ XkbRF_RulesPtr rulesSet = NULL;
+ char fileName[MAXPATHLEN] = "";
+ char *rf = _XklGetRulesSetName( XKB_DEFAULT_RULESET );
+ char *locale = NULL;
+
+ if( rf == NULL )
+ {
+ _xklLastErrorMsg = "Could not find the XKB rules set";
+ return NULL;
+ }
+
+ locale = setlocale( LC_ALL, NULL );
+
+ snprintf( fileName, sizeof fileName, XKB_BASE "/rules/%s", rf );
+ XklDebug( 160, "Loading rules from [%s]\n", fileName );
+
+ rulesSet = XkbRF_Load( fileName, locale, True, True );
+
+ if( rulesSet == NULL )
+ {
+ _xklLastErrorMsg = "Could not load rules";
+ return NULL;
+ }
+ return rulesSet;
}
-static void
-xkl_rules_set_free(void)
+static void _XklFreeRulesSet( void )
{
- if (xkl_rules)
- XkbRF_Free(xkl_rules, True);
- xkl_rules = NULL;
+ if ( _xklRules )
+ XkbRF_Free( _xklRules, True );
+ _xklRules = NULL;
}
#endif
-void
-xkl_xkb_init_config_registry(XklConfigRegistry * config)
+void _XklXkbConfigInit( void )
{
#ifdef XKB_HEADERS_PRESENT
- XkbInitAtoms(NULL);
+ XkbInitAtoms( NULL );
#endif
}
-gboolean
-xkl_xkb_load_config_registry(XklConfigRegistry * config)
+Bool _XklXkbConfigLoadRegistry( void )
{
- struct stat stat_buf;
- char file_name[MAXPATHLEN] = "";
- char *rf =
- xkl_engine_get_ruleset_name(xkl_config_registry_get_engine
- (config),
- XKB_DEFAULT_RULESET);
+ struct stat statBuf;
+ char fileName[MAXPATHLEN] = "";
+ char* rf = _XklGetRulesSetName( XKB_DEFAULT_RULESET );
- if (rf == NULL)
- return FALSE;
+ if ( rf == NULL )
+ return False;
- snprintf(file_name, sizeof file_name, XKB_BASE "/rules/%s.xml",
- rf);
+ snprintf( fileName, sizeof fileName, XKB_BASE "/rules/%s.xml", rf );
- if (stat(file_name, &stat_buf) != 0) {
- g_strlcpy(file_name, XML_CFG_FALLBACK_PATH,
- sizeof file_name);
- }
+ if( stat( fileName, &statBuf ) != 0 )
+ {
+ strncpy( fileName, XML_CFG_FALLBACK_PATH, sizeof fileName );
+ fileName[ MAXPATHLEN - 1 ] = '\0';
+ }
- return xkl_config_registry_load_from_file(config, file_name);
+ return XklConfigLoadRegistryFromFile( fileName );
}
#ifdef XKB_HEADERS_PRESENT
-gboolean
-xkl_xkb_config_native_prepare(XklEngine * engine,
- const XklConfigRec * data,
- XkbComponentNamesPtr component_names_ptr)
+Bool _XklXkbConfigPrepareNative( const XklConfigRecPtr data, XkbComponentNamesPtr componentNamesPtr )
{
- XkbRF_VarDefsRec xkl_var_defs;
- gboolean got_components;
-
- memset(&xkl_var_defs, 0, sizeof(xkl_var_defs));
-
- xkl_rules = xkl_rules_set_load(engine);
- if (!xkl_rules) {
- return FALSE;
- }
-
- xkl_var_defs.model = (char *) data->model;
-
- if (data->layouts != NULL)
- xkl_var_defs.layout = xkl_config_rec_merge_layouts(data);
-
- if (data->variants != NULL)
- xkl_var_defs.variant = xkl_config_rec_merge_variants(data);
-
- if (data->options != NULL)
- xkl_var_defs.options = xkl_config_rec_merge_options(data);
-
- got_components =
- XkbRF_GetComponents(xkl_rules, &xkl_var_defs,
- component_names_ptr);
-
- g_free(xkl_var_defs.layout);
- g_free(xkl_var_defs.variant);
- g_free(xkl_var_defs.options);
-
- if (!got_components) {
- xkl_last_error_message =
- "Could not translate rules into components";
- /* Just cleanup the stuff in case of failure */
- xkl_xkb_config_native_cleanup(engine, component_names_ptr);
-
- return FALSE;
- }
-
- if (xkl_debug_level >= 200) {
- xkl_debug(200, "keymap: %s\n",
- component_names_ptr->keymap);
- xkl_debug(200, "keycodes: %s\n",
- component_names_ptr->keycodes);
- xkl_debug(200, "compat: %s\n",
- component_names_ptr->compat);
- xkl_debug(200, "types: %s\n", component_names_ptr->types);
- xkl_debug(200, "symbols: %s\n",
- component_names_ptr->symbols);
- xkl_debug(200, "geometry: %s\n",
- component_names_ptr->geometry);
- }
- return TRUE;
+ XkbRF_VarDefsRec _xklVarDefs;
+ Bool gotComponents;
+
+ memset( &_xklVarDefs, 0, sizeof( _xklVarDefs ) );
+
+ _xklRules = _XklLoadRulesSet();
+ if( !_xklRules )
+ {
+ return False;
+ }
+
+ _xklVarDefs.model = ( char * ) data->model;
+
+ if( data->layouts != NULL )
+ _xklVarDefs.layout = _XklConfigRecMergeLayouts( data );
+
+ if( data->variants != NULL )
+ _xklVarDefs.variant = _XklConfigRecMergeVariants( data );
+
+ if( data->options != NULL )
+ _xklVarDefs.options = _XklConfigRecMergeOptions( data );
+
+ gotComponents = XkbRF_GetComponents( _xklRules, &_xklVarDefs, componentNamesPtr );
+
+ free( _xklVarDefs.layout );
+ free( _xklVarDefs.variant );
+ free( _xklVarDefs.options );
+
+ if( !gotComponents )
+ {
+ _xklLastErrorMsg = "Could not translate rules into components";
+ /* Just cleanup the stuff in case of failure */
+ _XklXkbConfigCleanupNative( componentNamesPtr );
+
+ return False;
+ }
+
+ if ( _xklDebugLevel >= 200 )
+ {
+ XklDebug( 200, "keymap: %s\n", componentNamesPtr->keymap );
+ XklDebug( 200, "keycodes: %s\n", componentNamesPtr->keycodes );
+ XklDebug( 200, "compat: %s\n", componentNamesPtr->compat );
+ XklDebug( 200, "types: %s\n", componentNamesPtr->types );
+ XklDebug( 200, "symbols: %s\n", componentNamesPtr->symbols );
+ XklDebug( 200, "geometry: %s\n", componentNamesPtr->geometry );
+ }
+ return True;
}
-void
-xkl_xkb_config_native_cleanup(XklEngine * engine,
- XkbComponentNamesPtr component_names_ptr)
+void _XklXkbConfigCleanupNative( XkbComponentNamesPtr componentNamesPtr )
{
- xkl_rules_set_free();
-
- g_free(component_names_ptr->keymap);
- g_free(component_names_ptr->keycodes);
- g_free(component_names_ptr->compat);
- g_free(component_names_ptr->types);
- g_free(component_names_ptr->symbols);
- g_free(component_names_ptr->geometry);
+ _XklFreeRulesSet();
+
+ free(componentNamesPtr->keymap);
+ free(componentNamesPtr->keycodes);
+ free(componentNamesPtr->compat);
+ free(componentNamesPtr->types);
+ free(componentNamesPtr->symbols);
+ free(componentNamesPtr->geometry);
}
-static XkbDescPtr
-xkl_config_get_keyboard(XklEngine * engine,
- XkbComponentNamesPtr component_names_ptr,
- gboolean activate)
+static XkbDescPtr _XklConfigGetKeyboard( XkbComponentNamesPtr componentNamesPtr, Bool activate )
{
- XkbDescPtr xkb = NULL;
+ XkbDescPtr xkb = NULL;
#if 0
- xkb = XkbGetKeyboardByName(_xklDpy,
- XkbUseCoreKbd,
- &componentNames,
- XkbGBN_AllComponentsMask &
- (~XkbGBN_GeometryMask),
- XkbGBN_AllComponentsMask &
- (~XkbGBN_GeometryMask), activate);
+ xkb = XkbGetKeyboardByName( _xklDpy,
+ XkbUseCoreKbd,
+ &componentNames,
+ XkbGBN_AllComponentsMask &
+ ( ~XkbGBN_GeometryMask ),
+ XkbGBN_AllComponentsMask &
+ ( ~XkbGBN_GeometryMask ),
+ activate );
#else
- char xkm_fn[L_tmpnam];
- char xkb_fn[L_tmpnam];
- FILE *tmpxkm;
- XkbFileInfo result;
- int xkmloadres;
-
- Display *display = xkl_engine_get_display(engine);
-
- if (tmpnam(xkm_fn) != NULL && tmpnam(xkb_fn) != NULL) {
- pid_t cpid, pid;
- int status = 0;
- FILE *tmpxkb;
-
- xkl_debug(150, "tmp XKB/XKM file names: [%s]/[%s]\n",
- xkb_fn, xkm_fn);
- if ((tmpxkb = fopen(xkb_fn, "w")) != NULL) {
- fprintf(tmpxkb, "xkb_keymap {\n");
- fprintf(tmpxkb,
- " xkb_keycodes { include \"%s\" };\n",
- component_names_ptr->keycodes);
- fprintf(tmpxkb,
- " xkb_types { include \"%s\" };\n",
- component_names_ptr->types);
- fprintf(tmpxkb,
- " xkb_compat { include \"%s\" };\n",
- component_names_ptr->compat);
- fprintf(tmpxkb,
- " xkb_symbols { include \"%s\" };\n",
- component_names_ptr->symbols);
- fprintf(tmpxkb,
- " xkb_geometry { include \"%s\" };\n",
- component_names_ptr->geometry);
- fprintf(tmpxkb, "};\n");
- fclose(tmpxkb);
-
- xkl_debug(150, "xkb_keymap {\n"
- " xkb_keycodes { include \"%s\" };\n"
- " xkb_types { include \"%s\" };\n"
- " xkb_compat { include \"%s\" };\n"
- " xkb_symbols { include \"%s\" };\n"
- " xkb_geometry { include \"%s\" };\n};\n",
- component_names_ptr->keycodes,
- component_names_ptr->types,
- component_names_ptr->compat,
- component_names_ptr->symbols,
- component_names_ptr->geometry);
-
- cpid = fork();
- switch (cpid) {
- case -1:
- xkl_debug(0, "Could not fork: %d\n",
- errno);
- break;
- case 0:
- /* child */
- xkl_debug(160, "Executing %s\n", XKBCOMP);
- xkl_debug(160, "%s %s %s %s %s %s %s\n",
- XKBCOMP, XKBCOMP, "-I",
- "-I" XKB_BASE, "-xkm", xkb_fn,
- xkm_fn);
- execl(XKBCOMP, XKBCOMP, "-I",
- "-I" XKB_BASE, "-xkm", xkb_fn,
- xkm_fn, NULL);
- xkl_debug(0, "Could not exec %s: %d\n",
- XKBCOMP, errno);
- exit(1);
- default:
- /* parent */
- pid = waitpid(cpid, &status, 0);
- xkl_debug(150,
- "Return status of %d (well, started %d): %d\n",
- pid, cpid, status);
- memset((char *) &result, 0,
- sizeof(result));
- result.xkb = XkbAllocKeyboard();
-
- if (Success ==
- XkbChangeKbdDisplay(display,
- &result)) {
- xkl_debug(150,
- "Hacked the kbddesc - set the display...\n");
- if ((tmpxkm =
- fopen(xkm_fn, "r")) != NULL) {
- xkmloadres =
- XkmReadFile(tmpxkm,
- XkmKeymapLegal,
- XkmKeymapLegal,
- &result);
- xkl_debug(150,
- "Loaded %s output as XKM file, got %d (comparing to %d)\n",
- XKBCOMP,
- (int) xkmloadres,
- (int)
- XkmKeymapLegal);
- if ((int) xkmloadres !=
- (int) XkmKeymapLegal) {
- xkl_debug(150,
- "Loaded legal keymap\n");
- if (activate) {
- xkl_debug
- (150,
- "Activating it...\n");
- if (XkbWriteToServer(&result)) {
- xkl_debug
- (150,
- "Updating the keyboard...\n");
- xkb = result.xkb;
- } else {
- xkl_debug
- (0,
- "Could not write keyboard description to the server\n");
- }
- } else /* no activate, just load */
- xkb =
- result.
- xkb;
- } else { /* could not load properly */
-
- xkl_debug(0,
- "Could not load %s output as XKM file, got %d (asked %d)\n",
- XKBCOMP,
- (int)
- xkmloadres,
- (int)
- XkmKeymapLegal);
- }
- fclose(tmpxkm);
- xkl_debug(160,
- "Unlinking the temporary xkm file %s\n",
- xkm_fn);
- if (xkl_debug_level < 500) { /* don't remove on high debug levels! */
- if (remove(xkm_fn)
- == -1)
- xkl_debug
- (0,
- "Could not unlink the temporary xkm file %s: %d\n",
- xkm_fn,
- errno);
- } else
- xkl_debug(500,
- "Well, not really - the debug level is too high: %d\n",
- xkl_debug_level);
- } else { /* could not open the file */
-
- xkl_debug(0,
- "Could not open the temporary xkm file %s\n",
- xkm_fn);
- }
- } else { /* could not assign to display */
-
- xkl_debug(0,
- "Could not change the keyboard description to display\n");
- }
- if (xkb == NULL)
- XkbFreeKeyboard(result.xkb,
- XkbAllComponentsMask,
- True);
- break;
- }
- xkl_debug(160,
- "Unlinking the temporary xkb file %s\n",
- xkb_fn);
- if (xkl_debug_level < 500) { /* don't remove on high debug levels! */
- if (remove(xkb_fn) == -1)
- xkl_debug(0,
- "Could not unlink the temporary xkb file %s: %d\n",
- xkb_fn, errno);
- } else
- xkl_debug(500,
- "Well, not really - the debug level is too high: %d\n",
- xkl_debug_level);
- } else { /* could not open input tmp file */
-
- xkl_debug(0,
- "Could not open tmp XKB file [%s]: %d\n",
- xkb_fn, errno);
- }
- } else {
- xkl_debug(0, "Could not get tmp names\n");
- }
+ char xkmFN[L_tmpnam];
+ char xkbFN[L_tmpnam];
+ FILE* tmpxkm;
+ XkbFileInfo result;
+ int xkmloadres;
+
+ if ( tmpnam( xkmFN ) != NULL &&
+ tmpnam( xkbFN ) != NULL )
+ {
+ pid_t cpid, pid;
+ int status = 0;
+ FILE *tmpxkb;
+
+ XklDebug( 150, "tmp XKB/XKM file names: [%s]/[%s]\n", xkbFN, xkmFN );
+ if( (tmpxkb = fopen( xkbFN, "w" )) != NULL )
+ {
+ fprintf( tmpxkb, "xkb_keymap {\n" );
+ fprintf( tmpxkb, " xkb_keycodes { include \"%s\" };\n", componentNamesPtr->keycodes );
+ fprintf( tmpxkb, " xkb_types { include \"%s\" };\n", componentNamesPtr->types );
+ fprintf( tmpxkb, " xkb_compat { include \"%s\" };\n", componentNamesPtr->compat );
+ fprintf( tmpxkb, " xkb_symbols { include \"%s\" };\n", componentNamesPtr->symbols );
+ fprintf( tmpxkb, " xkb_geometry { include \"%s\" };\n", componentNamesPtr->geometry );
+ fprintf( tmpxkb, "};\n" );
+ fclose( tmpxkb );
+
+ XklDebug( 150, "xkb_keymap {\n"
+ " xkb_keycodes { include \"%s\" };\n"
+ " xkb_types { include \"%s\" };\n"
+ " xkb_compat { include \"%s\" };\n"
+ " xkb_symbols { include \"%s\" };\n"
+ " xkb_geometry { include \"%s\" };\n};\n",
+ componentNamesPtr->keycodes,
+ componentNamesPtr->types,
+ componentNamesPtr->compat,
+ componentNamesPtr->symbols,
+ componentNamesPtr->geometry );
+
+ XSync( _xklDpy, False );
+ /* From this point, ALL errors should be intercepted only by libxklavier*/
+ _xklCriticalSection = True;
+
+ cpid=fork();
+ switch( cpid )
+ {
+ case -1:
+ XklDebug( 0, "Could not fork: %d\n", errno );
+ break;
+ case 0:
+ /* child */
+ XklDebug( 160, "Executing %s\n", XKBCOMP );
+ XklDebug( 160, "%s %s %s %s %s %s %s\n",
+ XKBCOMP, XKBCOMP, "-I", "-I" XKB_BASE, "-xkm", xkbFN, xkmFN );
+ execl( XKBCOMP, XKBCOMP, "-I", "-I" XKB_BASE, "-xkm", xkbFN, xkmFN, NULL );
+ XklDebug( 0, "Could not exec %s: %d\n", XKBCOMP, errno );
+ exit( 1 );
+ default:
+ /* parent */
+ pid = waitpid( cpid, &status, 0 );
+ XklDebug( 150, "Return status of child process %d "
+ "(well, at least it started as %d): %d\n",
+ pid, cpid, status );
+
+ memset( (char *)&result, 0, sizeof(result) );
+ result.xkb = XkbAllocKeyboard();
+
+ if( Success == XkbChangeKbdDisplay( _xklDpy, &result ) )
+ {
+ XklDebug( 150, "Hacked the kbddesc - set the display...\n" );
+ if( (tmpxkm = fopen( xkmFN, "r" )) != NULL )
+ {
+ xkmloadres = XkmReadFile( tmpxkm, XkmKeymapLegal, XkmKeymapLegal, &result);
+ XklDebug( 150, "Loaded %s output as XKM file, got %d (comparing to %d)\n",
+ XKBCOMP, (int)xkmloadres, (int)XkmKeymapLegal );
+ if ( (int)xkmloadres != (int)XkmKeymapLegal )
+ {
+ XklDebug( 150, "Loaded legal keymap\n" );
+ if( activate )
+ {
+ XklDebug( 150, "Activating it...\n" );
+ if( XkbWriteToServer(&result) )
+ {
+ XklDebug( 150, "Updating the keyboard...\n" );
+ xkb = result.xkb;
+ } else
+ {
+ XklDebug( 0, "Could not write keyboard description to the server\n" );
+ }
+ } else /* no activate, just load */
+ xkb = result.xkb;
+ } else /* could not load properly */
+ {
+ XklDebug( 0, "Could not load %s output as XKM file, got %d (asked %d)\n",
+ XKBCOMP, (int)xkmloadres, (int)XkmKeymapLegal );
+ }
+ fclose( tmpxkm );
+ XklDebug( 160, "Unlinking the temporary xkm file %s\n", xkmFN );
+ if ( _xklDebugLevel < 500 ) /* don't remove on high debug levels! */
+ {
+ if ( remove( xkmFN ) == -1 )
+ XklDebug( 0, "Could not unlink the temporary xkm file %s: %d\n",
+ xkmFN, errno );
+ } else
+ XklDebug( 500, "Well, not really - the debug level is too high: %d\n", _xklDebugLevel );
+ } else /* could not open the file */
+ {
+ XklDebug( 0, "Could not open the temporary xkm file %s\n", xkmFN );
+ }
+ } else /* could not assign to display */
+ {
+ XklDebug( 0, "Could not change the keyboard description to display\n" );
+ }
+ if ( xkb == NULL )
+ XkbFreeKeyboard( result.xkb, XkbAllComponentsMask, True );
+ break;
+ }
+ XSync( _xklDpy, False );
+ /* Return to normal X error processing */
+ _xklCriticalSection = False;
+
+ XklDebug( 160, "Unlinking the temporary xkb file %s\n", xkbFN );
+ if ( _xklDebugLevel < 500 ) /* don't remove on high debug levels! */
+ {
+ if ( remove( xkbFN ) == -1 )
+ XklDebug( 0, "Could not unlink the temporary xkb file %s: %d\n",
+ xkbFN, errno );
+ } else
+ XklDebug( 500, "Well, not really - the debug level is too high: %d\n", _xklDebugLevel );
+ } else /* could not open input tmp file */
+ {
+ XklDebug( 0, "Could not open tmp XKB file [%s]: %d\n", xkbFN, errno );
+ }
+ } else
+ {
+ XklDebug( 0, "Could not get tmp names\n" );
+ }
#endif
- return xkb;
+ return xkb;
}
-#else /* no XKB headers */
-gboolean
-xkl_xkb_config_native_prepare(const XklConfigRec * data,
- gpointer componentNamesPtr)
+#else /* no XKB headers */
+Bool _XklXkbConfigPrepareNative( const XklConfigRecPtr data, void * componentNamesPtr )
{
- return FALSE;
+ return False;
}
-void
-_XklXkbConfigCleanupNative(gpointer componentNamesPtr)
+void _XklXkbConfigCleanupNative( void * componentNamesPtr )
{
}
#endif
/* check only client side support */
-gboolean
-xkl_xkb_multiple_layouts_supported(XklEngine * engine)
+Bool _XklXkbConfigMultipleLayoutsSupported( void )
{
- enum { NON_SUPPORTED, SUPPORTED, UNCHECKED };
+ enum { NON_SUPPORTED, SUPPORTED, UNCHECKED };
- static int support_state = UNCHECKED;
+ static int supportState = UNCHECKED;
- if (support_state == UNCHECKED) {
- XklConfigRec data;
- char *layouts[] = { "us", "de", NULL };
- char *variants[] = { NULL, NULL, NULL };
+ if( supportState == UNCHECKED )
+ {
+ XklConfigRec data;
+ char *layouts[] = { "us", "de" };
+ char *variants[] = { NULL, NULL };
#ifdef XKB_HEADERS_PRESENT
- XkbComponentNamesRec component_names;
- memset(&component_names, 0, sizeof(component_names));
+ XkbComponentNamesRec componentNames;
+ memset( &componentNames, 0, sizeof( componentNames ) );
#endif
- data.model = "pc105";
- data.layouts = layouts;
- data.variants = variants;
- data.options = NULL;
+ data.model = "pc105";
+ data.numVariants =
+ data.numLayouts = 2;
+ data.numOptions = 0;
+ data.layouts = layouts;
+ data.variants = variants;
+ data.options = NULL;
- xkl_debug(100, "!!! Checking multiple layouts support\n");
- support_state = NON_SUPPORTED;
+ XklDebug( 100, "!!! Checking multiple layouts support\n" );
+ supportState = NON_SUPPORTED;
#ifdef XKB_HEADERS_PRESENT
- if (xkl_xkb_config_native_prepare
- (engine, &data, &component_names)) {
- xkl_debug(100,
- "!!! Multiple layouts ARE supported\n");
- support_state = SUPPORTED;
- xkl_xkb_config_native_cleanup(engine,
- &component_names);
- } else {
- xkl_debug(100,
- "!!! Multiple layouts ARE NOT supported\n");
- }
+ if( _XklXkbConfigPrepareNative( &data, &componentNames ) )
+ {
+ XklDebug( 100, "!!! Multiple layouts ARE supported\n" );
+ supportState = SUPPORTED;
+ _XklXkbConfigCleanupNative( &componentNames );
+ } else
+ {
+ XklDebug( 100, "!!! Multiple layouts ARE NOT supported\n" );
+ }
#endif
- }
- return support_state == SUPPORTED;
+ }
+ return supportState == SUPPORTED;
}
-gboolean
-xkl_xkb_activate_config_rec(XklEngine * engine, const XklConfigRec * data)
+Bool _XklXkbConfigActivate( const XklConfigRecPtr data )
{
- gboolean rv = FALSE;
+ Bool rv = False;
#if 0
- {
- int i;
- XklDebug(150, "New model: [%s]\n", data->model);
- XklDebug(150, "New layouts: %p\n", data->layouts);
- for (i = data->numLayouts; --i >= 0;)
- XklDebug(150, "New layout[%d]: [%s]\n", i,
- data->layouts[i]);
- XklDebug(150, "New variants: %p\n", data->variants);
- for (i = data->numVariants; --i >= 0;)
- XklDebug(150, "New variant[%d]: [%s]\n", i,
- data->variants[i]);
- XklDebug(150, "New options: %p\n", data->options);
- for (i = data->numOptions; --i >= 0;)
- XklDebug(150, "New option[%d]: [%s]\n", i,
- data->options[i]);
- }
+ {
+ int i;
+ XklDebug( 150, "New model: [%s]\n", data->model );
+ XklDebug( 150, "New layouts: %p\n", data->layouts );
+ for( i = data->numLayouts; --i >= 0; )
+ XklDebug( 150, "New layout[%d]: [%s]\n", i, data->layouts[i] );
+ XklDebug( 150, "New variants: %p\n", data->variants );
+ for( i = data->numVariants; --i >= 0; )
+ XklDebug( 150, "New variant[%d]: [%s]\n", i, data->variants[i] );
+ XklDebug( 150, "New options: %p\n", data->options );
+ for( i = data->numOptions; --i >= 0; )
+ XklDebug( 150, "New option[%d]: [%s]\n", i, data->options[i] );
+ }
#endif
#ifdef XKB_HEADERS_PRESENT
- XkbComponentNamesRec component_names;
- memset(&component_names, 0, sizeof(component_names));
-
- if (xkl_xkb_config_native_prepare(engine, data, &component_names)) {
- XkbDescPtr xkb;
- xkb =
- xkl_config_get_keyboard(engine, &component_names,
- TRUE);
- if (xkb != NULL) {
- if (xkl_config_rec_set_to_root_window_property
- (data,
- xkl_engine_priv(engine, base_config_atom),
- xkl_engine_get_ruleset_name(engine,
- XKB_DEFAULT_RULESET),
- engine))
- /* We do not need to check the result of _XklGetRulesSetName -
- because PrepareBeforeKbd did it for us */
- rv = TRUE;
- else
- xkl_last_error_message =
- "Could not set names property";
- XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
- } else {
- xkl_last_error_message =
- "Could not load keyboard description";
- }
- xkl_xkb_config_native_cleanup(engine, &component_names);
- }
+ XkbComponentNamesRec componentNames;
+ memset( &componentNames, 0, sizeof( componentNames ) );
+
+ if( _XklXkbConfigPrepareNative( data, &componentNames ) )
+ {
+ XkbDescPtr xkb;
+ xkb = _XklConfigGetKeyboard( &componentNames, True );
+ if( xkb != NULL )
+ {
+ if( XklSetNamesProp
+ ( xklVTable->baseConfigAtom, _XklGetRulesSetName( XKB_DEFAULT_RULESET ), data ) )
+ /* We do not need to check the result of _XklGetRulesSetName -
+ because PrepareBeforeKbd did it for us */
+ rv = True;
+ else
+ _xklLastErrorMsg = "Could not set names property";
+ XkbFreeKeyboard( xkb, XkbAllComponentsMask, True );
+ } else
+ {
+ _xklLastErrorMsg = "Could not load keyboard description";
+ }
+ _XklXkbConfigCleanupNative( &componentNames );
+ }
#endif
- return rv;
+ return rv;
}
-gboolean
-xkl_xkb_write_config_rec_to_file(XklEngine * engine, const char *file_name,
- const XklConfigRec * data,
- const gboolean binary)
+Bool _XklXkbConfigWriteFile( const char *fileName,
+ const XklConfigRecPtr data,
+ const Bool binary )
{
- gboolean rv = FALSE;
+ Bool rv = False;
#ifdef XKB_HEADERS_PRESENT
- XkbComponentNamesRec component_names;
- FILE *output = fopen(file_name, "w");
- XkbFileInfo dump_info;
-
- if (output == NULL) {
- xkl_last_error_message = "Could not open the XKB file";
- return FALSE;
- }
-
- memset(&component_names, 0, sizeof(component_names));
-
- if (xkl_xkb_config_native_prepare(engine, data, &component_names)) {
- XkbDescPtr xkb;
- xkb =
- xkl_config_get_keyboard(engine, &component_names,
- FALSE);
- if (xkb != NULL) {
- dump_info.defined = 0;
- dump_info.xkb = xkb;
- dump_info.type = XkmKeymapFile;
- if (binary)
- rv = XkbWriteXKMFile(output, &dump_info);
- else
- rv = XkbWriteXKBFile(output, &dump_info,
- True, NULL, NULL);
-
- XkbFreeKeyboard(xkb, XkbGBN_AllComponentsMask,
- True);
- } else
- xkl_last_error_message =
- "Could not load keyboard description";
- xkl_xkb_config_native_cleanup(engine, &component_names);
- }
- fclose(output);
+ XkbComponentNamesRec componentNames;
+ FILE *output = fopen( fileName, "w" );
+ XkbFileInfo dumpInfo;
+
+ if( output == NULL )
+ {
+ _xklLastErrorMsg = "Could not open the XKB file";
+ return False;
+ }
+
+ memset( &componentNames, 0, sizeof( componentNames ) );
+
+ if( _XklXkbConfigPrepareNative( data, &componentNames ) )
+ {
+ XkbDescPtr xkb;
+ xkb = _XklConfigGetKeyboard( &componentNames, False );
+ if( xkb != NULL )
+ {
+ dumpInfo.defined = 0;
+ dumpInfo.xkb = xkb;
+ dumpInfo.type = XkmKeymapFile;
+ if( binary )
+ rv = XkbWriteXKMFile( output, &dumpInfo );
+ else
+ rv = XkbWriteXKBFile( output, &dumpInfo, True, NULL, NULL );
+
+ XkbFreeKeyboard( xkb, XkbGBN_AllComponentsMask, True );
+ } else
+ _xklLastErrorMsg = "Could not load keyboard description";
+ _XklXkbConfigCleanupNative( &componentNames );
+ }
+ fclose( output );
#endif
- return rv;
+ return rv;
}
diff --git a/libxklavier/xklavier_evt.c b/libxklavier/xklavier_evt.c
index 40dd41a..785ac72 100644
--- a/libxklavier/xklavier_evt.c
+++ b/libxklavier/xklavier_evt.c
@@ -1,433 +1,327 @@
-#include <string.h>
#include <time.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/Xlibint.h>
#include "xklavier_private.h"
-gint
-xkl_engine_filter_events(XklEngine * engine, XEvent * xev)
+int XklFilterEvents( XEvent * xev )
{
- XAnyEvent *pe = (XAnyEvent *) xev;
- xkl_debug(400,
- "**> Filtering event %d of type %d from window %d\n",
- pe->serial, pe->type, pe->window);
- xkl_engine_ensure_vtable_inited(engine);
- if (!xkl_engine_vcall(engine, process_x_event) (engine, xev))
- switch (xev->type) { /* core events */
- case FocusIn:
- xkl_engine_process_focus_in_evt(engine,
- &xev->xfocus);
- break;
- case FocusOut:
- xkl_engine_process_focus_out_evt(engine,
- &xev->xfocus);
- break;
- case PropertyNotify:
- xkl_engine_process_property_evt(engine,
- &xev->xproperty);
- break;
- case CreateNotify:
- xkl_engine_process_create_window_evt(engine,
- &xev->
- xcreatewindow);
- break;
- case DestroyNotify:
- xkl_debug(150,
- "Window " WINID_FORMAT " destroyed\n",
- xev->xdestroywindow.window);
- break;
- case UnmapNotify:
- xkl_debug(200,
- "Window " WINID_FORMAT " unmapped\n",
- xev->xunmap.window);
- break;
- case MapNotify:
- case GravityNotify:
- xkl_debug(200, "%s\n",
- xkl_event_get_name(xev->type));
- break; /* Ignore these events */
- case ReparentNotify:
- xkl_debug(200,
- "Window " WINID_FORMAT " reparented to "
- WINID_FORMAT "\n", xev->xreparent.window,
- xev->xreparent.parent);
- break; /* Ignore these events */
- case MappingNotify:
- xkl_debug(200, "%s\n",
- xkl_event_get_name(xev->type));
- xkl_engine_reset_all_info(engine,
- "X event: MappingNotify");
- break;
- default:
- {
- xkl_debug(200, "Unknown event %d [%s]\n",
- xev->type,
- xkl_event_get_name(xev->type));
- return 1;
- }
- }
- xkl_debug(400, "Filtered event %d of type %d from window %d **>\n",
- pe->serial, pe->type, pe->window);
- return 1;
+ XAnyEvent *pe = ( XAnyEvent * ) xev;
+ XklDebug( 400, "**> Filtering event %d of type %d from window %d\n",
+ pe->serial, pe->type, pe->window );
+ _XklEnsureVTableInited();
+ if ( !xklVTable->xklEventHandler( xev ) )
+ switch ( xev->type )
+ { /* core events */
+ case FocusIn:
+ _XklFocusInEvHandler( &xev->xfocus );
+ break;
+ case FocusOut:
+ _XklFocusOutEvHandler( &xev->xfocus );
+ break;
+ case PropertyNotify:
+ _XklPropertyEvHandler( &xev->xproperty );
+ break;
+ case CreateNotify:
+ _XklCreateEvHandler( &xev->xcreatewindow );
+ break;
+ case DestroyNotify:
+ XklDebug( 150, "Window " WINID_FORMAT " destroyed\n",
+ xev->xdestroywindow.window );
+ break;
+ case UnmapNotify:
+ XklDebug( 200, "Window " WINID_FORMAT " unmapped\n",
+ xev->xunmap.window );
+ break;
+ case MapNotify:
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
+ break;
+ case MappingNotify:
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
+ _XklResetAllInfo( "X event: MappingNotify" );
+ break;
+ case GravityNotify:
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
+ break;
+ case ReparentNotify:
+ XklDebug( 200, "Window " WINID_FORMAT " reparented to " WINID_FORMAT "\n",
+ xev->xreparent.window, xev->xreparent.parent );
+ break;
+ default:
+ {
+ XklDebug( 200, "Unknown event %d [%s]\n",
+ xev->type, _XklGetEventName( xev->type ) );
+ return 1;
+ }
+ }
+ XklDebug( 400, "Filtered event %d of type %d from window %d **>\n",
+ pe->serial, pe->type, pe->window );
+ return 1;
}
-/*
+/**
* FocusIn handler
*/
-void
-xkl_engine_process_focus_in_evt(XklEngine * engine,
- XFocusChangeEvent * fev)
+void _XklFocusInEvHandler( XFocusChangeEvent * fev )
{
- Window win;
- Window toplevel_win;
- XklState selected_window_state;
-
- if (!
- (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES))
- return;
-
- win = fev->window;
-
- switch (fev->mode) {
- case NotifyNormal:
- case NotifyWhileGrabbed:
- break;
- default:
- xkl_debug(160,
- "Window " WINID_FORMAT
- " has got focus during special action %d\n", win,
- fev->mode);
- return;
- }
-
- xkl_debug(150, "Window " WINID_FORMAT ", '%s' has got focus\n",
- win, xkl_get_debug_window_title(engine, win));
-
- if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) {
- return;
- }
-
- xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' has got focus\n",
- toplevel_win, xkl_get_debug_window_title(engine,
- toplevel_win));
-
- if (xkl_engine_get_toplevel_window_state
- (engine, toplevel_win, &selected_window_state)) {
- if (xkl_engine_priv(engine, curr_toplvl_win) !=
- toplevel_win) {
- gboolean old_win_transparent, new_win_transparent;
- XklState tmp_state;
-
- old_win_transparent =
- xkl_engine_is_toplevel_window_transparent
- (engine,
- xkl_engine_priv(engine, curr_toplvl_win));
- if (old_win_transparent)
- xkl_debug(150,
- "Leaving transparent window\n");
-
- /*
- * Reload the current state from the current window.
- * Do not do it for transparent window - we keep the state from
- * the _previous_ window.
- */
- if (!old_win_transparent &&
- xkl_engine_get_toplevel_window_state(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- &tmp_state))
- {
- xkl_engine_update_current_state(engine,
- tmp_state.
- group,
- tmp_state.
- indicators,
- "Loading current (previous) state from the current (previous) window");
- }
-
- xkl_engine_priv(engine, curr_toplvl_win) =
- toplevel_win;
- xkl_debug(150,
- "CurClient:changed to " WINID_FORMAT
- ", '%s'\n", xkl_engine_priv(engine,
- curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)));
-
- new_win_transparent =
- xkl_engine_is_toplevel_window_transparent
- (engine, toplevel_win);
- if (new_win_transparent)
- xkl_debug(150,
- "Entering transparent window\n");
-
- if (xkl_engine_is_group_per_toplevel_window(engine)
- == !new_win_transparent) {
- /* We skip restoration only if we return to the same app window */
- gboolean do_skip = FALSE;
- if (xkl_engine_priv
- (engine, skip_one_restore)) {
- xkl_engine_priv(engine,
- skip_one_restore) =
- FALSE;
- if (toplevel_win ==
- xkl_engine_priv(engine,
- prev_toplvl_win))
- do_skip = TRUE;
- }
-
- if (do_skip) {
- xkl_debug(150,
- "Skipping one restore as requested - instead, "
- "saving the current group into the window state\n");
- xkl_engine_save_toplevel_window_state
- (engine, toplevel_win,
- &xkl_engine_priv(engine,
- curr_state));
- } else {
- if (xkl_engine_priv
- (engine,
- curr_state).group !=
- selected_window_state.group) {
- xkl_debug(150,
- "Restoring the group from %d to %d after gaining focus\n",
- xkl_engine_priv
- (engine,
- curr_state).
- group,
- selected_window_state.
- group);
- /*
- * For fast mouse movements - the state is probably not updated yet
- * (because of the group change notification being late).
- * so we'll enforce the update. But this should only happen in GPA mode
- */
- xkl_engine_update_current_state
- (engine,
- selected_window_state.
- group,
- selected_window_state.
- indicators,
- "Enforcing fast update of the current state");
- xkl_engine_lock_group
- (engine,
- selected_window_state.
- group);
- } else {
- xkl_debug(150,
- "Both old and new focused window "
- "have group %d so no point restoring it\n",
- selected_window_state.
- group);
- xkl_engine_one_switch_to_secondary_group_performed
- (engine);
- }
- }
-
- if ((xkl_engine_priv(engine, features) &
- XKLF_CAN_TOGGLE_INDICATORS)
- &&
- xkl_engine_get_indicators_handling
- (engine)) {
- xkl_debug(150,
- "Restoring the indicators from %X to %X after gaining focus\n",
- xkl_engine_priv(engine,
- curr_state).
- indicators,
- selected_window_state.
- indicators);
- xkl_engine_ensure_vtable_inited
- (engine);
- xkl_engine_vcall(engine,
- set_indicators)
- (engine,
- &selected_window_state);
- } else
- xkl_debug(150,
- "Not restoring the indicators %X after gaining focus: indicator handling is not enabled\n",
- xkl_engine_priv(engine,
- curr_state).
- indicators);
- } else
- xkl_debug(150,
- "Not restoring the group %d after gaining focus: global layout (xor transparent window)\n",
- xkl_engine_priv(engine,
- curr_state).
- group);
- } else
- xkl_debug(150,
- "Same app window - just do nothing\n");
- } else {
- xkl_debug(150, "But it does not have xklavier_state\n");
- if (xkl_engine_if_window_has_wm_state(engine, win)) {
- xkl_debug(150,
- "But it does have wm_state so we'll add it\n");
- xkl_engine_priv(engine, curr_toplvl_win) =
- toplevel_win;
- xkl_debug(150,
- "CurClient:changed to " WINID_FORMAT
- ", '%s'\n", xkl_engine_priv(engine,
- curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)));
- xkl_engine_add_toplevel_window(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- (Window) NULL,
- FALSE,
- &xkl_engine_priv
- (engine,
- curr_state));
- } else
- xkl_debug(150,
- "And it does have wm_state either\n");
- }
+ Window win;
+ Window appWin;
+ XklState selectedWindowState;
+
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
+ win = fev->window;
+
+ switch ( fev->mode )
+ {
+ case NotifyNormal:
+ case NotifyWhileGrabbed:
+ break;
+ default:
+ XklDebug( 160,
+ "Window " WINID_FORMAT
+ " has got focus during special action %d\n", win, fev->mode );
+ return;
+ }
+
+ XklDebug( 150, "Window " WINID_FORMAT ", '%s' has got focus\n", win,
+ _XklGetDebugWindowTitle( win ) );
+
+ if( !_XklGetAppWindow( win, &appWin ) )
+ {
+ return;
+ }
+
+ XklDebug( 150, "Appwin " WINID_FORMAT ", '%s' has got focus\n", appWin,
+ _XklGetDebugWindowTitle( appWin ) );
+
+ if( XklGetState( appWin, &selectedWindowState ) )
+ {
+ if( _xklCurClient != appWin )
+ {
+ Bool oldWinTransparent, newWinTransparent;
+ XklState tmpState;
+
+ oldWinTransparent = _XklIsTransparentAppWindow( _xklCurClient );
+ if( oldWinTransparent )
+ XklDebug( 150, "Leaving transparent window\n" );
+
+ /**
+ * Reload the current state from the current window.
+ * Do not do it for transparent window - we keep the state from
+ * the _previous_ window.
+ */
+ if ( !oldWinTransparent && XklGetState ( _xklCurClient, &tmpState ) )
+ {
+ _XklUpdateCurState( tmpState.group,
+ tmpState.indicators,
+ "Loading current (previous) state from the current (previous) window" );
+ }
+
+ _xklCurClient = appWin;
+ XklDebug( 150, "CurClient:changed to " WINID_FORMAT ", '%s'\n",
+ _xklCurClient, _XklGetDebugWindowTitle( _xklCurClient ) );
+
+ newWinTransparent = _XklIsTransparentAppWindow( appWin );
+ if( newWinTransparent )
+ XklDebug( 150, "Entering transparent window\n" );
+
+ if( XklIsGroupPerApp() == !newWinTransparent )
+ {
+ /* We skip restoration only if we return to the same app window */
+ Bool doSkip = False;
+ if( _xklSkipOneRestore )
+ {
+ _xklSkipOneRestore = False;
+ if( appWin == _xklPrevAppWindow )
+ doSkip = True;
+ }
+
+ if( doSkip )
+ {
+ XklDebug( 150,
+ "Skipping one restore as requested - instead, saving the current group into the window state\n" );
+ _XklSaveAppState( appWin, &_xklCurState );
+ } else
+ {
+ if( _xklCurState.group != selectedWindowState.group )
+ {
+ XklDebug( 150,
+ "Restoring the group from %d to %d after gaining focus\n",
+ _xklCurState.group, selectedWindowState.group );
+ /**
+ * For fast mouse movements - the state is probably not updated yet
+ * (because of the group change notification being late).
+ * so we'll enforce the update. But this should only happen in GPA mode
+ */
+ _XklUpdateCurState( selectedWindowState.group,
+ selectedWindowState.indicators,
+ "Enforcing fast update of the current state" );
+ XklLockGroup( selectedWindowState.group );
+ } else
+ {
+ XklDebug( 150,
+ "Both old and new focused window have group %d so no point restoring it\n",
+ selectedWindowState.group );
+ _XklOneSwitchToSecondaryGroupPerformed();
+ }
+ }
+
+ if( ( xklVTable->features & XKLF_CAN_TOGGLE_INDICATORS ) &&
+ XklGetIndicatorsHandling( ) )
+ {
+ XklDebug( 150,
+ "Restoring the indicators from %X to %X after gaining focus\n",
+ _xklCurState.indicators, selectedWindowState.indicators );
+ _XklEnsureVTableInited();
+ (*xklVTable->xklSetIndicatorsHandler)( &selectedWindowState );
+ } else
+ XklDebug( 150,
+ "Not restoring the indicators %X after gaining focus: indicator handling is not enabled\n",
+ _xklCurState.indicators );
+ } else
+ XklDebug( 150,
+ "Not restoring the group %d after gaining focus: global layout (xor transparent window)\n",
+ _xklCurState.group );
+ } else
+ XklDebug( 150, "Same app window - just do nothing\n" );
+ } else
+ {
+ XklDebug( 150, "But it does not have xklavier_state\n" );
+ if( _XklHasWmState( win ) )
+ {
+ XklDebug( 150, "But it does have wm_state so we'll add it\n" );
+ _xklCurClient = appWin;
+ XklDebug( 150, "CurClient:changed to " WINID_FORMAT ", '%s'\n",
+ _xklCurClient, _XklGetDebugWindowTitle( _xklCurClient ) );
+ _XklAddAppWindow( _xklCurClient, ( Window ) NULL, False,
+ &_xklCurState );
+ } else
+ XklDebug( 150, "And it does have wm_state either\n" );
+ }
}
-/*
+/**
* FocusOut handler
*/
-void
-xkl_engine_process_focus_out_evt(XklEngine * engine,
- XFocusChangeEvent * fev)
+void _XklFocusOutEvHandler( XFocusChangeEvent * fev )
{
- if (!
- (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES))
- return;
-
- if (fev->mode != NotifyNormal) {
- xkl_debug(200,
- "Window " WINID_FORMAT
- " has lost focus during special action %d\n",
- fev->window, fev->mode);
- return;
- }
-
- xkl_debug(160, "Window " WINID_FORMAT ", '%s' has lost focus\n",
- fev->window, xkl_get_debug_window_title(engine,
- fev->window));
-
- if (xkl_engine_is_window_transparent(engine, fev->window)) {
- xkl_debug(150, "Leaving transparent window!\n");
-/*
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
+ if( fev->mode != NotifyNormal )
+ {
+ XklDebug( 200,
+ "Window " WINID_FORMAT
+ " has lost focus during special action %d\n", fev->window,
+ fev->mode );
+ return;
+ }
+
+ XklDebug( 160, "Window " WINID_FORMAT ", '%s' has lost focus\n",
+ fev->window, _XklGetDebugWindowTitle( fev->window ) );
+
+ if( XklIsTransparent( fev->window ) )
+ {
+
+ XklDebug( 150, "Leaving transparent window!\n" );
+/**
* If we are leaving the transparent window - we skip the restore operation.
* This is useful for secondary groups switching from the transparent control
* window.
*/
- xkl_engine_priv(engine, skip_one_restore) = TRUE;
- } else {
- Window p;
- if (xkl_engine_find_toplevel_window
- (engine, fev->window, &p))
- xkl_engine_priv(engine, prev_toplvl_win) = p;
- }
+ _xklSkipOneRestore = True;
+ } else
+ {
+ Window p;
+ if( _XklGetAppWindow( fev->window, &p ) )
+ _xklPrevAppWindow = p;
+ }
}
-/*
+/**
* PropertyChange handler
* Interested in :
* + for XKLL_MANAGE_WINDOW_STATES
* - WM_STATE property for all windows
* - Configuration property of the root window
*/
-void
-xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * pev)
+void _XklPropertyEvHandler( XPropertyEvent * pev )
{
- if (400 <= xkl_debug_level) {
- char *atom_name =
- XGetAtomName(xkl_engine_get_display(engine),
- pev->atom);
- if (atom_name != NULL) {
- xkl_debug(400,
- "The property '%s' changed for "
- WINID_FORMAT "\n", atom_name,
- pev->window);
- XFree(atom_name);
- } else {
- xkl_debug(200,
- "Some magic property changed for "
- WINID_FORMAT "\n", pev->window);
- }
- }
-
- if (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES) {
- if (pev->atom == xkl_engine_priv(engine, atoms)[WM_STATE]) {
- gboolean has_xkl_state =
- xkl_engine_get_state(engine, pev->window,
- NULL);
-
- if (pev->state == PropertyNewValue) {
- xkl_debug(160,
- "New value of WM_STATE on window "
- WINID_FORMAT "\n", pev->window);
- if (!has_xkl_state) { /* Is this event the first or not? */
- xkl_engine_add_toplevel_window
- (engine, pev->window, (Window)
- NULL, FALSE,
- &xkl_engine_priv(engine,
- curr_state));
- }
- } else { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
- xkl_debug(160,
- "Something (%d) happened to WM_STATE of window 0x%x\n",
- pev->state, pev->window);
- xkl_engine_select_input_merging(engine,
- pev->
- window,
- PropertyChangeMask);
- if (has_xkl_state) {
- xkl_engine_delete_state(engine,
- pev->
- window);
- }
- }
- } else
- if (pev->atom ==
- xkl_engine_priv(engine, base_config_atom)
- && pev->window == xkl_engine_priv(engine,
- root_window)) {
- if (pev->state == PropertyNewValue) {
- /* If root window got new *_NAMES_PROP_ATOM -
- it most probably means new keyboard config is loaded by somebody */
- xkl_engine_reset_all_info
- (engine,
- "New value of *_NAMES_PROP_ATOM on root window");
- }
- }
- } /* XKLL_MANAGE_WINDOW_STATES */
+ if( 400 <= _xklDebugLevel )
+ {
+ char *atomName = XGetAtomName( _xklDpy, pev->atom );
+ if( atomName != NULL )
+ {
+ XklDebug( 400, "The property '%s' changed for " WINID_FORMAT "\n",
+ atomName, pev->window );
+ XFree( atomName );
+ } else
+ {
+ XklDebug( 200, "Some magic property changed for " WINID_FORMAT "\n",
+ pev->window );
+ }
+ }
+
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ {
+ if( pev->atom == _xklAtoms[WM_STATE] )
+ {
+ Bool hasXklState = XklGetState( pev->window, NULL );
+
+ if( pev->state == PropertyNewValue )
+ {
+ XklDebug( 160, "New value of WM_STATE on window " WINID_FORMAT "\n",
+ pev->window );
+ if( !hasXklState ) /* Is this event the first or not? */
+ {
+ _XklAddAppWindow( pev->window, ( Window ) NULL, False,
+ &_xklCurState );
+ }
+ } else
+ { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
+ XklDebug( 160, "Something (%d) happened to WM_STATE of window 0x%x\n",
+ pev->state, pev->window );
+ _XklSelectInputMerging( pev->window, PropertyChangeMask );
+ if( hasXklState )
+ {
+ XklDelState( pev->window );
+ }
+ }
+ } else
+ if( pev->atom == xklVTable->baseConfigAtom
+ && pev->window == _xklRootWindow )
+ {
+ if( pev->state == PropertyNewValue )
+ {
+ /* If root window got new *_NAMES_PROP_ATOM -
+ it most probably means new keyboard config is loaded by somebody */
+ _XklResetAllInfo( "New value of *_NAMES_PROP_ATOM on root window" );
+ }
+ }
+ } /* XKLL_MANAGE_WINDOW_STATES */
}
-/*
+/**
* CreateNotify handler. Just interested in properties and focus events...
*/
-void
-xkl_engine_process_create_window_evt(XklEngine * engine,
- XCreateWindowEvent * cev)
+void _XklCreateEvHandler( XCreateWindowEvent * cev )
{
- if (!
- (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES))
- return;
-
- xkl_debug(200,
- "Under-root window " WINID_FORMAT
- "/%s (%d,%d,%d x %d) is created\n", cev->window,
- xkl_get_debug_window_title(engine, cev->window), cev->x,
- cev->y, cev->width, cev->height);
-
- if (!cev->override_redirect) {
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
+ XklDebug( 200,
+ "Under-root window " WINID_FORMAT
+ "/%s (%d,%d,%d x %d) is created\n", cev->window,
+ _XklGetDebugWindowTitle( cev->window ), cev->x, cev->y,
+ cev->width, cev->height );
+
+ if( !cev->override_redirect )
+ {
/* ICCCM 4.1.6: override-redirect is NOT private to
* client (and must not be changed - am I right?)
* We really need only PropertyChangeMask on this window but even in the case of
@@ -435,173 +329,134 @@ xkl_engine_process_create_window_evt(XklEngine * engine,
* event + SelectInput request is not zero) and we definitely will (my system DO)
* lose FocusIn/Out events after the following call of PropertyNotifyHandler.
* So I just decided to purify this extra FocusChangeMask in the FocusIn/OutHandler. */
- xkl_engine_select_input_merging(engine, cev->window,
- PropertyChangeMask |
- FocusChangeMask);
-
- if (xkl_engine_if_window_has_wm_state(engine, cev->window)) {
- xkl_debug(200,
- "Just created window already has WM_STATE - so I'll add it");
- xkl_engine_add_toplevel_window(engine, cev->window,
- (Window) NULL,
- FALSE,
- &xkl_engine_priv
- (engine,
- curr_state));
- }
- }
+ _XklSelectInputMerging( cev->window,
+ PropertyChangeMask | FocusChangeMask );
+
+ if( _XklHasWmState( cev->window ) )
+ {
+ XklDebug( 200,
+ "Just created window already has WM_STATE - so I'll add it" );
+ _XklAddAppWindow( cev->window, ( Window ) NULL, False, &_xklCurState );
+ }
+ }
}
-/*
+/**
* Just error handler - sometimes we get BadWindow error for already gone
* windows, so we'll just ignore
*/
-void
-xkl_process_error(Display * dpy, XErrorEvent * evt)
+void _XklErrHandler( Display * dpy, XErrorEvent * evt )
{
- char buf[128] = "";
- XklEngine *engine = xkl_get_the_engine();
-
- xkl_engine_priv(engine, last_error_code) = evt->error_code;
- switch (xkl_engine_priv(engine, last_error_code)) {
- case BadWindow:
- case BadAccess:
- {
- XGetErrorText(xkl_engine_get_display(engine),
- evt->error_code, buf,
- sizeof(buf));
- /* in most cases this means we are late:) */
- xkl_debug(200,
- "ERROR: %p, " WINID_FORMAT ", %d [%s], "
- "X11 request: %d, minor code: %d\n", dpy,
- (unsigned long) evt->resourceid,
- (int) evt->error_code, buf,
- (int) evt->request_code,
- (int) evt->minor_code);
- break;
- }
- default:
- (*xkl_engine_priv(engine, default_error_handler)) (dpy,
- evt);
- }
+ char buf[128] = "";
+ _xklLastErrorCode = evt->error_code;
+ switch ( _xklLastErrorCode )
+ {
+ case BadWindow:
+ case BadAccess:
+ {
+ XGetErrorText( dpy, _xklLastErrorCode, buf, sizeof(buf) );
+ /* in most cases this means we are late:) */
+ XklDebug( 200, "ERROR: %p, " WINID_FORMAT ", %d [%s], "
+ "X11 request: %d, minor code: %d\n",
+ dpy,
+ ( unsigned long ) evt->resourceid,
+ ( int ) evt->error_code, buf,
+ ( int ) evt->request_code,
+ ( int ) evt->minor_code );
+ break;
+ }
+ default:
+ XklDebug( 200, "Unexpected by libxklavier X ERROR: %p, " WINID_FORMAT ", %d [%s], "
+ "X11 request: %d, minor code: %d\n",
+ dpy,
+ ( unsigned long ) evt->resourceid,
+ ( int ) evt->error_code, buf,
+ ( int ) evt->request_code,
+ ( int ) evt->minor_code );
+ if( !_xklCriticalSection )
+ ( *_xklDefaultErrHandler ) ( dpy, evt );
+ }
}
-/*
+/**
* Some common functionality for Xkb handler
*/
-void
-xkl_engine_process_state_modification(XklEngine * engine,
- XklEngineStateChange change_type,
- gint grp, guint inds,
- gboolean set_inds)
+void _XklStateModificationHandler( XklStateChange changeType,
+ int grp,
+ unsigned inds,
+ Bool setInds )
{
- Window focused, focused_toplevel;
- XklState old_state;
- gint revert;
- gboolean have_old_state = TRUE;
- gboolean set_group = change_type == GROUP_CHANGED;
-
- XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert);
-
- if ((focused == None) || (focused == PointerRoot)) {
- xkl_debug(160, "Something with focus: " WINID_FORMAT "\n",
- focused);
- return;
- }
-
- /*
- * Only if we manage states - otherwise xkl_engine_priv(engine,curr_toplvl_win) does not make sense
- */
- if (!xkl_engine_find_toplevel_window
- (engine, focused, &focused_toplevel)
- && xkl_engine_priv(engine,
- listener_type) & XKLL_MANAGE_WINDOW_STATES)
- focused_toplevel = xkl_engine_priv(engine, curr_toplvl_win); /* what else can I do */
-
- xkl_debug(150, "Focused window: " WINID_FORMAT ", '%s'\n",
- focused_toplevel,
- xkl_get_debug_window_title(engine, focused_toplevel));
- if (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES) {
- xkl_debug(150, "CurClient: " WINID_FORMAT ", '%s'\n",
- xkl_engine_priv(engine, curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)));
-
- if (focused_toplevel !=
- xkl_engine_priv(engine, curr_toplvl_win)) {
- /*
- * If not state - we got the new window
- */
- if (!xkl_engine_get_toplevel_window_state
- (engine, focused_toplevel, &old_state)) {
- xkl_engine_update_current_state(engine,
- grp, inds,
- "Updating the state from new focused window");
- if (xkl_engine_priv(engine, listener_type)
- & XKLL_MANAGE_WINDOW_STATES)
- xkl_engine_add_toplevel_window
- (engine, focused_toplevel,
- (Window) NULL, FALSE,
- &xkl_engine_priv(engine,
- curr_state));
- }
- /*
- * There is state - just get the state from the window
- */
- else {
- grp = old_state.group;
- inds = old_state.indicators;
- }
- xkl_engine_priv(engine, curr_toplvl_win) =
- focused_toplevel;
- xkl_debug(160,
- "CurClient:changed to " WINID_FORMAT
- ", '%s'\n", xkl_engine_priv(engine,
- curr_toplvl_win),
- xkl_get_debug_window_title(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win)));
- }
- /* If the window already has this this state - we are just restoring it!
- (see the second parameter of stateCallback */
- have_old_state =
- xkl_engine_get_toplevel_window_state(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- &old_state);
- } else { /* just tracking the stuff, no smart things */
-
- xkl_debug(160,
- "Just updating the current state in the tracking mode\n");
- memcpy(&old_state, &xkl_engine_priv(engine, curr_state),
- sizeof(XklState));
- }
-
- if (set_group || have_old_state) {
- xkl_engine_update_current_state(engine,
- set_group ? grp :
- old_state.group,
- set_inds ? inds :
- old_state.indicators,
- "Restoring the state from the window");
- }
-
- if (have_old_state)
- xkl_engine_try_call_state_func(engine, change_type,
- &old_state);
-
- if (xkl_engine_priv(engine, listener_type) &
- XKLL_MANAGE_WINDOW_STATES)
- xkl_engine_save_toplevel_window_state(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- &xkl_engine_priv
- (engine,
- curr_state));
+ Window focused, focusedApp;
+ XklState oldState;
+ int revert;
+ Bool haveOldState = True;
+ Bool setGroup = changeType == GROUP_CHANGED;
+
+ XGetInputFocus( _xklDpy, &focused, &revert );
+
+ if( ( focused == None ) || ( focused == PointerRoot ) )
+ {
+ XklDebug( 160, "Something with focus: " WINID_FORMAT "\n", focused );
+ return;
+ }
+
+ /**
+ * Only if we manage states - otherwise _xklCurClient does not make sense
+ */
+ if( !_XklGetAppWindow( focused, &focusedApp ) &&
+ _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ focusedApp = _xklCurClient; /* what else can I do */
+
+ XklDebug( 150, "Focused window: " WINID_FORMAT ", '%s'\n", focusedApp,
+ _XklGetDebugWindowTitle( focusedApp ) );
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ {
+ XklDebug( 150, "CurClient: " WINID_FORMAT ", '%s'\n", _xklCurClient,
+ _XklGetDebugWindowTitle( _xklCurClient ) );
+
+ if( focusedApp != _xklCurClient )
+ {
+ /**
+ * If not state - we got the new window
+ */
+ if ( !_XklGetAppState( focusedApp, &oldState ) )
+ {
+ _XklUpdateCurState( grp, inds,
+ "Updating the state from new focused window" );
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ _XklAddAppWindow( focusedApp, ( Window ) NULL, False, &_xklCurState );
+ }
+ /**
+ * There is state - just get the state from the window
+ */
+ else
+ {
+ grp = oldState.group;
+ inds = oldState.indicators;
+ }
+ _xklCurClient = focusedApp;
+ XklDebug( 160, "CurClient:changed to " WINID_FORMAT ", '%s'\n",
+ _xklCurClient, _XklGetDebugWindowTitle( _xklCurClient ) );
+ }
+ /* If the window already has this this state - we are just restoring it!
+ (see the second parameter of stateCallback */
+ haveOldState = _XklGetAppState( _xklCurClient, &oldState );
+ } else /* just tracking the stuff, no smart things */
+ {
+ XklDebug( 160, "Just updating the current state in the tracking mode\n" );
+ memcpy( &oldState, &_xklCurState, sizeof( XklState ) );
+ }
+
+ if( setGroup || haveOldState )
+ {
+ _XklUpdateCurState( setGroup ? grp : oldState.group,
+ setInds ? inds : oldState.indicators,
+ "Restoring the state from the window" );
+ }
+
+ if( haveOldState )
+ _XklTryCallStateCallback( changeType, &oldState );
+
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ _XklSaveAppState( _xklCurClient, &_xklCurState );
}
diff --git a/libxklavier/xklavier_private.h b/libxklavier/xklavier_private.h
index 30aef9e..7fbc6f5 100644
--- a/libxklavier/xklavier_private.h
+++ b/libxklavier/xklavier_private.h
@@ -3,384 +3,352 @@
#include <stdio.h>
-#include <libxml/xpath.h>
+#include <libxklavier/xklavier_config.h>
-#include <libxklavier/xklavier.h>
+typedef Bool ( *XklConfigActivateHandler )( const XklConfigRecPtr data );
-enum { WM_NAME,
- WM_STATE,
- XKLAVIER_STATE,
- XKLAVIER_TRANSPARENT,
- XKLAVIER_ALLOW_SECONDARY,
- TOTAL_ATOMS
-};
-
-struct _XklEnginePrivate {
-
- gboolean group_per_toplevel_window;
-
- gboolean handle_indicators;
-
- gboolean skip_one_restore;
-
- gint default_group;
-
- guint listener_type;
-
- guint secondary_groups_mask;
-
- Window root_window;
-
- Window prev_toplvl_win;
-
- Window curr_toplvl_win;
-
- XErrorHandler default_error_handler;
-
- Status last_error_code;
-
- XklState curr_state;
-
- Atom atoms[TOTAL_ATOMS];
-
- Display *display;
-
- /*
- * Backend name
- */
- const gchar *backend_id;
-
- /*
- * Functions supported by the backend, combination of XKLF_* constants
- */
- guint8 features;
-
- /*
- * Activates the configuration.
- * xkb: create proper the XkbDescRec and send it to the server
- * xmodmap: save the property, init layout #1
- */
- gboolean(*activate_config_rec) (XklEngine * engine,
- const XklConfigRec * data);
-
- /*
- * Background-specific initialization.
- * xkb: XkbInitAtoms - init internal xkb atoms table
- * xmodmap: void.
- */
- void (*init_config_registry) (XklConfigRegistry * config);
-
- /*
- * Loads the registry tree into DOM (using whatever path(s))
- * The XklVTConfigFreeRegistry is static - no virtualization necessary.
- * xkb: loads xml from XKB_BASE+"/rules/"+ruleset+".xml"
- * xmodmap: loads xml from XMODMAP_BASE+"/"+ruleset+".xml"
- */
- gboolean(*load_config_registry) (XklConfigRegistry * config);
-
- /*
- * Write the configuration into the file (binary/textual)
- * xkb: write xkb or xkm file
- * xmodmap: if text requested, just dump XklConfigRec to the
- * file - not really useful. If binary - fail (not supported)
- */
- gboolean(*write_config_rec_to_file) (XklEngine * engine,
- const gchar * file_name,
- const XklConfigRec * data,
- const gboolean binary);
-
- /*
- * Get the list of the group names
- * xkb: return cached list of the group names
- * xmodmap: return the list of layouts from the internal XklConfigRec
- */
- const gchar **(*get_groups_names) (XklEngine * engine);
-
- /*
- * Get the maximum number of loaded groups
- * xkb: returns 1 or XkbNumKbdGroups
- * xmodmap: return 0
- */
- guint(*get_max_num_groups) (XklEngine * engine);
-
- /*
- * Get the number of loaded groups
- * xkb: return from the cached XkbDesc
- * xmodmap: return number of layouts from internal XklConfigRec
- */
- guint(*get_num_groups) (XklEngine * engine);
-
- /*
- * Switches the keyboard to the group N
- * xkb: simple one-liner to call the XKB function
- * xmodmap: changes the root window property
- * (listener invokes xmodmap with appropriate config file).
- */
- void (*lock_group) (XklEngine * engine, gint group);
-
- /*
- * Handles X events.
- * xkb: XkbEvent handling
- * xmodmap: keep track on the root window properties. What else can we do?
- */
- gint(*process_x_event) (XklEngine * engine, XEvent * xev);
-
- /*
- * Flushes the cached server config info.
- * xkb: frees XkbDesc
- * xmodmap: frees internal XklConfigRec
- */
- void (*free_all_info) (XklEngine * engine);
-
- /*
- * Compares the cached info with the actual one, from the server
- * xkb: Compares some parts of XkbDescPtr
- * xmodmap: returns False
- */
- gboolean(*if_cached_info_equals_actual) (XklEngine * engine);
-
- /*
- * Loads the configuration info from the server
- * xkb: loads XkbDesc, names, indicators
- * xmodmap: loads internal XklConfigRec from server
- */
- gboolean(*load_all_info) (XklEngine * engine);
-
- /*
- * Gets the current state
- * xkb: XkbGetState and XkbGetIndicatorState
- * xmodmap: check the root window property (regarding the group)
- */
- void (*get_server_state) (XklEngine * engine,
- XklState * current_state_out);
-
- /*
- * Stop tracking the keyboard-related events
- * xkb: XkbSelectEvents(..., 0)
- * xmodmap: Ungrab the switching shortcut.
- */
- gint(*pause_listen) (XklEngine * engine);
-
- /*
- * Start tracking the keyboard-related events
- * xkb: XkbSelectEvents + XkbSelectEventDetails
- * xmodmap: Grab the switching shortcut.
- */
- gint(*resume_listen) (XklEngine * engine);
-
- /*
- * Set the indicators state from the XklState
- * xkb: XklSetIndicator for all indicators
- * xmodmap: NULL. Not supported
- */
- void (*set_indicators) (XklEngine * engine,
- const XklState * window_state);
-
- /*
- * Perform the cleanup
- */
- void (*finalize) (XklEngine * engine);
-
- /* all data is private - no direct access */
- /*
- * The base configuration atom.
- * xkb: _XKB_RF_NAMES_PROP_ATOM
- * xmodmap: "_XMM_NAMES"
- */
- Atom base_config_atom;
-
- /*
- * The configuration backup atom
- * xkb: "_XKB_RULES_NAMES_BACKUP"
- * xmodmap: "_XMM_NAMES_BACKUP"
- */
- Atom backup_config_atom;
-
- /*
- * Fallback for missing model
- */
- const gchar *default_model;
-
- /*
- * Fallback for missing layout
- */
- const gchar *default_layout;
-
- /*
- * Any stuff backend might need to put in here
- */
- gpointer backend;
-};
-
-extern XklEngine *xkl_get_the_engine(void);
-
-struct _XklConfigRegistryPrivate {
- XklEngine *engine;
-
- xmlDocPtr doc;
-
- xmlXPathContextPtr xpath_context;
-};
-
-extern void xkl_engine_ensure_vtable_inited(XklEngine * engine);
-
-extern void xkl_engine_process_focus_in_evt(XklEngine * engine,
- XFocusChangeEvent * fev);
-extern void xkl_engine_process_focus_out_evt(XklEngine * engine,
- XFocusChangeEvent * fev);
-extern void xkl_engine_process_property_evt(XklEngine * engine,
- XPropertyEvent * rev);
-extern void xkl_engine_process_create_window_evt(XklEngine * engine,
- XCreateWindowEvent * cev);
-
-extern void xkl_process_error(Display * dpy, XErrorEvent * evt);
-
-extern void xkl_engine_process_state_modification(XklEngine * engine,
- XklEngineStateChange
- change_type, gint group,
- unsigned inds,
- gboolean set_indicators);
-
-extern Window xkl_engine_get_registered_parent(XklEngine * engine,
- Window win);
-extern void xkl_engine_reset_all_info(XklEngine * engine,
- const gchar reason[]);
-extern gboolean xkl_engine_load_window_tree(XklEngine * engine);
-extern gboolean xkl_engine_load_subtree(XklEngine * engine, Window window,
- gint level, XklState * init_state);
-
-extern gboolean xkl_engine_if_window_has_wm_state(XklEngine * engine,
- Window win);
-
-
-/**
- * Toplevel window stuff
- */
-extern void xkl_engine_add_toplevel_window(XklEngine * engine, Window win,
- Window parent, gboolean force,
- XklState * init_state);
-
-extern gboolean xkl_engine_find_toplevel_window_bottom_to_top(XklEngine *
- engine,
- Window win,
- Window *
- toplevel_win_out);
+typedef void ( *XklConfigInitHandler )( void );
+
+typedef Bool ( *XklConfigLoadRegistryHandler )( void );
+
+typedef Bool ( *XklConfigWriteFileHandler )( const char *fileName,
+ const XklConfigRecPtr data,
+ const Bool binary );
+
+typedef int ( *XklEventHandler )( XEvent *xev );
+
+typedef void ( *XklFreeAllInfoHandler )( void );
+
+typedef const char **( *XklGetGroupNamesHandler )( void );
+
+typedef unsigned ( *XklGetMaxNumGroupsHandler )( void );
+
+typedef unsigned ( *XklGetNumGroupsHandler )( void );
+
+typedef void ( *XklGetRealStateHandler)( XklState * curState_return );
+
+typedef Bool ( *XklIfCachedInfoEqualsActualHandler) ( void );
+
+typedef Bool ( *XklLoadAllInfoHandler )( void );
+
+typedef void ( *XklLockGroupHandler )( int group );
+
+typedef int ( *XklPauseResumeListenHandler )( void );
+
+typedef void ( *XklSetIndicatorsHandler )( const XklState *windowState );
+
+typedef struct
+{
+ /**
+ * Backend name
+ */
+ const char *id;
+
+ /**
+ * Functions supported by the backend, combination of XKLF_* constants
+ */
+ int features;
+
+ /**
+ * Activates the configuration.
+ * xkb: create proper the XkbDescRec and send it to the server
+ * xmodmap: save the property, init layout #1
+ */
+ XklConfigActivateHandler xklConfigActivateHandler;
+
+ /**
+ * Background-specific initialization.
+ * xkb: XkbInitAtoms - init internal xkb atoms table
+ * xmodmap: void.
+ */
+ XklConfigInitHandler xklConfigInitHandler; /* private */
+
+ /**
+ * Loads the registry tree into DOM (using whatever path(s))
+ * The XklConfigFreeRegistry is static - no virtualization necessary.
+ * xkb: loads xml from XKB_BASE+"/rules/"+ruleset+".xml"
+ * xmodmap: loads xml from XMODMAP_BASE+"/"+ruleset+".xml"
+ */
+ XklConfigLoadRegistryHandler xklConfigLoadRegistryHandler;
+
+ /**
+ * Write the configuration into the file (binary/textual)
+ * xkb: write xkb or xkm file
+ * xmodmap: if text requested, just dump XklConfigRec to the
+ * file - not really useful. If binary - fail (not supported)
+ */
+ XklConfigWriteFileHandler xklConfigWriteFileHandler;
+
+ /**
+ * Handles X events.
+ * xkb: XkbEvent handling
+ * xmodmap: keep track on the root window properties. What else can we do?
+ */
+ XklEventHandler xklEventHandler;
+
+ /**
+ * Flushes the cached server config info.
+ * xkb: frees XkbDesc
+ * xmodmap: frees internal XklConfigRec
+ */
+ XklFreeAllInfoHandler xklFreeAllInfoHandler; /* private */
+
+ /**
+ * Get the list of the group names
+ * xkb: return cached list of the group names
+ * xmodmap: return the list of layouts from the internal XklConfigRec
+ */
+ XklGetGroupNamesHandler xklGetGroupNamesHandler;
+
+ /**
+ * Get the maximum number of loaded groups
+ * xkb: returns 1 or XkbNumKbdGroups
+ * xmodmap: return 0
+ */
+ XklGetMaxNumGroupsHandler xklGetMaxNumGroupsHandler;
+
+ /**
+ * Get the number of loaded groups
+ * xkb: return from the cached XkbDesc
+ * xmodmap: return number of layouts from internal XklConfigRec
+ */
+ XklGetNumGroupsHandler xklGetNumGroupsHandler;
+
+ /**
+ * Gets the current stateCallback
+ * xkb: XkbGetState and XkbGetIndicatorState
+ * xmodmap: check the root window property (regarding the group)
+ */
+ XklGetRealStateHandler xklGetRealStateHandler;
+
+ /**
+ * Compares the cached info with the actual one, from the server
+ * xkb: Compares some parts of XkbDescPtr
+ * xmodmap: returns False
+ */
+ XklIfCachedInfoEqualsActualHandler xklIfCachedInfoEqualsActualHandler;
+
+ /**
+ * Loads the configuration info from the server
+ * xkb: loads XkbDesc, names, indicators
+ * xmodmap: loads internal XklConfigRec from server
+ */
+ XklLoadAllInfoHandler xklLoadAllInfoHandler; /* private */
+
+ /**
+ * Switches the keyboard to the group N
+ * xkb: simple one-liner to call the XKB function
+ * xmodmap: changes the root window property
+ * (listener invokes xmodmap with appropriate config file).
+ */
+ XklLockGroupHandler xklLockGroupHandler;
+
+ /**
+ * Stop tracking the keyboard-related events
+ * xkb: XkbSelectEvents(..., 0)
+ * xmodmap: Ungrab the switching shortcut.
+ */
+ XklPauseResumeListenHandler xklPauseListenHandler;
+
+ /**
+ * Start tracking the keyboard-related events
+ * xkb: XkbSelectEvents + XkbSelectEventDetails
+ * xmodmap: Grab the switching shortcut.
+ */
+ XklPauseResumeListenHandler xklResumeListenHandler;
+
+ /**
+ * Set the indicators state from the XklState
+ * xkb: _XklSetIndicator for all indicators
+ * xmodmap: NULL. Not supported
+ */
+ XklSetIndicatorsHandler xklSetIndicatorsHandler; /* private */
+
+ /* all data is private - no direct access */
+ /**
+ * The base configuration atom.
+ * xkb: _XKB_RF_NAMES_PROP_ATOM
+ * xmodmap: "_XMM_NAMES"
+ */
+ Atom baseConfigAtom;
+
+ /**
+ * The configuration backup atom
+ * xkb: "_XKB_RULES_NAMES_BACKUP"
+ * xmodmap: "_XMM_NAMES_BACKUP"
+ */
+ Atom backupConfigAtom;
+
+ /**
+ * Fallback for missing model
+ */
+ const char* defaultModel;
+
+ /**
+ * Fallback for missing layout
+ */
+ const char* defaultLayout;
+
+} XklVTable;
+
+extern void _XklEnsureVTableInited( void );
+
+extern void _XklAddAppWindow( Window win, Window parent, Bool force,
+ XklState * initState );
+extern Bool _XklGetAppWindowBottomToTop( Window win, Window * appWin_return );
+extern Bool _XklGetAppWindow( Window win, Window * appWin_return );
+
+extern void _XklFocusInEvHandler( XFocusChangeEvent * fev );
+extern void _XklFocusOutEvHandler( XFocusChangeEvent * fev );
+extern void _XklPropertyEvHandler( XPropertyEvent * rev );
+extern void _XklCreateEvHandler( XCreateWindowEvent * cev );
+
+extern void _XklErrHandler( Display * dpy, XErrorEvent * evt );
+
+extern Window _XklGetRegisteredParent( Window win );
+extern Bool _XklLoadAllInfo( void );
+extern void _XklFreeAllInfo( void );
+extern void _XklResetAllInfo( const char reason[] );
+extern Bool _XklLoadWindowTree( void );
+extern Bool _XklLoadSubtree( Window window, int level, XklState * initState );
+
+extern Bool _XklHasWmState( Window win );
+
+extern Bool _XklGetAppState( Window appWin, XklState * state_return );
+extern void _XklDelAppState( Window appWin );
+extern void _XklSaveAppState( Window appWin, XklState * state );
-extern gboolean xkl_engine_find_toplevel_window(XklEngine * engine,
- Window win,
- Window * toplevel_win_out);
+extern void _XklSelectInputMerging( Window win, long mask );
-extern gboolean xkl_engine_is_toplevel_window_transparent(XklEngine *
- engine,
- Window
- toplevel_win);
+extern char *_XklGetDebugWindowTitle( Window win );
-extern void xkl_engine_set_toplevel_window_transparent(XklEngine * engine,
- Window toplevel_win,
- gboolean
- transparent);
+extern Status _XklStatusQueryTree( Display * display,
+ Window w,
+ Window * root_return,
+ Window * parent_return,
+ Window ** children_return,
+ unsigned int *nchildren_return );
-extern gboolean xkl_engine_get_toplevel_window_state(XklEngine * engine,
- Window toplevel_win,
- XklState * state_out);
+extern Bool _XklSetIndicator( int indicatorNum, Bool set );
-extern void xkl_engine_remove_toplevel_window_state(XklEngine * engine,
- Window toplevel_win);
-extern void xkl_engine_save_toplevel_window_state(XklEngine * engine,
- Window toplevel_win,
- XklState * state);
-/***/
+extern void _XklTryCallStateCallback( XklStateChange changeType,
+ XklState * oldState );
-extern void xkl_engine_select_input_merging(XklEngine * engine, Window win,
- gulong mask);
+extern void _XklI18NInit( );
-extern gchar *xkl_get_debug_window_title(XklEngine * engine, Window win);
+extern char *_XklLocaleFromUtf8( const char *utf8string );
-extern Status xkl_engine_query_tree(XklEngine * engine,
- Window w,
- Window * root_out,
- Window * parent_out,
- Window ** children_out,
- guint * nchildren_out);
+extern int _XklGetLanguagePriority( const char *language );
-extern void xkl_engine_try_call_state_func(XklEngine * engine,
- XklEngineStateChange
- change_type,
- XklState * old_state);
+extern char* _XklGetRulesSetName( const char defaultRuleset[] );
-extern void xkl_i18n_init(void);
+extern Bool _XklConfigGetFullFromServer( char **rulesFileOut,
+ XklConfigRecPtr data );
-extern gchar *xkl_locale_from_utf8(const gchar * utf8string);
+extern char *_XklConfigRecMergeByComma( const char **array,
+ const int arrayLength );
-extern gint xkl_get_language_priority(const gchar * language);
+extern char *_XklConfigRecMergeLayouts( const XklConfigRecPtr data );
-extern gchar *xkl_engine_get_ruleset_name(XklEngine * engine,
- const gchar default_ruleset[]);
+extern char *_XklConfigRecMergeVariants( const XklConfigRecPtr data );
-extern gboolean xkl_config_rec_get_full_from_server(gchar **
- rules_file_out,
- XklConfigRec * data,
- XklEngine * engine);
+extern char *_XklConfigRecMergeOptions( const XklConfigRecPtr data );
-extern gchar *xkl_strings_concat_comma_separated(gchar ** array);
+extern void _XklConfigRecSplitByComma( char ***array,
+ int *arraySize, const char *merged );
-extern void xkl_strings_split_comma_separated(gchar *** array,
- const gchar * merged);
+extern void _XklConfigRecSplitLayouts( XklConfigRecPtr data,
+ const char *merged );
-/**
- * XConfigRec
- */
-extern gchar *xkl_config_rec_merge_layouts(const XklConfigRec * data);
+extern void _XklConfigRecSplitVariants( XklConfigRecPtr data,
+ const char *merged );
-extern gchar *xkl_config_rec_merge_variants(const XklConfigRec * data);
+extern void _XklConfigRecSplitOptions( XklConfigRecPtr data,
+ const char *merged );
-extern gchar *xkl_config_rec_merge_options(const XklConfigRec * data);
+extern void XklConfigDump( FILE* file,
+ XklConfigRecPtr data );
+
+extern const char *_XklGetEventName( int requestId );
-extern void xkl_config_rec_split_layouts(XklConfigRec * data,
- const gchar * merged);
+extern Bool _XklIsTransparentAppWindow( Window appWin );
-extern void xkl_config_rec_split_variants(XklConfigRec * data,
- const gchar * merged);
+extern void _XklUpdateCurState( int group, unsigned indicators, const char reason[] );
-extern void xkl_config_rec_split_options(XklConfigRec * data,
- const gchar * merged);
-/***/
+extern void _XklStateModificationHandler( XklStateChange changeType,
+ int grp,
+ unsigned inds,
+ Bool setInds );
-extern void xkl_config_rec_dump(FILE * file, XklConfigRec * data);
+extern int _XklXkbInit( void );
-extern const gchar *xkl_event_get_name(gint type);
+extern int _XklXmmInit( void );
-extern void xkl_engine_update_current_state(XklEngine * engine, gint group,
- unsigned indicators,
- const gchar reason[]);
+extern Bool _XklIsOneSwitchToSecondaryGroupAllowed( void );
-extern gint xkl_xkb_init(XklEngine * engine);
+extern void _XklOneSwitchToSecondaryGroupPerformed( void );
-extern gint xkl_xmm_init(XklEngine * engine);
+extern Display *_xklDpy;
-extern gboolean
-xkl_engine_is_one_switch_to_secondary_group_allowed(XklEngine * engine);
+extern Window _xklRootWindow;
-extern void xkl_engine_one_switch_to_secondary_group_performed(XklEngine *
- engine);
+extern XklState _xklCurState;
+
+extern Window _xklCurClient;
+
+extern Status _xklLastErrorCode;
+
+extern const char *_xklLastErrorMsg;
+
+extern XErrorHandler _xklDefaultErrHandler;
+
+extern char *_xklIndicatorNames[];
+
+enum { WM_NAME,
+ WM_STATE,
+ XKLAVIER_STATE,
+ XKLAVIER_TRANSPARENT,
+ XKLAVIER_ALLOW_SECONDARY,
+ TOTAL_ATOMS };
#define XKLAVIER_STATE_PROP_LENGTH 2
/* taken from XFree86 maprules.c */
-#define XKB_RF_NAMES_PROP_MAXLEN 1024
+#define _XKB_RF_NAMES_PROP_MAXLEN 1024
+
+extern Atom _xklAtoms[];
+
+extern Bool _xklAllowSecondaryGroupOnce;
+
+extern int _xklDefaultGroup;
+
+extern Bool _xklSkipOneRestore;
+
+extern int _xklSecondaryGroupsMask;
+
+extern int _xklDebugLevel;
+
+extern int _xklListenerType;
+
+extern Window _xklPrevAppWindow;
#define WINID_FORMAT "%lx"
-#define xkl_engine_priv(engine,member) (engine)->priv->member
-#define xkl_engine_backend(engine,type,member) ((type*)((engine)->priv->backend))->member
-#define xkl_engine_get_display(engine) (xkl_engine_priv(engine,display))
-#define xkl_engine_vcall(engine,func) (*(engine)->priv->func)
+extern XklConfigCallback _xklConfigCallback;
-#define xkl_config_registry_priv(config,member) (config)->priv->member
-#define xkl_config_registry_get_engine(config) ((config)->priv->engine)
+extern void *_xklConfigCallbackData;
-extern gint xkl_debug_level;
+extern XklVTable *xklVTable;
-extern const gchar *xkl_last_error_message;
+extern Bool _xklCriticalSection;
+
+#ifdef __STRICT_ANSI__
+/* these are functions which are NOT in ANSI C.
+ Probably we should provide the implementation */
+extern int snprintf( char *s, size_t maxlen,
+ const char *format, ... );
+
+extern char *strdup( const char *s );
+#endif
#endif