337 lines
10 KiB
Diff
337 lines
10 KiB
Diff
--- ois-v1-3/src/win32/Win32Keyboard.cpp 1970-01-01 01:00:00.000000000 +0100
|
|
+++ patched/src/win32/Win32Keyboard.cpp 2010-07-10 06:33:27.000000000 +0200
|
|
@@ -0,0 +1,333 @@
|
|
+/*
|
|
+The zlib/libpng License
|
|
+
|
|
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
|
|
+
|
|
+This software is provided 'as-is', without any express or implied warranty. In no event will
|
|
+the authors be held liable for any damages arising from the use of this software.
|
|
+
|
|
+Permission is granted to anyone to use this software for any purpose, including commercial
|
|
+applications, and to alter it and redistribute it freely, subject to the following
|
|
+restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not claim that
|
|
+ you wrote the original software. If you use this software in a product,
|
|
+ an acknowledgment in the product documentation would be appreciated but is
|
|
+ not required.
|
|
+
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "win32/Win32InputManager.h"
|
|
+#include "win32/Win32KeyBoard.h"
|
|
+#include "OISException.h"
|
|
+#include "OISEvents.h"
|
|
+#include <sstream>
|
|
+
|
|
+using namespace OIS;
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+Win32Keyboard::Win32Keyboard( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
|
|
+ : Keyboard(creator->inputSystemName(), buffered, 0, creator)
|
|
+{
|
|
+ mKeyboard = 0;
|
|
+ mDirectInput = pDI;
|
|
+ coopSetting = coopSettings;
|
|
+
|
|
+ //Clear our keyboard state buffer
|
|
+ memset( &KeyBuffer, 0, 256 );
|
|
+ deadKey = '\0';
|
|
+ static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(true);
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::_initialize()
|
|
+{
|
|
+ mModifiers = 0;
|
|
+ deadKey = '\0';
|
|
+
|
|
+ if(FAILED(mDirectInput->CreateDevice(GUID_SysKeyboard, &mKeyboard, NULL)))
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> Could not init device!");
|
|
+
|
|
+ if(FAILED(mKeyboard->SetDataFormat(&c_dfDIKeyboard)))
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> format error!");
|
|
+
|
|
+ HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
|
|
+
|
|
+ if(FAILED(mKeyboard->SetCooperativeLevel( hwin, coopSetting)))
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> coop error!");
|
|
+
|
|
+ if( mBuffered )
|
|
+ {
|
|
+ DIPROPDWORD dipdw;
|
|
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
|
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
+ dipdw.diph.dwObj = 0;
|
|
+ dipdw.diph.dwHow = DIPH_DEVICE;
|
|
+ dipdw.dwData = KEYBOARD_DX_BUFFERSIZE;
|
|
+
|
|
+ if (FAILED(mKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph )))
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> buffer error!");
|
|
+ }
|
|
+
|
|
+ HRESULT hr = mKeyboard->Acquire();
|
|
+ if(FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> aquire error!");
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+Win32Keyboard::~Win32Keyboard()
|
|
+{
|
|
+ if(mKeyboard)
|
|
+ {
|
|
+ mKeyboard->Unacquire();
|
|
+ mKeyboard->Release();
|
|
+ mKeyboard = 0;
|
|
+ }
|
|
+ static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(false);
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::capture()
|
|
+{
|
|
+ if( mBuffered )
|
|
+ _readBuffered();
|
|
+ else
|
|
+ _read();
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::_readBuffered()
|
|
+{
|
|
+ DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE];
|
|
+ DWORD entries = KEYBOARD_DX_BUFFERSIZE;
|
|
+ HRESULT hr;
|
|
+ //Only one keyboard allowed per app, so static is ok
|
|
+ static bool verifyAfterAltTab = false;
|
|
+
|
|
+ hr = mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
|
|
+ if( hr != DI_OK )
|
|
+ {
|
|
+ hr = mKeyboard->Acquire();
|
|
+ if (hr == E_ACCESSDENIED)
|
|
+ verifyAfterAltTab = true;
|
|
+
|
|
+ while( hr == DIERR_INPUTLOST )
|
|
+ hr = mKeyboard->Acquire();
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if( FAILED(hr) )
|
|
+ OIS_EXCEPT( E_General, "Win32Keyboard::_readBuffered() >> Problem with Device!" );
|
|
+
|
|
+ //Update keyboard and modifier states.. And, if mListener, fire events
|
|
+ for(unsigned int i = 0; i < entries; ++i )
|
|
+ {
|
|
+ //If the listener returns false, that means that we are probably deleted...
|
|
+ //send no more events and just leave as the this pointer is invalid now...
|
|
+ bool ret = true;
|
|
+ KeyCode kc = (KeyCode)diBuff[ i ].dwOfs;
|
|
+
|
|
+ //Store result in our keyBuffer too
|
|
+ KeyBuffer[kc] = static_cast<unsigned char>(diBuff[ i ].dwData);
|
|
+
|
|
+ if( diBuff[ i ].dwData & 0x80 )
|
|
+ {
|
|
+ //Turn on modifier
|
|
+ if( kc == KC_LCONTROL || kc == KC_RCONTROL )
|
|
+ mModifiers |= Ctrl;
|
|
+ else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
|
|
+ mModifiers |= Shift;
|
|
+ else if( kc == KC_LMENU || kc == KC_RMENU )
|
|
+ mModifiers |= Alt;
|
|
+
|
|
+ if( mListener )
|
|
+ ret = mListener->keyPressed( KeyEvent( this, kc, _translateText(kc) ) );
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ //Turn off modifier
|
|
+ if( kc == KC_LCONTROL || kc == KC_RCONTROL )
|
|
+ mModifiers &= ~Ctrl;
|
|
+ else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
|
|
+ mModifiers &= ~Shift;
|
|
+ else if( kc == KC_LMENU || kc == KC_RMENU )
|
|
+ mModifiers &= ~Alt;
|
|
+
|
|
+ //Fire off event
|
|
+ if( mListener )
|
|
+ ret = mListener->keyReleased( KeyEvent( this, kc, 0 ) );
|
|
+ }
|
|
+
|
|
+ if(ret == false)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // If a lost device/access denied was detected, recover gracefully with new events
|
|
+ if(verifyAfterAltTab)
|
|
+ {
|
|
+ bool ret = true;
|
|
+
|
|
+ //Copy old buffer to temp location to compare against
|
|
+ unsigned char keyBufferCopy[256];
|
|
+ memcpy(keyBufferCopy, KeyBuffer, 256);
|
|
+
|
|
+ //Update new state
|
|
+ _read();
|
|
+
|
|
+ for (unsigned i = 0; i < 256; i++)
|
|
+ {
|
|
+ if (keyBufferCopy[i] != KeyBuffer[i])
|
|
+ {
|
|
+ if (mListener)
|
|
+ {
|
|
+ if (KeyBuffer[i])
|
|
+ ret = mListener->keyPressed( KeyEvent( this, (KeyCode)i, _translateText((KeyCode)i) ) );
|
|
+ else
|
|
+ ret = mListener->keyReleased( KeyEvent( this, (KeyCode)i, 0 ) );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ //If user returned false from callback, return immediately
|
|
+ if(ret == false)
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ verifyAfterAltTab = false;
|
|
+ }
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::_read()
|
|
+{
|
|
+ HRESULT hr = mKeyboard->GetDeviceState( sizeof(KeyBuffer), &KeyBuffer );
|
|
+
|
|
+ if( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED )
|
|
+ {
|
|
+ hr = mKeyboard->Acquire();
|
|
+ if (hr != DIERR_OTHERAPPHASPRIO)
|
|
+ mKeyboard->GetDeviceState(sizeof(KeyBuffer), &KeyBuffer);
|
|
+ }
|
|
+
|
|
+ //Set Shift, Ctrl, Alt
|
|
+ mModifiers = 0;
|
|
+ if( isKeyDown(KC_LCONTROL) || isKeyDown(KC_RCONTROL) )
|
|
+ mModifiers |= Ctrl;
|
|
+ if( isKeyDown(KC_LSHIFT) || isKeyDown(KC_RSHIFT) )
|
|
+ mModifiers |= Shift;
|
|
+ if( isKeyDown(KC_LMENU) || isKeyDown(KC_RMENU) )
|
|
+ mModifiers |= Alt;
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+int Win32Keyboard::_translateText( KeyCode kc )
|
|
+{
|
|
+ if( mTextMode == Off )
|
|
+ return 0;
|
|
+
|
|
+ BYTE keyState[256];
|
|
+ HKL layout = GetKeyboardLayout(0);
|
|
+ if( GetKeyboardState(keyState) == 0 )
|
|
+ return 0;
|
|
+
|
|
+ unsigned int vk = MapVirtualKeyEx(kc, 3, layout);
|
|
+ if( vk == 0 )
|
|
+ return 0;
|
|
+
|
|
+ WCHAR buff[3] = {0};
|
|
+ int ascii = ToUnicodeEx(vk, kc, keyState, buff, 3, 0, layout);
|
|
+
|
|
+ if(ascii == 1 && deadKey != '\0' )
|
|
+ {
|
|
+ // A dead key is stored and we have just converted a character key
|
|
+ // Combine the two into a single character
|
|
+ WCHAR wcBuff[3] = {buff[0], deadKey, '\0'};
|
|
+ WCHAR out[3];
|
|
+
|
|
+ deadKey = '\0';
|
|
+ if(FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
|
|
+ return out[0];
|
|
+ }
|
|
+ else if (ascii == 1)
|
|
+ { // We have a single character
|
|
+ deadKey = '\0';
|
|
+ return buff[0];
|
|
+ }
|
|
+ else if(ascii == 2)
|
|
+ { // Convert a non-combining diacritical mark into a combining diacritical mark
|
|
+ // Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
|
|
+ // http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
|
|
+ switch(buff[0]) {
|
|
+ case 0x5E: // Circumflex accent: â
|
|
+ deadKey = 0x302; break;
|
|
+ case 0x60: // Grave accent: à
|
|
+ deadKey = 0x300; break;
|
|
+ case 0xA8: // Diaeresis: ü
|
|
+ deadKey = 0x308; break;
|
|
+ case 0xB4: // Acute accent: é
|
|
+ deadKey = 0x301; break;
|
|
+ case 0xB8: // Cedilla: ç
|
|
+ deadKey = 0x327; break;
|
|
+ default:
|
|
+ deadKey = buff[0]; break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+bool Win32Keyboard::isKeyDown( KeyCode key ) const
|
|
+{
|
|
+ return (KeyBuffer[key] & 0x80) != 0;
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+const std::string& Win32Keyboard::getAsString(KeyCode kc)
|
|
+{
|
|
+ char temp[256];
|
|
+
|
|
+ DIPROPSTRING prop;
|
|
+ prop.diph.dwSize = sizeof(DIPROPSTRING);
|
|
+ prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
+ prop.diph.dwObj = static_cast<DWORD>(kc);
|
|
+ prop.diph.dwHow = DIPH_BYOFFSET;
|
|
+
|
|
+ if (SUCCEEDED(mKeyboard->GetProperty(DIPROP_KEYNAME, &prop.diph)))
|
|
+ {
|
|
+ // convert the WCHAR in "wsz" to multibyte
|
|
+ if (WideCharToMultiByte(CP_ACP, 0, prop.wsz, -1, temp, sizeof(temp), NULL, NULL))
|
|
+ return mGetString.assign(temp);
|
|
+ }
|
|
+
|
|
+ std::stringstream ss;
|
|
+ ss << "Key_" << (int)kc;
|
|
+ return mGetString.assign(ss.str());
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::copyKeyStates( char keys[256] ) const
|
|
+{
|
|
+ for(int i = 0; i < 256; ++i)
|
|
+ keys[i] = KeyBuffer[i] > 0; //Normalise the DX values (0x80)
|
|
+}
|
|
+
|
|
+//--------------------------------------------------------------------------------------------------//
|
|
+void Win32Keyboard::setBuffered(bool buffered)
|
|
+{
|
|
+ if( buffered != mBuffered )
|
|
+ {
|
|
+ if(mKeyboard)
|
|
+ {
|
|
+ mKeyboard->Unacquire();
|
|
+ mKeyboard->Release();
|
|
+ mKeyboard = 0;
|
|
+ }
|
|
+
|
|
+ mBuffered = buffered;
|
|
+ _initialize();
|
|
+ }
|
|
+}
|