Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/ois/win32/Win32KeyBoard.cpp @ 1344

Last change on this file since 1344 was 1219, checked in by rgrieder, 17 years ago

merged input branch back to trunk. Not yet tested on tardis

File size: 9.0 KB
Line 
1/*
2The zlib/libpng License
3
4Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6This software is provided 'as-is', without any express or implied warranty. In no event will
7the authors be held liable for any damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose, including commercial
10applications, and to alter it and redistribute it freely, subject to the following
11restrictions:
12
13    1. The origin of this software must not be misrepresented; you must not claim that
14                you wrote the original software. If you use this software in a product,
15                an acknowledgment in the product documentation would be appreciated but is
16                not required.
17
18    2. Altered source versions must be plainly marked as such, and must not be
19                misrepresented as being the original software.
20
21    3. This notice may not be removed or altered from any source distribution.
22*/
23#include "Win32/Win32InputManager.h"
24#include "Win32/Win32KeyBoard.h"
25#include "OISException.h"
26#include "OISEvents.h"
27#include <sstream>
28
29using namespace OIS;
30
31//--------------------------------------------------------------------------------------------------//
32Win32Keyboard::Win32Keyboard( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
33        : Keyboard(creator->inputSystemName(), buffered, 0, creator)
34{
35        mKeyboard = 0;
36        mDirectInput = pDI;
37        coopSetting = coopSettings;
38
39        //Clear our keyboard state buffer
40        memset( &KeyBuffer, 0, 256 );
41        deadKey = '\0';
42        static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(true);
43}
44
45//--------------------------------------------------------------------------------------------------//
46void Win32Keyboard::_initialize()
47{
48        mModifiers = 0;
49        deadKey = '\0';
50
51        if(FAILED(mDirectInput->CreateDevice(GUID_SysKeyboard, &mKeyboard, NULL)))
52                OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> Could not init device!");
53
54        if(FAILED(mKeyboard->SetDataFormat(&c_dfDIKeyboard)))
55                OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> format error!");
56
57        HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
58
59        if(FAILED(mKeyboard->SetCooperativeLevel( hwin, coopSetting)))
60                OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> coop error!");
61
62        if( mBuffered )
63        {
64                DIPROPDWORD dipdw;
65                dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
66                dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
67                dipdw.diph.dwObj        = 0;
68                dipdw.diph.dwHow        = DIPH_DEVICE;
69                dipdw.dwData            = KEYBOARD_DX_BUFFERSIZE;
70
71                if (FAILED(mKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph )))
72                        OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> buffer error!");
73        }
74
75        HRESULT hr = mKeyboard->Acquire();
76        if(FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
77                OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> aquire error!");
78}
79
80//--------------------------------------------------------------------------------------------------//
81Win32Keyboard::~Win32Keyboard()
82{
83        if(mKeyboard)
84        {
85                mKeyboard->Unacquire();
86                mKeyboard->Release();
87                mKeyboard = 0;
88        }
89        static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(false);
90}
91
92//--------------------------------------------------------------------------------------------------//
93void Win32Keyboard::capture()
94{
95        if( mBuffered )
96                _readBuffered();
97        else
98                _read();
99}
100
101//--------------------------------------------------------------------------------------------------//
102void Win32Keyboard::_readBuffered()
103{
104        DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE];
105        DWORD entries = KEYBOARD_DX_BUFFERSIZE;
106        HRESULT hr;
107
108        hr = mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
109        if( hr != DI_OK )
110        {
111                hr = mKeyboard->Acquire();
112                while( hr == DIERR_INPUTLOST )
113                        hr = mKeyboard->Acquire();
114                return;
115        }
116
117        if( FAILED(hr) )
118                OIS_EXCEPT( E_General, "Win32Keyboard::_readBuffered() >> Problem with Device!" );
119
120        //Update keyboard and modifier states.. And, if mListener, fire events
121        for(unsigned int i = 0; i < entries; ++i )
122        {
123                //If the mListener returns false, that means that we are probably deleted...
124                //send no more events and just leave as the this pointer is invalid now...
125                bool ret = true;
126                KeyCode kc = (KeyCode)diBuff[ i ].dwOfs;
127                       
128                //Store result in our keyBuffer too
129                KeyBuffer[kc] = static_cast<unsigned char>(diBuff[ i ].dwData);
130                       
131                if( diBuff[ i ].dwData & 0x80 )
132                {
133                        //Turn on modifier
134                        if( kc == KC_LCONTROL || kc == KC_RCONTROL )
135                                mModifiers |= Ctrl;
136                        else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
137                                mModifiers |= Shift;
138                        else if( kc == KC_LMENU || kc == KC_RMENU )
139                                mModifiers |= Alt;
140
141                        if( mListener )
142                                ret = mListener->keyPressed( KeyEvent( this, kc, _translateText(kc) ) );
143                }
144                else
145                {
146                        //Turn off modifier
147                        if( kc == KC_LCONTROL || kc == KC_RCONTROL )
148                                mModifiers &= ~Ctrl;
149                        else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
150                                mModifiers &= ~Shift;
151                        else if( kc == KC_LMENU || kc == KC_RMENU )
152                                mModifiers &= ~Alt;
153
154                        //Fire off event
155                        if( mListener )
156                                ret = mListener->keyReleased( KeyEvent( this, kc, 0 ) );
157                }
158
159                if(ret == false)
160                        break;
161        }
162}
163
164//--------------------------------------------------------------------------------------------------//
165void Win32Keyboard::_read()
166{
167    HRESULT  hr = mKeyboard->GetDeviceState( sizeof(KeyBuffer), &KeyBuffer );
168
169        if( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED )
170        {
171                hr = mKeyboard->Acquire();
172                if (hr != DIERR_OTHERAPPHASPRIO)
173                        mKeyboard->GetDeviceState(sizeof(KeyBuffer), &KeyBuffer);
174        }
175
176        //Set Shift, Ctrl, Alt
177        mModifiers = 0;
178        if( isKeyDown(KC_LCONTROL) || isKeyDown(KC_RCONTROL) )
179                mModifiers |= Ctrl;
180        if( isKeyDown(KC_LSHIFT) || isKeyDown(KC_RSHIFT) )
181                mModifiers |= Shift;
182        if( isKeyDown(KC_LMENU) || isKeyDown(KC_RMENU) )
183                mModifiers |= Alt;
184}
185
186//--------------------------------------------------------------------------------------------------//
187int Win32Keyboard::_translateText( KeyCode kc )
188{
189        if( mTextMode == Off )
190                return 0;
191
192        BYTE keyState[256];
193        HKL  layout = GetKeyboardLayout(0);
194        if( GetKeyboardState(keyState) == 0 )
195                return 0;
196
197        unsigned int vk = MapVirtualKeyEx(kc, 3, layout);
198        if( vk == 0 )
199                return 0;
200
201        unsigned char buff[3] = {0,0,0};
202        int ascii = ToAsciiEx(vk, kc, keyState, (LPWORD) buff, 0, layout);
203        //WCHAR wide[3];
204        //int ascii = ToUnicodeEx(vk, kc, keyState, wide, 3, 0, layout);
205        if(ascii == 1 && deadKey != '\0' )
206        {
207                // A dead key is stored and we have just converted a character key
208                // Combine the two into a single character
209                WCHAR wcBuff[3] = {buff[0], deadKey, '\0'};
210                WCHAR out[3];
211               
212                deadKey = '\0';
213                if(FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
214                        return out[0];
215        }
216        else if (ascii == 1)
217        {       // We have a single character
218                deadKey = '\0';
219                return buff[0];
220        }
221        else if(ascii == 2)
222        {       // Convert a non-combining diacritical mark into a combining diacritical mark
223                // Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
224                // http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
225                switch(buff[0]) {
226                case 0x5E: // Circumflex accent: â
227                        deadKey = 0x302; break;
228                case 0x60: // Grave accent: à
229                        deadKey = 0x300; break;
230                case 0xA8: // Diaeresis: ü
231                        deadKey = 0x308; break;
232                case 0xB4: // Acute accent: é
233                        deadKey = 0x301; break;
234                case 0xB8: // Cedilla: ç
235                        deadKey = 0x327; break;
236                default:
237                        deadKey = buff[0]; break;
238                }
239        }
240
241        return 0;
242}
243
244//--------------------------------------------------------------------------------------------------//
245bool Win32Keyboard::isKeyDown( KeyCode key )
246{
247        return (KeyBuffer[key] & 0x80) != 0;
248}
249
250//--------------------------------------------------------------------------------------------------//
251const std::string& Win32Keyboard::getAsString( KeyCode kc )
252{
253        char temp[256];
254
255        DIPROPSTRING prop;
256        prop.diph.dwSize = sizeof(DIPROPSTRING);
257        prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
258        prop.diph.dwObj = static_cast<DWORD>(kc);
259        prop.diph.dwHow = DIPH_BYOFFSET;
260
261        if ( SUCCEEDED( mKeyboard->GetProperty( DIPROP_KEYNAME, &prop.diph ) ) )
262        {
263                // convert the WCHAR in "wsz" to multibyte
264                if ( WideCharToMultiByte( CP_ACP, 0, prop.wsz, -1, temp, sizeof(temp), NULL, NULL) )
265                        return mGetString.assign( temp );
266        }
267
268        std::stringstream ss;
269        ss << "Key_" << (int)kc;
270        return mGetString.assign( ss.str() );
271}
272
273//--------------------------------------------------------------------------------------------------//
274void Win32Keyboard::copyKeyStates( char keys[256] )
275{
276        for(int i = 0; i < 256; ++i)
277                keys[i] = KeyBuffer[i] > 0; //Normalise the DX values (0x80)
278}
279
280//--------------------------------------------------------------------------------------------------//
281void Win32Keyboard::setBuffered(bool buffered)
282{
283        if( buffered != mBuffered )
284        {
285                if(mKeyboard)
286                {
287                        mKeyboard->Unacquire();
288                        mKeyboard->Release();
289                        mKeyboard = 0;
290                }
291               
292                mBuffered = buffered;
293                _initialize();
294        }
295}
Note: See TracBrowser for help on using the repository browser.