diff options
author | Luo Jinghua <sunmoon1997@gmail.com> | 2010-10-21 14:45:58 +0800 |
---|---|---|
committer | Luo Jinghua <sunmoon1997@gmail.com> | 2010-10-22 08:55:20 +0800 |
commit | 6875e66e7a4b5fa74486d5318a387a3674073ac8 (patch) | |
tree | f4f99636e7b300ea304cd53712ce9d6dfd4bdfd3 /src | |
parent | 213444d3638b99164c3efcbe2ede8c92303503ea (diff) |
linux: support the event interface
Only mouse is supported.
Diffstat (limited to 'src')
-rwxr-xr-x | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/linux/EventHelpers.cpp | 59 | ||||
-rwxr-xr-x | src/linux/LinuxInputManager.cpp | 50 | ||||
-rwxr-xr-x | src/linux/LinuxKeyboard.cpp | 15 | ||||
-rwxr-xr-x | src/linux/LinuxMouse.cpp | 11 | ||||
-rw-r--r-- | src/linux/LinuxMouseEvents.cpp | 251 |
6 files changed, 381 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 83892d2..7d63ffa 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,7 @@ libOIS_la_SOURCES = OISInputManager.cpp \ ./linux/EventHelpers.cpp \ ./linux/LinuxInputManager.cpp \ ./linux/LinuxJoyStickEvents.cpp \ + ./linux/LinuxMouseEvents.cpp \ ./linux/LinuxForceFeedback.cpp \ ./linux/LinuxKeyboard.cpp \ ./linux/LinuxMouse.cpp @@ -20,6 +21,6 @@ libOIS_la_SOURCES = OISInputManager.cpp \ libOIS_la_LDFLAGS = -release @PACKAGE_VERSION@ #libOIS_la_LDFLAGS = -version-info $(shell echo "@PACKAGE_VERSION@" | tr '.' ':') -libOIS_la_LIBADD = $(STLPORT_LIBS) -L/usr/X11R6/lib -lX11 +libOIS_la_LIBADD = $(STLPORT_LIBS) $(X11_LIBS) #eof "$Id: Makefile.am,v 1.15.2.1 2008/02/14 03:33:36 pjcast Exp $" diff --git a/src/linux/EventHelpers.cpp b/src/linux/EventHelpers.cpp index 002ea41..772e2a5 100644 --- a/src/linux/EventHelpers.cpp +++ b/src/linux/EventHelpers.cpp @@ -164,6 +164,65 @@ bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js ) return joyButtonFound; } +bool EventUtils::isMouse( int deviceID, MouseInfo &mouse ) +{ + if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" ); + + DeviceComponentInfo info = getComponentInfo( deviceID ); + + int buttons = 0; + bool mouseButtonFound = false; + mouse.button_map.clear(); + + #ifdef OIS_LINUX_MOUSE_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 mouse only button + if( (*i >= BTN_MOUSE && *i <= BTN_JOYSTICK) ) + mouseButtonFound = true; + + mouse.button_map[*i] = buttons++; + + #ifdef OIS_LINUX_MOUSE_DEBUG + cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1); + #endif + } + + //Mouse Buttons found, so it must be a mousestick or pad + if( mouseButtonFound && info.relAxes.size() ) + { + mouse.joyFileD = deviceID; + mouse.vendor = getName(deviceID); + mouse.buttons = buttons; + mouse.axes = info.relAxes.size() + info.absAxes.size(); + mouse.hats = info.hats.size(); + + //Map the Axes + #ifdef OIS_LINUX_MOUSE_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 ) + { + mouse.axis_map[*i] = axes; + + input_absinfo absinfo; + ioctl(deviceID, EVIOCGABS(*i), &absinfo); + mouse.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum); + + #ifdef OIS_LINUX_MOUSE_DEBUG + cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes; + #endif + + ++axes; + } + } + + return mouseButtonFound; +} + //-----------------------------------------------------------------------------// std::string EventUtils::getName( int deviceID ) { diff --git a/src/linux/LinuxInputManager.cpp b/src/linux/LinuxInputManager.cpp index 01fc23a..f4faf4c 100755 --- a/src/linux/LinuxInputManager.cpp +++ b/src/linux/LinuxInputManager.cpp @@ -23,6 +23,7 @@ restrictions: #include "linux/LinuxInputManager.h" #include "linux/LinuxKeyboard.h" #include "linux/LinuxJoyStickEvents.h" +#include "linux/LinuxMouseEvents.h" #include "linux/LinuxMouse.h" #include "OISException.h" #include <cstdlib> @@ -49,6 +50,9 @@ LinuxInputManager::LinuxInputManager() : InputManager("X11InputManager") //--------------------------------------------------------------------------------// LinuxInputManager::~LinuxInputManager() { + //Close all mouses + LinuxMouseEvents::_clearMouses(unusedMouseList); + //Close all joysticks LinuxJoyStick::_clearJoys(unusedJoyStickList); } @@ -65,6 +69,7 @@ void LinuxInputManager::_initialize( ParamList ¶mList ) //--------------------------------------------------------------------------------// void LinuxInputManager::_parseConfigSettings( ParamList ¶mList ) { +#ifdef HAVE_X11 ParamList::iterator i = paramList.find("WINDOW"); if( i == paramList.end() ) OIS_EXCEPT( E_InvalidParam, "LinuxInputManager >> No WINDOW!" ); @@ -93,12 +98,17 @@ void LinuxInputManager::_parseConfigSettings( ParamList ¶mList ) if( i != paramList.end() ) if( i->second == "false" ) hideMouse = false; +#endif } //--------------------------------------------------------------------------------// void LinuxInputManager::_enumerateDevices() { - //Enumerate all attached devices + //Enumerate all attached mouse devices + unusedMouseList = LinuxMouseEvents::_scanMouses(); + mouses = unusedMouseList.size(); + + //Enumerate all attached joystick devices unusedJoyStickList = LinuxJoyStick::_scanJoys(); joySticks = unusedJoyStickList.size(); } @@ -117,6 +127,9 @@ DeviceList LinuxInputManager::freeDeviceList() for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i) ret.insert(std::make_pair(OISJoyStick, i->vendor)); + for(MouseInfoList::iterator i = unusedMouseList.begin(); i != unusedMouseList.end(); ++i) + ret.insert(std::make_pair(OISMouse, i->vendor)); + return ret; } @@ -126,7 +139,7 @@ int LinuxInputManager::totalDevices(Type iType) switch(iType) { case OISKeyboard: return 1; - case OISMouse: return 1; + case OISMouse: return 1 + mouses; case OISJoyStick: return joySticks; default: return 0; } @@ -138,7 +151,7 @@ int LinuxInputManager::freeDevices(Type iType) switch(iType) { case OISKeyboard: return keyboardUsed ? 0 : 1; - case OISMouse: return mouseUsed ? 0 : 1; + case OISMouse: return (mouseUsed ? 0 : 1) + (int)unusedMouseList.size(); case OISJoyStick: return (int)unusedJoyStickList.size(); default: return 0; } @@ -151,6 +164,12 @@ bool LinuxInputManager::vendorExist(Type iType, const std::string & vendor) { return true; } + else if( iType == OISMouse ) + { + for(MouseInfoList::iterator i = unusedMouseList.begin(); i != unusedMouseList.end(); ++i) + if(i->vendor == vendor) + return true; + } else if( iType == OISJoyStick ) { for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i) @@ -176,8 +195,27 @@ Object* LinuxInputManager::createObject(InputManager *creator, Type iType, bool } case OISMouse: { - if( mouseUsed == false ) + bool haveX11 = false; +#ifdef HAVE_X11 + haveX11 = true; +#endif + + if( (haveX11 || unusedMouseList.empty()) && mouseUsed == false ) + { obj = new LinuxMouse(this, bufferMode, grabMouse, hideMouse); + } + if (!obj) + { + for(MouseInfoList::iterator i = unusedMouseList.begin(); i != unusedMouseList.end(); ++i) + { + if(vendor == "" || i->vendor == vendor) + { + obj = new LinuxMouseEvents(this, bufferMode, *i); + unusedMouseList.erase(i); + break; + } + } + } break; } case OISJoyStick: @@ -212,6 +250,10 @@ void LinuxInputManager::destroyObject( Object* obj ) { unusedJoyStickList.push_back( ((LinuxJoyStick*)obj)->_getJoyInfo() ); } + if( obj->type() == OISMouse && obj->vendor() != mInputSystemName ) + { + unusedMouseList.push_back( ((LinuxMouseEvents*)obj)->_getMouseInfo() ); + } delete obj; } diff --git a/src/linux/LinuxKeyboard.cpp b/src/linux/LinuxKeyboard.cpp index 75d98ca..beafa3a 100755 --- a/src/linux/LinuxKeyboard.cpp +++ b/src/linux/LinuxKeyboard.cpp @@ -25,8 +25,11 @@ restrictions: #include "OISException.h" #include "OISEvents.h" +#ifdef HAVE_X11 #include <X11/keysym.h> #include <X11/Xutil.h> +#endif + #include <cstring> using namespace OIS; @@ -35,6 +38,7 @@ using namespace OIS; LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab, bool useXRepeat) : Keyboard(creator->inputSystemName(), buffered, 0, creator) { +#ifdef HAVE_X11 setlocale(LC_CTYPE, ""); //Set the locale to (hopefully) the users LANG UTF-8 Env var display = 0; @@ -185,7 +189,7 @@ LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab, bo 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)); - +#endif static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true); } @@ -196,6 +200,7 @@ void LinuxKeyboard::_initialize() memset( &KeyBuffer, 0, 256 ); mModifiers = 0; +#ifdef HAVE_X11 if( display ) XCloseDisplay(display); display = 0; window = static_cast<LinuxInputManager*>(mCreator)->_getWindow(); @@ -226,11 +231,13 @@ void LinuxKeyboard::_initialize() XAutoRepeatOff( display ); } +#endif } //-------------------------------------------------------------------// LinuxKeyboard::~LinuxKeyboard() { +#ifdef HAVE_X11 if( display ) { if( oldXAutoRepeat ) @@ -241,7 +248,7 @@ LinuxKeyboard::~LinuxKeyboard() XCloseDisplay(display); } - +#endif static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true); } @@ -297,6 +304,7 @@ bool LinuxKeyboard::isKeyDown( KeyCode key ) //-------------------------------------------------------------------// void LinuxKeyboard::capture() { +#ifdef HAVE_X11 KeySym key; XEvent event; LinuxInputManager* linMan = static_cast<LinuxInputManager*>(mCreator); @@ -371,6 +379,7 @@ void LinuxKeyboard::capture() } } } +#endif } //-------------------------------------------------------------------// @@ -425,6 +434,7 @@ const std::string& LinuxKeyboard::getAsString( KeyCode kc ) mGetString = "Unknown"; char *temp = 0; +#ifdef HAVE_X11 XtoOIS_KeyMap::iterator i = keyConversion.begin(), e = keyConversion.end(); @@ -438,6 +448,7 @@ const std::string& LinuxKeyboard::getAsString( KeyCode kc ) break; } } +#endif return mGetString; } diff --git a/src/linux/LinuxMouse.cpp b/src/linux/LinuxMouse.cpp index a12e030..c987447 100755 --- a/src/linux/LinuxMouse.cpp +++ b/src/linux/LinuxMouse.cpp @@ -53,6 +53,7 @@ void LinuxMouse::_initialize() oldXMouseX = oldXMouseY = 6; oldXMouseZ = 0; +#ifdef HAVE_X11 if( display ) XCloseDisplay(display); display = 0; window = static_cast<LinuxInputManager*>(mCreator)->_getWindow(); @@ -78,6 +79,7 @@ void LinuxMouse::_initialize() 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 ); +#endif grab( grabMouse ); hide( hideMouse ); @@ -88,6 +90,7 @@ void LinuxMouse::_initialize() //-------------------------------------------------------------------// LinuxMouse::~LinuxMouse() { +#ifdef HAVE_X11 if( display ) { grab(false); @@ -95,7 +98,7 @@ LinuxMouse::~LinuxMouse() XFreeCursor(display, cursor); XCloseDisplay(display); } - +#endif static_cast<LinuxInputManager*>(mCreator)->_setMouseUsed(false); } @@ -152,6 +155,7 @@ void LinuxMouse::capture() //-------------------------------------------------------------------// void LinuxMouse::_processXEvents() { +#ifdef HAVE_X11 //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; @@ -249,22 +253,27 @@ void LinuxMouse::_processXEvents() } } } +#endif } //-------------------------------------------------------------------// void LinuxMouse::grab(bool grab) { +#ifdef HAVE_X11 if( grab ) XGrabPointer(display, window, True, 0, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); else XUngrabPointer(display, CurrentTime); +#endif } //-------------------------------------------------------------------// void LinuxMouse::hide(bool hide) { +#ifdef HAVE_X11 if( hide ) XDefineCursor(display, window, cursor); else XUndefineCursor(display, window); +#endif } diff --git a/src/linux/LinuxMouseEvents.cpp b/src/linux/LinuxMouseEvents.cpp new file mode 100644 index 0000000..bfe9ac6 --- /dev/null +++ b/src/linux/LinuxMouseEvents.cpp @@ -0,0 +1,251 @@ +/* +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 "OISConfig.h" + +#include "linux/LinuxMouseEvents.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_MOUSE_DEBUG + +#ifdef OIS_LINUX_MOUSE_DEBUG +# include <iostream> + using namespace std; +#endif + +//-------------------------------------------------------------------// +LinuxMouseEvents::LinuxMouseEvents(InputManager* creator, bool buffered, const MouseInfo& mouse) + : Mouse(mouse.vendor, buffered, mouse.devId, creator) +{ + mMouse = mouse.joyFileD; + + mButtonMap = mouse.button_map; + mAxisMap = mouse.axis_map; + mRanges = mouse.axis_range; +} + +//-------------------------------------------------------------------// +LinuxMouseEvents::~LinuxMouseEvents() +{ +} + +//-------------------------------------------------------------------// +void LinuxMouseEvents::_initialize() +{ + mState.clear(); + + if( mMouse == -1 ) + OIS_EXCEPT(E_InputDeviceNonExistant, + "LinuxMouse::_initialize() >> Mouse Not Found!"); +} + +//-------------------------------------------------------------------// +void LinuxMouseEvents::capture() +{ + mState.X.rel = mState.Y.rel = mState.Z.rel = 0; + + //Used to determine if an axis has been changed and needs an event + bool axisMoved = false; + +#define MOUSE_BUFFERSIZE 64 + //We are in non blocking mode - we just read once, and try to fill up buffer + input_event mouse[MOUSE_BUFFERSIZE]; + int ret = read(mMouse, &mouse, sizeof(struct input_event) * MOUSE_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(mouse[i].type) + { + case EV_KEY: //Button + { + MouseButtonID button = (MouseButtonID)mButtonMap[mouse[i].code]; + + #ifdef OIS_LINUX_MOUSE_DEBUG + std::cout << "\nButton Code: " << mouse[i].code << ", OIS Value: " << button << std::endl; + #endif + + //Check to see whether push or released event... + if(mouse[i].value) + { + if( mBuffered && mListener ) + if(!mListener->mousePressed(MouseEvent(this,mState), button)) return; + } + else + { + if( mBuffered && mListener ) + if(!mListener->mouseReleased(MouseEvent(this,mState), button)) return; + } + break; + } + //Relative Axes (Do any mouses actually have a relative axis?) + case EV_REL: + switch (mouse[i].code) + { + case REL_X: + mState.X.rel = mouse[i].value; + axisMoved = true; + break; + case REL_Y: + mState.Y.rel = mouse[i].value; + axisMoved = true; + break; + case REL_Z: + mState.Z.rel = mouse[i].value; + axisMoved = true; + break; + default: + break; + } + + default: + break; + } + } + + if (axisMoved) + { + mState.X.abs += mState.X.rel; + mState.Y.abs += mState.Y.rel; + mState.Z.abs += mState.Z.rel; + + //Clip values to window + 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; + } + + //All axes and POVs are combined into one movement per pair per captured frame + if( mBuffered && mListener ) + { + if( axisMoved && mListener->mouseMoved( MouseEvent(this,mState)) == false ) + return; + } +} + +//-------------------------------------------------------------------// +void LinuxMouseEvents::setBuffered(bool buffered) +{ + if( buffered != mBuffered ) + { + mBuffered = buffered; + _initialize(); + } +} + +//-------------------------------------------------------------------// +MouseInfo LinuxMouseEvents::_getMouseInfo() +{ + MouseInfo mouse; + + mouse.devId = mDevID; + mouse.joyFileD = mMouse; + mouse.vendor = mVendor; + mouse.button_map = mButtonMap; + mouse.axis_map = mAxisMap; + mouse.axis_range = mRanges; + + return mouse; +} + +//-------------------------------------------------------------------// +MouseInfoList LinuxMouseEvents::_scanMouses() +{ + MouseInfoList mouses; + + //Search through all of the event devices.. and identify which ones are mouses + //xxx move this to InputManager, as it can also scan all other events + for(int i = 0; i < 255; ++i ) + { + std::stringstream s; + s << "/dev/input/event" << i; + int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK ); + if (fd == -1) + continue; + + #ifdef OIS_LINUX_MOUSE_DEBUG + std::cout << "\nOpening " << s.str() << "..."; + #endif + try + { + MouseInfo mouse; + if( EventUtils::isMouse(fd, mouse) ) + { + mouses.push_back(mouse); + #ifdef OIS_LINUX_MOUSE_DEBUG + std::cout << "\n__Mouse added to list"; + #endif + } + else + { + #ifdef OIS_LINUX_MOUSE_DEBUG + std::cout << "\n__Not a mouse!!"; + #endif + close(fd); + } + } + catch(...) + { + #ifdef OIS_LINUX_MOUSE_DEBUG + std::cout << "\nException caught!!"; + #endif + close(fd); + } + } + + return mouses; +} + +//-------------------------------------------------------------------// +void LinuxMouseEvents::_clearMouses(MouseInfoList &mouses) +{ + for(MouseInfoList::iterator i = mouses.begin(); i != mouses.end(); ++i) + close(i->joyFileD); + mouses.clear(); +} + +//-------------------------------------------------------------------// +Interface* LinuxMouseEvents::queryInterface(Interface::IType type) +{ + return 0; +} |