// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef NL_DI_KEYBOARD_H
#define NL_DI_KEYBOARD_H
#include "nel/misc/types_nl.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/input_device_server.h"
#include "nel/misc/keyboard_device.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/bit_set.h"
namespace NLMISC
{
class CWinEventEmitter;
//
struct EDirectInputNoKeyboard : public EDirectInput
{
EDirectInputNoKeyboard() : EDirectInput("No keyboard found") {}
};
struct CKeyConv;
/**
* Direct Input implementation of a keyboard.
* \see CDIEventEmitter
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CDIKeyboard : public IKeyboardDevice
{
public:
bool ShiftPressed, CtrlPressed, AltPressed;
public:
///\name Object
//@{
/** Create a keyboard device, that must then be deleted by the caller
* An optional WinEventEmiter can be provided, so that its flags can be in sync
* with a win32 keyboard flags (shift, ctrl, and alt)
*/
static CDIKeyboard *createKeyboardDevice(IDirectInput8 *di8,
HWND hwnd,
CDIEventEmitter *diEventEmitter,
CWinEventEmitter *we = NULL
) throw(EDirectInput);
// dtor
virtual ~CDIKeyboard();
//@}
///\name From IInputDevice
//@{
virtual bool setBufferSize(uint size);
virtual uint getBufferSize() const;
//@}
///\name From IInputDevice
//@{
uint getKeyRepeatDelay() const { return _RepeatDelay; }
void setKeyRepeatDelay(uint delay) { nlassert(delay > 0); _RepeatDelay = delay; }
uint getKeyRepeatPeriod() const { return _RepeatPeriod; }
void setKeyRepeatPeriod(uint period) { nlassert(period > 0); _RepeatPeriod = period; }
void disableRepetition(const TKey *keyTab, uint numKey);
uint getNumDisabledRepetition() const;
void getDisabledRepetitions(TKey *destTab) const;
//@}
TMouseButton buildKeyboardFlags() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
private:
//
bool _CapsLockToggle; // true if caps lock off is triggered by caps lock, false if it toggled by shift
uint _RepeatDelay; // the delay before a key is repeated (in ms)
uint _RepeatPeriod; // The period for key repetitions (in ms)
//
LPDIRECTINPUTDEVICE8 _Keyboard;
uint _KeyboardBufferSize;
// virtual code state
uint8 _VKKeyState[NumKeys];
// tells for which keys repetition is disabled
CBitSet _RepetitionDisabled;
// The date at which the last key pressed has been pressed (not using 64 bits since note handled by Direct Input)
uint32 _FirstPressDate;
// The last date at which key repetition occured (not using 64 bits since note handled by Direct Input)
uint32 _LastEmitDate;
// The system date at which the last polling occured (not using 64 bits since note handled by Direct Input)
uint32 _PollTime;
uint _LastDIKeyPressed;
CWinEventEmitter *_WE;
HWND _hWnd;
HKL _KBLayout;
//
CDIEventEmitter *_DIEventEmitter;
//
static const CKeyConv *DIKeyToNelKeyTab[NumKeys];
private:
/// ctor
CDIKeyboard(CWinEventEmitter *we, HWND hwnd);
/** Convert a direct input scancode to a virtual key. Note that DirectInput scancodes do not always match system scan codes.
* Repeatable has a meaning only for extended keys
*/
TKey DIKeyToNelKey(uint diKey, bool &extKey, bool &repeatable);
/** This update virtual key state table.
* \param keyValue contains the value to send to a EventKeyDown or EventKeyUp message.
* \param charValue contains the value that must be used for Unicode conversion (which generate EventChar messages)
*/
void updateVKKeyState(uint diKey, bool pressed, TKey &keyValue, TKey &charValue);
// Use the given virtual key code and the current keyb state to produce Unicode
void sendUnicode(TKey vkey, uint dikey, CEventServer *server, bool pressed);
// Build a TKeyButton value from the state of shift, ctrl and alt
TKeyButton buildKeyButtonsFlags() const;
// Update the state of this object and send the appropriate message when a direct / input key has been pressed / released
void keyTriggered(bool pressed, uint key, CEventServer *server, uint32 date);
// The same as buildKeyButtonsFlags(), but the return is a TMouseButtonValue (with no mouse value setupped)
TMouseButton buildKeyboardButtonFlags() const;
// setup the state of the Ctrl, Alt and Shift key from the state in the _VKKeyState buffer
void updateCtrlAltShiftValues();
/// Repeat the current key, and create events
void repeatKey(uint32 currentDate, CEventServer *server);
/// Build a date by using an event time stamp, or generate one if NULL
uint32 buildDateFromEvent(const IInputDeviceEvent *deviceEvent);
///\name From IInputDevice
//@{
virtual void poll(CInputDeviceServer *dev);
virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server);
virtual void transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage);
//@}
};
} // NLMISC
#endif // NL_OS_WINDOWS
#endif // NL_DI_KEYBOARD_H
/* End of di_keyboard.h */