/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"


#include <stdio.h>

#include "unx/saldisp.hxx"
#include "unx/saldata.hxx"
#include "unx/i18n_xkb.hxx"

SalI18N_KeyboardExtension::SalI18N_KeyboardExtension( Display* pDisplay)
:	mbUseExtension( true )
,	mnDefaultGroup( 0 )
{
	mpDisplay = pDisplay;

	// allow user to set the default keyboard group idx or to disable the usage
	// of x keyboard extension at all:
	// 		setenv SAL_XKEYBOARDGROUP		disables keyboard extension
	// 		setenv SAL_XKEYBOARDGROUP 2		sets the keyboard group index to 2
	// keyboard group index must be in [1,4], may be specified in hex or decimal
	static char *pUseKeyboardExtension = getenv( "SAL_XKEYBOARDGROUP" );
	if ( pUseKeyboardExtension != NULL )
	{
		mbUseExtension = pUseKeyboardExtension[0] != '\0' ;
		if ( mbUseExtension )
			mnDefaultGroup = strtol( pUseKeyboardExtension, NULL, 0 );
		if ( mnDefaultGroup > XkbMaxKbdGroup )
			mnDefaultGroup = 0;
	}

	// query XServer support for XKB Extension,
	// do not call XQueryExtension() / XInitExtension() due to possible version
	// clashes !
	if ( mbUseExtension )
	{
		int nMajorExtOpcode;
		int nExtMajorVersion = XkbMajorVersion;
		int nExtMinorVersion = XkbMinorVersion;

		mbUseExtension = (sal_Bool)XkbQueryExtension( mpDisplay,
			&nMajorExtOpcode, (int*)&mnEventBase, (int*)&mnErrorBase,
			&nExtMajorVersion, &nExtMinorVersion );
	}

	// query notification for changes of the keyboard group
	if ( mbUseExtension )
	{
		#define XkbGroupMask (  XkbGroupStateMask | XkbGroupBaseMask \
						  	  | XkbGroupLatchMask | XkbGroupLockMask )

		mbUseExtension = XkbSelectEventDetails( mpDisplay,
			XkbUseCoreKbd, XkbStateNotify, XkbGroupMask, XkbGroupMask );
	}

	// query initial keyboard group
	if ( mbUseExtension )
	{
		XkbStateRec aStateRecord;
		XkbGetState( mpDisplay, XkbUseCoreKbd, &aStateRecord );
		mnGroup = aStateRecord.group;
	}
}

void
SalI18N_KeyboardExtension::Dispatch( XEvent* pEvent)
{
	// must the event be handled?
	if (   !mbUseExtension
		|| (pEvent->type != mnEventBase) )
		return;

	// only handle state notify events for now, and only interested
	// in group details
	sal_uInt32 nXKBType = ((XkbAnyEvent*)pEvent)->xkb_type;
	switch ( nXKBType )
	{
		case XkbStateNotify:

			mnGroup = ((XkbStateNotifyEvent*)pEvent)->group;
			break;

		default:

#if OSL_DEBUG_LEVEL > 1
			fprintf(stderr, "Got unrequested XkbAnyEvent %#x/%i\n",
				static_cast<unsigned int>(nXKBType), static_cast<int>(nXKBType) );
#endif
			break;
	}
}

sal_uInt32 SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32 nKeyCode,
	sal_uInt32 nShiftState, sal_uInt32 nGroup ) const
{
	nShiftState &= ShiftMask;

	KeySym nKeySymbol = XkbKeycodeToKeysym( mpDisplay, nKeyCode, nGroup, nShiftState );
	return nKeySymbol;
}
