Blame libxklavier/xklavier_xkb.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 <time.h>
Packit Service 93d855
#include <stdlib.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
#include "xklavier_private_xkb.h"
Packit Service 93d855
Packit Service 93d855
#ifdef HAVE_XINPUT
Packit Service 93d855
#include <X11/extensions/XI.h>
Packit Service 93d855
#include <X11/extensions/XInput.h>
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
Packit Service 93d855
const gchar **
Packit Service 93d855
xkl_xkb_get_groups_names(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return (const gchar **) xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						   group_names);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
const gchar **
Packit Service 93d855
xkl_xkb_get_indicators_names(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return (const gchar **) xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						   indicator_names);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xkb_pause_listen(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	XkbSelectEvents(xkl_engine_get_display(engine),
Packit Service 93d855
			xkl_engine_backend(engine, XklXkb, device_id),
Packit Service 93d855
			XkbAllEventsMask, 0);
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xkb_resume_listen(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
#ifdef HAVE_XINPUT
Packit Service 93d855
	int xitype;
Packit Service 93d855
	XEventClass xiclass;
Packit Service 93d855
#endif
Packit Service 93d855
	/* What events we want */
Packit Service 93d855
#define XKB_EVT_MASK \
Packit Service 93d855
         (XkbStateNotifyMask| \
Packit Service 93d855
          XkbNamesNotifyMask| \
Packit Service 93d855
          XkbControlsNotifyMask| \
Packit Service 93d855
          XkbIndicatorStateNotifyMask| \
Packit Service 93d855
          XkbIndicatorMapNotifyMask| \
Packit Service 93d855
          XkbNewKeyboardNotifyMask)
Packit Service 93d855
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
	XkbSelectEvents(display,
Packit Service 93d855
			xkl_engine_backend(engine, XklXkb, device_id),
Packit Service 93d855
			XKB_EVT_MASK, XKB_EVT_MASK);
Packit Service 93d855
Packit Service 93d855
#define XKB_STATE_EVT_DTL_MASK \
Packit Service 93d855
         (XkbGroupStateMask)
Packit Service 93d855
Packit Service 93d855
	XkbSelectEventDetails(display,
Packit Service 93d855
			      xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						 device_id),
Packit Service 93d855
			      XkbStateNotify, XKB_STATE_EVT_DTL_MASK,
Packit Service 93d855
			      XKB_STATE_EVT_DTL_MASK);
Packit Service 93d855
Packit Service 93d855
#define XKB_NAMES_EVT_DTL_MASK \
Packit Service 93d855
         (XkbGroupNamesMask|XkbIndicatorNamesMask)
Packit Service 93d855
Packit Service 93d855
	XkbSelectEventDetails(display,
Packit Service 93d855
			      xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						 device_id),
Packit Service 93d855
			      XkbNamesNotify, XKB_NAMES_EVT_DTL_MASK,
Packit Service 93d855
			      XKB_NAMES_EVT_DTL_MASK);
