Blame libxklavier/xklavier_evt.c

Packit Service 93d855
/*
Packit Service 93d855
 * Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org>
Packit Service 93d855
 *
Packit Service 93d855
 * This library is free software; you can redistribute it and/or
Packit Service 93d855
 * modify it under the terms of the GNU Lesser General Public
Packit Service 93d855
 * License as published by the Free Software Foundation; either
Packit Service 93d855
 * version 2 of the License, or (at your option) any later version.
Packit Service 93d855
 *
Packit Service 93d855
 * This library is distributed in the hope that it will be useful,
Packit Service 93d855
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 93d855
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 93d855
 * Lesser General Public License for more details.
Packit Service 93d855
 *
Packit Service 93d855
 * You should have received a copy of the GNU Lesser General Public
Packit Service 93d855
 * License along with this library; if not, write to the
Packit Service 93d855
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit Service 93d855
 * Boston, MA 02111-1307, USA.
Packit Service 93d855
 */
Packit Service 93d855
Packit Service 93d855
#include <string.h>
Packit Service 93d855
#include <time.h>
Packit Service 93d855
Packit Service 93d855
#include <X11/Xatom.h>
Packit Service 93d855
#include <X11/Xlib.h>
Packit Service 93d855
#include <X11/Xutil.h>
Packit Service 93d855
Packit Service 93d855
#include "xklavier_private.h"
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_engine_filter_events(XklEngine * engine, XEvent * xev)
Packit Service 93d855
{
Packit Service 93d855
	XAnyEvent *pe = (XAnyEvent *) xev;
Packit Service 93d855
	xkl_debug(400,
Packit Service 93d855
		  "**> Filtering event %d of type %d from window %d\n",
Packit Service 93d855
		  pe->serial, pe->type, pe->window);
Packit Service 93d855
	xkl_engine_ensure_vtable_inited(engine);
Packit Service 93d855
	if (!xkl_engine_vcall(engine, process_x_event) (engine, xev))
Packit Service 93d855
		switch (xev->type) {	/* core events */
Packit Service 93d855
		case FocusIn:
Packit Service 93d855
			xkl_engine_process_focus_in_evt(engine,
Packit Service 93d855
							&xev->xfocus);
Packit Service 93d855
			break;
Packit Service 93d855
		case FocusOut:
Packit Service 93d855
			xkl_engine_process_focus_out_evt(engine,
Packit Service 93d855
							 &xev->xfocus);
Packit Service 93d855
			break;
Packit Service 93d855
		case PropertyNotify:
Packit Service 93d855
			xkl_engine_process_property_evt(engine,
Packit Service 93d855
							&xev->xproperty);
Packit Service 93d855
			break;
Packit Service 93d855
		case CreateNotify:
Packit Service 93d855
			xkl_engine_process_create_window_evt(engine,
Packit Service 93d855
							     &xev->xcreatewindow);
Packit Service 93d855
			break;
Packit Service 93d855
		case DestroyNotify:
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "Window " WINID_FORMAT " destroyed\n",
Packit Service 93d855
				  xev->xdestroywindow.window);
Packit Service 93d855
			break;
Packit Service 93d855
		case UnmapNotify:
Packit Service 93d855
			xkl_debug(200,
Packit Service 93d855
				  "Window " WINID_FORMAT " unmapped\n",
Packit Service 93d855
				  xev->xunmap.window);
Packit Service 93d855
			break;
Packit Service 93d855
		case MapNotify:
Packit Service 93d855
		case GravityNotify:
Packit Service 93d855
			xkl_debug(200, "%s\n",
Packit Service 93d855
				  xkl_event_get_name(xev->type));
Packit Service 93d855
			break;	/* Ignore these events */
Packit Service 93d855
		case ReparentNotify:
Packit Service 93d855
			xkl_debug(200,
Packit Service 93d855
				  "Window " WINID_FORMAT " reparented to "
Packit Service 93d855
				  WINID_FORMAT "\n", xev->xreparent.window,
Packit Service 93d855
				  xev->xreparent.parent);
Packit Service 93d855
			break;	/* Ignore these events */
Packit Service 93d855
		case MappingNotify:
Packit Service 93d855
			xkl_debug(200, "%s\n",
Packit Service 93d855
				  xkl_event_get_name(xev->type));
Packit Service 93d855
			xkl_engine_reset_all_info(engine, FALSE,
Packit Service 93d855
						  "X event: MappingNotify");
Packit Service 93d855
			break;
Packit Service 93d855
		default:
Packit Service 93d855
			{
Packit Service 93d855
				xkl_debug(200, "Unknown event %d [%s]\n",
Packit Service 93d855
					  xev->type,
Packit Service 93d855
					  xkl_event_get_name(xev->type));
Packit Service 93d855
				return 1;
Packit Service 93d855
			}
Packit Service 93d855
		}
