00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "vlSDL/SDLWindow.hpp"
00033 #include "vlGraphics/OpenGL.hpp"
00034 #include "vlGraphics/Applet.hpp"
00035 #include "vlCore/VisualizationLibrary.hpp"
00036 #include "vlCore/Log.hpp"
00037 #include "vlCore/Say.hpp"
00038 #include <algorithm>
00039 #include <SDL.h>
00040 #include <map>
00041
00042 #ifdef WIN32
00043 #include <SDL_syswm.h>
00044 #include <shellapi.h>
00045 #endif
00046
00047 using namespace vlSDL;
00048 using namespace vl;
00049
00050 namespace
00051 {
00052 SDLWindow* mSDLWindow = NULL;
00053 bool mUpdateFlag = true;
00054
00055 std::map<int, vl::EKey> key_translation_map;
00056
00057 int key_translation_vec[] =
00058 {
00059 SDLK_0, vl::Key_0,
00060 SDLK_1, vl::Key_1,
00061 SDLK_2, vl::Key_2,
00062 SDLK_3, vl::Key_3,
00063 SDLK_4, vl::Key_4,
00064 SDLK_5, vl::Key_5,
00065 SDLK_6, vl::Key_6,
00066 SDLK_7, vl::Key_7,
00067 SDLK_8, vl::Key_8,
00068 SDLK_9, vl::Key_9,
00069
00070 SDLK_a, vl::Key_A,
00071 SDLK_b, vl::Key_B,
00072 SDLK_c, vl::Key_C,
00073 SDLK_d, vl::Key_D,
00074 SDLK_e, vl::Key_E,
00075 SDLK_f, vl::Key_F,
00076 SDLK_g, vl::Key_G,
00077 SDLK_h, vl::Key_H,
00078 SDLK_i, vl::Key_I,
00079 SDLK_j, vl::Key_J,
00080 SDLK_k, vl::Key_K,
00081 SDLK_l, vl::Key_L,
00082 SDLK_m, vl::Key_M,
00083 SDLK_n, vl::Key_N,
00084 SDLK_o, vl::Key_O,
00085 SDLK_p, vl::Key_P,
00086 SDLK_q, vl::Key_Q,
00087 SDLK_r, vl::Key_R,
00088 SDLK_s, vl::Key_S,
00089 SDLK_t, vl::Key_T,
00090 SDLK_u, vl::Key_U,
00091 SDLK_v, vl::Key_V,
00092 SDLK_w, vl::Key_W,
00093 SDLK_x, vl::Key_X,
00094 SDLK_y, vl::Key_Y,
00095 SDLK_z, vl::Key_Z,
00096
00097 SDLK_RETURN, vl::Key_Return,
00098 SDLK_BACKSPACE, vl::Key_BackSpace,
00099 SDLK_SPACE, vl::Key_Space,
00100 SDLK_TAB, vl::Key_Tab,
00101 SDLK_CLEAR, vl::Key_Clear,
00102 SDLK_ESCAPE, vl::Key_Escape,
00103 SDLK_EXCLAIM, vl::Key_Exclam,
00104 SDLK_QUOTEDBL, vl::Key_QuoteDbl,
00105 SDLK_HASH, vl::Key_Hash,
00106 SDLK_DOLLAR, vl::Key_Dollar,
00107 SDLK_AMPERSAND, vl::Key_Ampersand,
00108 SDLK_QUOTE, vl::Key_Quote,
00109 SDLK_LEFTPAREN, vl::Key_LeftParen,
00110 SDLK_RIGHTPAREN, vl::Key_RightParen,
00111 SDLK_ASTERISK, vl::Key_Asterisk,
00112 SDLK_PLUS, vl::Key_Plus,
00113 SDLK_COMMA, vl::Key_Comma,
00114 SDLK_MINUS, vl::Key_Minus,
00115 SDLK_PERIOD, vl::Key_Period,
00116 SDLK_SLASH, vl::Key_Slash,
00117 SDLK_COLON, vl::Key_Colon,
00118 SDLK_SEMICOLON, vl::Key_Semicolon,
00119 SDLK_LESS, vl::Key_Less,
00120 SDLK_EQUALS, vl::Key_Equal,
00121 SDLK_GREATER, vl::Key_Greater,
00122 SDLK_QUESTION, vl::Key_Question,
00123 SDLK_AT, vl::Key_At,
00124 SDLK_LEFTBRACKET, vl::Key_LeftBracket,
00125 SDLK_BACKSLASH, vl::Key_BackSlash,
00126 SDLK_RIGHTBRACKET, vl::Key_RightBracket,
00127 SDLK_CARET, vl::Key_Caret,
00128 SDLK_UNDERSCORE, vl::Key_Underscore,
00129 SDLK_BACKQUOTE, vl::Key_QuoteLeft,
00130
00131
00132
00133 SDLK_LEFT, vl::Key_Left,
00134 SDLK_RIGHT, vl::Key_Right,
00135 SDLK_UP, vl::Key_Up,
00136 SDLK_DOWN, vl::Key_Down,
00137 SDLK_LCTRL, vl::Key_LeftCtrl,
00138 SDLK_RCTRL, vl::Key_RightCtrl,
00139 SDLK_LSHIFT, vl::Key_LeftShift,
00140 SDLK_RSHIFT, vl::Key_RightShift,
00141 SDLK_LALT, vl::Key_LeftAlt,
00142 SDLK_RALT, vl::Key_RightAlt,
00143 SDLK_INSERT, vl::Key_Insert,
00144 SDLK_DELETE, vl::Key_Delete,
00145 SDLK_HOME, vl::Key_Home,
00146 SDLK_END, vl::Key_End,
00147 SDLK_PAGEUP, vl::Key_PageUp,
00148 SDLK_PAGEDOWN, vl::Key_PageDown,
00149 SDLK_PAUSE, vl::Key_Pause,
00150 SDLK_PRINT, vl::Key_Print,
00151 SDLK_F1, vl::Key_F1,
00152 SDLK_F2, vl::Key_F2,
00153 SDLK_F3, vl::Key_F3,
00154 SDLK_F4, vl::Key_F4,
00155 SDLK_F5, vl::Key_F5,
00156 SDLK_F6, vl::Key_F6,
00157 SDLK_F7, vl::Key_F7,
00158 SDLK_F8, vl::Key_F8,
00159 SDLK_F9, vl::Key_F9,
00160 SDLK_F10, vl::Key_F10,
00161 SDLK_F11, vl::Key_F11,
00162 SDLK_F12, vl::Key_F12,
00163 0,0
00164 };
00165 }
00166
00167 SDL_Surface* SDLWindow::mScreen = NULL;
00168
00169 SDLWindow::SDLWindow()
00170 {
00171 }
00172
00173 SDLWindow::~SDLWindow()
00174 {
00175 }
00176
00177 SDLWindow::SDLWindow( const vl::String& title, const vl::OpenGLContextFormat& info, int , int , int width, int height)
00178 {
00179 initSDLWindow(title, info, width, height);
00180 }
00181
00182 bool SDLWindow::initSDLWindow(const vl::String& title, const vl::OpenGLContextFormat& info, int x, int y, int width, int height)
00183 {
00184 if (mScreen || mSDLWindow)
00185 {
00186 vl::Log::error("SDL supports only one window at a time.\n");
00187 VL_TRAP();
00188 return false;
00189 }
00190
00191 framebuffer()->setWidth(width);
00192 framebuffer()->setHeight(height);
00193 mSDLWindow = this;
00194
00195
00196 for(int i=0; key_translation_vec[i]; i+=2)
00197 key_translation_map[ key_translation_vec[i] ] = (vl::EKey)key_translation_vec[i+1];
00198
00199
00200
00201 char win_pos[32] = {0};
00202 sprintf ( win_pos, "SDL_VIDEO_WINDOW_POS=%d,%d", x, y );
00203 SDL_putenv(win_pos);
00204
00205
00206
00207
00208 if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
00209 {
00210 printf("Unable to init SDL: %s\n", SDL_GetError());
00211 return false;
00212 }
00213
00214 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, info.rgbaBits().r());
00215 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, info.rgbaBits().g());
00216 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, info.rgbaBits().b());
00217 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, info.rgbaBits().a());
00218
00219 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, info.accumRGBABits().r());
00220 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, info.accumRGBABits().g());
00221 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, info.accumRGBABits().b());
00222 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, info.accumRGBABits().a());
00223
00224 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, info.depthBufferBits());
00225 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, info.stencilBufferBits());
00226
00227 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, info.doubleBuffer()?1:0);
00228 SDL_GL_SetAttribute(SDL_GL_STEREO, info.stereo());
00229 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, info.multisample()?1:0);
00230 if (info.multisample())
00231 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, info.multisampleSamples());
00232 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, info.vSync());
00233
00234 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
00235 Uint32 flags = SDL_OPENGL | (info.fullscreen() ? SDL_FULLSCREEN : 0);
00236 width = width !=0 ? width : SDL_GetVideoInfo()->current_w;
00237 height = height !=0 ? height : SDL_GetVideoInfo()->current_h;
00238 mScreen = SDL_SetVideoMode( width, height, bpp, flags );
00239 if (mScreen == 0)
00240 {
00241 vl::Log::print( vl::Say("\n error: SDL_SetVideoMode(%n, %n, %n, %hn) failed: %s\n") << width << height << bpp << flags << SDL_GetError() );
00242 exit(1);
00243 }
00244
00245
00246
00247 int viewport[4];
00248 glGetIntegerv(GL_VIEWPORT, viewport);
00249 VL_CHECK(viewport[0] == 0);
00250 VL_CHECK(viewport[1] == 0);
00251 if (viewport[2] != mScreen->w || viewport[3] != mScreen->h)
00252 {
00253 vl::Log::print( vl::Say("\n warning: OpenGL reported %nx%n as video size but SDL says %nx%n\n") << viewport[2] << viewport[3] << mScreen->w << mScreen->h );
00254 VL_TRAP()
00255 }
00256
00257
00258 initGLContext();
00259
00260 dispatchInitEvent();
00261 dispatchResizeEvent(width, height);
00262
00263 #ifndef NDEBUG
00264 vl::Log::print( vl::Say("SDL screen: %n x %n x %n %s\n") << mScreen->w << mScreen->h << mScreen->format->BitsPerPixel << (info.fullscreen() ? "fullscreen" : "windowed") );
00265 #endif
00266
00267 SDL_EnableUNICODE(1);
00268
00269 #ifdef WIN32
00270
00271 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
00272 static SDL_SysWMinfo pInfo;
00273 SDL_VERSION(&pInfo.version);
00274 SDL_GetWMInfo(&pInfo);
00275 HWND hWnd = pInfo.window;
00276 DWORD ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
00277 ExStyle |= WS_EX_ACCEPTFILES;
00278 SetWindowLong(hWnd, GWL_EXSTYLE, ExStyle);
00279
00280
00281
00282
00283 #endif
00284
00285
00286
00287 SDL_ShowCursor(true);
00288 SDL_WM_GrabInput(SDL_GRAB_OFF);
00289 setWindowTitle(title);
00290
00291
00292
00293 SDL_PumpEvents();
00294 SDL_Event event;
00295 while ( SDL_PollEvent(&event) ) {}
00296
00297 return true;
00298 }
00299
00300 void SDLWindow::translateEvent( SDL_Event * ev )
00301 {
00302 vl::EKey key = vl::Key_None;
00303 unsigned short unicode = 0;
00304 if ( ev && (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) )
00305 {
00306 if( key_translation_map.find(ev->key.keysym.sym) != key_translation_map.end() )
00307 key = key_translation_map[ ev->key.keysym.sym ];
00308 else
00309 key = vl::Key_Unknown;
00310
00311 unicode = ev->key.keysym.unicode;
00312 }
00313
00315
00317
00318
00319
00320
00321
00322 if (ev->type == SDL_KEYDOWN)
00323 {
00324 switch(key)
00325 {
00326 default: break;
00327
00328 case vl::Key_LeftCtrl:
00329 case vl::Key_RightCtrl:
00330 dispatchKeyPressEvent(unicode, vl::Key_Ctrl);
00331 break;
00332
00333 case vl::Key_LeftShift:
00334 case vl::Key_RightShift:
00335 dispatchKeyPressEvent(unicode, vl::Key_Shift);
00336 break;
00337
00338 case vl::Key_LeftAlt:
00339 case vl::Key_RightAlt:
00340 dispatchKeyPressEvent(unicode, vl::Key_Alt);
00341 break;
00342 }
00343 dispatchKeyPressEvent(unicode, key);
00344 }
00345 else
00346 if (ev->type == SDL_KEYUP)
00347 {
00348 switch(key)
00349 {
00350 default: break;
00351
00352 case vl::Key_LeftCtrl:
00353 case vl::Key_RightCtrl:
00354 dispatchKeyReleaseEvent(unicode, vl::Key_Ctrl);
00355 break;
00356
00357 case vl::Key_LeftShift:
00358 case vl::Key_RightShift:
00359 dispatchKeyReleaseEvent(unicode, vl::Key_Shift);
00360 break;
00361
00362 case vl::Key_LeftAlt:
00363 case vl::Key_RightAlt:
00364 dispatchKeyReleaseEvent(unicode, vl::Key_Alt);
00365 break;
00366 }
00367 dispatchKeyReleaseEvent(unicode, key);
00368 }
00369 else
00370 if (ev->type == SDL_MOUSEBUTTONDOWN)
00371 {
00372 if (ev->button.button == SDL_BUTTON_WHEELUP)
00373 dispatchMouseWheelEvent(1);
00374 else
00375 if (ev->button.button == SDL_BUTTON_WHEELDOWN)
00376 dispatchMouseWheelEvent(-1);
00377 else
00378 if (ev->button.button == SDL_BUTTON_LEFT)
00379 dispatchMouseDownEvent(vl::LeftButton, ev->button.x, ev->button.y);
00380 else
00381 if (ev->button.button == SDL_BUTTON_RIGHT)
00382 dispatchMouseDownEvent(vl::RightButton, ev->button.x, ev->button.y);
00383 else
00384 if (ev->button.button == SDL_BUTTON_MIDDLE)
00385 dispatchMouseDownEvent(vl::MiddleButton, ev->button.x, ev->button.y);
00386 }
00387 else
00388 if (ev->type == SDL_MOUSEBUTTONUP)
00389 {
00390
00391
00392
00393
00394
00395
00396
00397 if (ev->button.button == SDL_BUTTON_LEFT)
00398 dispatchMouseUpEvent(vl::LeftButton, ev->button.x, ev->button.y);
00399 else
00400 if (ev->button.button == SDL_BUTTON_RIGHT)
00401 dispatchMouseUpEvent(vl::RightButton, ev->button.x, ev->button.y);
00402 else
00403 if (ev->button.button == SDL_BUTTON_MIDDLE)
00404 dispatchMouseUpEvent(vl::MiddleButton, ev->button.x, ev->button.y);
00405 }
00406 else
00407 if (ev->type == SDL_MOUSEMOTION)
00408 {
00409 dispatchMouseMoveEvent(ev->motion.x, ev->motion.y);
00410 }
00411 else
00412 if (ev->type == SDL_VIDEORESIZE)
00413 {
00414
00415
00416 }
00417 else
00418 if( ev->type == SDL_SYSWMEVENT )
00419 {
00420 #ifdef WIN32
00421 if (ev->syswm.msg->msg == WM_DROPFILES)
00422 {
00423 HDROP hDrop = (HDROP) ev->syswm.msg->wParam;
00424 int count = DragQueryFile(hDrop, 0xFFFFFFFF, 0, 0);
00425 const int char_count = 1024;
00426 std::vector<String> files;
00427 for(int i=0; i<count; ++i)
00428 {
00429 wchar_t file_path[char_count];
00430 memset(file_path, 0, char_count);
00431 DragQueryFile(hDrop,i,file_path,char_count);
00432 files.push_back(file_path);
00433 }
00434 dispatchFileDroppedEvent(files);
00435 }
00436 #endif
00437 }
00438 else
00439 if (ev->type == SDL_QUIT)
00440 {
00441 quitApplication();
00442 }
00443 }
00444
00445 void vlSDL::messageLoop()
00446 {
00447 SDL_Event ev;
00448 while(mSDLWindow)
00449 {
00450 if ( SDL_PollEvent(&ev) )
00451 mSDLWindow->translateEvent(&ev);
00452 else
00453 {
00454 if ( mUpdateFlag || mSDLWindow->continuousUpdate() )
00455 {
00456 mSDLWindow->dispatchRunEvent();
00457 mUpdateFlag = false;
00458 }
00459 else
00460 {
00461
00462 SDL_Delay(10);
00463 }
00464 }
00465 }
00466
00467 SDL_Quit();
00468 }
00469
00470 void SDLWindow::quitApplication()
00471 {
00472 dispatchDestroyEvent();
00473 mSDLWindow = NULL;
00474 }
00475
00476 void SDLWindow::update()
00477 {
00478 mUpdateFlag = true;
00479 }
00480
00481 void SDLWindow::setWindowTitle(const vl::String& title)
00482 {
00483 SDL_WM_SetCaption(title.toStdString().c_str(), title.toStdString().c_str());
00484 }
00485
00486 void SDLWindow::swapBuffers()
00487 {
00488 SDL_GL_SwapBuffers();
00489 }
00490
00491 void SDLWindow::setPosition(int x, int y)
00492 {
00493 #ifdef WIN32
00494 static SDL_SysWMinfo pInfo;
00495 SDL_VERSION(&pInfo.version);
00496 SDL_GetWMInfo(&pInfo);
00497 HWND hWnd = pInfo.window;
00498
00499 SetWindowPos(hWnd, 0, x, y, 0, 0, SWP_NOSIZE );
00500 #endif
00501 }
00502