svn merge -r38300:38400 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / intern / ghost / intern / GHOST_SystemSDL.cpp
1 /*
2  * $Id: GHOST_SystemSDL.cpp 38349 2011-07-13 00:49:22Z gsrb3d $
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * Contributor(s): Campbell Barton
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  */
23
24 /** \file ghost/intern/GHOST_SystemSDL.cpp
25  *  \ingroup GHOST
26  */
27
28 #include <assert.h>
29
30 #include "GHOST_SystemSDL.h"
31
32 #include "GHOST_WindowManager.h"
33
34 #include "GHOST_EventCursor.h"
35 #include "GHOST_EventKey.h"
36 #include "GHOST_EventButton.h"
37 #include "GHOST_EventWheel.h"
38
39 GHOST_SystemSDL::GHOST_SystemSDL()
40     :
41       GHOST_System()
42 {
43         if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) {
44                 printf ("Error initializing SDL:  %s\n", SDL_GetError());
45         }
46
47         /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); */
48     /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); */
49     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
50     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
51     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
52     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
53     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
54     SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
55 }
56
57 GHOST_SystemSDL::~GHOST_SystemSDL()
58 {
59         SDL_Quit();
60 }
61
62 GHOST_IWindow *
63 GHOST_SystemSDL::createWindow(const STR_String& title,
64                               GHOST_TInt32 left,
65                               GHOST_TInt32 top,
66                               GHOST_TUns32 width,
67                               GHOST_TUns32 height,
68                               GHOST_TWindowState state,
69                               GHOST_TDrawingContextType type,
70                               bool stereoVisual,
71                               const GHOST_TUns16 numOfAASamples,
72                               const GHOST_TEmbedderWindowID parentWindow
73                               )
74 {
75         GHOST_WindowSDL *window= NULL;
76
77         window= new GHOST_WindowSDL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1);
78
79         if (window) {
80                 if (window->getValid()) {
81                         m_windowManager->addWindow(window);
82                         pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
83                 }
84                 else {
85                         delete window;
86                         window= NULL;
87                 }
88         }
89         return window;
90 }
91
92 GHOST_TSuccess
93 GHOST_SystemSDL::init() {
94         GHOST_TSuccess success = GHOST_System::init();
95
96         if (success) {
97                 m_displayManager = new GHOST_DisplayManagerSDL(this);
98
99                 if (m_displayManager) {
100                         return GHOST_kSuccess;
101                 }
102         }
103
104         return GHOST_kFailure;
105 }
106
107 void
108 GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32& width,
109                                           GHOST_TUns32& height) const
110 {
111         SDL_DisplayMode mode;
112         SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */
113         width= mode.w;
114         height= mode.h;
115 }
116
117 GHOST_TUns8
118 GHOST_SystemSDL::getNumDisplays() const
119 {
120         return SDL_GetNumVideoDisplays();
121 }
122
123 GHOST_TSuccess
124 GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const
125 {
126         SDL_Keymod mod= SDL_GetModState();
127
128         keys.set(GHOST_kModifierKeyLeftShift,    (mod & KMOD_LSHIFT) != 0);
129         keys.set(GHOST_kModifierKeyRightShift,   (mod & KMOD_RSHIFT) != 0);
130         keys.set(GHOST_kModifierKeyLeftControl,  (mod & KMOD_LCTRL) != 0);
131         keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0);
132         keys.set(GHOST_kModifierKeyLeftAlt,      (mod & KMOD_LALT) != 0);
133         keys.set(GHOST_kModifierKeyRightAlt,     (mod & KMOD_RALT) != 0);
134         keys.set(GHOST_kModifierKeyOS,           (mod & (KMOD_LGUI|KMOD_RGUI)) != 0);
135
136         return GHOST_kSuccess;
137 }
138
139 #define GXMAP(k,x,y) case x: k= y; break;
140
141 static GHOST_TKey
142 convertSDLKey(SDL_Scancode key)
143 {
144         GHOST_TKey type;
145
146         if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) {
147                 type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA));
148         } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) {
149                 type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0));
150         } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) {
151                 type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1));
152         } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) {
153                 type= GHOST_TKey(key - SDL_SCANCODE_F13 + int(GHOST_kKeyF13));
154         } else {
155                 switch(key) {
156                         /* TODO SDL_SCANCODE_NONUSBACKSLASH */
157
158                 GXMAP(type,SDL_SCANCODE_BACKSPACE,      GHOST_kKeyBackSpace);
159                 GXMAP(type,SDL_SCANCODE_TAB,            GHOST_kKeyTab);
160                 GXMAP(type,SDL_SCANCODE_RETURN,         GHOST_kKeyEnter);
161                 GXMAP(type,SDL_SCANCODE_ESCAPE,         GHOST_kKeyEsc);
162                 GXMAP(type,SDL_SCANCODE_SPACE,          GHOST_kKeySpace);
163
164                 GXMAP(type,SDL_SCANCODE_SEMICOLON,      GHOST_kKeySemicolon);
165                 GXMAP(type,SDL_SCANCODE_PERIOD,         GHOST_kKeyPeriod);
166                 GXMAP(type,SDL_SCANCODE_COMMA,          GHOST_kKeyComma);
167                 GXMAP(type,SDL_SCANCODE_APOSTROPHE,     GHOST_kKeyQuote);
168                 GXMAP(type,SDL_SCANCODE_GRAVE,          GHOST_kKeyAccentGrave);
169                 GXMAP(type,SDL_SCANCODE_MINUS,          GHOST_kKeyMinus);
170                 GXMAP(type,SDL_SCANCODE_SLASH,          GHOST_kKeySlash);
171                 GXMAP(type,SDL_SCANCODE_BACKSLASH,      GHOST_kKeyBackslash);
172                 GXMAP(type,SDL_SCANCODE_KP_EQUALS,      GHOST_kKeyEqual);
173                 GXMAP(type,SDL_SCANCODE_LEFTBRACKET,    GHOST_kKeyLeftBracket);
174                 GXMAP(type,SDL_SCANCODE_RIGHTBRACKET,   GHOST_kKeyRightBracket);
175                 GXMAP(type,SDL_SCANCODE_PAUSE,          GHOST_kKeyPause);
176
177                 GXMAP(type,SDL_SCANCODE_LSHIFT,         GHOST_kKeyLeftShift);
178                 GXMAP(type,SDL_SCANCODE_RSHIFT,         GHOST_kKeyRightShift);
179                 GXMAP(type,SDL_SCANCODE_LCTRL,          GHOST_kKeyLeftControl);
180                 GXMAP(type,SDL_SCANCODE_RCTRL,          GHOST_kKeyRightControl);
181                 GXMAP(type,SDL_SCANCODE_LALT,           GHOST_kKeyLeftAlt);
182                 GXMAP(type,SDL_SCANCODE_RALT,           GHOST_kKeyRightAlt);
183                 GXMAP(type,SDL_SCANCODE_RGUI,           GHOST_kKeyOS);
184
185                 GXMAP(type,SDL_SCANCODE_INSERT,         GHOST_kKeyInsert);
186                 GXMAP(type,SDL_SCANCODE_DELETE,         GHOST_kKeyDelete);
187                 GXMAP(type,SDL_SCANCODE_HOME,           GHOST_kKeyHome);
188                 GXMAP(type,SDL_SCANCODE_END,            GHOST_kKeyEnd);
189                 GXMAP(type,SDL_SCANCODE_PAGEUP,         GHOST_kKeyUpPage);
190                 GXMAP(type,SDL_SCANCODE_PAGEDOWN,       GHOST_kKeyDownPage);
191
192                 GXMAP(type,SDL_SCANCODE_LEFT,           GHOST_kKeyLeftArrow);
193                 GXMAP(type,SDL_SCANCODE_RIGHT,          GHOST_kKeyRightArrow);
194                 GXMAP(type,SDL_SCANCODE_UP,             GHOST_kKeyUpArrow);
195                 GXMAP(type,SDL_SCANCODE_DOWN,           GHOST_kKeyDownArrow);
196
197                 GXMAP(type,SDL_SCANCODE_CAPSLOCK,       GHOST_kKeyCapsLock);
198                 GXMAP(type,SDL_SCANCODE_SCROLLLOCK,     GHOST_kKeyScrollLock);
199                 GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR,   GHOST_kKeyNumLock);
200
201                 /* keypad events */
202
203                 /* note, sdl defines a bunch of kp defines I never saw before like
204                  * SDL_SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_XOR - campbell */
205                 GXMAP(type,SDL_SCANCODE_KP_0,           GHOST_kKeyNumpad0);
206                 GXMAP(type,SDL_SCANCODE_KP_1,           GHOST_kKeyNumpad1);
207                 GXMAP(type,SDL_SCANCODE_KP_2,           GHOST_kKeyNumpad2);
208                 GXMAP(type,SDL_SCANCODE_KP_3,           GHOST_kKeyNumpad3);
209                 GXMAP(type,SDL_SCANCODE_KP_4,           GHOST_kKeyNumpad4);
210                 GXMAP(type,SDL_SCANCODE_KP_5,           GHOST_kKeyNumpad5);
211                 GXMAP(type,SDL_SCANCODE_KP_6,           GHOST_kKeyNumpad6);
212                 GXMAP(type,SDL_SCANCODE_KP_7,           GHOST_kKeyNumpad7);
213                 GXMAP(type,SDL_SCANCODE_KP_8,           GHOST_kKeyNumpad8);
214                 GXMAP(type,SDL_SCANCODE_KP_9,           GHOST_kKeyNumpad9);
215                 GXMAP(type,SDL_SCANCODE_KP_PERIOD,      GHOST_kKeyNumpadPeriod);
216
217         GXMAP(type,SDL_SCANCODE_KP_ENTER,       GHOST_kKeyNumpadEnter);
218         GXMAP(type,SDL_SCANCODE_KP_PLUS,        GHOST_kKeyNumpadPlus);
219         GXMAP(type,SDL_SCANCODE_KP_MINUS,       GHOST_kKeyNumpadMinus);
220         GXMAP(type,SDL_SCANCODE_KP_MULTIPLY,    GHOST_kKeyNumpadAsterisk);
221         GXMAP(type,SDL_SCANCODE_KP_DIVIDE,      GHOST_kKeyNumpadSlash);
222
223         /* Media keys in some keyboards and laptops with XFree86/Xorg */
224         GXMAP(type,SDL_SCANCODE_AUDIOPLAY,      GHOST_kKeyMediaPlay);
225         GXMAP(type,SDL_SCANCODE_AUDIOSTOP,      GHOST_kKeyMediaStop);
226         GXMAP(type,SDL_SCANCODE_AUDIOPREV,      GHOST_kKeyMediaFirst);
227         // GXMAP(type,XF86XK_AudioRewind,       GHOST_kKeyMediaFirst);
228         GXMAP(type,SDL_SCANCODE_AUDIONEXT,      GHOST_kKeyMediaLast);
229
230                 default:
231                         type= GHOST_kKeyUnknown;
232                         break;
233                 }
234         }
235
236         return type;
237 }
238 #undef GXMAP
239
240
241 void
242 GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
243 {
244         GHOST_Event * g_event= NULL;
245
246         switch(sdl_event->type) {
247         case SDL_WINDOWEVENT:
248                 {
249                         SDL_WindowEvent &sdl_sub_evt= sdl_event->window;
250                         GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
251                         //assert(window != NULL); // can be NULL on close window.
252
253                         switch (sdl_sub_evt.event) {
254                         case SDL_WINDOWEVENT_EXPOSED:
255                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window);
256                                 break;
257                         case SDL_WINDOWEVENT_RESIZED:
258                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window);
259                                 break;
260                         case SDL_WINDOWEVENT_MOVED:
261                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window);
262                                 break;
263                         case SDL_WINDOWEVENT_FOCUS_GAINED:
264                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window);
265                                 break;
266                         case SDL_WINDOWEVENT_FOCUS_LOST:
267                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window);
268                                 break;
269                         case SDL_WINDOWEVENT_CLOSE:
270                                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
271                                 break;
272                         }
273                 }
274                 break;
275         case SDL_QUIT:
276                 g_event= new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL);
277                 break;
278
279         case SDL_MOUSEMOTION:
280                 {
281                         SDL_MouseMotionEvent &sdl_sub_evt= sdl_event->motion;
282                         SDL_Window *sdl_win= SDL_GetWindowFromID(sdl_sub_evt.windowID);
283                         GHOST_WindowSDL *window= findGhostWindow(sdl_win);
284                         assert(window != NULL);
285
286                         int x_win, y_win;
287                         SDL_GetWindowPosition(sdl_win, &x_win, &y_win);
288
289                         GHOST_TInt32 x_root= sdl_sub_evt.x + x_win;
290                         GHOST_TInt32 y_root= sdl_sub_evt.y + y_win;
291
292 #if 0
293                         if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
294                         {
295                                 GHOST_TInt32 x_new= x_root;
296                                 GHOST_TInt32 y_new= y_root;
297                                 GHOST_TInt32 x_accum, y_accum;
298                                 GHOST_Rect bounds;
299
300                                 /* fallback to window bounds */
301                                 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
302                                         window->getClientBounds(bounds);
303
304                                 /* could also clamp to screen bounds
305                                  * wrap with a window outside the view will fail atm  */
306                                 bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */
307                                 window->getCursorGrabAccum(x_accum, y_accum);
308
309                                 // cant use setCursorPosition because the mouse may have no focus!
310                                 if(x_new != x_root || y_new != y_root) {
311                                         if (1 ) { //xme.time > m_last_warp) {
312                                                 /* when wrapping we don't need to add an event because the
313                                                  * setCursorPosition call will cause a new event after */
314                                                 SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); /* wrap */
315                                                 window->setCursorGrabAccum(x_accum + (x_root - x_new), y_accum + (y_root - y_new));
316                                                 // m_last_warp= lastEventTime(xme.time);
317                                         } else {
318                                                 // setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
319                                                 SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win);
320                                         }
321
322                                         g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_new, y_new);
323                                 }
324                                 else {
325                                         g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root + x_accum, y_root + y_accum);
326                                 }
327                         }
328                         else
329 #endif
330                         {
331                                 g_event= new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root, y_root);
332                         }
333                         break;
334                 }
335         case SDL_MOUSEBUTTONUP:
336         case SDL_MOUSEBUTTONDOWN:
337                 {
338                         SDL_MouseButtonEvent &sdl_sub_evt= sdl_event->button;
339                         GHOST_TButtonMask gbmask= GHOST_kButtonMaskLeft;
340                         GHOST_TEventType type= (sdl_sub_evt.state==SDL_PRESSED) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp;
341
342                         GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
343                         assert(window != NULL);
344
345                         /* process rest of normal mouse buttons */
346                         if(sdl_sub_evt.button == SDL_BUTTON_LEFT)
347                                 gbmask= GHOST_kButtonMaskLeft;
348                         else if(sdl_sub_evt.button == SDL_BUTTON_MIDDLE)
349                                 gbmask= GHOST_kButtonMaskMiddle;
350                         else if(sdl_sub_evt.button == SDL_BUTTON_RIGHT)
351                                 gbmask= GHOST_kButtonMaskRight;
352                         /* these buttons are untested! */
353                         else if(sdl_sub_evt.button == SDL_BUTTON_X1)
354                                 gbmask= GHOST_kButtonMaskButton4;
355                         else if(sdl_sub_evt.button == SDL_BUTTON_X2)
356                                 gbmask= GHOST_kButtonMaskButton5;
357                         else
358                                 break;
359
360                         g_event= new GHOST_EventButton(getMilliSeconds(), type, window, gbmask);
361                         break;
362                 }
363         case SDL_MOUSEWHEEL:
364                 {
365                         SDL_MouseWheelEvent &sdl_sub_evt= sdl_event->wheel;
366                         GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
367                         assert(window != NULL);
368                         g_event= new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
369                 }
370                 break;
371         case SDL_KEYDOWN:
372         case SDL_KEYUP:
373                 {
374                         SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key;
375                         GHOST_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
376
377                         GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID));
378                         assert(window != NULL);
379
380                         GHOST_TKey gkey= convertSDLKey(sdl_sub_evt.keysym.scancode);
381                         /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */
382                         g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sdl_sub_evt.keysym.sym);
383                 }
384                 break;
385         }
386
387         if (g_event) {
388                 pushEvent(g_event);
389         }
390 }
391
392 GHOST_TSuccess
393 GHOST_SystemSDL::getCursorPosition(GHOST_TInt32& x,
394                                    GHOST_TInt32& y) const
395 {
396         int x_win, y_win;
397         SDL_Window *win= SDL_GetMouseFocus();
398         SDL_GetWindowPosition(win, &x_win, &y_win);
399
400         int xi, yi;
401         SDL_GetMouseState(&xi, &yi);
402         x= xi + x_win;
403         y= yi + x_win;
404
405         return GHOST_kSuccess;
406 }
407
408 GHOST_TSuccess
409 GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x,
410                                    GHOST_TInt32 y)
411 {
412         int x_win, y_win;
413         SDL_Window *win= SDL_GetMouseFocus();
414         SDL_GetWindowPosition(win, &x_win, &y_win);
415
416         SDL_WarpMouseInWindow(win, x - x_win, y - y_win);
417         return GHOST_kSuccess;
418 }
419
420 bool
421 GHOST_SystemSDL::generateWindowExposeEvents()
422 {
423         vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin();
424         vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end();
425         bool anyProcessed= false;
426
427         for (;w_start != w_end; ++w_start) {
428                 GHOST_Event * g_event= new
429                         GHOST_Event(
430                                 getMilliSeconds(),
431                                 GHOST_kEventWindowUpdate,
432                                 *w_start
433                         );
434
435                 (*w_start)->validate();
436
437                 if (g_event) {
438                         printf("Expose events pushed\n");
439                         pushEvent(g_event);
440                         anyProcessed= true;
441                 }
442         }
443
444         m_dirty_windows.clear();
445         return anyProcessed;
446 }
447
448
449 bool
450 GHOST_SystemSDL::processEvents(bool waitForEvent)
451 {
452         // Get all the current events -- translate them into
453         // ghost events and call base class pushEvent() method.
454
455         bool anyProcessed= false;
456
457         do {
458                 GHOST_TimerManager* timerMgr= getTimerManager();
459
460                 if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) {
461                         GHOST_TUns64 next= timerMgr->nextFireTime();
462
463                         if (next==GHOST_kFireTimeNever) {
464                                 SDL_WaitEventTimeout(NULL, -1);
465                                 //SleepTillEvent(m_display, -1);
466                         } else {
467                                 GHOST_TInt64 maxSleep= next - getMilliSeconds();
468
469                                 if(maxSleep >= 0) {
470                                         SDL_WaitEventTimeout(NULL, next - getMilliSeconds());
471                                         // SleepTillEvent(m_display, next - getMilliSeconds()); // X11
472                                 }
473                         }
474                 }
475
476                 if (timerMgr->fireTimers(getMilliSeconds())) {
477                         anyProcessed= true;
478                 }
479
480                 SDL_Event sdl_event;
481                 while (SDL_PollEvent(&sdl_event)) {
482                         processEvent(&sdl_event);
483                         anyProcessed= true;
484                 }
485
486                 if (generateWindowExposeEvents()) {
487                         anyProcessed= true;
488                 }
489         } while (waitForEvent && !anyProcessed);
490
491         return anyProcessed;
492 }
493
494
495 GHOST_WindowSDL *
496 GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
497 {
498         if (sdl_win == NULL) return NULL;
499
500         // It is not entirely safe to do this as the backptr may point
501         // to a window that has recently been removed.
502         // We should always check the window manager's list of windows
503         // and only process events on these windows.
504
505         vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows();
506
507         vector<GHOST_IWindow *>::iterator win_it= win_vec.begin();
508         vector<GHOST_IWindow *>::const_iterator win_end= win_vec.end();
509
510         for (; win_it != win_end; ++win_it) {
511                 GHOST_WindowSDL * window= static_cast<GHOST_WindowSDL *>(*win_it);
512                 if (window->getSDLWindow() == sdl_win) {
513                         return window;
514                 }
515         }
516         return NULL;
517 }
518
519
520 void
521 GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind)
522 {
523         GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
524
525         m_dirty_windows.push_back(bad_wind);
526 }
527
528
529 GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const
530 {
531         Uint8 state= SDL_GetMouseState(NULL, NULL);
532         buttons.set(GHOST_kButtonMaskLeft,   (state & SDL_BUTTON_LMASK) != 0);
533         buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0);
534         buttons.set(GHOST_kButtonMaskRight,  (state & SDL_BUTTON_RMASK) != 0);
535
536         return GHOST_kSuccess;
537 }
538
539 GHOST_TUns8 *
540 GHOST_SystemSDL::getClipboard(bool selection) const
541 {
542         return (GHOST_TUns8 *)SDL_GetClipboardText();
543 }
544
545 void
546 GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const
547 {
548         SDL_SetClipboardText(buffer);
549 }
550
551 GHOST_TUns64
552 GHOST_SystemSDL::getMilliSeconds()
553 {
554         return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */
555 }