Packit Service 93d855
	xkl_debug(400, "Filtered event %d of type %d from window %d **>\n",
Packit Service 93d855
		  pe->serial, pe->type, pe->window);
Packit Service 93d855
	return 1;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * FocusIn handler
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_engine_process_focus_in_evt(XklEngine * engine,
Packit Service 93d855
				XFocusChangeEvent * fev)
Packit Service 93d855
{
Packit Service 93d855
	Window win;
Packit Service 93d855
	Window prev_toplevel_win =
Packit Service 93d855
	    xkl_engine_priv(engine, curr_toplvl_win);
Packit Service 93d855
	Window toplevel_win;
Packit Service 93d855
	XklState selected_window_state;
Packit Service 93d855
Packit Service 93d855
	if (!
Packit Service 93d855
	    (xkl_engine_is_listening_for
Packit Service 93d855
	     (engine, XKLL_MANAGE_WINDOW_STATES)))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	win = fev->window;
Packit Service 93d855
Packit Service 93d855
	switch (fev->mode) {
Packit Service 93d855
	case NotifyNormal:
Packit Service 93d855
	case NotifyWhileGrabbed:
Packit Service 93d855
		break;
Packit Service 93d855
	default:
Packit Service 93d855
		xkl_debug(160,
Packit Service 93d855
			  "Window " WINID_FORMAT
Packit Service 93d855
			  " has got focus during special action %d\n", win,
Packit Service 93d855
			  fev->mode);
Packit Service 93d855
		return;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_debug(150, "Window " WINID_FORMAT ", '%s' has got focus\n",
Packit Service 93d855
		  win, xkl_get_debug_window_title(engine, win));
Packit Service 93d855
Packit Service 93d855
	if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) {
Packit Service 93d855
		return;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' has got focus\n",
Packit Service 93d855
		  toplevel_win, xkl_get_debug_window_title(engine,
Packit Service 93d855
							   toplevel_win));
Packit Service 93d855
Packit Service 93d855
	if (xkl_engine_get_toplevel_window_state
Packit Service 93d855
	    (engine, toplevel_win, &selected_window_state)) {
Packit Service 93d855
		if (prev_toplevel_win != toplevel_win) {
Packit Service 93d855
			gboolean new_win_transparent;
Packit Service 93d855
			Window parent = (Window) NULL, root =
Packit Service 93d855
			    (Window) NULL, *children = NULL;
Packit Service 93d855
			guint nchildren = 0;
Packit Service 93d855
Packit Service 93d855
			/*
Packit Service 93d855
			 * If previous focused window exists - handle transparency and state
Packit Service 93d855
			 * (optional)
Packit Service 93d855
			 */
Packit Service 93d855
			if (xkl_engine_query_tree
Packit Service 93d855
			    (engine, prev_toplevel_win, &root, &parent,
Packit Service 93d855
			     &children, &nchildren) == Success) {
Packit Service 93d855
				XklState tmp_state;
Packit Service 93d855
				gboolean old_win_transparent =
Packit Service 93d855
				    xkl_engine_is_toplevel_window_transparent
Packit Service 93d855
				    (engine, prev_toplevel_win);
Packit Service 93d855
Packit Service 93d855
				if (children != NULL)
Packit Service 93d855
					XFree(children);
Packit Service 93d855
Packit Service 93d855
				if (old_win_transparent)
Packit Service 93d855
					xkl_debug(150,
Packit Service 93d855
						  "Leaving transparent window\n");
Packit Service 93d855
				/*
Packit Service 93d855
				 * Reload the current state from the current window. 
Packit Service 93d855
				 * Do not do it for transparent window - we keep the state from 
Packit Service 93d855
				 * the _previous_ window.
Packit Service 93d855
				 */
Packit Service 93d855
				if (!old_win_transparent
Packit Service 93d855
				    &&
Packit Service 93d855
				    xkl_engine_get_toplevel_window_state
Packit Service 93d855
				    (engine, prev_toplevel_win,
Packit Service 93d855
				     &tmp_state)) {
Packit Service 93d855
					xkl_engine_update_current_state
Packit Service 93d855
					    (engine, tmp_state.group,
Packit Service 93d855
					     tmp_state.indicators,
Packit Service 93d855
					     "Loading current (previous) state from the current (previous) window");
Packit Service 93d855
				}
Packit Service 93d855
			} else
Packit Service 93d855
				xkl_debug(150,
Packit Service 93d855
					  "Current (previous) window "
Packit Service 93d855
					  WINID_FORMAT
Packit Service 93d855
					  " does not exist any more, so transparency/state are not analyzed\n",
Packit Service 93d855
					  prev_toplevel_win);
Packit Service 93d855
Packit Service 93d855
			xkl_engine_priv(engine, curr_toplvl_win) =
Packit Service 93d855
			    toplevel_win;
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "CurClient:changed to " WINID_FORMAT
Packit Service 93d855
				  ", '%s'\n", xkl_engine_priv(engine,
Packit Service 93d855
							      curr_toplvl_win),
Packit Service 93d855
				  xkl_get_debug_window_title(engine,
Packit Service 93d855
							     xkl_engine_priv
Packit Service 93d855
							     (engine,
Packit Service 93d855
							      curr_toplvl_win)));
Packit Service 93d855
Packit Service 93d855
			new_win_transparent =
Packit Service 93d855
			    xkl_engine_is_toplevel_window_transparent
Packit Service 93d855
			    (engine, toplevel_win);
Packit Service 93d855
			if (new_win_transparent)
Packit Service 93d855
				xkl_debug(150,
Packit Service 93d855
					  "Entering transparent window\n");
Packit Service 93d855
Packit Service 93d855
			if (xkl_engine_is_group_per_toplevel_window(engine)
Packit Service 93d855
			    == !new_win_transparent) {
Packit Service 93d855
				/* We skip restoration only if we return to the same app window */
Packit Service 93d855
				gboolean do_skip = FALSE;
Packit Service 93d855
				if (xkl_engine_priv
Packit Service 93d855
				    (engine, skip_one_restore)) {
Packit Service 93d855
					xkl_engine_priv(engine,
Packit Service 93d855
							skip_one_restore) =
Packit Service 93d855
					    FALSE;
Packit Service 93d855
					if (toplevel_win ==
Packit Service 93d855
					    xkl_engine_priv(engine,
Packit Service 93d855
							    prev_toplvl_win))
Packit Service 93d855
						do_skip = TRUE;
Packit Service 93d855
				}
Packit Service 93d855
Packit Service 93d855
				if (do_skip) {
Packit Service 93d855
					xkl_debug(150,
Packit Service 93d855
						  "Skipping one restore as requested - instead, "
Packit Service 93d855
						  "saving the current group into the window state\n");
Packit Service 93d855
					xkl_engine_save_toplevel_window_state
Packit Service 93d855
					    (engine, toplevel_win,
Packit Service 93d855
					     &xkl_engine_priv(engine,
Packit Service 93d855
							      curr_state));
Packit Service 93d855
				} else {
Packit Service 93d855
					if (xkl_engine_priv
Packit Service 93d855
					    (engine,
Packit Service 93d855
					     curr_state).group !=
Packit Service 93d855
					    selected_window_state.group) {
Packit Service 93d855
						xkl_debug(150,
Packit Service 93d855
							  "Restoring the group from %d to %d after gaining focus\n",
Packit Service 93d855
							  xkl_engine_priv
Packit Service 93d855
							  (engine,
Packit Service 93d855
							   curr_state).group,
Packit Service 93d855
							  selected_window_state.group);
Packit Service 93d855
						/*
Packit Service 93d855
						 *  For fast mouse movements - the state is probably not updated yet
Packit Service 93d855
						 *  (because of the group change notification being late).
Packit Service 93d855
						 *  so we'll enforce the update. But this should only happen in GPA mode
Packit Service 93d855
						 */
Packit Service 93d855
						xkl_engine_update_current_state
Packit Service 93d855
						    (engine,
Packit Service 93d855
						     selected_window_state.group,
Packit Service 93d855
						     selected_window_state.indicators,
Packit Service 93d855
						     "Enforcing fast update of the current state");
Packit Service 93d855
						xkl_engine_lock_group
Packit Service 93d855
						    (engine,
Packit Service 93d855
						     selected_window_state.group);
Packit Service 93d855
						xkl_engine_priv(engine, skip_one_save) = TRUE;
Packit Service 93d855
					} else {
Packit Service 93d855
						xkl_debug(150,
Packit Service 93d855
							  "Both old and new focused window "
Packit Service 93d855
							  "have group %d so no point restoring it\n",
Packit Service 93d855
							  selected_window_state.group);
Packit Service 93d855
						xkl_engine_one_switch_to_secondary_group_performed
Packit Service 93d855
						    (engine);
Packit Service 93d855
					}
Packit Service 93d855
				}
Packit Service 93d855
Packit Service 93d855
				if ((xkl_engine_priv(engine, features) &
Packit Service 93d855
				     XKLF_CAN_TOGGLE_INDICATORS)
Packit Service 93d855
				    &&
Packit Service 93d855
				    xkl_engine_get_indicators_handling
Packit Service 93d855
				    (engine)) {
Packit Service 93d855
					xkl_debug(150,
Packit Service 93d855
						  "Restoring the indicators from %X to %X after gaining focus\n",
Packit Service 93d855
						  xkl_engine_priv(engine,
Packit Service 93d855
								  curr_state).indicators,
Packit Service 93d855
						  selected_window_state.indicators);
Packit Service 93d855
					xkl_engine_ensure_vtable_inited
Packit Service 93d855
					    (engine);
Packit Service 93d855
					xkl_engine_vcall(engine,
Packit Service 93d855
							 set_indicators)
Packit Service 93d855
					    (engine,
Packit Service 93d855
					     &selected_window_state);
Packit Service 93d855
				} else
Packit Service 93d855
					xkl_debug(150,
Packit Service 93d855
						  "Not restoring the indicators %X after gaining focus: indicator handling is not enabled\n",
Packit Service 93d855
						  xkl_engine_priv(engine,
Packit Service 93d855
								  curr_state).indicators);
Packit Service 93d855
			} else
Packit Service 93d855
				xkl_debug(150,
Packit Service 93d855
					  "Not restoring the group %d after gaining focus: global layout (xor transparent window)\n",
Packit Service 93d855
					  xkl_engine_priv(engine,
Packit Service 93d855
							  curr_state).group);
Packit Service 93d855
		} else
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "Same app window - just do nothing\n");
Packit Service 93d855
	} else {
Packit Service 93d855
		xkl_debug(150, "But it does not have xklavier_state\n");
Packit Service 93d855
		if (xkl_engine_if_window_has_wm_state(engine, win)) {
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "But it does have wm_state so we'll add it\n");
Packit Service 93d855
			xkl_engine_priv(engine, curr_toplvl_win) =
Packit Service 93d855
			    toplevel_win;
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "CurClient:changed to " WINID_FORMAT
Packit Service 93d855
				  ", '%s'\n", xkl_engine_priv(engine,
Packit Service 93d855
							      curr_toplvl_win),
Packit Service 93d855
				  xkl_get_debug_window_title(engine,
Packit Service 93d855
							     xkl_engine_priv
Packit Service 93d855
							     (engine,
Packit Service 93d855
							      curr_toplvl_win)));
