00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <eq/base/base.h>
00019 #include <pthread.h>
00020 #include <eq/base/perThread.h>
00021
00022 #include "wglEventHandler.h"
00023
00024 #include "log.h"
00025 #include "event.h"
00026 #include "window.h"
00027 #include "wglWindow.h"
00028
00029 #include <eq/base/debug.h>
00030 #include <eq/base/executionListener.h>
00031
00032 #include <algorithm>
00033 #include <windowsx.h>
00034
00035 using namespace eq::base;
00036 using namespace std;
00037 using namespace stde;
00038
00039 namespace eq
00040 {
00041
00042
00043 #define SCANCODE_MASK 0xff0000
00044 #define SCANCODE_SHIFT_L 0x2a0000
00045 #define SCANCODE_SHIFT_R 0x360000
00046 #define RIGHT_ALT_OR_CTRL 0x1000000
00047
00048 #ifndef MK_XBUTTON1
00049 # define MK_XBUTTON1 0x20
00050 #endif
00051 #ifndef MK_XBUTTON2
00052 # define MK_XBUTTON2 0x40
00053 #endif
00054 #ifndef GET_XBUTTON_WPARAM
00055 # define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
00056 #endif
00057 #ifndef GET_KEYSTATE_WPARAM
00058 # define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
00059 #endif
00060
00061
00062 namespace
00063 {
00064 class HandlerMap
00065 #ifdef WIN32_VC
00066 : public hash_map< HWND, WGLEventHandler* >
00067 #else
00068 : public hash_map< void*, WGLEventHandler* >
00069 #endif
00070 {
00071 public:
00072 virtual ~HandlerMap() {}
00073
00074 void notifyPerThreadDelete()
00075 {
00076 if( !empty( ))
00077 EQWARN << size()
00078 << " WGL event handlers registered during thread exit"
00079 << endl;
00080 delete this;
00081 }
00082 };
00083
00084 static PerThread< HandlerMap > _handlers;
00085
00086
00087
00088 static void registerHandler( HWND hWnd, WGLEventHandler* handler )
00089 {
00090 if( _handlers == 0 )
00091 _handlers = new HandlerMap;
00092
00093 HandlerMap* map = _handlers.get();
00094 EQASSERT( map->find( hWnd ) == map->end( ));
00095
00096 (*map)[hWnd] = handler;
00097 }
00098
00099 static void deregisterHandler( HWND hWnd )
00100 {
00101 HandlerMap* map = _handlers.get();
00102 EQASSERT( map )
00103 EQASSERT( map->find( hWnd ) != map->end( ));
00104
00105 map->erase( hWnd );
00106 }
00107
00108 static WGLEventHandler* getEventHandler( HWND hWnd )
00109 {
00110 HandlerMap* map = _handlers.get();
00111 if( !map || map->find( hWnd ) == map->end( ))
00112 return 0;
00113
00114 return (*map)[hWnd];
00115 }
00116 }
00117
00118 WGLEventHandler::WGLEventHandler( WGLWindowIF* window )
00119 : _window( window ),
00120 _buttonState( PTR_BUTTON_NONE )
00121 {
00122 _hWnd = window->getWGLWindowHandle();
00123
00124 if( !_hWnd )
00125 {
00126 EQWARN << "Window has no window handle" << endl;
00127 return;
00128 }
00129
00130 registerHandler( _hWnd, this );
00131 _prevWndProc = (WNDPROC)SetWindowLongPtr( _hWnd, GWLP_WNDPROC,
00132 (LONG_PTR)wndProc );
00133 if( _prevWndProc == wndProc )
00134 _prevWndProc = DefWindowProc;
00135 }
00136
00137 WGLEventHandler::~WGLEventHandler()
00138 {
00139 SetWindowLongPtr( _hWnd, GWLP_WNDPROC, (LONG_PTR)_prevWndProc );
00140 deregisterHandler( _hWnd );
00141 }
00142
00143 LRESULT CALLBACK WGLEventHandler::wndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
00144 LPARAM lParam )
00145 {
00146 WGLEventHandler* handler = getEventHandler( hWnd );
00147 if( !handler )
00148 {
00149 EQERROR << "Message arrived for unregistered window" << endl;
00150 return DefWindowProc( hWnd, uMsg, wParam, lParam );
00151 }
00152
00153 return handler->_wndProc( hWnd, uMsg, wParam, lParam );
00154 }
00155
00156 void WGLEventHandler::_syncButtonState( WPARAM wParam )
00157 {
00158 uint32_t buttons = PTR_BUTTON_NONE;
00159 if( wParam & MK_LBUTTON ) buttons |= PTR_BUTTON1;
00160 if( wParam & MK_MBUTTON ) buttons |= PTR_BUTTON2;
00161 if( wParam & MK_RBUTTON ) buttons |= PTR_BUTTON3;
00162 if( wParam & MK_XBUTTON1 ) buttons |= PTR_BUTTON4;
00163 if( wParam & MK_XBUTTON2 ) buttons |= PTR_BUTTON5;
00164
00165 #ifndef NDEBUG
00166 if( _buttonState != buttons )
00167
00168 EQWARN << "WM_MOUSEMOVE reports button state " << buttons
00169 << ", but internal state is " << _buttonState << endl;
00170 #endif
00171
00172 _buttonState = buttons;
00173 }
00174
00175 namespace
00176 {
00177 void _getWindowSize( HWND hWnd, ResizeEvent& event )
00178 {
00179 RECT rect;
00180 GetClientRect( hWnd, &rect );
00181 event.w = rect.right - rect.left;
00182 event.h = rect.bottom - rect.top;
00183
00184
00185
00186 POINT point;
00187 point.x = rect.left;
00188 point.y = rect.top;
00189 ClientToScreen( hWnd, &point );
00190 event.x = point.x;
00191 event.y = point.y;
00192 }
00193 }
00194 LRESULT CALLBACK WGLEventHandler::_wndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
00195 LPARAM lParam )
00196 {
00197 WGLWindowEvent event;
00198 event.uMsg = uMsg;
00199 event.wParam = wParam;
00200 event.lParam = lParam;
00201
00202 Window* const window = _window->getWindow();
00203
00204 LONG result = 0;
00205 switch( uMsg )
00206 {
00207 case WM_SHOWWINDOW:
00208 if( wParam == TRUE )
00209 event.type = Event::WINDOW_SHOW;
00210 else
00211 event.type = Event::WINDOW_HIDE;
00212
00213 _getWindowSize( hWnd, event.resize );
00214 break;
00215
00216 case WM_CREATE:
00217 case WM_SIZE:
00218 case WM_MOVE:
00219 case WM_WINDOWPOSCHANGED:
00220 {
00221 _getWindowSize( hWnd, event.resize );
00222 const bool hasArea = (event.resize.w >0 && event.resize.h > 0);
00223 const PixelViewport& pvp = window->getPixelViewport();
00224
00225
00226 if( !hasArea && pvp.hasArea( ))
00227 event.type = Event::WINDOW_HIDE;
00228 else if( hasArea && !pvp.hasArea( ))
00229 event.type = Event::WINDOW_SHOW;
00230 else
00231 event.type = Event::WINDOW_RESIZE;
00232 break;
00233 }
00234
00235 case WM_CLOSE:
00236 case WM_DESTROY:
00237 event.type = Event::WINDOW_CLOSE;
00238 break;
00239
00240 case WM_PAINT:
00241 {
00242 if( GetUpdateRect( hWnd, 0, false ) == 0 )
00243 return DefWindowProc( hWnd, uMsg, wParam, lParam );
00244
00245 event.type = Event::WINDOW_EXPOSE;
00246 break;
00247 }
00248
00249 case WM_MOUSEMOVE:
00250 {
00251 _syncButtonState( wParam );
00252
00253 event.type = Event::POINTER_MOTION;
00254 event.pointerMotion.x = GET_X_LPARAM( lParam );
00255 event.pointerMotion.y = GET_Y_LPARAM( lParam );
00256 event.pointerMotion.buttons = _buttonState;
00257
00258 _computePointerDelta( window, event );
00259 _getRenderContext( window, event );
00260 break;
00261 }
00262
00263 case WM_LBUTTONDOWN:
00264 _buttonState |= PTR_BUTTON1;
00265 event.type = Event::POINTER_BUTTON_PRESS;
00266 event.pointerButtonPress.x = GET_X_LPARAM( lParam );
00267 event.pointerButtonPress.y = GET_Y_LPARAM( lParam );
00268 event.pointerButtonPress.buttons = _buttonState;
00269 event.pointerButtonPress.button = PTR_BUTTON1;
00270
00271 _computePointerDelta( window, event );
00272 _getRenderContext( window, event );
00273 break;
00274
00275 case WM_MBUTTONDOWN:
00276 _buttonState |= PTR_BUTTON2;
00277 event.type = Event::POINTER_BUTTON_PRESS;
00278 event.pointerButtonPress.x = GET_X_LPARAM( lParam );
00279 event.pointerButtonPress.y = GET_Y_LPARAM( lParam );
00280 event.pointerButtonPress.buttons = _buttonState;
00281 event.pointerButtonPress.button = PTR_BUTTON2;
00282
00283 _computePointerDelta( window, event );
00284 _getRenderContext( window, event );
00285 break;
00286
00287 case WM_RBUTTONDOWN:
00288 _buttonState |= PTR_BUTTON3;
00289 event.type = Event::POINTER_BUTTON_PRESS;
00290 event.pointerButtonPress.x = GET_X_LPARAM( lParam );
00291 event.pointerButtonPress.y = GET_Y_LPARAM( lParam );
00292 event.pointerButtonPress.buttons = _buttonState;
00293 event.pointerButtonPress.button = PTR_BUTTON3;
00294
00295 _computePointerDelta( window, event );
00296 _getRenderContext( window, event );
00297 break;
00298
00299 case WM_XBUTTONDOWN:
00300 event.type = Event::POINTER_BUTTON_PRESS;
00301 event.pointerButtonPress.x = GET_X_LPARAM( lParam );
00302 event.pointerButtonPress.y = GET_Y_LPARAM( lParam );
00303
00304 if( GET_XBUTTON_WPARAM( wParam ) & XBUTTON1 )
00305 event.pointerButtonRelease.button = PTR_BUTTON4;
00306 else
00307 event.pointerButtonRelease.button = PTR_BUTTON5;
00308
00309 _buttonState |= event.pointerButtonPress.button;
00310 _syncButtonState( GET_KEYSTATE_WPARAM( wParam ));
00311 event.pointerButtonPress.buttons = _buttonState;
00312
00313 _computePointerDelta( window, event );
00314 _getRenderContext( window, event );
00315 result = TRUE;
00316 break;
00317
00318 case WM_LBUTTONUP:
00319 _buttonState &= ~PTR_BUTTON1;
00320 event.type = Event::POINTER_BUTTON_RELEASE;
00321 event.pointerButtonRelease.x = GET_X_LPARAM( lParam );
00322 event.pointerButtonRelease.y = GET_Y_LPARAM( lParam );
00323 event.pointerButtonRelease.buttons = _buttonState;
00324 event.pointerButtonRelease.button = PTR_BUTTON1;
00325
00326 _computePointerDelta( window, event );
00327 _getRenderContext( window, event );
00328 break;
00329
00330 case WM_MBUTTONUP:
00331 _buttonState &= ~PTR_BUTTON2;
00332 event.type = Event::POINTER_BUTTON_RELEASE;
00333 event.pointerButtonRelease.x = GET_X_LPARAM( lParam );
00334 event.pointerButtonRelease.y = GET_Y_LPARAM( lParam );
00335 event.pointerButtonRelease.buttons = _buttonState;
00336 event.pointerButtonRelease.button = PTR_BUTTON2;
00337
00338 _computePointerDelta( window, event );
00339 _getRenderContext( window, event );
00340 break;
00341
00342 case WM_RBUTTONUP:
00343 _buttonState &= ~PTR_BUTTON3;
00344 event.type = Event::POINTER_BUTTON_RELEASE;
00345 event.pointerButtonRelease.x = GET_X_LPARAM( lParam );
00346 event.pointerButtonRelease.y = GET_Y_LPARAM( lParam );
00347 event.pointerButtonRelease.buttons = _buttonState;
00348 event.pointerButtonRelease.button = PTR_BUTTON3;
00349
00350 _computePointerDelta( window, event );
00351 _getRenderContext( window, event );
00352 break;
00353
00354 case WM_XBUTTONUP:
00355 event.type = Event::POINTER_BUTTON_RELEASE;
00356 event.pointerButtonRelease.x = GET_X_LPARAM( lParam );
00357 event.pointerButtonRelease.y = GET_Y_LPARAM( lParam );
00358
00359 if( GET_XBUTTON_WPARAM( wParam ) & XBUTTON1 )
00360 event.pointerButtonRelease.button = PTR_BUTTON4;
00361 else
00362 event.pointerButtonRelease.button = PTR_BUTTON5;
00363
00364 _buttonState &= ~event.pointerButtonRelease.button;
00365 _syncButtonState( GET_KEYSTATE_WPARAM( wParam ));
00366 event.pointerButtonRelease.buttons =_buttonState;
00367
00368 _computePointerDelta( window, event );
00369 _getRenderContext( window, event );
00370 result = TRUE;
00371 break;
00372
00373 case WM_SYSKEYDOWN:
00374 case WM_KEYDOWN:
00375 event.type = Event::KEY_PRESS;
00376 event.keyPress.key = _getKey( lParam, wParam );
00377 break;
00378
00379 case WM_SYSKEYUP:
00380 case WM_KEYUP:
00381 event.type = Event::KEY_RELEASE;
00382 event.keyRelease.key = _getKey( lParam, wParam );
00383 break;
00384
00385 case WM_SYSCOMMAND:
00386 switch( wParam )
00387 {
00388 case SC_MONITORPOWER:
00389 case SC_SCREENSAVE:
00390 if( lParam >= 0 )
00391 {
00392 event.type = Event::WINDOW_SCREENSAVER;
00393 break;
00394 }
00395
00396 default:
00397 event.type = Event::UNKNOWN;
00398 EQVERB << "Unhandled system command 0x" << hex << wParam
00399 << dec << endl;
00400 break;
00401 }
00402 break;
00403
00404 default:
00405 event.type = Event::UNKNOWN;
00406 EQVERB << "Unhandled message 0x" << hex << uMsg << dec << endl;
00407 break;
00408 }
00409
00410 event.originator = window->getID();
00411
00412 EQLOG( LOG_EVENTS ) << "received event: " << event << endl;
00413
00414 if( _window->processEvent( event ))
00415 return result;
00416
00417 return CallWindowProc( _prevWndProc, hWnd, uMsg, wParam, lParam );
00418 }
00419
00420 uint32_t WGLEventHandler::_getKey( LPARAM lParam, WPARAM wParam )
00421 {
00422 switch( wParam )
00423 {
00424 case VK_ESCAPE: return KC_ESCAPE;
00425 case VK_BACK: return KC_BACKSPACE;
00426 case VK_RETURN: return KC_RETURN;
00427 case VK_TAB: return KC_TAB;
00428 case VK_HOME: return KC_HOME;
00429 case VK_LEFT: return KC_LEFT;
00430 case VK_UP: return KC_UP;
00431 case VK_RIGHT: return KC_RIGHT;
00432 case VK_DOWN: return KC_DOWN;
00433 case VK_PRIOR: return KC_PAGE_UP;
00434 case VK_NEXT: return KC_PAGE_DOWN;
00435 case VK_END: return KC_END;
00436 case VK_F1: return KC_F1;
00437 case VK_F2: return KC_F2;
00438 case VK_F3: return KC_F3;
00439 case VK_F4: return KC_F4;
00440 case VK_F5: return KC_F5;
00441 case VK_F6: return KC_F6;
00442 case VK_F7: return KC_F7;
00443 case VK_F8: return KC_F8;
00444 case VK_F9: return KC_F9;
00445 case VK_F10: return KC_F10;
00446 case VK_F11: return KC_F11;
00447 case VK_F12: return KC_F12;
00448 case VK_F13: return KC_F13;
00449 case VK_F14: return KC_F14;
00450 case VK_F15: return KC_F15;
00451 case VK_F16: return KC_F16;
00452 case VK_F17: return KC_F17;
00453 case VK_F18: return KC_F18;
00454 case VK_F19: return KC_F19;
00455 case VK_F20: return KC_F20;
00456 case VK_F21: return KC_F21;
00457 case VK_F22: return KC_F22;
00458 case VK_F23: return KC_F23;
00459 case VK_F24: return KC_F24;
00460 case VK_SHIFT:
00461 switch( lParam & SCANCODE_MASK )
00462 {
00463 case SCANCODE_SHIFT_L: return KC_SHIFT_L;
00464 case SCANCODE_SHIFT_R: return KC_SHIFT_R;
00465 }
00466 break;
00467
00468 case VK_CONTROL:
00469 if( lParam & RIGHT_ALT_OR_CTRL )
00470 return KC_CONTROL_R;
00471 return KC_CONTROL_L;
00472
00473 case VK_MENU:
00474 if( lParam & RIGHT_ALT_OR_CTRL )
00475 return KC_ALT_R;
00476 return KC_ALT_L;
00477
00478 default:
00479
00480 if( wParam >= ' ' && wParam <= '~' )
00481 return wParam;
00482 break;
00483 }
00484 EQWARN << "Unrecognized virtual key code " << wParam << endl;
00485 return KC_VOID;
00486 }
00487 }