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