Packit Service 93d855
			xkl_engine_add_toplevel_window(engine,
Packit Service 93d855
						       xkl_engine_priv
Packit Service 93d855
						       (engine,
Packit Service 93d855
							curr_toplvl_win),
Packit Service 93d855
						       (Window) NULL,
Packit Service 93d855
						       FALSE,
Packit Service 93d855
						       &xkl_engine_priv
Packit Service 93d855
						       (engine,
Packit Service 93d855
							curr_state));
Packit Service 93d855
		} else
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "And it does have wm_state either\n");
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/* 
Packit Service 93d855
 * FocusOut handler
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_engine_process_focus_out_evt(XklEngine * engine,
Packit Service 93d855
				 XFocusChangeEvent * fev)
Packit Service 93d855
{
Packit Service 93d855
	if (!
Packit Service 93d855
	    (xkl_engine_is_listening_for
Packit Service 93d855
	     (engine, XKLL_MANAGE_WINDOW_STATES)))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	if (fev->mode != NotifyNormal) {
Packit Service 93d855
		xkl_debug(200,
Packit Service 93d855
			  "Window " WINID_FORMAT
Packit Service 93d855
			  " has lost focus during special action %d\n",
Packit Service 93d855
			  fev->window, fev->mode);
Packit Service 93d855
		return;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_debug(160, "Window " WINID_FORMAT ", '%s' has lost focus\n",
Packit Service 93d855
		  fev->window, xkl_get_debug_window_title(engine,
Packit Service 93d855
							  fev->window));
Packit Service 93d855
Packit Service 93d855
	if (xkl_engine_is_toplevel_window_transparent(engine, fev->window)) {
Packit Service 93d855
		xkl_debug(150, "Leaving transparent window!\n");
Packit Service 93d855
/* 
Packit Service 93d855
 * If we are leaving the transparent window - we skip the restore operation.
Packit Service 93d855
 * This is useful for secondary groups switching from the transparent control 
Packit Service 93d855
 * window.
Packit Service 93d855
 */
