Blender V2.61 - r43446

GHOST_SystemSDL.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00027 #include <assert.h>
00028 
00029 #include "GHOST_SystemSDL.h"
00030 
00031 #include "GHOST_WindowManager.h"
00032 
00033 #include "GHOST_EventCursor.h"
00034 #include "GHOST_EventKey.h"
00035 #include "GHOST_EventButton.h"
00036 #include "GHOST_EventWheel.h"
00037 
00038 GHOST_SystemSDL::GHOST_SystemSDL()
00039     :
00040       GHOST_System()
00041 {
00042     if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) {
00043         printf ("Error initializing SDL:  %s\n", SDL_GetError());
00044     }
00045 
00046     /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); */
00047     /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); */
00048     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00049     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
00050     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
00051     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
00052     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
00053     SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
00054 }
00055 
00056 GHOST_SystemSDL::~GHOST_SystemSDL()
00057 {
00058     SDL_Quit();
00059 }
00060 
00061 GHOST_IWindow *
00062 GHOST_SystemSDL::createWindow(const STR_String& title,
00063                               GHOST_TInt32 left,
00064                               GHOST_TInt32 top,
00065                               GHOST_TUns32 width,
00066                               GHOST_TUns32 height,
00067                               GHOST_TWindowState state,
00068                               GHOST_TDrawingContextType type,
00069                               bool stereoVisual,
00070                               const GHOST_TUns16 numOfAASamples,
00071                               const GHOST_TEmbedderWindowID parentWindow
00072                               )
00073 {
00074     GHOST_WindowSDL *window= NULL;
00075 
00076     window= new GHOST_WindowSDL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1);
00077 
00078     if (window) {
00079         if (window->getValid()) {
00080             m_windowManager->addWindow(window);
00081             pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
00082         }
00083         else {
00084             delete window;
00085             window= NULL;
00086         }
00087     }
00088     return window;
00089 }
00090 
00091 GHOST_TSuccess
00092 GHOST_SystemSDL::init() {
00093     GHOST_TSuccess success = GHOST_System::init();
00094 
00095     if (success) {
00096         m_displayManager = new GHOST_DisplayManagerSDL(this);
00097 
00098         if (m_displayManager) {
00099             return GHOST_kSuccess;
00100         }
00101     }
00102 
00103     return GHOST_kFailure;
00104 }
00105 
00106 void
00107 GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32& width,
00108                                           GHOST_TUns32& height) const
00109 {
00110     SDL_DisplayMode mode;
00111     SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */
00112     width= mode.w;
00113     height= mode.h;
00114 }
00115 
00116 GHOST_TUns8
00117 GHOST_SystemSDL::getNumDisplays() const
00118 {
00119     return SDL_GetNumVideoDisplays();
00120 }
00121 
00122 GHOST_TSuccess
00123 GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const
00124 {
00125     SDL_Keymod mod= SDL_GetModState();
00126 
00127     keys.set(GHOST_kModifierKeyLeftShift,    (mod & KMOD_LSHIFT) != 0);
00128     keys.set(GHOST_kModifierKeyRightShift,   (mod & KMOD_RSHIFT) != 0);
00129     keys.set(GHOST_kModifierKeyLeftControl,  (mod & KMOD_LCTRL) != 0);
00130     keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0);
00131     keys.set(GHOST_kModifierKeyLeftAlt,      (mod & KMOD_LALT) != 0);
00132     keys.set(GHOST_kModifierKeyRightAlt,     (mod & KMOD_RALT) != 0);
00133     keys.set(GHOST_kModifierKeyOS,           (mod & (KMOD_LGUI|KMOD_RGUI)) != 0);
00134 
00135     return GHOST_kSuccess;
00136 }
00137 
00138 #define GXMAP(k,x,y) case x: k= y; break;
00139 
00140 static GHOST_TKey
00141 convertSDLKey(SDL_Scancode key)
00142 {
00143     GHOST_TKey type;
00144 
00145     if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) {
00146         type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA));
00147     } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) {
00148         type= (key == SDL_SCANCODE_0) ? GHOST_kKey0 : GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey1));
00149     } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) {
00150         type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1));
00151     } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) {
00152         type= GHOST_TKey(key - SDL_SCANCODE_F13 + int(GHOST_kKeyF13));
00153     } else {
00154         switch(key) {
00155             /* TODO SDL_SCANCODE_NONUSBACKSLASH */
00156 
00157         GXMAP(type,SDL_SCANCODE_BACKSPACE,      GHOST_kKeyBackSpace);
00158         GXMAP(type,SDL_SCANCODE_TAB,            GHOST_kKeyTab);
00159         GXMAP(type,SDL_SCANCODE_RETURN,         GHOST_kKeyEnter);
00160         GXMAP(type,SDL_SCANCODE_ESCAPE,         GHOST_kKeyEsc);
00161         GXMAP(type,SDL_SCANCODE_SPACE,          GHOST_kKeySpace);
00162 
00163         GXMAP(type,SDL_SCANCODE_SEMICOLON,      GHOST_kKeySemicolon);
00164         GXMAP(type,SDL_SCANCODE_PERIOD,         GHOST_kKeyPeriod);
00165         GXMAP(type,SDL_SCANCODE_COMMA,          GHOST_kKeyComma);
00166         GXMAP(type,SDL_SCANCODE_APOSTROPHE,     GHOST_kKeyQuote);
00167         GXMAP(type,SDL_SCANCODE_GRAVE,          GHOST_kKeyAccentGrave);
00168         GXMAP(type,SDL_SCANCODE_MINUS,          GHOST_kKeyMinus);
00169         GXMAP(type,SDL_SCANCODE_EQUALS,         GHOST_kKeyEqual);
00170 
00171         GXMAP(type,SDL_SCANCODE_SLASH,          GHOST_kKeySlash);
00172         GXMAP(type,SDL_SCANCODE_BACKSLASH,      GHOST_kKeyBackslash);
00173         GXMAP(type,SDL_SCANCODE_KP_EQUALS,      GHOST_kKeyEqual);
00174         GXMAP(type,SDL_SCANCODE_LEFTBRACKET,    GHOST_kKeyLeftBracket);
00175         GXMAP(type,SDL_SCANCODE_RIGHTBRACKET,   GHOST_kKeyRightBracket);
00176         GXMAP(type,SDL_SCANCODE_PAUSE,          GHOST_kKeyPause);
00177 
00178         GXMAP(type,SDL_SCANCODE_LSHIFT,         GHOST_kKeyLeftShift);
00179         GXMAP(type,SDL_SCANCODE_RSHIFT,         GHOST_kKeyRightShift);
00180         GXMAP(type,SDL_SCANCODE_LCTRL,          GHOST_kKeyLeftControl);
00181         GXMAP(type,SDL_SCANCODE_RCTRL,          GHOST_kKeyRightControl);
00182         GXMAP(type,SDL_SCANCODE_LALT,           GHOST_kKeyLeftAlt);
00183         GXMAP(type,SDL_SCANCODE_RALT,           GHOST_kKeyRightAlt);
00184         GXMAP(type,SDL_SCANCODE_LGUI,           GHOST_kKeyOS);
00185         GXMAP(type,SDL_SCANCODE_RGUI,           GHOST_kKeyOS);
00186 
00187         GXMAP(type,SDL_SCANCODE_INSERT,         GHOST_kKeyInsert);
00188         GXMAP(type,SDL_SCANCODE_DELETE,         GHOST_kKeyDelete);
00189         GXMAP(type,SDL_SCANCODE_HOME,           GHOST_kKeyHome);
00190         GXMAP(type,SDL_SCANCODE_END,            GHOST_kKeyEnd);
00191         GXMAP(type,SDL_SCANCODE_PAGEUP,         GHOST_kKeyUpPage);
00192         GXMAP(type,SDL_SCANCODE_PAGEDOWN,       GHOST_kKeyDownPage);
00193 
00194         GXMAP(type,SDL_SCANCODE_LEFT,           GHOST_kKeyLeftArrow);
00195         GXMAP(type,SDL_SCANCODE_RIGHT,          GHOST_kKeyRightArrow);
00196         GXMAP(type,SDL_SCANCODE_UP,             GHOST_kKeyUpArrow);
00197         GXMAP(type,SDL_SCANCODE_DOWN,           GHOST_kKeyDownArrow);
00198 
00199         GXMAP(type,SDL_SCANCODE_CAPSLOCK,       GHOST_kKeyCapsLock);
00200         GXMAP(type,SDL_SCANCODE_SCROLLLOCK,     GHOST_kKeyScrollLock);
00201         GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR,   GHOST_kKeyNumLock);
00202         GXMAP(type,SDL_SCANCODE_PRINTSCREEN,    GHOST_kKeyPrintScreen);
00203 
00204         /* keypad events */
00205 
00206         /* note, sdl defines a bunch of kp defines I never saw before like
00207          * SDL_SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_XOR - campbell */
00208         GXMAP(type,SDL_SCANCODE_KP_0,           GHOST_kKeyNumpad0);
00209         GXMAP(type,SDL_SCANCODE_KP_1,           GHOST_kKeyNumpad1);
00210         GXMAP(type,SDL_SCANCODE_KP_2,           GHOST_kKeyNumpad2);
00211         GXMAP(type,SDL_SCANCODE_KP_3,           GHOST_kKeyNumpad3);
00212         GXMAP(type,SDL_SCANCODE_KP_4,           GHOST_kKeyNumpad4);
00213         GXMAP(type,SDL_SCANCODE_KP_5,           GHOST_kKeyNumpad5);
00214         GXMAP(type,SDL_SCANCODE_KP_6,           GHOST_kKeyNumpad6);
00215         GXMAP(type,SDL_SCANCODE_KP_7,           GHOST_kKeyNumpad7);
00216         GXMAP(type,SDL_SCANCODE_KP_8,           GHOST_kKeyNumpad8);
00217         GXMAP(type,SDL_SCANCODE_KP_9,           GHOST_kKeyNumpad9);
00218         GXMAP(type,SDL_SCANCODE_KP_PERIOD,      GHOST_kKeyNumpadPeriod);
00219 
00220         GXMAP(type,SDL_SCANCODE_KP_ENTER,       GHOST_kKeyNumpadEnter);
00221         GXMAP(type,SDL_SCANCODE_KP_PLUS,        GHOST_kKeyNumpadPlus);
00222         GXMAP(type,SDL_SCANCODE_KP_MINUS,       GHOST_kKeyNumpadMinus);
00223         GXMAP(type,SDL_SCANCODE_KP_MULTIPLY,    GHOST_kKeyNumpadAsterisk);
00224         GXMAP(type,SDL_SCANCODE_KP_DIVIDE,      GHOST_kKeyNumpadSlash);
00225 
00226         /* Media keys in some keyboards and laptops with XFree86/Xorg */
00227         GXMAP(type,SDL_SCANCODE_AUDIOPLAY,      GHOST_kKeyMediaPlay);
00228         GXMAP(type,SDL_SCANCODE_AUDIOSTOP,      GHOST_kKeyMediaStop);
00229         GXMAP(type,SDL_SCANCODE_AUDIOPREV,      GHOST_kKeyMediaFirst);
00230         // GXMAP(type,XF86XK_AudioRewind,       GHOST_kKeyMediaFirst);
00231         GXMAP(type,SDL_SCANCODE_AUDIONEXT,      GHOST_kKeyMediaLast);
00232 
00233         default:
00234             printf("Unknown\n");
00235             type= GHOST_kKeyUnknown;
00236             break;
00237         }
00238     }
00239 
00240     return type;
00241 }
00242 #undef GXMAP
00243 
00244 
00245 void
00246 GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
00247 {
00248     GHOST_Event * g_event= NULL;
00249 
00250     switch(sdl_event->type) {
00251     case SDL_WINDOWEVENT:
00252         {
00253             SDL_WindowEvent &sdl_sub_evt= sdl_event->window;
00254             GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
00255             //assert(window != NULL); // can be NULL on close window.
00256 
00257             switch (sdl_sub_evt.event) {
00258             case SDL_WINDOWEVENT_EXPOSED:
00259                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window);
00260                 break;
00261             case SDL_WINDOWEVENT_RESIZED:
00262                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window);
00263                 break;
00264             case SDL_WINDOWEVENT_MOVED:
00265                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window);
00266                 break;
00267             case SDL_WINDOWEVENT_FOCUS_GAINED:
00268                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window);
00269                 break;
00270             case SDL_WINDOWEVENT_FOCUS_LOST:
00271                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window);
00272                 break;
00273             case SDL_WINDOWEVENT_CLOSE:
00274                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
00275                 break;
00276             }
00277         }
00278         break;
00279     case SDL_QUIT:
00280         g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL);
00281         break;
00282 
00283     case SDL_MOUSEMOTION:
00284         {
00285             SDL_MouseMotionEvent &sdl_sub_evt= sdl_event->motion;
00286             SDL_Window *sdl_win= SDL_GetWindowFromID(sdl_sub_evt.windowID);
00287             GHOST_WindowSDL *window= findGhostWindow(sdl_win);
00288             assert(window != NULL);
00289 
00290             int x_win, y_win;
00291             SDL_GetWindowPosition(sdl_win, &x_win, &y_win);
00292 
00293             GHOST_TInt32 x_root= sdl_sub_evt.x + x_win;
00294             GHOST_TInt32 y_root= sdl_sub_evt.y + y_win;
00295 
00296 #if 0
00297             if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
00298             {
00299                 GHOST_TInt32 x_new= x_root;
00300                 GHOST_TInt32 y_new= y_root;
00301                 GHOST_TInt32 x_accum, y_accum;
00302                 GHOST_Rect bounds;
00303 
00304                 /* fallback to window bounds */
00305                 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
00306                     window->getClientBounds(bounds);
00307 
00308                 /* could also clamp to screen bounds
00309                  * wrap with a window outside the view will fail atm  */
00310                 bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */
00311                 window->getCursorGrabAccum(x_accum, y_accum);
00312 
00313                 // cant use setCursorPosition because the mouse may have no focus!
00314                 if(x_new != x_root || y_new != y_root) {
00315                     if (1 ) { //xme.time > m_last_warp) {
00316                         /* when wrapping we don't need to add an event because the
00317                          * setCursorPosition call will cause a new event after */
00318                         SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); /* wrap */
00319                         window->setCursorGrabAccum(x_accum + (x_root - x_new), y_accum + (y_root - y_new));
00320                         // m_last_warp= lastEventTime(xme.time);
00321                     } else {
00322                         // setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
00323                         SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win);
00324                     }
00325 
00326                     g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_new, y_new);
00327                 }
00328                 else {
00329                     g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root + x_accum, y_root + y_accum);
00330                 }
00331             }
00332             else
00333 #endif
00334             {
00335                 g_event= new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root, y_root);
00336             }
00337             break;
00338         }
00339     case SDL_MOUSEBUTTONUP:
00340     case SDL_MOUSEBUTTONDOWN:
00341         {
00342             SDL_MouseButtonEvent &sdl_sub_evt= sdl_event->button;
00343             GHOST_TButtonMask gbmask= GHOST_kButtonMaskLeft;
00344             GHOST_TEventType type= (sdl_sub_evt.state==SDL_PRESSED) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp;
00345 
00346             GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
00347             assert(window != NULL);
00348 
00349             /* process rest of normal mouse buttons */
00350             if(sdl_sub_evt.button == SDL_BUTTON_LEFT)
00351                 gbmask= GHOST_kButtonMaskLeft;
00352             else if(sdl_sub_evt.button == SDL_BUTTON_MIDDLE)
00353                 gbmask= GHOST_kButtonMaskMiddle;
00354             else if(sdl_sub_evt.button == SDL_BUTTON_RIGHT)
00355                 gbmask= GHOST_kButtonMaskRight;
00356             /* these buttons are untested! */
00357             else if(sdl_sub_evt.button == SDL_BUTTON_X1)
00358                 gbmask= GHOST_kButtonMaskButton4;
00359             else if(sdl_sub_evt.button == SDL_BUTTON_X2)
00360                 gbmask= GHOST_kButtonMaskButton5;
00361             else
00362                 break;
00363 
00364             g_event= new GHOST_EventButton(getMilliSeconds(), type, window, gbmask);
00365             break;
00366         }
00367     case SDL_MOUSEWHEEL:
00368         {
00369             SDL_MouseWheelEvent &sdl_sub_evt= sdl_event->wheel;
00370             GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
00371             assert(window != NULL);
00372             g_event= new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
00373         }
00374         break;
00375     case SDL_KEYDOWN:
00376     case SDL_KEYUP:
00377         {
00378             SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key;
00379             SDL_Keycode sym= sdl_sub_evt.keysym.sym;
00380             GHOST_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
00381 
00382             GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
00383             assert(window != NULL);
00384 
00385             GHOST_TKey gkey= convertSDLKey(sdl_sub_evt.keysym.scancode);
00386             /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */
00387             /* printf("%d\n", sym); */
00388             if(sym > 127) {
00389                 switch(sym) {
00390                     case SDLK_KP_DIVIDE: sym= '/'; break;
00391                     case SDLK_KP_MULTIPLY: sym= '*'; break;
00392                     case SDLK_KP_MINUS: sym= '-'; break;
00393                     case SDLK_KP_PLUS: sym= '+'; break;
00394                     case SDLK_KP_1: sym= '1'; break;
00395                     case SDLK_KP_2: sym= '2'; break;
00396                     case SDLK_KP_3: sym= '3'; break;
00397                     case SDLK_KP_4: sym= '4'; break;
00398                     case SDLK_KP_5: sym= '5'; break;
00399                     case SDLK_KP_6: sym= '6'; break;
00400                     case SDLK_KP_7: sym= '7'; break;
00401                     case SDLK_KP_8: sym= '8'; break;
00402                     case SDLK_KP_9: sym= '9'; break;
00403                     case SDLK_KP_0: sym= '0'; break;
00404                     case SDLK_KP_PERIOD: sym= '.'; break;
00405                     default: sym= 0; break;
00406                 }
00407             }
00408             else {
00409                 if(sdl_sub_evt.keysym.mod & (KMOD_LSHIFT|KMOD_RSHIFT)) {
00410                     /* lame US keyboard assumptions */
00411                     if(sym >= 'a' && sym <= ('a' + 32)) {
00412                         sym -= 32;
00413                     }
00414                     else {
00415                         switch(sym) {
00416                             case '`': sym= '~'; break;
00417                             case '1': sym= '!'; break;
00418                             case '2': sym= '@'; break;
00419                             case '3': sym= '#'; break;
00420                             case '4': sym= '$'; break;
00421                             case '5': sym= '%'; break;
00422                             case '6': sym= '^'; break;
00423                             case '7': sym= '&'; break;
00424                             case '8': sym= '*'; break;
00425                             case '9': sym= '('; break;
00426                             case '0': sym= ')'; break;
00427                             case '-': sym= '_'; break;
00428                             case '=': sym= '+'; break;
00429                             case '[': sym= '{'; break;
00430                             case ']': sym= '}'; break;
00431                             case '\\': sym= '|'; break;
00432                             case ';': sym= ':'; break;
00433                             case '\'': sym= '"'; break;
00434                             case ',': sym= '<'; break;
00435                             case '.': sym= '>'; break;
00436                             case '/': sym= '?'; break;
00437                             default:            break;
00438                         }
00439                     }
00440                 }
00441             }
00442 
00443             g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL);
00444         }
00445         break;
00446     }
00447 
00448     if (g_event) {
00449         pushEvent(g_event);
00450     }
00451 }
00452 
00453 GHOST_TSuccess
00454 GHOST_SystemSDL::getCursorPosition(GHOST_TInt32& x,
00455                                    GHOST_TInt32& y) const
00456 {
00457     int x_win, y_win;
00458     SDL_Window *win= SDL_GetMouseFocus();
00459     SDL_GetWindowPosition(win, &x_win, &y_win);
00460 
00461     int xi, yi;
00462     SDL_GetMouseState(&xi, &yi);
00463     x= xi + x_win;
00464     y= yi + x_win;
00465 
00466     return GHOST_kSuccess;
00467 }
00468 
00469 GHOST_TSuccess
00470 GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x,
00471                                    GHOST_TInt32 y)
00472 {
00473     int x_win, y_win;
00474     SDL_Window *win= SDL_GetMouseFocus();
00475     SDL_GetWindowPosition(win, &x_win, &y_win);
00476 
00477     SDL_WarpMouseInWindow(win, x - x_win, y - y_win);
00478     return GHOST_kSuccess;
00479 }
00480 
00481 bool
00482 GHOST_SystemSDL::generateWindowExposeEvents()
00483 {
00484     vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin();
00485     vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end();
00486     bool anyProcessed= false;
00487 
00488     for (;w_start != w_end; ++w_start) {
00489         GHOST_Event * g_event= new
00490             GHOST_Event(
00491                 getMilliSeconds(),
00492                 GHOST_kEventWindowUpdate,
00493                 *w_start
00494             );
00495 
00496         (*w_start)->validate();
00497 
00498         if (g_event) {
00499             printf("Expose events pushed\n");
00500             pushEvent(g_event);
00501             anyProcessed= true;
00502         }
00503     }
00504 
00505     m_dirty_windows.clear();
00506     return anyProcessed;
00507 }
00508 
00509 
00510 bool
00511 GHOST_SystemSDL::processEvents(bool waitForEvent)
00512 {
00513     // Get all the current events -- translate them into
00514     // ghost events and call base class pushEvent() method.
00515 
00516     bool anyProcessed= false;
00517 
00518     do {
00519         GHOST_TimerManager* timerMgr= getTimerManager();
00520 
00521         if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) {
00522             GHOST_TUns64 next= timerMgr->nextFireTime();
00523 
00524             if (next==GHOST_kFireTimeNever) {
00525                 SDL_WaitEventTimeout(NULL, -1);
00526                 //SleepTillEvent(m_display, -1);
00527             } else {
00528                 GHOST_TInt64 maxSleep= next - getMilliSeconds();
00529 
00530                 if(maxSleep >= 0) {
00531                     SDL_WaitEventTimeout(NULL, next - getMilliSeconds());
00532                     // SleepTillEvent(m_display, next - getMilliSeconds()); // X11
00533                 }
00534             }
00535         }
00536 
00537         if (timerMgr->fireTimers(getMilliSeconds())) {
00538             anyProcessed= true;
00539         }
00540 
00541         SDL_Event sdl_event;
00542         while (SDL_PollEvent(&sdl_event)) {
00543             processEvent(&sdl_event);
00544             anyProcessed= true;
00545         }
00546 
00547         if (generateWindowExposeEvents()) {
00548             anyProcessed= true;
00549         }
00550     } while (waitForEvent && !anyProcessed);
00551 
00552     return anyProcessed;
00553 }
00554 
00555 
00556 GHOST_WindowSDL *
00557 GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
00558 {
00559     if (sdl_win == NULL) return NULL;
00560 
00561     // It is not entirely safe to do this as the backptr may point
00562     // to a window that has recently been removed.
00563     // We should always check the window manager's list of windows
00564     // and only process events on these windows.
00565 
00566     vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows();
00567 
00568     vector<GHOST_IWindow *>::iterator win_it= win_vec.begin();
00569     vector<GHOST_IWindow *>::const_iterator win_end= win_vec.end();
00570 
00571     for (; win_it != win_end; ++win_it) {
00572         GHOST_WindowSDL * window= static_cast<GHOST_WindowSDL *>(*win_it);
00573         if (window->getSDLWindow() == sdl_win) {
00574             return window;
00575         }
00576     }
00577     return NULL;
00578 }
00579 
00580 
00581 void
00582 GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind)
00583 {
00584     GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
00585 
00586     m_dirty_windows.push_back(bad_wind);
00587 }
00588 
00589 
00590 GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const
00591 {
00592     Uint8 state= SDL_GetMouseState(NULL, NULL);
00593     buttons.set(GHOST_kButtonMaskLeft,   (state & SDL_BUTTON_LMASK) != 0);
00594     buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0);
00595     buttons.set(GHOST_kButtonMaskRight,  (state & SDL_BUTTON_RMASK) != 0);
00596 
00597     return GHOST_kSuccess;
00598 }
00599 
00600 GHOST_TUns8 *
00601 GHOST_SystemSDL::getClipboard(bool selection) const
00602 {
00603     return (GHOST_TUns8 *)SDL_GetClipboardText();
00604 }
00605 
00606 void
00607 GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const
00608 {
00609     SDL_SetClipboardText(buffer);
00610 }
00611 
00612 GHOST_TUns64
00613 GHOST_SystemSDL::getMilliSeconds()
00614 {
00615     return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */
00616 }