Update of /cvsroot/simspark/simspark/spark/utility/ois/linux In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv13856/linux Added Files: Tag: projectx EventHelpers.cpp EventHelpers.h LinuxForceFeedback.cpp LinuxForceFeedback.h LinuxInputManager.cpp LinuxInputManager.h LinuxJoyStick.h LinuxJoyStickEvents.cpp LinuxJoyStickEvents.h LinuxKeyboard.cpp LinuxKeyboard.h LinuxMouse.cpp LinuxMouse.h LinuxPrereqs.h Log Message: added OIS Library sources --- NEW FILE: LinuxJoyStickEvents.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 "OISConfig.h" #include "linux/LinuxJoyStickEvents.h" #include "linux/LinuxInputManager.h" #include "linux/LinuxForceFeedback.h" #include "linux/EventHelpers.h" #include "OISEvents.h" #include "OISException.h" #include <fcntl.h> //Needed to Open a file descriptor #include <cassert> #include <linux/input.h> #include <sstream> using namespace OIS; //#define OIS_LINUX_JOY_DEBUG #ifdef OIS_LINUX_JOY_DEBUG # include <iostream> using namespace std; #endif //-------------------------------------------------------------------// LinuxJoyStick::LinuxJoyStick(bool buffered, const JoyStickInfo& js) { mBuffered = buffered; mType = OISJoyStick; mDevID = js.devId; mJoyStick = js.joyFileD; mVendor = js.vendor; numAxes = js.axes; numButtons = js.buttons; numHats = js.hats; mButtonMap = js.button_map; mAxisMap = js.axis_map; mRanges = js.axis_range; ff_effect = 0; } //-------------------------------------------------------------------// LinuxJoyStick::~LinuxJoyStick() { EventUtils::removeForceFeedback( &ff_effect ); } //-------------------------------------------------------------------// void LinuxJoyStick::_initialize() { //Clear old joy state mState.mAxes.resize(mAxisMap.size()); mState.clear(); //This will create and new us a force feedback structure if it exists EventUtils::enumerateForceFeedback( mJoyStick, &ff_effect ); if( mJoyStick == -1 ) OIS_EXCEPT(E_InputDeviceNonExistant, "LinuxJoyStick::_initialize() >> JoyStick Not Found!"); } //-------------------------------------------------------------------// void LinuxJoyStick::capture() { static const short POV_MASK[8] = {0,0,1,1,2,2,3,3}; //Used to determine if an axis has been changed and needs an event bool axisMoved[32] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; //We are in non blocking mode - we just read once, and try to fill up buffer input_event js[JOY_BUFFERSIZE]; int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE); if( ret <= 0 ) return; //Determine how many whole events re read up ret /= sizeof(struct input_event); for(int i = 0; i < ret; ++i) { switch(js[i].type) { case EV_KEY: //Button { int button = mButtonMap[js[i].code]; #ifdef OIS_LINUX_JOY_DEBUG std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl; #endif //Check to see whether push or released event... if(js[i].value) { mState.buttons |= (1 << button); if( mBuffered && listener ) if(!listener->buttonPressed(JoyStickEvent(this,mState), button)) return; } else { mState.buttons &= ~(1 << button); if( mBuffered && listener ) if(!listener->buttonReleased(JoyStickEvent(this,mState), button)) return; } break; } case EV_ABS: //Absoulte Axis { //A Stick (BrakeDefine is the highest possible Axis) if( js[i].code <= ABS_BRAKE ) { int axis = mAxisMap[js[i].code]; assert( axis < 32 && "Too many axes, not supported. Report this to OIS forums!" ); axisMoved[axis] = true; //check for rescaling: if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS ) { //Scale is perfect mState.mAxes[axis].abs = js[i].value; } else { //Rescale float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max); mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion)); } } else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed { //Normalise the POV to between 0-7 //Even is X Axis, Odd is Y Axis unsigned char LinuxPovNumber = js[i].code - 16; short OIS_POVIndex = POV_MASK[LinuxPovNumber]; //Handle X Axis first (Even) (left right) if((LinuxPovNumber & 0x0001) == 0) { //Why do this? Because, we use a bit field, and when this axis is east, //it can't possibly be west too. So clear out the two X axes, then refil //it in with the new direction bit. //Clear the East/West Bit Flags first mState.mPOV[OIS_POVIndex].direction &= 0x11110011; if( js[i].value == -1 ) //Left mState.mPOV[OIS_POVIndex].direction |= Pov::West; else if( js[i].value == 1 ) //Right mState.mPOV[OIS_POVIndex].direction |= Pov::East; } //Handle Y Axis (Odd) (up down) else { //Clear the North/South Bit Flags first mState.mPOV[OIS_POVIndex].direction &= 0x11111100; if( js[i].value == -1 ) //Up mState.mPOV[OIS_POVIndex].direction |= Pov::North; else if( js[i].value == 1 ) //Down mState.mPOV[OIS_POVIndex].direction |= Pov::South; } if( mBuffered && listener ) if( listener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false ) return; } break; } //Relative Axes (Do any joysticks actually have a relative axis?) case EV_REL: default: break; } } //All axes and POVs are combined into one movement per pair per captured frame if( mBuffered && listener ) { for( int i = 0; i < 32; ++i ) if( axisMoved[i] ) if( listener->axisMoved( JoyStickEvent(this,mState), i) == false ) return; } } //-------------------------------------------------------------------// void LinuxJoyStick::setBuffered(bool buffered) { if( buffered != mBuffered ) { mBuffered = buffered; _initialize(); } } //-------------------------------------------------------------------// JoyStickInfo LinuxJoyStick::_getJoyInfo() { JoyStickInfo js; js.devId = mDevID; js.joyFileD = mJoyStick; js.vendor = mVendor; js.axes = numAxes; js.buttons = numButtons; js.hats = numHats; js.button_map = mButtonMap; js.axis_map = mAxisMap; js.axis_range = mRanges; return js; } //-------------------------------------------------------------------// JoyStickInfoList LinuxJoyStick::_scanJoys() { JoyStickInfoList joys; //Search through all of the event devices.. and identify which ones are joysticks //xxx move this to InputManager, as it can also scan all other events for(int i = 0; i < 32; ++i ) { std::stringstream s; s << "/dev/input/event" << i; int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK ); #ifdef OIS_LINUX_JOY_DEBUG std::cout << "\nOpening " << s.str() << "..."; #endif try { JoyStickInfo js; if( EventUtils::isJoyStick(fd, js) ) { joys.push_back(js); #ifdef OIS_LINUX_JOY_DEBUG std::cout << "\n__Joystick added to list"; #endif } else { #ifdef OIS_LINUX_JOY_DEBUG std::cout << "\n__Not a joystick!!"; #endif close(fd); } } catch(...) { #ifdef OIS_LINUX_JOY_DEBUG std::cout << "\nException caught!!"; #endif close(fd); } } return joys; } //-------------------------------------------------------------------// void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys) { for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i) close(i->joyFileD); joys.clear(); } //-------------------------------------------------------------------// Interface* LinuxJoyStick::queryInterface(Interface::IType type) { if( ff_effect && type == Interface::ForceFeedback ) return ff_effect; return 0; } --- NEW FILE: LinuxMouse.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 friosom any source distribution. */ #include "linux/LinuxMouse.h" #include "linux/LinuxInputManager.h" #include "OISException.h" #include "OISEvents.h" using namespace OIS; //-------------------------------------------------------------------// LinuxMouse::LinuxMouse(InputManager* creator, bool buffered, bool grab, bool hide) { mCreator = creator; mBuffered = buffered; mType = OISMouse; listener = 0; display = 0; window = 0; cursor = 0; grabMouse = grab; hideMouse = hide; } //-------------------------------------------------------------------// void LinuxMouse::_initialize() { //Clear old state mState.clear(); mMoved = false; mWarped = false; oldXMouseX = oldXMouseY = XMouseX = XMouseY = 6; oldXMouseZ = 0; if( display ) XCloseDisplay(display); display = 0; window = static_cast<LinuxInputManager*>(mCreator)->_getWindow(); //Create our local X listener connection if( !(display = XOpenDisplay(0)) ) OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> Error opening X!"); //Set it to recieve Mouse Input events if( XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | PointerMotionMask) == BadWindow ) OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> X error!"); //Warp mouse inside window XWarpPointer(display,None,window,0,0,0,0, 6,6); //Create a blank cursor: Pixmap bm_no; XColor black, dummy; Colormap colormap; static char no_data[] = { 0,0,0,0,0,0,0,0 }; colormap = DefaultColormap( display, DefaultScreen(display) ); XAllocNamedColor( display, colormap, "black", &black, &dummy ); bm_no = XCreateBitmapFromData( display, window, no_data, 8, 8 ); cursor = XCreatePixmapCursor( display, bm_no, bm_no, &black, &black, 0, 0 ); grab( grabMouse ); hide( hideMouse ); mouseFocusLost = false; } //-------------------------------------------------------------------// LinuxMouse::~LinuxMouse() { if( display ) { grab(false); hide(false); XFreeCursor(display, cursor); XCloseDisplay(display); } } //-------------------------------------------------------------------// void LinuxMouse::setBuffered(bool buffered) { mBuffered = buffered; } //-------------------------------------------------------------------// void LinuxMouse::capture() { //Clear out last frames values mState.X.rel = 0; mState.Y.rel = 0; mState.Z.rel = 0; _processXEvents(); mWarped = false; if( mMoved == true ) { //Compute this frames Relative X & Y motion mState.X.rel = XMouseX - oldXMouseX; mState.Y.rel = XMouseY - oldXMouseY; //Store old values for next time to compute relative motion oldXMouseX = XMouseX; oldXMouseY = XMouseY; mState.X.abs += mState.X.rel; mState.Y.abs += mState.Y.rel; mState.Z.abs += mState.Z.rel; if( grabMouse ) { //We only need to clip when we are warping mouse around if( mState.X.abs < 0 ) mState.X.abs = 0; else if( mState.X.abs > mState.width ) mState.X.abs = mState.width; if( mState.Y.abs < 0 ) mState.Y.abs = 0; else if( mState.Y.abs > mState.height ) mState.Y.abs = mState.height; if( mouseFocusLost == false ) { //Keep mouse in window (fudge factor) if(XMouseX<5 || XMouseX>mState.width-5 || XMouseY<5 || XMouseY>mState.height-5 ) { oldXMouseX = XMouseX = mState.width >> 1; oldXMouseY = XMouseY = mState.height >> 1; XWarpPointer(display,None,window,0,0,0,0,XMouseX, XMouseY); mWarped = true; } } } if( mBuffered && listener ) listener->mouseMoved( MouseEvent( this, mState ) ); mMoved = false; } //Check for losing/gaining mouse grab focus (alt-tab, etc) if( grabMouse ) { if( static_cast<LinuxInputManager*>(mCreator)->_getGrabState() ) { if( mouseFocusLost ) { //We just regained mouse grab focus grab( true ); hide( hideMouse ); mouseFocusLost = false; } } else { if( mouseFocusLost == false ) {//We just lost mouse grab focus grab( false ); hide( false ); mouseFocusLost = true; } } } } //-------------------------------------------------------------------// void LinuxMouse::_processXEvents() { //X11 Button Events: 1=left 2=middle 3=right; Our Bit Postion: 1=Left 2=Right 3=Middle char mask[4] = {0,1,4,2}; XEvent event; //Poll x11 for events mouse events while( XPending(display) > 0 ) { XNextEvent(display, &event); if( event.type == MotionNotify ) { XMouseX = event.xmotion.x; XMouseY = event.xmotion.y; //Mouse can sometimes get bad data when warping, // so compensate (kindof a hack.. happens with long delays between capture's) if( mWarped && grabMouse ) { if(XMouseX<5 || XMouseX>mState.width-5) { XMouseX = oldXMouseX; continue; } else if(XMouseY<5 || XMouseY>mState.height-5) { XMouseY = oldXMouseY; continue; } } mMoved = true; } else if( event.type == ButtonPress ) { static_cast<LinuxInputManager*>(mCreator)->_setGrabState(true); if( event.xbutton.button < 4 ) { mState.buttons |= mask[event.xbutton.button]; if( mBuffered && listener ) if( listener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)(mask[event.xbutton.button] >> 1)) == false ) return; } } else if( event.type == ButtonRelease ) { if( event.xbutton.button < 4 ) { mState.buttons &= ~mask[event.xbutton.button]; if( mBuffered && listener ) if( listener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)(mask[event.xbutton.button] >> 1)) == false ) return; } //The Z axis gets pushed/released pair message (this is up) else if( event.xbutton.button == 4 ) { mState.Z.rel += 120; mMoved = true; } //The Z axis gets pushed/released pair message (this is down) else if( event.xbutton.button == 5 ) { mState.Z.rel -= 120; mMoved = true; } } } } //-------------------------------------------------------------------// void LinuxMouse::grab(bool grab) { if( grab ) XGrabPointer(display, window, True, 0, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); else XUngrabPointer(display, CurrentTime); } //-------------------------------------------------------------------// void LinuxMouse::hide(bool hide) { if( hide ) XDefineCursor(display, window, cursor); else XUndefineCursor(display, window); } --- NEW FILE: LinuxKeyboard.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 "linux/LinuxInputManager.h" #include "linux/LinuxKeyboard.h" #include "OISException.h" #include "OISEvents.h" #include <X11/keysym.h> #include <X11/Xutil.h> using namespace OIS; #include <iostream> //-------------------------------------------------------------------// LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab, bool useXRepeat) { mCreator = creator; mBuffered = buffered; mType = OISKeyboard; listener = 0; display = 0; window = 0; grabKeyboard = grab; keyFocusLost = false; xAutoRepeat = useXRepeat; oldXAutoRepeat = false; //X Key Map to KeyCode keyConversion.insert(XtoOIS_KeyMap::value_type(XK_1, KC_1)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_2, KC_2)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_3, KC_3)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_4, KC_4)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_5, KC_5)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_6, KC_6)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_7, KC_7)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_8, KC_8)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_9, KC_9)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_0, KC_0)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_BackSpace, KC_BACK)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_minus, KC_MINUS)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_equal, KC_EQUALS)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_space, KC_SPACE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_comma, KC_COMMA)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_period, KC_PERIOD)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_backslash, KC_BACKSLASH)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_slash, KC_SLASH)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketleft, KC_LBRACKET)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketright, KC_RBRACKET)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Escape,KC_ESCAPE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Caps_Lock, KC_CAPITAL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Tab, KC_TAB)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Return, KC_RETURN)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_L, KC_LCONTROL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_R, KC_RCONTROL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_colon, KC_COLON)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_semicolon, KC_SEMICOLON)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_apostrophe, KC_APOSTROPHE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_grave, KC_GRAVE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_b, KC_B)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_a, KC_A)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_c, KC_C)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_d, KC_D)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_e, KC_E)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_f, KC_F)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_g, KC_G)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_h, KC_H)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_i, KC_I)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_j, KC_J)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_k, KC_K)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_l, KC_L)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_m, KC_M)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_n, KC_N)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_o, KC_O)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_p, KC_P)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_q, KC_Q)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_r, KC_R)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_s, KC_S)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_t, KC_T)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_u, KC_U)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_v, KC_V)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_w, KC_W)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_x, KC_X)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_y, KC_Y)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_z, KC_Z)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F1, KC_F1)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F2, KC_F2)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F3, KC_F3)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F4, KC_F4)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F5, KC_F5)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F6, KC_F6)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F7, KC_F7)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F8, KC_F8)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F9, KC_F9)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F10, KC_F10)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F11, KC_F11)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F12, KC_F12)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F13, KC_F13)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F14, KC_F14)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F15, KC_F15)); //Keypad keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_0, KC_NUMPAD0)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_1, KC_NUMPAD1)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_2, KC_NUMPAD2)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_3, KC_NUMPAD3)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_4, KC_NUMPAD4)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_5, KC_NUMPAD5)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_6, KC_NUMPAD6)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_7, KC_NUMPAD7)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_8, KC_NUMPAD8)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_9, KC_NUMPAD9)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Add, KC_ADD)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Decimal, KC_DECIMAL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Divide, KC_DIVIDE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Enter, KC_NUMPADENTER)); //Keypad with numlock off keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Home, KC_NUMPAD7)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Up, KC_UP)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Down, KC_DOWN)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Left, KC_LEFT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Right, KC_RIGHT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Up, KC_PGUP)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Down, KC_PGDOWN)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Home, KC_HOME)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_End, KC_END)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Num_Lock, KC_NUMLOCK)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_R, KC_RSHIFT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_L, KC_LSHIFT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_R, KC_RMENU)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_L, KC_LMENU)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Delete, KC_DELETE)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_L, KC_LWIN)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_R, KC_RWIN)); keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Menu, KC_APPS)); } //-------------------------------------------------------------------// void LinuxKeyboard::_initialize() { //Clear our keyboard state buffer memset( &KeyBuffer, 0, 256 ); mModifiers = 0; if( display ) XCloseDisplay(display); display = 0; window = static_cast<LinuxInputManager*>(mCreator)->_getWindow(); //Create our local X listener connection if( !(display = XOpenDisplay(0)) ) OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize >> Error opening X!"); //Set it to recieve Input events if( XSelectInput(display, window, KeyPressMask | KeyReleaseMask) == BadWindow ) OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize: X error!"); if( grabKeyboard ) XGrabKeyboard(display,window,True,GrabModeAsync,GrabModeAsync,CurrentTime); keyFocusLost = false; if( xAutoRepeat == false ) { //We do not want to blindly turn on autorepeat later when quiting if //it was not on to begin with.. So, let us check and see first XKeyboardState old; XGetKeyboardControl( display, &old ); oldXAutoRepeat = false; if( old.global_auto_repeat == AutoRepeatModeOn ) oldXAutoRepeat = true; XAutoRepeatOff( display ); } } //-------------------------------------------------------------------// LinuxKeyboard::~LinuxKeyboard() { if( display ) { if( oldXAutoRepeat ) XAutoRepeatOn(display); if( grabKeyboard ) XUngrabKeyboard(display, CurrentTime); XCloseDisplay(display); } } //-------------------------------------------------------------------// bool LinuxKeyboard::isKeyDown( KeyCode key ) { return (KeyBuffer[key]); } //-------------------------------------------------------------------// void LinuxKeyboard::capture() { KeySym key; XEvent event; LinuxInputManager* linMan = static_cast<LinuxInputManager*>(mCreator); while( XPending(display) > 0 ) { XNextEvent(display, &event); if( KeyPress == event.type ) { char buffer[3] = {0,0,0}; if( mTextMode != Off ) /*int bytes =*/ XLookupString(&event.xkey, buffer, 3, &key, 0); //Mask out the modifier states X11 sets and read again event.xkey.state &= ~ShiftMask; event.xkey.state &= ~LockMask; XLookupString(&event.xkey, 0, 0,&key, 0); _injectKeyDown(key, buffer[0]); //Just printing out some debugging info.. to verify all chars are mapped //std::cout << "KEY PRESSED X=" << event.xkey.keycode; //std::cout << "\n KeySym=" << key << std::endl; //Check for Alt-Tab if( event.xkey.state & Mod1Mask && key == XK_Tab ) linMan->_setGrabState(false); } else if( KeyRelease == event.type ) { //Mask out the modifier states X sets.. or we will get improper values event.xkey.state &= ~ShiftMask; event.xkey.state &= ~LockMask; //Else, it is a valid key release XLookupString(&event.xkey,NULL,0,&key,NULL); _injectKeyUp(key); } } //If grabbing mode is on.. Handle focus lost/gained via Alt-Tab and mouse clicks if( grabKeyboard ) { if( linMan->_getGrabState() == false ) { // are no longer grabbing if( keyFocusLost == false ) { //UnGrab KeyBoard XUngrabKeyboard(display, CurrentTime); keyFocusLost = true; } } else { //We are grabbing - and regained focus if( keyFocusLost == true ) { //ReGrab KeyBoard XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); keyFocusLost = false; } } } } //-------------------------------------------------------------------// void LinuxKeyboard::setBuffered(bool buffered) { mBuffered = buffered; } //-------------------------------------------------------------------// bool LinuxKeyboard::_injectKeyDown( KeySym key, int text ) { KeyCode kc = keyConversion[key]; KeyBuffer[kc] = 1; //Turn on modifier flags 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( mBuffered && listener ) return listener->keyPressed(KeyEvent(this,kc,text)); return true; } //-------------------------------------------------------------------// bool LinuxKeyboard::_injectKeyUp( KeySym key ) { KeyCode kc = keyConversion[key]; KeyBuffer[kc] = 0; //Turn off modifier flags 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( mBuffered && listener ) return listener->keyReleased(KeyEvent(this, kc, 0)); return true; } //-------------------------------------------------------------------// const std::string& LinuxKeyboard::getAsString( KeyCode kc ) { mGetString = "Unknown"; char *temp = 0; XtoOIS_KeyMap::iterator i = keyConversion.begin(), e = keyConversion.end(); for( ; i != e; ++i ) { if( i->second == kc ) { temp = XKeysymToString(i->first); if( temp ) mGetString = temp; break; } } return mGetString; } //-------------------------------------------------------------------// void LinuxKeyboard::copyKeyStates( char keys[256] ) { memcpy( keys, KeyBuffer, 256 ); } --- NEW FILE: LinuxForceFeedback.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef OIS_LinuxForceFeedBack_H #define OIS_LinuxForceFeedBack_H #include "linux/LinuxPrereqs.h" #include "OISForceFeedback.h" namespace OIS { class LinuxForceFeedback : public ForceFeedback { public: LinuxForceFeedback(); ~LinuxForceFeedback(); /** @copydoc ForceFeedback::setMasterGain */ void setMasterGain(float); /** @copydoc ForceFeedback::setAutoCenterMode */ void setAutoCenterMode(bool); /** @copydoc ForceFeedback::upload */ void upload( const Effect* effect ); /** @copydoc ForceFeedback::modify */ void modify( const Effect* effect ); /** @copydoc ForceFeedback::remove */ void remove( const Effect* effect ); /** FF is not yet implemented fully on Linux.. just retun 0 for now. todo, xxx */ short int getFFAxesNumber() { return 0; } }; } #endif //OIS_LinuxForceFeedBack_H --- NEW FILE: LinuxInputManager.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 "linux/LinuxInputManager.h" #include "linux/LinuxKeyboard.h" #include "linux/LinuxJoyStickEvents.h" #include "linux/LinuxMouse.h" #include "OISException.h" using namespace OIS; const std::string LinuxInputManager::iName = "X11 Linux Input Manager"; //--------------------------------------------------------------------------------// LinuxInputManager::LinuxInputManager() { window = 0; //Default settings grabMouse = true; grabKeyboard = true; hideMouse = true; mGrabs = true; useXRepeat = false; } //--------------------------------------------------------------------------------// LinuxInputManager::~LinuxInputManager() { LinuxJoyStick::_clearJoys(unusedJoyStickList); } //--------------------------------------------------------------------------------// void LinuxInputManager::_initialize( ParamList ¶mList ) { _parseConfigSettings( paramList ); //Enumerate all devices attached _enumerateDevices(); } //--------------------------------------------------------------------------------// void LinuxInputManager::_parseConfigSettings( ParamList ¶mList ) { ParamList::iterator i = paramList.find("WINDOW"); if( i == paramList.end() ) OIS_EXCEPT( E_InvalidParam, "LinuxInputManager >> No WINDOW!" ); //TODO 64 bit proof this little conversion xxx wip window = strtoul(i->second.c_str(), 0, 10); //--------- Keyboard Settings ------------// i = paramList.find("XAutoRepeatOn"); if( i != paramList.end() ) if( i->second == "true" ) useXRepeat = true; i = paramList.find("x11_keyboard_grab"); if( i != paramList.end() ) if( i->second == "false" ) grabKeyboard = false; //--------- Mouse Settings ------------// i = paramList.find("x11_mouse_grab"); if( i != paramList.end() ) if( i->second == "false" ) grabMouse = false; i = paramList.find("x11_mouse_hide"); if( i != paramList.end() ) if( i->second == "false" ) hideMouse = false; } //--------------------------------------------------------------------------------// void LinuxInputManager::_enumerateDevices() { //Enumerate all attached devices unusedJoyStickList = LinuxJoyStick::_scanJoys(); joySticks = unusedJoyStickList.size(); } //--------------------------------------------------------------------------------// int LinuxInputManager::numJoysticks() { return joySticks; } //--------------------------------------------------------------------------------// int LinuxInputManager::numMice() { return 1; } //--------------------------------------------------------------------------------// int LinuxInputManager::numKeyBoards() { return 1; } //----------------------------------------------------------------------------// Object* LinuxInputManager::createInputObject( Type iType, bool bufferMode ) { Object* obj = 0; switch( iType ) { case OISKeyboard: obj = new LinuxKeyboard(this, bufferMode, grabKeyboard, useXRepeat); break; case OISMouse: obj = new LinuxMouse(this, bufferMode, grabMouse, hideMouse); break; case OISJoyStick: { //Find a JoyStick not in use JoyStickInfoList::iterator i = unusedJoyStickList.begin(); if( i != unusedJoyStickList.end() ) { obj = new LinuxJoyStick(bufferMode, *i); unusedJoyStickList.erase(i); break; } OIS_EXCEPT(E_InputDeviceNonExistant, "No JoySticks Available!"); } default: OIS_EXCEPT( E_InputDeviceNotSupported, "Device Not Supported!"); } //Seperate initialization from construction.. as bad things happen when //throwing exceptions from constructors try { obj->_initialize(); } catch(...) { delete obj; throw; //rethrow the exception } return obj; } //----------------------------------------------------------------------------// void LinuxInputManager::destroyInputObject( Object* obj ) { if( obj ) { //We put joys back into unused list if( obj->type() == OISJoyStick ) unusedJoyStickList.push_back(((LinuxJoyStick*)obj)->_getJoyInfo()); delete obj; } } --- NEW FILE: LinuxKeyboard.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef _LINUX_KEYBOARD_H_EADER_ #define _LINUX_KEYBOARD_H_EADER_ #include "linux/LinuxPrereqs.h" #include "OISKeyboard.h" #include <X11/Xlib.h> namespace OIS { /** Linux implementation of Keyboard object - uses x11 */ class LinuxKeyboard : public Keyboard { public: LinuxKeyboard(InputManager* creator, bool buffered, bool grab, bool useXRepeat ); virtual ~LinuxKeyboard(); /** @copydoc Keyboard::isKeyDown */ virtual bool isKeyDown( KeyCode key ); /** @copydoc Keyboard::getAsString */ virtual const std::string& getAsString( KeyCode kc ); /** @copydoc Keyboard::copyKeyStates */ virtual void copyKeyStates( char keys[256] ); /** @copydoc Object::setBuffered */ virtual void setBuffered(bool buffered); /** @copydoc Object::capture */ virtual void capture(); /** @copydoc Object::queryInterface */ virtual Interface* queryInterface(Interface::IType) {return 0;} /** @copydoc Object::_initialize */ virtual void _initialize(); protected: bool _injectKeyDown( KeySym key, int text ); bool _injectKeyUp( KeySym key ); //! 1:1 Conversion Map between X Key Events and OIS KeyCodes typedef std::map<KeySym, KeyCode> XtoOIS_KeyMap; XtoOIS_KeyMap keyConversion; //! Depressed Key List char KeyBuffer[256]; //! X11 Stuff Window window; Display *display; bool grabKeyboard; bool keyFocusLost; bool xAutoRepeat; bool oldXAutoRepeat; std::string mGetString; }; } #endif //_LINUX_KEYBOARD_H_EADER_ --- NEW FILE: LinuxForceFeedback.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 "linux/LinuxForceFeedback.h" #include "OISException.h" using namespace OIS; //--------------------------------------------------------------// LinuxForceFeedback::LinuxForceFeedback() { } //--------------------------------------------------------------// LinuxForceFeedback::~LinuxForceFeedback() { } //--------------------------------------------------------------// void LinuxForceFeedback::setMasterGain(float) { } //--------------------------------------------------------------// void LinuxForceFeedback::setAutoCenterMode(bool) { } //--------------------------------------------------------------// void LinuxForceFeedback::upload( const Effect* /*effect*/ ) { } //--------------------------------------------------------------// void LinuxForceFeedback::modify( const Effect* /*effect*/ ) { } //--------------------------------------------------------------// void LinuxForceFeedback::remove( const Effect* /*effect*/ ) { } --- NEW FILE: LinuxPrereqs.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef _LINUX_INPUTSYSTEM_PREREQS_H #define _LINUX_INPUTSYSTEM_PREREQS_H //Bring in any auto generated config files #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "OISPrereqs.h" //! Max number of elements to collect from buffered input #define JOY_BUFFERSIZE 10 namespace OIS { class LinuxInputManager; class LinuxKeyboard; class LinuxJoyStick; class LinuxMouse; class LinuxForceFeedback; struct Range { Range() {}; Range(int _min, int _max) : min(_min), max(_max) {}; int min, max; }; struct JoyStickInfo { JoyStickInfo(): devId(-1),joyFileD(-1),version(0),axes(0),buttons(0),hats(0) {} //! Device number (/dev/input/j#) or /dev/input/event# int devId; //! File descriptor int joyFileD; //! Driver version int version; //! Joy vendor std::string vendor; //! Number of axes unsigned char axes; //! Number of buttons unsigned char buttons; //! Number of hats unsigned char hats; //! Maps Linux button values to OIS buttons values std::map<int, int> button_map; //! Maps Linux axis values to OIS axis std::map<int, int> axis_map; //! Maps OIS axis values to it's range std::map<int, Range> axis_range; }; typedef std::vector< JoyStickInfo > JoyStickInfoList; } #endif //_LINUX_INPUTSYSTEM_PREREQS_H --- NEW FILE: LinuxInputManager.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef OIS_LinuxInputManager_H #define OIS_LinuxInputManager_H #include "linux/LinuxPrereqs.h" #include "OISInputManager.h" #include <X11/Xlib.h> namespace OIS { /** Linux X11 InputManager specialization - Using lowlevel joys */ class LinuxInputManager : public InputManager { public: LinuxInputManager(); virtual ~LinuxInputManager(); /** @copydoc InputManager::inputSystemName */ virtual const std::string& inputSystemName() { return iName; } /** @copydoc InputManager::numJoysticks */ virtual int numJoysticks(); /** @copydoc InputManager::numMice */ virtual int numMice(); /** @copydoc InputManager::numKeyBoards */ virtual int numKeyBoards(); /** @copydoc InputManager::createInputObject */ Object* createInputObject( Type iType, bool bufferMode ); /** @copydoc InputManager::destroyInputObject */ void destroyInputObject( Object* obj ); //! Method for retrieving the XWindow Handle Window _getWindow() {return window;} //! Internal method for checking if regrabbing is needed void _setGrabState(bool grab) {mGrabs = grab;} bool _getGrabState() {return mGrabs;} protected: /** @copydoc InputManager::_initialize */ void _initialize( ParamList ¶mList ); //! internal class method for dealing with param list void _parseConfigSettings( ParamList ¶mList ); //! internal class method for finding attached devices void _enumerateDevices(); //! List of unused joysticks ready to be used JoyStickInfoList unusedJoyStickList; //! Number of joysticks found char joySticks; //! Input manager string name static const std::string iName; //! X11 Stuff Window window; /// Keyboard, Mouse Settings bool grabMouse, grabKeyboard; bool mGrabs; bool hideMouse; //! By default, keyboard disables XRepeatRate bool useXRepeat; }; } #endif --- NEW FILE: LinuxJoyStickEvents.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef _LINUX_JOYSTICK_H_EADER_ #define _LINUX_JOYSTICK_H_EADER_ #include "linux/LinuxPrereqs.h" #include "OISJoyStick.h" namespace OIS { /** Linux specialization of JoyStick class.. This version is favored over the other.. and has the *possibility* of Force Feedback.. notice I say possibility, i make no gaurantees under linux, as FF support is sketchy at best AFAIK. */ class LinuxJoyStick : public JoyStick { public: LinuxJoyStick(bool buffered, const JoyStickInfo& js); virtual ~LinuxJoyStick(); /** @copydoc Object::setBuffered */ virtual void setBuffered(bool buffered); /** @copydoc Object::capture */ virtual void capture(); /** @copydoc Object::queryInterface */ virtual Interface* queryInterface(Interface::IType type); /** @copydoc Object::_initialize */ virtual void _initialize(); /** @remarks For internal use only... Returns a structure to the manager, to make the device availiable for use again */ JoyStickInfo _getJoyInfo(); static JoyStickInfoList _scanJoys(); static void _clearJoys(JoyStickInfoList &joys); protected: int mJoyStick; LinuxForceFeedback* ff_effect; std::map <int, int> mButtonMap; std::map <int, int> mAxisMap; std::map <int, Range> mRanges; }; } #endif //_LINUX_JOYSTICK_H_EADER_ --- NEW FILE: EventHelpers.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef _LINUX_OISEVENT_HEADER_ #define _LINUX_OISEVENT_HEADER_ #include "linux/LinuxPrereqs.h" #define OIS_MAX_DEVICES 32 #define OIS_DEVICE_NAME 128 namespace OIS { class EventUtils { public: static bool isJoyStick( int deviceID, JoyStickInfo &js ); static bool isMouse( int ) {return false;} static bool isKeyboard( int ) {return false;} //Double pointer is so that we can set the value of the sent pointer static void enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff ); static void removeForceFeedback( LinuxForceFeedback** ff ); static std::string getName( int deviceID ); }; } #endif --- NEW FILE: LinuxMouse.h --- /* The zlib/libpng License Copyright (c) 2006 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. */ #ifndef _LINUX_MOUSE_H_EADER_ #define _LINUX_MOUSE_H_EADER_ #include "linux/LinuxPrereqs.h" #include "OISMouse.h" #include <X11/Xlib.h> namespace OIS { class LinuxMouse : public Mouse { public: LinuxMouse(InputManager* creator, bool buffered, bool grab, bool hide); virtual ~LinuxMouse(); /** @copydoc Object::setBuffered */ virtual void setBuffered(bool buffered); /** @remarks Note: Calling this will also update the keyboard (X11 updates in a single event queue). Updates State and/or raises event for buffered mode.. */ virtual void capture(); /** @copydoc Object::queryInterface */ virtual Interface* queryInterface(Interface::IType) {return 0;} /** @copydoc Object::_initialize */ virtual void _initialize(); void grab(bool grab); void hide(bool hide); protected: void _processXEvents(); bool mMoved, mWarped; //Since X11 provides us with absolute values, we need to keep track of //relative values long oldXMouseX, oldXMouseY, oldXMouseZ; //We use these to keep track of the cuurent absolute X Mouse position long XMouseX, XMouseY; //! X11 Stuff Window window; Display *display; Cursor cursor; //A blank cursor bool grabMouse; bool hideMouse; bool mouseFocusLost; }; } #endif //_LINUX_MOUSE_H_EADER_ --- NEW FILE: EventHelpers.cpp --- /* The zlib/libpng License Copyright (c) 2006 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 "linux/EventHelpers.h" #include "linux/LinuxPrereqs.h" #include "linux/LinuxForceFeedback.h" #include "OISException.h" #include "OISJoyStick.h" #include <linux/input.h> //#define OIS_LINUX_JOY_DEBUG #ifdef OIS_LINUX_JOY_DEBUG # include <iostream> using namespace std; #endif using namespace OIS; struct DeviceComponentInfo { std::vector<int> buttons, relAxes, absAxes, hats; }; bool inline isBitSet(unsigned long bits[], unsigned int bit) { return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1; } //-----------------------------------------------------------------------------// DeviceComponentInfo getComponentInfo( int deviceID ) { unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1]; memset( info, 0, sizeof(info) ); DeviceComponentInfo components; //Read "all" (hence 0) components of the device - read into first entry ioctl(deviceID, EVIOCGBIT(0, EV_MAX), info[0]); for (int i = 0; i < EV_MAX; i++) { if( isBitSet(info[0], i) ) { memset( info[1], 0, sizeof(info) / 2 ); ioctl(deviceID, EVIOCGBIT(i, KEY_MAX), info[1]); for (int j = 0; j < KEY_MAX; j++) { if( isBitSet(info[1], j) ) { if(i == EV_ABS) { //input_absinfo abInfo; //ioctl( fd, EVIOCGABS(j), abInfo ); if( j >= ABS_HAT0X && j <= ABS_HAT3Y ) { components.hats.push_back(j); } else { components.absAxes.push_back(j); //input_absinfo absinfo; //ioctl(deviceID, EVIOCGABS(j), &absinfo); //We cannot actually change these values :| //absinfo.minimum = JoyStick::MIN_AXIS; //absinfo.maximum = JoyStick::MAX_AXIS; //ioctl(deviceID, EVIOCSABS(j), &absinfo); } } else if(i == EV_REL) { components.relAxes.push_back(j); } else if(i == EV_KEY) { components.buttons.push_back(j); } } } } } return components; } //-----------------------------------------------------------------------------// bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js ) { if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" ); DeviceComponentInfo info = getComponentInfo( deviceID ); int buttons = 0; bool joyButtonFound = false; js.button_map.clear(); #ifdef OIS_LINUX_JOY_DEBUG cout << "\n\nDisplaying ButtonMapping Status:"; #endif for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i ) { //Check to ensure we find at least one joy only button if( (*i >= BTN_JOYSTICK && *i <= BTN_THUMBR) || (*i >= BTN_WHEEL && *i <= BTN_GEAR_UP ) ) joyButtonFound = true; js.button_map[*i] = buttons++; #ifdef OIS_LINUX_JOY_DEBUG cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1); #endif } //Joy Buttons found, so it must be a joystick or pad if( joyButtonFound ) { js.joyFileD = deviceID; js.vendor = getName(deviceID); js.buttons = buttons; js.axes = info.relAxes.size() + info.absAxes.size(); js.hats = info.hats.size(); //Map the Axes #ifdef OIS_LINUX_JOY_DEBUG cout << "\n\nDisplaying AxisMapping Status:"; #endif int axes = 0; for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i ) { js.axis_map[*i] = axes; input_absinfo absinfo; ioctl(deviceID, EVIOCGABS(*i), &absinfo); js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum); #ifdef OIS_LINUX_JOY_DEBUG cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes; #endif ++axes; } } return joyButtonFound; } //-----------------------------------------------------------------------------// std::string EventUtils::getName( int deviceID ) { char name[OIS_DEVICE_NAME]; ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name); return std::string(name); } //-----------------------------------------------------------------------------// void EventUtils::enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff ) { //Linux Event to OIS Event Mappings std::map<int, Effect::EType> typeMap; typeMap[FF_CONSTANT] = Effect::Constant; typeMap[FF_RAMP] = Effect::Ramp; typeMap[FF_SPRING] = Effect::Spring; typeMap[FF_FRICTION] = Effect::Friction; typeMap[FF_SQUARE] = Effect::Square; typeMap[FF_TRIANGLE] = Effect::Triangle; typeMap[FF_SINE] = Effect::Sine; typeMap[FF_SAW_UP] = Effect::SawToothUp; typeMap[FF_SAW_DOWN] = Effect::SawToothDown; typeMap[FF_DAMPER] = Effect::Damper; typeMap[FF_INERTIA] = Effect::Inertia; typeMap[FF_CUSTOM] = Effect::Custom; std::map<int, Effect::EForce> forceMap; forceMap[FF_CONSTANT] = Effect::ConstantForce; forceMap[FF_RAMP] = Effect::RampForce; forceMap[FF_PERIODIC] = Effect::PeriodicForce; forceMap[FF_CUSTOM] = Effect::CustomForce; //Remove any previously existing memory and create fresh removeForceFeedback( ff ); *ff = new LinuxForceFeedback(); unsigned long info[4] = {0,0,0,0}; unsigned long subinfo[4]= {0,0,0,0}; //Read overall force feedback components of the device ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(long)*4), info); //FF Axes //if( isBitSet(info, ABS_X) ) //X Axis //if( isBitSet(info, ABS_Y) ) //Y Axis //if( isBitSet(info, ABS_WHEEL) ) //Wheel //FF Effects for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ ) { if(isBitSet(info, effect)) { //std::cout << "\tEffect Type: " << effect << std::endl; memset(subinfo, 0, sizeof(subinfo)); //Read any info about this supported effect ioctl(deviceID, EVIOCGBIT(effect, sizeof(long)*4), subinfo); for( int force = 0; force < FF_MAX; force++ ) { if(isBitSet(subinfo, force)) (*ff)->_addEffectTypes( forceMap[force], typeMap[effect] ); } } } //Check to see if any effects were added, else destroy the pointer const ForceFeedback::SupportedEffectList &list = (*ff)->getSupportedEffects(); if( list.size() == 0 ) removeForceFeedback( ff ); } //-----------------------------------------------------------------------------// void EventUtils::removeForceFeedback( LinuxForceFeedback** ff ) { delete *ff; *ff = 0; } --- NEW FILE: LinuxJoyStick.h --- /* The zlib/libpng License Copyright (c) 2006 Phillip Castaneda (pjcast -- www.wreckedgames.com) This software is provided 'as-is', without any ... [truncated message content] |