Blame libxklavier/xklavier_xkb.c

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