Packit Service 93d855
#ifdef HAVE_XINPUT
Packit Service 93d855
	if (xkl_engine_priv(engine, features) & XKLF_DEVICE_DISCOVERY) {
Packit Service 93d855
		DevicePresence(display, xitype, xiclass);
Packit Service 93d855
		XSelectExtensionEvent(display,
Packit Service 93d855
				      xkl_engine_priv(engine, root_window),
Packit Service 93d855
				      &xiclass, 1);
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, xi_event_type) = xitype;
Packit Service 93d855
	} else
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, xi_event_type) = -1;
Packit Service 93d855
#endif
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
guint
Packit Service 93d855
xkl_xkb_get_max_num_groups(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_engine_priv(engine,
Packit Service 93d855
			       features) & XKLF_MULTIPLE_LAYOUTS_SUPPORTED
Packit Service 93d855
	    ? XkbNumKbdGroups : 1;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
guint
Packit Service 93d855
xkl_xkb_get_num_groups(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
				  cached_desc)->ctrls->num_groups;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
#define KBD_MASK \
Packit Service 93d855
    ( 0 )
Packit Service 93d855
#define CTRLS_MASK \
Packit Service 93d855
  ( XkbSlowKeysMask )
Packit Service 93d855
#define NAMES_MASK \
Packit Service 93d855
  ( XkbGroupNamesMask | XkbIndicatorNamesMask )
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_free_all_info(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gint i;
Packit Service 93d855
	gchar **pi = xkl_engine_backend(engine, XklXkb, indicator_names);
Packit Service 93d855
	XkbDescPtr desc;
Packit Service 93d855
Packit Service 93d855
	for (i = 0; i < XkbNumIndicators; i++, pi++) {
Packit Service 93d855
		/* only free non-empty ones */
Packit Service 93d855
		if (*pi && **pi)
Packit Service 93d855
			XFree(*pi);
Packit Service 93d855
	}
Packit Service 93d855
	desc = xkl_engine_backend(engine, XklXkb, cached_desc);
Packit Service 93d855
	if (desc != NULL) {
Packit Service 93d855
		int i;
Packit Service 93d855
		char **group_name =
Packit Service 93d855
		    xkl_engine_backend(engine, XklXkb, group_names);
Packit Service 93d855
		for (i = desc->ctrls->num_groups; --i >= 0; group_name++)
Packit Service 93d855
			if (*group_name) {
Packit Service 93d855
				XFree(*group_name);
Packit Service 93d855
				*group_name = NULL;
Packit Service 93d855
			}
Packit Service 93d855
		XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, cached_desc) = NULL;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* just in case - never actually happens... */
Packit Service 93d855
	desc = xkl_engine_backend(engine, XklXkb, actual_desc);
Packit Service 93d855
	if (desc != NULL) {
Packit Service 93d855
		XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, actual_desc) = NULL;
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
xkl_xkb_load_actual_desc(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gboolean rv = FALSE;
Packit Service 93d855
	Status status;
Packit Service 93d855
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
	XkbDescPtr desc = XkbGetMap(display, KBD_MASK,
Packit Service 93d855
				    xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						       device_id));
Packit Service 93d855
	xkl_engine_backend(engine, XklXkb, actual_desc) = desc;
Packit Service 93d855
	if (desc != NULL) {
Packit Service 93d855
		rv = Success == (status = XkbGetControls(display,
Packit Service 93d855
							 CTRLS_MASK,
Packit Service 93d855
							 desc)) &&
Packit Service 93d855
		    Success == (status = XkbGetNames(display,
Packit Service 93d855
						     NAMES_MASK,
Packit Service 93d855
						     desc)) &&
Packit Service 93d855
		    Success == (status = XkbGetIndicatorMap(display,
Packit Service 93d855
							    XkbAllIndicatorsMask,
Packit Service 93d855
							    desc));
Packit Service 93d855
		if (!rv) {
Packit Service 93d855
			xkl_last_error_message =
Packit Service 93d855
			    "Could not load controls/names/indicators";
Packit Service 93d855
			xkl_debug(0, "%s: %d\n", xkl_last_error_message,
Packit Service 93d855
				  status);
Packit Service 93d855
			XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
Packit Service 93d855
			xkl_engine_backend(engine, XklXkb, actual_desc) =
Packit Service 93d855
			    NULL;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_if_cached_info_equals_actual(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gint i;
Packit Service 93d855
	Atom *pa1, *pa2;
Packit Service 93d855
	gboolean rv = FALSE;
Packit Service 93d855
Packit Service 93d855
	if (xkl_xkb_load_actual_desc(engine)) {
Packit Service 93d855
		/* First, compare the number of groups */
Packit Service 93d855
		XkbDescPtr cached =
Packit Service 93d855
		    xkl_engine_backend(engine, XklXkb, cached_desc);
Packit Service 93d855
		XkbDescPtr actual =
Packit Service 93d855
		    xkl_engine_backend(engine, XklXkb, actual_desc);
Packit Service 93d855
Packit Service 93d855
		if (cached->ctrls->num_groups == actual->ctrls->num_groups) {
Packit Service 93d855
			/* Then, compare group names, just atoms */
Packit Service 93d855
			pa1 = cached->names->groups;
Packit Service 93d855
			pa2 = actual->names->groups;
Packit Service 93d855
			for (i = cached->ctrls->num_groups; --i >= 0;
Packit Service 93d855
			     pa1++, pa2++)
Packit Service 93d855
				if (*pa1 != *pa2)
Packit Service 93d855
					break;
Packit Service 93d855
Packit Service 93d855
			/* Then, compare indicator names, just atoms */
Packit Service 93d855
			if (i < 0) {
Packit Service 93d855
				pa1 = cached->names->indicators;
Packit Service 93d855
				pa2 = actual->names->indicators;
Packit Service 93d855
				for (i = XkbNumIndicators; --i >= 0;
Packit Service 93d855
				     pa1++, pa2++)
Packit Service 93d855
					if (*pa1 != *pa2)
Packit Service 93d855
						break;
Packit Service 93d855
				rv = i < 0;
Packit Service 93d855
			}
Packit Service 93d855
		}
Packit Service 93d855
		/* 
Packit Service 93d855
		 * in case of failure, reuse in _XklXkbLoadAllInfo
Packit Service 93d855
		 * in case of success - free it
Packit Service 93d855
		 */
Packit Service 93d855
		if (rv) {
Packit Service 93d855
			XkbFreeKeyboard(actual, XkbAllComponentsMask,
Packit Service 93d855
					True);
Packit Service 93d855
			xkl_engine_backend(engine, XklXkb, actual_desc) =
Packit Service 93d855
			    NULL;
Packit Service 93d855
		}
Packit Service 93d855
	} else {
Packit Service 93d855
		xkl_debug(0,
Packit Service 93d855
			  "Could not load the XkbDescPtr for comparison\n");
Packit Service 93d855
	}
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Load some XKB parameters
Packit Service 93d855
 */
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_load_all_info(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gint i;
Packit Service 93d855
	Atom *pa;
Packit Service 93d855
	gchar **group_name;
Packit Service 93d855
	gchar **pi = xkl_engine_backend(engine, XklXkb, indicator_names);
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
	XkbDescPtr actual =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXkb, actual_desc);
Packit Service 93d855
	XkbDescPtr cached;
Packit Service 93d855
Packit Service 93d855
	if (actual == NULL)
Packit Service 93d855
		if (!xkl_xkb_load_actual_desc(engine)) {
Packit Service 93d855
			xkl_last_error_message = "Could not load keyboard";
Packit Service 93d855
			return FALSE;
Packit Service 93d855
		}
Packit Service 93d855
Packit Service 93d855
	/* take it from the cache (in most cases LoadAll is called from ResetAll which in turn ...) */
Packit Service 93d855
	cached = actual = xkl_engine_backend(engine, XklXkb, actual_desc);
Packit Service 93d855
	xkl_engine_backend(engine, XklXkb, cached_desc) =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXkb, actual_desc);
Packit Service 93d855
	xkl_engine_backend(engine, XklXkb, actual_desc) = NULL;
Packit Service 93d855
Packit Service 93d855
	/* First, output the number of the groups */
Packit Service 93d855
	xkl_debug(200, "found %d groups\n", cached->ctrls->num_groups);
Packit Service 93d855
Packit Service 93d855
	/* Then, cache (and output) the names of the groups */
Packit Service 93d855
	pa = cached->names->groups;
Packit Service 93d855
	group_name = xkl_engine_backend(engine, XklXkb, group_names);
Packit Service 93d855
	for (i = cached->ctrls->num_groups; --i >= 0; pa++, group_name++) {
Packit Service 93d855
		*group_name =
Packit Service 93d855
		    XGetAtomName(display,
Packit Service 93d855
				 *pa == None ? XInternAtom(display, "-",
Packit Service 93d855
							   False) : *pa);
Packit Service 93d855
		xkl_debug(200, "Group %d has name [%s]\n", i, *group_name);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, last_error_code) =
Packit Service 93d855
	    XkbGetIndicatorMap(display, XkbAllIndicatorsMask, cached);
Packit Service 93d855
Packit Service 93d855
	if (xkl_engine_priv(engine, last_error_code) != Success) {
Packit Service 93d855
		xkl_last_error_message = "Could not load indicator map";
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* Then, cache (and output) the names of the indicators */
Packit Service 93d855
	pa = cached->names->indicators;
Packit Service 93d855
	for (i = XkbNumIndicators; --i >= 0; pi++, pa++) {
Packit Service 93d855
		Atom a = *pa;
Packit Service 93d855
		if (a != None)
Packit Service 93d855
			*pi = XGetAtomName(display, a);
Packit Service 93d855
		else
Packit Service 93d855
			*pi = "";
Packit Service 93d855
Packit Service 93d855
		xkl_debug(200, "Indicator[%d] is %s\n", i, *pi);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_debug(200, "Real indicators are %X\n",
Packit Service 93d855
		  cached->indicators->phys_indicators);
Packit Service 93d855
Packit Service 93d855
	g_signal_emit_by_name(engine, "X-config-changed");
Packit Service 93d855
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_lock_group(XklEngine * engine, gint group)
Packit Service 93d855
{
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
	xkl_debug(100, "Posted request for change the group to %d ##\n",
Packit Service 93d855
		  group);
Packit Service 93d855
	XkbLockGroup(display,
Packit Service 93d855
		     xkl_engine_backend(engine, XklXkb, device_id), group);
Packit Service 93d855
	XSync(display, False);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Updates current internal state from X state
Packit Service 93d855
 */
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_get_server_state(XklEngine * engine, XklState * current_state_out)
Packit Service 93d855
{
Packit Service 93d855
	XkbStateRec state;
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
Packit Service 93d855
	current_state_out->group = 0;
Packit Service 93d855
	if (Success ==
Packit Service 93d855
	    XkbGetState(display,
Packit Service 93d855
			xkl_engine_backend(engine, XklXkb, device_id),
Packit Service 93d855
			&state))
Packit Service 93d855
		current_state_out->group = state.locked_group;
Packit Service 93d855
Packit Service 93d855
	if (Success ==
Packit Service 93d855
	    XkbGetIndicatorState(display,
Packit Service 93d855
				 xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						    device_id),
Packit Service 93d855
				 &current_state_out->indicators))
Packit Service 93d855
		current_state_out->indicators &=
Packit Service 93d855
		    xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
				       cached_desc)->indicators->
Packit Service 93d855
		    phys_indicators;
Packit Service 93d855
	else
Packit Service 93d855
		current_state_out->indicators = 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Actually taken from mxkbledpanel, valueChangedProc
Packit Service 93d855
 */
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_set_indicator(XklEngine * engine, gint indicator_num, gboolean set)
Packit Service 93d855
{
Packit Service 93d855
	XkbIndicatorMapPtr map;
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
	XkbDescPtr cached =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXkb, cached_desc);
Packit Service 93d855
Packit Service 93d855
	map = cached->indicators->maps + indicator_num;
Packit Service 93d855
Packit Service 93d855
	/* The 'flags' field tells whether this indicator is automatic
Packit Service 93d855
	 * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40),
Packit Service 93d855
	 * or neither (both - 0xC0).
Packit Service 93d855
	 *
Packit Service 93d855
	 * If NoAutomatic is set, the server ignores the rest of the 
Packit Service 93d855
	 * fields in the indicator map (i.e. it disables automatic control 
Packit Service 93d855
	 * of the LED).   If NoExplicit is set, the server prevents clients 
Packit Service 93d855
	 * from explicitly changing the value of the LED (using the core 
Packit Service 93d855
	 * protocol *or* XKB).   If NoAutomatic *and* NoExplicit are set, 
Packit Service 93d855
	 * the LED cannot be changed (unless you change the map first).   
Packit Service 93d855
	 * If neither NoAutomatic nor NoExplicit are set, the server will 
Packit Service 93d855
	 * change the LED according to the indicator map, but clients can 
Packit Service 93d855
	 * override that (until the next automatic change) using the core 
Packit Service 93d855
	 * protocol or XKB.
Packit Service 93d855
	 */
Packit Service 93d855
	switch (map->flags & (XkbIM_NoExplicit | XkbIM_NoAutomatic)) {
Packit Service 93d855
	case XkbIM_NoExplicit | XkbIM_NoAutomatic:
Packit Service 93d855
		{
Packit Service 93d855
			/* Can do nothing. Just ignore the indicator */
Packit Service 93d855
			return TRUE;
Packit Service 93d855
		}
Packit Service 93d855
Packit Service 93d855
	case XkbIM_NoAutomatic:
Packit Service 93d855
		{
Packit Service 93d855
			if (cached->names->indicators[indicator_num] !=
Packit Service 93d855
			    None)
Packit Service 93d855
				XkbSetNamedIndicator(display,
Packit Service 93d855
						     xkl_engine_backend
Packit Service 93d855
						     (engine, XklXkb,
Packit Service 93d855
						      device_id),
Packit Service 93d855
						     cached->names->
Packit Service 93d855
						     indicators
Packit Service 93d855
						     [indicator_num], set,
Packit Service 93d855
						     False, NULL);
Packit Service 93d855
			else {
Packit Service 93d855
				XKeyboardControl xkc;
Packit Service 93d855
				xkc.led = indicator_num;
Packit Service 93d855
				xkc.led_mode =
Packit Service 93d855
				    set ? LedModeOn : LedModeOff;
Packit Service 93d855
				XChangeKeyboardControl(display,
Packit Service 93d855
						       KBLed | KBLedMode,
Packit Service 93d855
						       &xkc);
Packit Service 93d855
				XSync(display, False);
Packit Service 93d855
			}
Packit Service 93d855
Packit Service 93d855
			return TRUE;
Packit Service 93d855
		}
Packit Service 93d855
Packit Service 93d855
	case XkbIM_NoExplicit:
Packit Service 93d855
		break;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* The 'ctrls' field tells what controls tell this indicator to
Packit Service 93d855
	 * to turn on:  RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4),
Packit Service 93d855
	 *              StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20),
Packit Service 93d855
	 *              TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100),
Packit Service 93d855
	 *              Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800),
Packit Service 93d855
	 *              InternalMods (0x1000), IgnoreLockMods (0x2000),
Packit Service 93d855
	 *              PerKeyRepeat (0x3000), or ControlsEnabled (0x4000)
Packit Service 93d855
	 */
Packit Service 93d855
	if (map->ctrls) {
Packit Service 93d855
		gulong which = map->ctrls;
Packit Service 93d855
Packit Service 93d855
		XkbGetControls(display, XkbAllControlsMask, cached);
Packit Service 93d855
		if (set)
Packit Service 93d855
			cached->ctrls->enabled_ctrls |= which;
Packit Service 93d855
		else
Packit Service 93d855
			cached->ctrls->enabled_ctrls &= ~which;
Packit Service 93d855
		XkbSetControls(display, which | XkbControlsEnabledMask,
Packit Service 93d855
			       cached);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* The 'which_groups' field tells when this indicator turns on
Packit Service 93d855
	 * for the 'groups' field:  base (0x1), latched (0x2), locked (0x4),
Packit Service 93d855
	 * or effective (0x8).
Packit Service 93d855
	 */
Packit Service 93d855
	if (map->groups) {
Packit Service 93d855
		gint i;
Packit Service 93d855
		guint group = 1;
Packit Service 93d855
Packit Service 93d855
		/* Turning on a group indicator is kind of tricky.  For
Packit Service 93d855
		 * now, we will just Latch or Lock the first group we find
Packit Service 93d855
		 * if that is what this indicator does.  Otherwise, we're
Packit Service 93d855
		 * just going to punt and get out of here.
Packit Service 93d855
		 */
Packit Service 93d855
		if (set) {
Packit Service 93d855
			for (i = XkbNumKbdGroups; --i >= 0;)
Packit Service 93d855
				if ((1 << i) & map->groups) {
Packit Service 93d855
					group = i;
Packit Service 93d855
					break;
Packit Service 93d855
				}
Packit Service 93d855
			if (map->which_groups & (XkbIM_UseLocked |
Packit Service 93d855
						 XkbIM_UseEffective)) {
Packit Service 93d855
				/* Important: Groups should be ignored here - because they are handled separately! */
Packit Service 93d855
				/* XklLockGroup( group ); */
Packit Service 93d855
			} else if (map->which_groups & XkbIM_UseLatched)
Packit Service 93d855
				XkbLatchGroup(display,
Packit Service 93d855
					      xkl_engine_backend(engine,
Packit Service 93d855
								 XklXkb,
Packit Service 93d855
								 device_id),
Packit Service 93d855
					      group);
Packit Service 93d855
			else {
Packit Service 93d855
				/* Can do nothing. Just ignore the indicator */
Packit Service 93d855
				return TRUE;
Packit Service 93d855
			}
Packit Service 93d855
		} else
Packit Service 93d855
			/* Turning off a group indicator will mean that we just
Packit Service 93d855
			 * Lock the first group that this indicator doesn't watch.
Packit Service 93d855
			 */
Packit Service 93d855
		{
Packit Service 93d855
			for (i = XkbNumKbdGroups; --i >= 0;)
Packit Service 93d855
				if (!((1 << i) & map->groups)) {
Packit Service 93d855
					group = i;
Packit Service 93d855
					break;
Packit Service 93d855
				}
Packit Service 93d855
			xkl_xkb_lock_group(engine, group);
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	/* The 'which_mods' field tells when this indicator turns on
Packit Service 93d855
	 * for the modifiers:  base (0x1), latched (0x2), locked (0x4),
Packit Service 93d855
	 *                     or effective (0x8).
Packit Service 93d855
	 *
Packit Service 93d855
	 * The 'real_mods' field tells whether this turns on when one of 
Packit Service 93d855
	 * the real X modifiers is set:  Shift (0x1), Lock (0x2), Control (0x4),
Packit Service 93d855
	 * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80). 
Packit Service 93d855
	 *
Packit Service 93d855
	 * The 'virtual_mods' field tells whether this turns on when one of
Packit Service 93d855
	 * the virtual modifiers is set.
Packit Service 93d855
	 *
Packit Service 93d855
	 * The 'mask' field tells what real X modifiers the virtual_modifiers
Packit Service 93d855
	 * map to?
Packit Service 93d855
	 */
Packit Service 93d855
	if (map->mods.real_mods || map->mods.mask) {
Packit Service 93d855
		guint affect, mods;
Packit Service 93d855
Packit Service 93d855
		affect = (map->mods.real_mods | map->mods.mask);
Packit Service 93d855
Packit Service 93d855
		mods = set ? affect : 0;
Packit Service 93d855
Packit Service 93d855
		if (map->which_mods &
Packit Service 93d855
		    (XkbIM_UseLocked | XkbIM_UseEffective))
Packit Service 93d855
			XkbLockModifiers(display,
Packit Service 93d855
					 xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
							    device_id),
Packit Service 93d855
					 affect, mods);
Packit Service 93d855
		else if (map->which_mods & XkbIM_UseLatched)
Packit Service 93d855
			XkbLatchModifiers(display,
Packit Service 93d855
					  xkl_engine_backend(engine,
Packit Service 93d855
							     XklXkb,
Packit Service 93d855
							     device_id),
Packit Service 93d855
					  affect, mods);
Packit Service 93d855
		else {
Packit Service 93d855
			return TRUE;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xkb_init(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
	gint opcode;
Packit Service 93d855
	gboolean xkl_xkb_ext_present;
Packit Service 93d855
	int xi_opc;
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, backend_id) = "XKB";
Packit Service 93d855
	xkl_engine_priv(engine, features) = XKLF_CAN_TOGGLE_INDICATORS |
Packit Service 93d855
	    XKLF_CAN_OUTPUT_CONFIG_AS_ASCII |
Packit Service 93d855
	    XKLF_CAN_OUTPUT_CONFIG_AS_BINARY;
Packit Service 93d855
	xkl_engine_priv(engine, activate_config_rec) =
Packit Service 93d855
	    xkl_xkb_activate_config_rec;
Packit Service 93d855
	xkl_engine_priv(engine, init_config_registry) =
Packit Service 93d855
	    xkl_xkb_init_config_registry;
Packit Service 93d855
	xkl_engine_priv(engine, load_config_registry) =
Packit Service 93d855
	    xkl_xkb_load_config_registry;
Packit Service 93d855
	xkl_engine_priv(engine, write_config_rec_to_file) =
Packit Service 93d855
	    xkl_xkb_write_config_rec_to_file;
Packit Service 93d855
	xkl_engine_priv(engine, get_groups_names) =
Packit Service 93d855
	    xkl_xkb_get_groups_names;
Packit Service 93d855
	xkl_engine_priv(engine, get_indicators_names) =
Packit Service 93d855
	    xkl_xkb_get_indicators_names;
Packit Service 93d855
	xkl_engine_priv(engine, get_max_num_groups) =
Packit Service 93d855
	    xkl_xkb_get_max_num_groups;
Packit Service 93d855
	xkl_engine_priv(engine, get_num_groups) = xkl_xkb_get_num_groups;
Packit Service 93d855
	xkl_engine_priv(engine, lock_group) = xkl_xkb_lock_group;
Packit Service 93d855
	xkl_engine_priv(engine, process_x_event) = xkl_xkb_process_x_event;
Packit Service 93d855
	xkl_engine_priv(engine, process_x_error) = xkl_xkb_process_x_error;
Packit Service 93d855
	xkl_engine_priv(engine, free_all_info) = xkl_xkb_free_all_info;
Packit Service 93d855
	xkl_engine_priv(engine, if_cached_info_equals_actual) =
Packit Service 93d855
	    xkl_xkb_if_cached_info_equals_actual;
Packit Service 93d855
	xkl_engine_priv(engine, load_all_info) = xkl_xkb_load_all_info;
Packit Service 93d855
	xkl_engine_priv(engine, get_server_state) =
Packit Service 93d855
	    xkl_xkb_get_server_state;
Packit Service 93d855
	xkl_engine_priv(engine, pause_listen) = xkl_xkb_pause_listen;
Packit Service 93d855
	xkl_engine_priv(engine, resume_listen) = xkl_xkb_resume_listen;
Packit Service 93d855
	xkl_engine_priv(engine, set_indicators) = xkl_xkb_set_indicators;
Packit Service 93d855
	xkl_engine_priv(engine, finalize) = xkl_xkb_term;
Packit Service 93d855
Packit Service 93d855
	if (getenv("XKL_XKB_DISABLE") != NULL)
Packit Service 93d855
		return -1;
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, backend) = g_new0(XklXkb, 1);
Packit Service 93d855
	xkl_engine_backend(engine, XklXkb, device_id) = XkbUseCoreKbd;
Packit Service 93d855
Packit Service 93d855
	xkl_xkb_ext_present = XkbQueryExtension(display,
Packit Service 93d855
						&opcode,
Packit Service 93d855
						&xkl_engine_backend(engine,
Packit Service 93d855
								    XklXkb,
Packit Service 93d855
								    event_type),
Packit Service 93d855
						&xkl_engine_backend(engine,
Packit Service 93d855
								    XklXkb,
Packit Service 93d855
								    error_code),
Packit Service 93d855
						NULL, NULL);
Packit Service 93d855
	if (!xkl_xkb_ext_present)
Packit Service 93d855
		return -1;
Packit Service 93d855
Packit Service 93d855
	xkl_debug(160,
Packit Service 93d855
		  "xkbEvenType: %X, xkbError: %X, display: %p, root: "
Packit Service 93d855
		  WINID_FORMAT "\n", xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
							event_type),
Packit Service 93d855
		  xkl_engine_backend(engine, XklXkb, error_code), display,
Packit Service 93d855
		  xkl_engine_priv(engine, root_window));
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, base_config_atom) =
Packit Service 93d855
	    XInternAtom(display, _XKB_RF_NAMES_PROP_ATOM, False);
Packit Service 93d855
	xkl_engine_priv(engine, backup_config_atom) =
Packit Service 93d855
	    XInternAtom(display, "_XKB_RULES_NAMES_BACKUP", False);
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, default_model) = "pc101";
Packit Service 93d855
	xkl_engine_priv(engine, default_layout) = "us";
Packit Service 93d855
Packit Service 93d855
	/* First, we have to assign xkl_vtable - 
Packit Service 93d855
	   because this function uses it */
Packit Service 93d855
Packit Service 93d855
	if (xkl_xkb_multiple_layouts_supported(engine))
Packit Service 93d855
		xkl_engine_priv(engine, features) |=
Packit Service 93d855
		    XKLF_MULTIPLE_LAYOUTS_SUPPORTED;
Packit Service 93d855
Packit Service 93d855
#if HAVE_XINPUT
Packit Service 93d855
	if (XQueryExtension
Packit Service 93d855
	    (display, "XInputExtension", &xi_opc,
Packit Service 93d855
	     &xkl_engine_backend(engine, XklXkb, xi_event_type),
Packit Service 93d855
	     &xkl_engine_backend(engine, XklXkb, xi_error_code))) {
Packit Service 93d855
		XExtensionVersion *ev =
Packit Service 93d855
		    XGetExtensionVersion(display, "XInputExtension");
Packit Service 93d855
		xkl_debug(150,
Packit Service 93d855
			  "XInputExtension found (%d, %d, %d) version %d.%d\n",
Packit Service 93d855
			  xi_opc, xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
						     xi_event_type),
Packit Service 93d855
			  xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
					     xi_error_code),
Packit Service 93d855
			  ev->major_version, ev->minor_version);
Packit Service 93d855
		/* DevicePresence is available from XI 1.4 */
Packit Service 93d855
		if ((ev->major_version * 10) + ev->minor_version >= 14) {
Packit Service 93d855
			xkl_debug(200, "DevicePresence available\n");
Packit Service 93d855
			xkl_engine_priv(engine, features) |=
Packit Service 93d855
			    XKLF_DEVICE_DISCOVERY;
Packit Service 93d855
		} else {
Packit Service 93d855
			xkl_debug(200, "DevicePresence not available\n");
Packit Service 93d855
		}
Packit Service 93d855
		XFree(ev);
Packit Service 93d855
	} else {
Packit Service 93d855
		xkl_debug(0, "XInputExtension not found\n");
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, xi_event_type) = -1;
Packit Service 93d855
		xkl_engine_backend(engine, XklXkb, xi_error_code) = -1;
Packit Service 93d855
	}