Packit Service 93d855
		xkl_engine_priv(engine, skip_one_restore) = TRUE;
Packit Service 93d855
	} else {
Packit Service 93d855
		Window p;
Packit Service 93d855
		if (xkl_engine_find_toplevel_window
Packit Service 93d855
		    (engine, fev->window, &p))
Packit Service 93d855
			xkl_engine_priv(engine, prev_toplvl_win) = p;
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * PropertyChange handler
Packit Service 93d855
 * Interested in :
Packit Service 93d855
 *  + for XKLL_MANAGE_WINDOW_STATES
Packit Service 93d855
 *    - WM_STATE property for all windows
Packit Service 93d855
 *    - Configuration property of the root window
Packit Service 93d855
 *  + for XKLL_TRACK_KEYBOARD_STATE
Packit Service 93d855
 *    - Configuration property of the root window
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * pev)
Packit Service 93d855
{
Packit Service 93d855
	if (400 <= xkl_debug_level) {
Packit Service 93d855
		char *atom_name =
Packit Service 93d855
		    XGetAtomName(xkl_engine_get_display(engine),
Packit Service 93d855
				 pev->atom);
Packit Service 93d855
		if (atom_name != NULL) {
Packit Service 93d855
			xkl_debug(400,
Packit Service 93d855
				  "The property '%s' changed for "
Packit Service 93d855
				  WINID_FORMAT "\n", atom_name,
Packit Service 93d855
				  pev->window);
Packit Service 93d855
			XFree(atom_name);
Packit Service 93d855
		} else {
Packit Service 93d855
			xkl_debug(200,
Packit Service 93d855
				  "Some magic property changed for "
Packit Service 93d855
				  WINID_FORMAT "\n", pev->window);
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (pev->atom == xkl_engine_priv(engine, atoms)[WM_STATE]) {
Packit Service 93d855
		if (xkl_engine_is_listening_for
Packit Service 93d855
		    (engine, XKLL_MANAGE_WINDOW_STATES)) {
Packit Service 93d855
			gboolean has_xkl_state =
Packit Service 93d855
			    xkl_engine_get_state(engine, pev->window,
Packit Service 93d855
						 NULL);
Packit Service 93d855
Packit Service 93d855
			if (pev->state == PropertyNewValue) {
Packit Service 93d855
				xkl_debug(160,
Packit Service 93d855
					  "New value of WM_STATE on window "
Packit Service 93d855
					  WINID_FORMAT "\n", pev->window);
Packit Service 93d855
				if (!has_xkl_state) {	/* Is this event the first or not? */
Packit Service 93d855
					xkl_engine_add_toplevel_window
Packit Service 93d855
					    (engine, pev->window, (Window)
Packit Service 93d855
					     NULL, FALSE,
Packit Service 93d855
					     &xkl_engine_priv(engine,
Packit Service 93d855
							      curr_state));
Packit Service 93d855
				}
Packit Service 93d855
			} else {	/* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
Packit Service 93d855
				xkl_debug(160,
Packit Service 93d855
					  "Something (%d) happened to WM_STATE of window 0x%x\n",
Packit Service 93d855
					  pev->state, pev->window);
Packit Service 93d855
				xkl_engine_select_input_merging(engine,
Packit Service 93d855
								pev->window,
Packit Service 93d855
								PropertyChangeMask);
Packit Service 93d855
				if (has_xkl_state) {
Packit Service 93d855
					xkl_engine_delete_state(engine,
Packit Service 93d855
								pev->window);
Packit Service 93d855
				}
Packit Service 93d855
			}
Packit Service 93d855
		}		/* XKLL_MANAGE_WINDOW_STATES */
Packit Service 93d855
	} else if (pev->atom == xkl_engine_priv(engine, base_config_atom)
Packit Service 93d855
		   && pev->window == xkl_engine_priv(engine, root_window)) {
Packit Service 93d855
		if (xkl_engine_is_listening_for
Packit Service 93d855
		    (engine,
Packit Service 93d855
		     XKLL_MANAGE_WINDOW_STATES) |
Packit Service 93d855
		    xkl_engine_is_listening_for(engine,
Packit Service 93d855
						XKLL_TRACK_KEYBOARD_STATE))
Packit Service 93d855
		{
Packit Service 93d855
			if (pev->state == PropertyNewValue) {
Packit Service 93d855
				/* If root window got new *_NAMES_PROP_ATOM -
Packit Service 93d855
				   it most probably means new keyboard config is loaded by somebody */
Packit Service 93d855
				xkl_engine_reset_all_info
Packit Service 93d855
				    (engine, TRUE,
Packit Service 93d855
				     "New value of *_NAMES_PROP_ATOM on root window");
Packit Service 93d855
			}
Packit Service 93d855
		}		/* XKLL_MANAGE_WINDOW_STATES | XKLL_TRACK_KEYBOARD_STATE */
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * CreateNotify handler. Just interested in properties and focus events...
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_engine_process_create_window_evt(XklEngine * engine,
Packit Service 93d855
				     XCreateWindowEvent * cev)
Packit Service 93d855
{
Packit Service 93d855
	if (!xkl_engine_is_listening_for
Packit Service 93d855
	    (engine, XKLL_MANAGE_WINDOW_STATES))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	xkl_debug(200,
Packit Service 93d855
		  "Under-root window " WINID_FORMAT
Packit Service 93d855
		  "/%s (%d,%d,%d x %d) is created\n", cev->window,
Packit Service 93d855
		  xkl_get_debug_window_title(engine, cev->window), cev->x,
Packit Service 93d855
		  cev->y, cev->width, cev->height);
Packit Service 93d855
Packit Service 93d855
	if (!cev->override_redirect) {
Packit Service 93d855
/* ICCCM 4.1.6: override-redirect is NOT private to
Packit Service 93d855
* client (and must not be changed - am I right?) 
Packit Service 93d855
* We really need only PropertyChangeMask on this window but even in the case of
Packit Service 93d855
* local server we can lose PropertyNotify events (the trip time for this CreateNotify
Packit Service 93d855
* event + SelectInput request is not zero) and we definitely will (my system DO)
Packit Service 93d855
* lose FocusIn/Out events after the following call of PropertyNotifyHandler.
Packit Service 93d855
* So I just decided to purify this extra FocusChangeMask in the FocusIn/OutHandler. */
Packit Service 93d855
		xkl_engine_select_input_merging(engine, cev->window,
Packit Service 93d855
						PropertyChangeMask |
Packit Service 93d855
						FocusChangeMask);
Packit Service 93d855
Packit Service 93d855
		if (xkl_engine_if_window_has_wm_state(engine, cev->window)) {
Packit Service 93d855
			xkl_debug(200,
Packit Service 93d855
				  "Just created window already has WM_STATE - so I'll add it");
Packit Service 93d855
			xkl_engine_add_toplevel_window(engine, cev->window,
Packit Service 93d855
						       (Window) NULL,
Packit Service 93d855
						       FALSE,
Packit Service 93d855
						       &xkl_engine_priv
Packit Service 93d855
						       (engine,
Packit Service 93d855
							curr_state));
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Just error handler - sometimes we get BadWindow error for already gone 
Packit Service 93d855
 * windows, so we'll just ignore
Packit Service 93d855
 * This handler can be called in the middle of the engine initialization -
Packit Service 93d855
 * so it is not fair to assume that the engine is available
Packit Service 93d855
 */
Packit Service 93d855
int
Packit Service 93d855
xkl_process_error(Display * dpy, XErrorEvent * evt)
Packit Service 93d855
{
Packit Service 93d855
	char buf[128] = "";
Packit Service 93d855
	XklEngine *engine = xkl_get_the_engine();
Packit Service 93d855
Packit Service 93d855
	if (engine != NULL)
Packit Service 93d855
		xkl_engine_priv(engine, last_error_code) = evt->error_code;
Packit Service 93d855
Packit Service 93d855
	switch (evt->error_code) {
Packit Service 93d855
	case BadAccess:
Packit Service 93d855
	case BadDrawable:
Packit Service 93d855
	case BadWindow:
Packit Service 93d855
	case BadMatch:
Packit Service 93d855
		{
Packit Service 93d855
			XGetErrorText(evt->display, evt->error_code, buf,
Packit Service 93d855
				      sizeof(buf));
Packit Service 93d855
			/* in most cases this means we are late:) */
Packit Service 93d855
			xkl_debug(200,
Packit Service 93d855
				  "ERROR: %p, " WINID_FORMAT ", %d [%s], "
Packit Service 93d855
				  "X11 request: %d, minor code: %d\n", dpy,
Packit Service 93d855
				  (unsigned long) evt->resourceid,
Packit Service 93d855
				  (int) evt->error_code, buf,
Packit Service 93d855
				  (int) evt->request_code,
Packit Service 93d855
				  (int) evt->minor_code);
Packit Service 93d855
			break;
Packit Service 93d855
		}
Packit Service 93d855
	default:
Packit Service 93d855
		if (engine != NULL
Packit Service 93d855
		    && xkl_engine_priv(engine, process_x_error)) {
Packit Service 93d855
			if (xkl_engine_priv(engine, process_x_error)
Packit Service 93d855
			    (engine, evt)) {
Packit Service 93d855
				xkl_debug(200,
Packit Service 93d855
					  "X ERROR processed by the engine: %p, "
Packit Service 93d855
					  WINID_FORMAT ", %d [%s], "
Packit Service 93d855
					  "X11 request: %d, minor code: %d\n",
Packit Service 93d855
					  dpy,
Packit Service 93d855
					  (unsigned long) evt->resourceid,
Packit Service 93d855
					  (int) evt->error_code, buf,
Packit Service 93d855
					  (int) evt->request_code,
Packit Service 93d855
					  (int) evt->minor_code);
Packit Service 93d855
				break;
Packit Service 93d855
			}
Packit Service 93d855
		}
Packit Service 93d855
		xkl_debug(200,
Packit Service 93d855
			  "Unexpected by libxklavier X ERROR: %p, "
Packit Service 93d855
			  WINID_FORMAT ", %d [%s], "
Packit Service 93d855
			  "X11 request: %d, minor code: %d\n", dpy,
Packit Service 93d855
			  (unsigned long) evt->resourceid,
Packit Service 93d855
			  (int) evt->error_code, buf,
Packit Service 93d855
			  (int) evt->request_code, (int) evt->minor_code);
Packit Service 93d855
		if (engine != NULL)
Packit Service 93d855
			if (!xkl_engine_priv(engine, critical_section))
Packit Service 93d855
				(*xkl_engine_priv
Packit Service 93d855
				 (engine, default_error_handler))
Packit Service 93d855
				    (dpy, evt);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* X ignores this return value anyway */
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Some common functionality for Xkb handler
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_engine_process_state_modification(XklEngine * engine,
Packit Service 93d855
				      XklEngineStateChange change_type,
Packit Service 93d855
				      gint grp, guint inds,
Packit Service 93d855
				      gboolean set_inds)
Packit Service 93d855
{
Packit Service 93d855
	Window focused, focused_toplevel;
Packit Service 93d855
	XklState old_state;
Packit Service 93d855
	gint revert;
Packit Service 93d855
	gboolean have_old_state = TRUE;
Packit Service 93d855
	gboolean set_group = change_type == GROUP_CHANGED;
Packit Service 93d855
Packit Service 93d855
	if (xkl_engine_priv(engine, skip_one_save)) {
Packit Service 93d855
		xkl_debug(160, "Skipping one callback");
Packit Service 93d855
		xkl_engine_priv(engine, skip_one_save) = FALSE;
Packit Service 93d855
		return;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert);
Packit Service 93d855
Packit Service 93d855
	if ((focused == None) || (focused == PointerRoot)) {
Packit Service 93d855
		xkl_debug(160, "Something with focus: " WINID_FORMAT "\n",
Packit Service 93d855
			  focused);
Packit Service 93d855
		return;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* 
Packit Service 93d855
	 * Only if we manage states - otherwise xkl_engine_priv(engine,curr_toplvl_win) does not make sense 
Packit Service 93d855
	 */
Packit Service 93d855
	if (!xkl_engine_find_toplevel_window
Packit Service 93d855
	    (engine, focused, &focused_toplevel)
Packit Service 93d855
	    && xkl_engine_is_listening_for(engine,
Packit Service 93d855
					   XKLL_MANAGE_WINDOW_STATES))
Packit Service 93d855
		focused_toplevel = xkl_engine_priv(engine, curr_toplvl_win);	/* what else can I do */
Packit Service 93d855
Packit Service 93d855
	xkl_debug(150, "Focused window: " WINID_FORMAT ", '%s'\n",
Packit Service 93d855
		  focused_toplevel,
Packit Service 93d855
		  xkl_get_debug_window_title(engine, focused_toplevel));
Packit Service 93d855
	if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) {
Packit Service 93d855
		xkl_debug(150, "CurClient: " WINID_FORMAT ", '%s'\n",
Packit Service 93d855
			  xkl_engine_priv(engine, curr_toplvl_win),
Packit Service 93d855
			  xkl_get_debug_window_title(engine,
Packit Service 93d855
						     xkl_engine_priv
Packit Service 93d855
						     (engine,
Packit Service 93d855
						      curr_toplvl_win)));
Packit Service 93d855
Packit Service 93d855
		if (focused_toplevel !=
Packit Service 93d855
		    xkl_engine_priv(engine, curr_toplvl_win)) {
Packit Service 93d855
			/*
Packit Service 93d855
			 * If not state - we got the new window
Packit Service 93d855
			 */
Packit Service 93d855
			if (!xkl_engine_get_toplevel_window_state
Packit Service 93d855
			    (engine, focused_toplevel, &old_state)) {
Packit Service 93d855
				xkl_engine_update_current_state(engine,
Packit Service 93d855
								grp, inds,
Packit Service 93d855
								"Updating the state from new focused window");
Packit Service 93d855
				if (xkl_engine_is_listening_for
Packit Service 93d855
				    (engine, XKLL_MANAGE_WINDOW_STATES))
Packit Service 93d855
					xkl_engine_add_toplevel_window
Packit Service 93d855
					    (engine, focused_toplevel,
Packit Service 93d855
					     (Window) NULL, FALSE,
Packit Service 93d855
					     &xkl_engine_priv(engine,
Packit Service 93d855
							      curr_state));
Packit Service 93d855
			}
Packit Service 93d855
			/*
Packit Service 93d855
			 * There is state - just get the state from the window
Packit Service 93d855
			 */
Packit Service 93d855
			else {
Packit Service 93d855
				grp = old_state.group;
Packit Service 93d855
				inds = old_state.indicators;
Packit Service 93d855
			}
Packit Service 93d855
			xkl_engine_priv(engine, curr_toplvl_win) =
Packit Service 93d855
			    focused_toplevel;
Packit Service 93d855
			xkl_debug(160,
Packit Service 93d855
				  "CurClient:changed to " WINID_FORMAT
Packit Service 93d855
				  ", '%s'\n", xkl_engine_priv(engine,
Packit Service 93d855
							      curr_toplvl_win),
Packit Service 93d855
				  xkl_get_debug_window_title(engine,
Packit Service 93d855
							     xkl_engine_priv
Packit Service 93d855
							     (engine,
Packit Service 93d855
							      curr_toplvl_win)));
Packit Service 93d855
		}
Packit Service 93d855
		/* If the window already has this this state - we are just restoring it!
Packit Service 93d855
		   (see the second parameter of stateCallback */
Packit Service 93d855
		have_old_state =
Packit Service 93d855
		    xkl_engine_get_toplevel_window_state(engine,
Packit Service 93d855
							 xkl_engine_priv
Packit Service 93d855
							 (engine,
Packit Service 93d855
							  curr_toplvl_win),
Packit Service 93d855
							 &old_state);
Packit Service 93d855
	} else {		/* just tracking the stuff, no smart things */
Packit Service 93d855
Packit Service 93d855
		xkl_debug(160,
Packit Service 93d855
			  "Just updating the current state in the tracking mode\n");
Packit Service 93d855
		memcpy(&old_state, &xkl_engine_priv(engine, curr_state),
Packit Service 93d855
		       sizeof(XklState));
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (set_group || have_old_state) {
Packit Service 93d855
		xkl_engine_update_current_state(engine,
Packit Service 93d855
						set_group ? grp :
Packit Service 93d855
						old_state.group,
Packit Service 93d855
						set_inds ? inds :
Packit Service 93d855
						old_state.indicators,
Packit Service 93d855
						"Restoring the state from the window");
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (have_old_state)
Packit Service 93d855
		xkl_engine_try_call_state_func(engine, change_type,
Packit Service 93d855
					       &old_state);
Packit Service 93d855
Packit Service 93d855
	if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES))
Packit Service 93d855
		xkl_engine_save_toplevel_window_state(engine,
Packit Service 93d855
						      xkl_engine_priv
Packit Service 93d855
						      (engine,
Packit Service 93d855
						       curr_toplvl_win),
Packit Service 93d855
						      &xkl_engine_priv
Packit Service 93d855
						      (engine,
Packit Service 93d855
						       curr_state));
Packit Service 93d855
}