summaryrefslogtreecommitdiff
path: root/libxklavier/xklavier_evt.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxklavier/xklavier_evt.c')
-rw-r--r--libxklavier/xklavier_evt.c949
1 files changed, 551 insertions, 398 deletions
diff --git a/libxklavier/xklavier_evt.c b/libxklavier/xklavier_evt.c
index 1540841..40dd41a 100644
--- a/libxklavier/xklavier_evt.c
+++ b/libxklavier/xklavier_evt.c
@@ -1,327 +1,433 @@
+#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"
-int XklFilterEvents( XEvent * xev )
+gint
+xkl_engine_filter_events(XklEngine * engine, XEvent * xev)
{
- 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;
+ 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;
}
-/**
+/*
* FocusIn handler
*/
-void _XklFocusInEvHandler( XFocusChangeEvent * fev )
+void
+xkl_engine_process_focus_in_evt(XklEngine * engine,
+ XFocusChangeEvent * fev)
{
- 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" );
- }
+ 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");
+ }
}
-/**
+/*
* FocusOut handler
*/
-void _XklFocusOutEvHandler( XFocusChangeEvent * fev )
+void
+xkl_engine_process_focus_out_evt(XklEngine * engine,
+ XFocusChangeEvent * fev)
{
- 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 (!
+ (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 we are leaving the transparent window - we skip the restore operation.
* This is useful for secondary groups switching from the transparent control
* window.
*/
- _xklSkipOneRestore = True;
- } else
- {
- Window p;
- if( _XklGetAppWindow( fev->window, &p ) )
- _xklPrevAppWindow = p;
- }
+ 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;
+ }
}
-/**
+/*
* PropertyChange handler
* Interested in :
* + for XKLL_MANAGE_WINDOW_STATES
* - WM_STATE property for all windows
* - Configuration property of the root window
*/
-void _XklPropertyEvHandler( XPropertyEvent * pev )
+void
+xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * pev)
{
- 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 */
+ 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 */
}
-/**
+/*
* CreateNotify handler. Just interested in properties and focus events...
*/
-void _XklCreateEvHandler( XCreateWindowEvent * cev )
+void
+xkl_engine_process_create_window_evt(XklEngine * engine,
+ XCreateWindowEvent * cev)
{
- 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 )
- {
+ 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) {
/* 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
@@ -329,126 +435,173 @@ void _XklCreateEvHandler( XCreateWindowEvent * cev )
* 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. */
- _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 );
- }
- }
+ 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));
+ }
+ }
}
-/**
+/*
* Just error handler - sometimes we get BadWindow error for already gone
* windows, so we'll just ignore
*/
-void _XklErrHandler( Display * dpy, XErrorEvent * evt )
+void
+xkl_process_error(Display * dpy, XErrorEvent * 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:
- ( *_xklDefaultErrHandler ) ( dpy, 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);
+ }
}
-/**
+/*
* Some common functionality for Xkb handler
*/
-void _XklStateModificationHandler( XklStateChange changeType,
- int grp,
- unsigned inds,
- Bool setInds )
+void
+xkl_engine_process_state_modification(XklEngine * engine,
+ XklEngineStateChange change_type,
+ gint grp, guint inds,
+ gboolean set_inds)
{
- 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 );
+ 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));
}