• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 The zlib/libpng License
3 
4 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5 
6 This software is provided 'as-is', without any express or implied warranty. In no event will
7 the authors be held liable for any damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial
10 applications, and to alter it and redistribute it freely, subject to the following
11 restrictions:
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 friosom any source distribution.
22 */
23 #include "linux/LinuxMouse.h"
24 #include "linux/LinuxInputManager.h"
25 #include "OISException.h"
26 #include "OISEvents.h"
27 
28 using namespace OIS;
29 
30 //-------------------------------------------------------------------//
LinuxMouse(InputManager * creator,bool buffered,bool grab,bool hide)31 LinuxMouse::LinuxMouse(InputManager* creator, bool buffered, bool grab, bool hide)
32 	: Mouse(creator->inputSystemName(), buffered, 0, creator)
33 {
34 	display = 0;
35 	window = 0;
36 	cursor = 0;
37 
38 	grabMouse = grab;
39 	hideMouse = hide;
40 
41 	static_cast<LinuxInputManager*>(mCreator)->_setMouseUsed(true);
42 }
43 
44 //-------------------------------------------------------------------//
_initialize()45 void LinuxMouse::_initialize()
46 {
47 	//Clear old state
48 	mState.clear();
49 	mMoved  = false;
50 	mWarped = false;
51 
52 	//6 is just some random value... hardly ever would anyone have a window smaller than 6
53 	oldXMouseX = oldXMouseY = 6;
54 	oldXMouseZ = 0;
55 
56 	if( display ) XCloseDisplay(display);
57 	display = 0;
58 	window = static_cast<LinuxInputManager*>(mCreator)->_getWindow();
59 
60 	//Create our local X mListener connection
61 	if( !(display = XOpenDisplay(0)) )
62 		OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> Error opening X!");
63 
64 	//Set it to recieve Mouse Input events
65 	if( XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | PointerMotionMask) == BadWindow )
66 		OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> X error!");
67 
68 	//Warp mouse inside window
69 	XWarpPointer(display,None,window,0,0,0,0, 6,6);
70 
71 	//Create a blank cursor:
72 	Pixmap bm_no;
73 	XColor black, dummy;
74 	Colormap colormap;
75 	static char no_data[] = { 0,0,0,0,0,0,0,0 };
76 
77 	colormap = DefaultColormap( display, DefaultScreen(display) );
78 	XAllocNamedColor( display, colormap, "black", &black, &dummy );
79 	bm_no = XCreateBitmapFromData( display, window, no_data, 8, 8 );
80 	cursor = XCreatePixmapCursor( display, bm_no, bm_no, &black, &black, 0, 0 );
81 
82 	grab( grabMouse );
83 	hide( hideMouse );
84 
85 	mouseFocusLost = false;
86 }
87 
88 //-------------------------------------------------------------------//
~LinuxMouse()89 LinuxMouse::~LinuxMouse()
90 {
91 	if( display )
92 	{
93 		grab(false);
94 		hide(false);
95 		XFreeCursor(display, cursor);
96 		XCloseDisplay(display);
97 	}
98 
99 	static_cast<LinuxInputManager*>(mCreator)->_setMouseUsed(false);
100 }
101 
102 //-------------------------------------------------------------------//
setBuffered(bool buffered)103 void LinuxMouse::setBuffered(bool buffered)
104 {
105 	mBuffered = buffered;
106 }
107 
108 //-------------------------------------------------------------------//
capture()109 void LinuxMouse::capture()
110 {
111 	//Clear out last frames values
112 	mState.X.rel = 0;
113 	mState.Y.rel = 0;
114 	mState.Z.rel = 0;
115 
116 	_processXEvents();
117 
118 	mWarped = false;
119 
120 	if( mMoved == true )
121 	{
122 		if( mBuffered && mListener )
123 			mListener->mouseMoved( MouseEvent( this, mState ) );
124 
125 		mMoved = false;
126 	}
127 
128 	//Check for losing/gaining mouse grab focus (alt-tab, etc)
129 	if( grabMouse )
130 	{
131 		if( static_cast<LinuxInputManager*>(mCreator)->_getGrabState() )
132 		{
133 			if( mouseFocusLost )	//We just regained mouse grab focus
134 			{
135 				grab( true );
136 				hide( hideMouse );
137 				mouseFocusLost = false;
138 			}
139 		}
140 		else
141 		{
142 			if( mouseFocusLost == false )	//We just lost mouse grab focus
143 			{
144 				grab( false );
145 				hide( false );
146 				mouseFocusLost = true;
147 			}
148 		}
149 	}
150 }
151 
152 //-------------------------------------------------------------------//
_processXEvents()153 void LinuxMouse::_processXEvents()
154 {
155 	//X11 Button Events: 1=left 2=middle 3=right; Our Bit Postion: 1=Left 2=Right 3=Middle
156 	char mask[4] = {0,1,4,2};
157 	XEvent event;
158 
159 	//Poll x11 for events mouse events
160 	while( XPending(display) > 0 )
161 	{
162 		XNextEvent(display, &event);
163 
164 		if( event.type == MotionNotify )
165 		{	//Mouse moved
166 			//Ignore out of bounds mouse if we just warped
167 			if( mWarped )
168 			{
169 				if(event.xmotion.x < 5 || event.xmotion.x > mState.width - 5 ||
170 				   event.xmotion.y < 5 || event.xmotion.y > mState.height - 5)
171 					continue;
172 			}
173 
174 			//Compute this frames Relative X & Y motion
175 			int dx = event.xmotion.x - oldXMouseX;
176 			int dy = event.xmotion.y - oldXMouseY;
177 
178 			//Store old values for next time to compute relative motion
179 			oldXMouseX = event.xmotion.x;
180 			oldXMouseY = event.xmotion.y;
181 
182 			mState.X.abs += dx;
183 			mState.Y.abs += dy;
184 			mState.X.rel += dx;
185 			mState.Y.rel += dy;
186 
187 			//Check to see if we are grabbing the mouse to the window (requires clipping and warping)
188 			if( grabMouse )
189 			{
190 				if( mState.X.abs < 0 )
191 					mState.X.abs = 0;
192 				else if( mState.X.abs > mState.width )
193 					mState.X.abs = mState.width;
194 
195 				if( mState.Y.abs < 0 )
196 					mState.Y.abs = 0;
197 				else if( mState.Y.abs > mState.height )
198 					mState.Y.abs = mState.height;
199 
200 				if( mouseFocusLost == false )
201 				{
202 					//Keep mouse in window (fudge factor)
203 					if(event.xmotion.x < 5 || event.xmotion.x > mState.width - 5 ||
204 					   event.xmotion.y < 5 || event.xmotion.y > mState.height - 5 )
205 					{
206 						oldXMouseX = mState.width >> 1;  //center x
207 						oldXMouseY = mState.height >> 1; //center y
208 						XWarpPointer(display, None, window, 0, 0, 0, 0, oldXMouseX, oldXMouseY);
209 						mWarped = true;
210 					}
211 				}
212 			}
213 			mMoved = true;
214 		}
215 		else if( event.type == ButtonPress )
216 		{	//Button down
217 			static_cast<LinuxInputManager*>(mCreator)->_setGrabState(true);
218 
219 			if( event.xbutton.button < 4 )
220 			{
221 				mState.buttons |= mask[event.xbutton.button];
222 				if( mBuffered && mListener )
223 					if( mListener->mousePressed( MouseEvent( this, mState ),
224 						(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
225 						return;
226 			}
227 		}
228 		else if( event.type == ButtonRelease )
229 		{	//Button up
230 			if( event.xbutton.button < 4 )
231 			{
232 				mState.buttons &= ~mask[event.xbutton.button];
233 				if( mBuffered && mListener )
234 					if( mListener->mouseReleased( MouseEvent( this, mState ),
235 						(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
236 						return;
237 			}
238 			//The Z axis gets pushed/released pair message (this is up)
239 			else if( event.xbutton.button == 4 )
240 			{
241 				mState.Z.rel += 120;
242 				mState.Z.abs += 120;
243 				mMoved = true;
244 			}
245 			//The Z axis gets pushed/released pair message (this is down)
246 			else if( event.xbutton.button == 5 )
247 			{
248 				mState.Z.rel -= 120;
249 				mState.Z.abs -= 120;
250 				mMoved = true;
251 			}
252 		}
253 	}
254 }
255 
256 //-------------------------------------------------------------------//
grab(bool grab)257 void LinuxMouse::grab(bool grab)
258 {
259 	if( grab )
260 		XGrabPointer(display, window, True, 0, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
261 	else
262 		XUngrabPointer(display, CurrentTime);
263 }
264 
265 //-------------------------------------------------------------------//
hide(bool hide)266 void LinuxMouse::hide(bool hide)
267 {
268 	if( hide )
269 		XDefineCursor(display, window, cursor);
270 	else
271 		XUndefineCursor(display, window);
272 }
273