Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlSDL/SDLWindow.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
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     // non unicode
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 /*x*/, int /*y*/, 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   // init key translation map
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   // SDL_VIDEO_WINDOW_POS
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   // setenv("SDL_VIDEO_CENTERED", "YES", 0);
00205 
00206   // init SDL
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   // window size problem
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   // OpenGL extensions initialization
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     // file drag & drop support
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     // The SDL gurus decided not to give us this option...
00280     // DWORD Style = GetWindowLong(hWnd, GWL_STYLE);
00281     // Style |= WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
00282     // SetWindowLong(hWnd, GWL_STYLE, Style);
00283   #endif
00284 
00285   // mouse
00286 
00287   SDL_ShowCursor(true);
00288   SDL_WM_GrabInput(SDL_GRAB_OFF);
00289   setWindowTitle(title);
00290 
00291   // event cleaning
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   //bool update = mUpdateFlag;
00317   //mUpdateFlag = continuousUpdate();
00318 
00319   //if (update)
00320   //  dispatchRunEvent();
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     // We only need SDL_MOUSEBUTTONDOWN's wheel messages
00391     /*if (ev->button.button == SDL_BUTTON_WHEELUP)
00392       mouseWheelEvent(1);
00393     else
00394     if (ev->button.button == SDL_BUTTON_WHEELDOWN)
00395       mouseWheelEvent(-1);
00396     else*/
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     // SDL is not able to resize OpenGL contexts
00415     // resizeEvent(ev->resize.w, ev->resize.h);
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         // rest for 10ms if there are not events to process, and we don't need to repaint
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 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:43.
Permission is granted to use this page to write and publish articles regarding Visualization Library.