Packit Service 93d855
#endif
Packit Service 93d855
	return 0;
Packit Service 93d855
#else
Packit Service 93d855
	xkl_debug(160,
Packit Service 93d855
		  "NO XKB LIBS, display: %p, root: " WINID_FORMAT
Packit Service 93d855
		  "\n", display, xkl_engine_priv(engine, root_window));
Packit Service 93d855
	return -1;
Packit Service 93d855
#endif
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_term(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
const gchar *
Packit Service 93d855
xkl_xkb_event_get_name(gint xkb_type)
Packit Service 93d855
{
Packit Service 93d855
	/* Not really good to use the fact of consecutivity
Packit Service 93d855
	   but XKB protocol extension is already standartized so... */
Packit Service 93d855
	static const gchar *evt_names[] = {
Packit Service 93d855
		"XkbNewKeyboardNotify",
Packit Service 93d855
		"XkbMapNotify",
Packit Service 93d855
		"XkbStateNotify",
Packit Service 93d855
		"XkbControlsNotify",
Packit Service 93d855
		"XkbIndicatorStateNotify",
Packit Service 93d855
		"XkbIndicatorMapNotify",
Packit Service 93d855
		"XkbNamesNotify",
Packit Service 93d855
		"XkbCompatMapNotify",
Packit Service 93d855
		"XkbBellNotify",
Packit Service 93d855
		"XkbActionMessage",
Packit Service 93d855
		"XkbAccessXNotify",
Packit Service 93d855
		"XkbExtensionDeviceNotify",
Packit Service 93d855
		"LASTEvent"
Packit Service 93d855
	};
Packit Service 93d855
	xkb_type -= XkbNewKeyboardNotify;
Packit Service 93d855
	if (xkb_type < 0 ||
Packit Service 93d855
	    xkb_type >= (sizeof(evt_names) / sizeof(evt_names[0])))
Packit Service 93d855
		return "UNKNOWN/OOR";
Packit Service 93d855
	return evt_names[xkb_type];
Packit Service 93d855
}
Packit Service 93d855
#endif