Blender  V2.59
GHOST_WindowSDL.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: GHOST_WindowSDL.cpp 38349 2011-07-13 00:49:22Z gsrb3d $
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 "GHOST_WindowSDL.h"
00029 #include "SDL_mouse.h"
00030 #include <assert.h>
00031 
00032 static SDL_GLContext s_firstContext= NULL;
00033 
00034 GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
00035                                  const STR_String& title,
00036                                  GHOST_TInt32 left,
00037                                  GHOST_TInt32 top,
00038                                  GHOST_TUns32 width,
00039                                  GHOST_TUns32 height,
00040                                  GHOST_TWindowState state,
00041                                  const GHOST_TEmbedderWindowID parentWindow,
00042                                  GHOST_TDrawingContextType type,
00043                                  const bool stereoVisual,
00044                                  const GHOST_TUns16 numOfAASamples
00045                                  )
00046     :
00047       GHOST_Window(width,height,state,type,stereoVisual,numOfAASamples),
00048       m_system (system),
00049       m_invalid_window(false),
00050       m_sdl_custom_cursor(NULL)
00051 {
00052         m_sdl_win= SDL_CreateWindow(title,
00053                                     left,
00054                                     top,
00055                                     width,
00056                                     height,
00057                                     SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
00058 
00059         //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
00060         //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
00061         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00062         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
00063         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
00064         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
00065         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
00066         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
00067 
00068         m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win);
00069 
00070         //fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
00071         //      theEvent->error_code, theEvent->request_code) ;
00072 
00073         setTitle(title);
00074 }
00075 
00076 GHOST_WindowSDL::~GHOST_WindowSDL()
00077 {
00078         if(m_sdl_custom_cursor) {
00079                 SDL_FreeCursor(m_sdl_custom_cursor);
00080         }
00081 
00082         if (m_sdl_glcontext != s_firstContext) {
00083                 SDL_GL_DeleteContext(m_sdl_glcontext);
00084         }
00085 
00086         SDL_DestroyWindow(m_sdl_win);
00087 }
00088 
00089 
00090 GHOST_TSuccess
00091 GHOST_WindowSDL::installDrawingContext(GHOST_TDrawingContextType type)
00092 {
00093         // only support openGL for now.
00094         GHOST_TSuccess success;
00095         switch (type) {
00096         case GHOST_kDrawingContextTypeOpenGL:
00097                 m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win);
00098 
00099                 if (m_sdl_glcontext != NULL) {
00100                         if (!s_firstContext) {
00101                                 s_firstContext= m_sdl_glcontext;
00102                         }
00103 
00104                         success= (SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext) < 0) ?
00105                                     GHOST_kFailure : GHOST_kSuccess;
00106                 }
00107                 else {
00108                         success= GHOST_kFailure;
00109                 }
00110 
00111                 break;
00112 
00113         case GHOST_kDrawingContextTypeNone:
00114                 success= GHOST_kSuccess;
00115                 break;
00116 
00117         default:
00118                 success= GHOST_kFailure;
00119         }
00120         return success;
00121 }
00122 
00123 
00124 GHOST_TSuccess
00125 GHOST_WindowSDL::invalidate(void)
00126 {
00127         // So the idea of this function is to generate an expose event
00128         // for the window.
00129         // Unfortunately X does not handle expose events for you and
00130         // it is the client's job to refresh the dirty part of the window.
00131         // We need to queue up invalidate calls and generate GHOST events
00132         // for them in the system.
00133 
00134         // We implement this by setting a boolean in this class to concatenate
00135         // all such calls into a single event for this window.
00136 
00137         // At the same time we queue the dirty windows in the system class
00138         // and generate events for them at the next processEvents call.
00139 
00140         if (m_invalid_window == false) {
00141                 m_system->addDirtyWindow(this);
00142                 m_invalid_window= true;
00143         }
00144 
00145         return GHOST_kSuccess;
00146 }
00147 
00148 
00149 GHOST_TSuccess
00150 GHOST_WindowSDL::swapBuffers()
00151 {
00152         if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
00153                 SDL_GL_SwapWindow(m_sdl_win);
00154                 return GHOST_kSuccess;
00155         }
00156         else {
00157                 return GHOST_kFailure;
00158         }
00159 }
00160 
00161 
00162 GHOST_TSuccess
00163 GHOST_WindowSDL::activateDrawingContext()
00164 {
00165         if (m_sdl_glcontext !=NULL) {
00166                 int status=SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext);
00167                 (void)status;
00168                 return GHOST_kSuccess;
00169         }
00170         return GHOST_kFailure;
00171 }
00172 
00173 
00174 GHOST_TSuccess
00175 GHOST_WindowSDL::removeDrawingContext()
00176 {
00177         GHOST_TSuccess success;
00178 
00179         if (m_sdl_glcontext != NULL) {
00180                 SDL_GL_DeleteContext(m_sdl_glcontext);
00181                 success= GHOST_kSuccess;
00182         }
00183         else {
00184                 success= GHOST_kFailure;
00185         }
00186         return success;
00187 }
00188 
00189 
00190 GHOST_TSuccess
00191 GHOST_WindowSDL::setState(GHOST_TWindowState state)
00192 {
00193         switch(state) {
00194         case GHOST_kWindowStateNormal:
00195                 SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
00196                 SDL_RestoreWindow(m_sdl_win);
00197                 break;
00198         case GHOST_kWindowStateMaximized:
00199                 SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
00200                 SDL_MaximizeWindow(m_sdl_win);
00201                 break;
00202         case GHOST_kWindowStateMinimized:
00203                 SDL_MinimizeWindow(m_sdl_win);
00204                 break;
00205         case GHOST_kWindowStateFullScreen:
00206                 SDL_SetWindowFullscreen(m_sdl_win, SDL_TRUE);
00207                 break;
00208         default:
00209                 break;
00210         }
00211 
00212         return GHOST_kSuccess;
00213 }
00214 
00215 
00216 GHOST_TWindowState
00217 GHOST_WindowSDL::getState() const
00218 {
00219         Uint32 flags= SDL_GetWindowFlags(m_sdl_win);
00220 
00221         if(flags & SDL_WINDOW_FULLSCREEN)      return GHOST_kWindowStateFullScreen;
00222         else if(flags & SDL_WINDOW_MAXIMIZED)  return GHOST_kWindowStateMaximized;
00223         else if(flags & SDL_WINDOW_MINIMIZED)  return GHOST_kWindowStateMinimized;
00224         return GHOST_kWindowStateNormal;
00225 }
00226 
00227 
00228 void
00229 GHOST_WindowSDL::setTitle(const STR_String& title)
00230 {
00231         SDL_SetWindowTitle(m_sdl_win, title.ReadPtr());
00232 }
00233 
00234 
00235 void
00236 GHOST_WindowSDL::getTitle(STR_String& title) const
00237 {
00238         title= SDL_GetWindowTitle(m_sdl_win);
00239 }
00240 
00241 
00242 void
00243 GHOST_WindowSDL::getWindowBounds(GHOST_Rect& bounds) const
00244 {
00245         getClientBounds(bounds);
00246 }
00247 
00248 
00249 void
00250 GHOST_WindowSDL::getClientBounds(GHOST_Rect& bounds) const
00251 {
00252         int x, y, w, h;
00253         SDL_GetWindowSize(m_sdl_win, &w, &h);
00254         SDL_GetWindowPosition(m_sdl_win, &x, &y);
00255 
00256         bounds.m_l= x;
00257         bounds.m_r= x + w;
00258         bounds.m_t= y;
00259         bounds.m_b= y + h;
00260 }
00261 
00262 GHOST_TSuccess
00263 GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width)
00264 {
00265         int height;
00266         SDL_GetWindowSize(m_sdl_win, NULL, &height);
00267         SDL_SetWindowSize(m_sdl_win, width, height);
00268         return GHOST_kSuccess;
00269 }
00270 
00271 GHOST_TSuccess
00272 GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height)
00273 {
00274         int width;
00275         SDL_GetWindowSize(m_sdl_win, &width, NULL);
00276         SDL_SetWindowSize(m_sdl_win, width, height);
00277         return GHOST_kSuccess;
00278 }
00279 
00280 GHOST_TSuccess
00281 GHOST_WindowSDL::setClientSize(GHOST_TUns32 width,
00282                                               GHOST_TUns32 height)
00283 {
00284         SDL_SetWindowSize(m_sdl_win, width, height);
00285         return GHOST_kSuccess;
00286 }
00287 
00288 void
00289 GHOST_WindowSDL::screenToClient( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const
00290 {
00291         /* XXXSDL_WEAK_ABS_COORDS */
00292         int x_win, y_win;
00293         SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
00294 
00295         outX = inX - x_win;
00296         outY = inY - y_win;
00297 }
00298 void
00299 GHOST_WindowSDL::clientToScreen( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const
00300 {
00301         /* XXXSDL_WEAK_ABS_COORDS */
00302         int x_win, y_win;
00303         SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
00304 
00305         outX = inX + x_win;
00306         outY = inY + y_win;
00307 }
00308 
00309 /* mouse cursor */
00310 static unsigned char sdl_std_cursor_mask_xterm[]= {0xef,0x01,0xff,0x01,0xff,0x01,0x7c,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x7c,0x00,0xff,0x01,0xff,0x01,0xef,0x01,};
00311 static unsigned char sdl_std_cursor_xterm[]= {0x00,0x77,0x00,0x1c,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x1c,0x00,0x77,0x00,0x00,0x00,0x00,};
00312 #define sdl_std_cursor_WIDTH_xterm  9
00313 #define sdl_std_cursor_HEIGHT_xterm 16
00314 #define sdl_std_cursor_HOT_X_xterm  -3
00315 #define sdl_std_cursor_HOT_Y_xterm  -7
00316 
00317 static unsigned char sdl_std_cursor_mask_watch[]= {0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,0xfe,0x1f,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfe,0x1f,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,};
00318 static unsigned char sdl_std_cursor_watch[]= {0xf8,0x07,0xf8,0x07,0xf8,0x07,0xfc,0x0f,0x86,0x18,0x83,0x30,0x81,0xe0,0xc1,0xe1,0xc1,0xe1,0x21,0xe0,0x13,0x30,0x06,0x18,0xfc,0x0f,0xf8,0x07,0xf8,0x07,0xf8,0x07,};
00319 #define sdl_std_cursor_WIDTH_watch  16
00320 #define sdl_std_cursor_HEIGHT_watch 16
00321 #define sdl_std_cursor_HOT_X_watch  -15
00322 #define sdl_std_cursor_HOT_Y_watch  -7
00323 
00324 static unsigned char sdl_std_cursor_mask_umbrella[]= {0xe8,0x76,0xfb,0xdf,0xfd,0x3f,0xfe,0xff,0xff,0x3f,0xff,0xff,0xcf,0x79,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x07,0xc0,0x07,0xc0,0x07,0xc0,0x07,0x80,0x03,};
00325 static unsigned char sdl_std_cursor_umbrella[]= {0x88,0x04,0x20,0x0a,0xc9,0x32,0xf2,0x09,0x4c,0x06,0x43,0x18,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x40,0x01,0x80,0x00,0x00,0x00,0x00,0x00,};
00326 #define sdl_std_cursor_WIDTH_umbrella  16
00327 #define sdl_std_cursor_HEIGHT_umbrella 16
00328 #define sdl_std_cursor_HOT_X_umbrella  -7
00329 #define sdl_std_cursor_HOT_Y_umbrella  -12
00330 
00331 static unsigned char sdl_std_cursor_mask_top_side[]= {0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xc0,0x01,0xe0,0x03,0xf0,0x07,0xf8,0x0f,0xdc,0x1d,0xcc,0x19,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,};
00332 static unsigned char sdl_std_cursor_top_side[]= {0xff,0x1f,0xff,0x1f,0x00,0x00,0x40,0x00,0xe0,0x00,0x50,0x01,0x48,0x02,0x44,0x04,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,};
00333 #define sdl_std_cursor_WIDTH_top_side  15
00334 #define sdl_std_cursor_HEIGHT_top_side 16
00335 #define sdl_std_cursor_HOT_X_top_side  -6
00336 #define sdl_std_cursor_HOT_Y_top_side  -14
00337 
00338 static unsigned char sdl_std_cursor_mask_top_right_corner[]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf0,0xfc,0xf7,0xfc,0xf7,0xfc,0xf7,0xc0,0xf7,0xe0,0xf7,0x70,0xf7,0x38,0xf7,0x1c,0xf7,0x0c,0xf7,0x00,0xf0,0x00,0xf0,};
00339 static unsigned char sdl_std_cursor_top_right_corner[]= {0xff,0x3f,0xff,0x3f,0x00,0x30,0x00,0x30,0x00,0x30,0xfc,0x31,0x80,0x31,0x40,0x31,0x20,0x31,0x10,0x31,0x08,0x31,0x04,0x31,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,};
00340 #define sdl_std_cursor_WIDTH_top_right_corner  16
00341 #define sdl_std_cursor_HEIGHT_top_right_corner 16
00342 #define sdl_std_cursor_HOT_X_top_right_corner  -13
00343 #define sdl_std_cursor_HOT_Y_top_right_corner  -14
00344 
00345 static unsigned char sdl_std_cursor_mask_top_left_corner[]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0xef,0x3f,0xef,0x3f,0xef,0x3f,0xef,0x03,0xef,0x07,0xef,0x0e,0xef,0x1c,0xef,0x38,0xef,0x30,0x0f,0x00,0x0f,0x00,};
00346 static unsigned char sdl_std_cursor_top_left_corner[]= {0xff,0x3f,0xff,0x3f,0x03,0x00,0x03,0x00,0x03,0x00,0xe3,0x0f,0x63,0x00,0xa3,0x00,0x23,0x01,0x23,0x02,0x23,0x04,0x23,0x08,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,};
00347 #define sdl_std_cursor_WIDTH_top_left_corner  16
00348 #define sdl_std_cursor_HEIGHT_top_left_corner 16
00349 #define sdl_std_cursor_HOT_X_top_left_corner  0
00350 #define sdl_std_cursor_HOT_Y_top_left_corner  -14
00351 
00352 static unsigned char sdl_std_cursor_mask_spraycan[]= {0x00,0x0c,0x18,0x0d,0x7c,0x0d,0x7c,0x0d,0x7e,0x0d,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,};
00353 static unsigned char sdl_std_cursor_spraycan[]= {0x00,0x06,0x80,0x00,0x2c,0x06,0x9e,0x00,0x16,0x06,0x3f,0x00,0x21,0x00,0x27,0x00,0x25,0x00,0x27,0x00,0x25,0x00,0x27,0x00,0x27,0x00,0x21,0x00,0x21,0x00,0x3f,0x00,};
00354 #define sdl_std_cursor_WIDTH_spraycan  12
00355 #define sdl_std_cursor_HEIGHT_spraycan 16
00356 #define sdl_std_cursor_HOT_X_spraycan  -9
00357 #define sdl_std_cursor_HOT_Y_spraycan  -14
00358 
00359 static unsigned char sdl_std_cursor_mask_sb_v_double_arrow[]= {0x38,0x00,0x7c,0x00,0xfe,0x00,0xff,0x01,0xff,0x01,0x7c,0x00,0x7c,0x00,0x7c,0x00,0x7c,0x00,0x7c,0x00,0xff,0x01,0xff,0x01,0xfe,0x00,0x7c,0x00,0x38,0x00,};
00360 static unsigned char sdl_std_cursor_sb_v_double_arrow[]= {0x10,0x00,0x38,0x00,0x7c,0x00,0xfe,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0xfe,0x00,0x7c,0x00,0x38,0x00,0x10,0x00,};
00361 #define sdl_std_cursor_WIDTH_sb_v_double_arrow  9
00362 #define sdl_std_cursor_HEIGHT_sb_v_double_arrow 15
00363 #define sdl_std_cursor_HOT_X_sb_v_double_arrow  -3
00364 #define sdl_std_cursor_HOT_Y_sb_v_double_arrow  -8
00365 
00366 static unsigned char sdl_std_cursor_mask_sb_h_double_arrow[]= {0x18,0x0c,0x1c,0x1c,0xfe,0x3f,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xfe,0x3f,0x1c,0x1c,0x18,0x0c,};
00367 static unsigned char sdl_std_cursor_sb_h_double_arrow[]= {0x00,0x00,0x08,0x08,0x0c,0x18,0xfe,0x3f,0x0f,0x78,0xfe,0x3f,0x0c,0x18,0x08,0x08,0x00,0x00};
00368 #define sdl_std_cursor_WIDTH_sb_h_double_arrow  15
00369 #define sdl_std_cursor_HEIGHT_sb_h_double_arrow 9
00370 #define sdl_std_cursor_HOT_X_sb_h_double_arrow  -7
00371 #define sdl_std_cursor_HOT_Y_sb_h_double_arrow  -4
00372 
00373 static unsigned char sdl_std_cursor_mask_right_side[]= {0x00,0xf0,0x00,0xf0,0xc0,0xf0,0xc0,0xf1,0x80,0xf3,0x00,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf7,0x80,0xf3,0xc0,0xf1,0xc0,0xf0,0x00,0xf0,0x00,0xf0,};
00374 static unsigned char sdl_std_cursor_right_side[]= {0x00,0x30,0x00,0x30,0x40,0x30,0x80,0x30,0x00,0x31,0x00,0x32,0xff,0x37,0x00,0x32,0x00,0x31,0x80,0x30,0x40,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,};
00375 #define sdl_std_cursor_WIDTH_right_side  16
00376 #define sdl_std_cursor_HEIGHT_right_side 15
00377 #define sdl_std_cursor_HOT_X_right_side  -13
00378 #define sdl_std_cursor_HOT_Y_right_side  -7
00379 
00380 static unsigned char sdl_std_cursor_mask_right_ptr[]= {0x00,0x03,0x80,0x03,0xc0,0x03,0xe0,0x03,0xf0,0x03,0xf8,0x03,0xfc,0x03,0xfe,0x03,0xff,0x03,0xff,0x03,0xf8,0x03,0xbc,0x03,0x3c,0x03,0x1e,0x00,0x1e,0x00,0x0c,0x00,};
00381 static unsigned char sdl_std_cursor_right_ptr[]= {0x00,0x80,0x00,0xc0,0x00,0xe0,0x00,0xf0,0x00,0xf8,0x00,0xfc,0x00,0xfe,0x00,0xff,0x00,0xf8,0x00,0xd8,0x00,0x8c,0x00,0x0c,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,};
00382 #define sdl_std_cursor_WIDTH_right_ptr  10
00383 #define sdl_std_cursor_HEIGHT_right_ptr 16
00384 #define sdl_std_cursor_HOT_X_right_ptr  -7
00385 #define sdl_std_cursor_HOT_Y_right_ptr  -14
00386 
00387 static unsigned char sdl_std_cursor_mask_question_arrow[]= {0xf8,0x00,0xfc,0x01,0xfe,0x03,0xff,0x07,0x8f,0x07,0x9f,0x07,0xde,0x07,0xfc,0x03,0xf8,0x01,0xf8,0x00,0xf8,0x00,0xfc,0x01,0xfe,0x03,0xfc,0x01,0xf8,0x00,0x70,0x00,};
00388 static unsigned char sdl_std_cursor_question_arrow[]= {0x7c,0x00,0xfe,0x00,0xc7,0x01,0x83,0x01,0x87,0x01,0xc6,0x01,0xe0,0x00,0x78,0x00,0x38,0x00,0x28,0x00,0x28,0x00,0xee,0x00,0x6c,0x00,0x38,0x00,0x10,0x00,0x00,0x00,};
00389 #define sdl_std_cursor_WIDTH_question_arrow  11
00390 #define sdl_std_cursor_HEIGHT_question_arrow 16
00391 #define sdl_std_cursor_HOT_X_question_arrow  -4
00392 #define sdl_std_cursor_HOT_Y_question_arrow  -8
00393 
00394 static unsigned char sdl_std_cursor_mask_pirate[]= {0xf0,0x03,0xf8,0x07,0xfc,0x0f,0xfe,0x1f,0xfe,0x1f,0xfc,0x0f,0xf8,0x07,0xf1,0x83,0xf1,0xe3,0xf3,0xf3,0xef,0x39,0x1e,0x1e,0xe0,0x01,0xfe,0xc7,0xff,0xff,0x0f,0x7c,};
00395 static unsigned char sdl_std_cursor_pirate[]= {0xe0,0x01,0xf0,0x03,0xf8,0x07,0xcc,0x0c,0xcc,0x0c,0xf8,0x07,0xf0,0x03,0xe0,0x01,0xe1,0x21,0xe1,0x61,0xc2,0x10,0x1c,0x0e,0xe0,0x01,0xf8,0x47,0x0f,0x7c,0x01,0x20,};
00396 #define sdl_std_cursor_WIDTH_pirate  16
00397 #define sdl_std_cursor_HEIGHT_pirate 16
00398 #define sdl_std_cursor_HOT_X_pirate  -7
00399 #define sdl_std_cursor_HOT_Y_pirate  -4
00400 
00401 static unsigned char sdl_std_cursor_mask_left_side[]= {0x0f,0x00,0x0f,0x00,0x0f,0x03,0x8f,0x03,0xcf,0x01,0xef,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x00,0xcf,0x01,0x8f,0x03,0x0f,0x03,0x0f,0x00,0x0f,0x00,};
00402 static unsigned char sdl_std_cursor_left_side[]= {0x03,0x00,0x03,0x00,0x83,0x00,0x43,0x00,0x23,0x00,0x13,0x00,0xfb,0x3f,0x13,0x00,0x23,0x00,0x43,0x00,0x83,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,};
00403 #define sdl_std_cursor_WIDTH_left_side  16
00404 #define sdl_std_cursor_HEIGHT_left_side 15
00405 #define sdl_std_cursor_HOT_X_left_side  0
00406 #define sdl_std_cursor_HOT_Y_left_side  -7
00407 
00408 static unsigned char sdl_std_cursor_mask_left_ptr[]= {0x03,0x00,0x07,0x00,0x0f,0x00,0x1f,0x00,0x3f,0x00,0x7f,0x00,0xff,0x00,0xff,0x01,0xff,0x03,0xff,0x03,0x7f,0x00,0xf7,0x00,0xf3,0x00,0xe0,0x01,0xe0,0x01,0xc0,0x00,};
00409 static unsigned char sdl_std_cursor_left_ptr[]= {0x00,0x00,0x02,0x00,0x06,0x00,0x0e,0x00,0x1e,0x00,0x3e,0x00,0x7e,0x00,0xfe,0x00,0xfe,0x00,0x3e,0x00,0x36,0x00,0x62,0x00,0x60,0x00,0xc0,0x00,0xc0,0x00,0x00,0x00,};
00410 #define sdl_std_cursor_WIDTH_left_ptr  10
00411 #define sdl_std_cursor_HEIGHT_left_ptr 16
00412 #define sdl_std_cursor_HOT_X_left_ptr  -8
00413 #define sdl_std_cursor_HOT_Y_left_ptr  -14
00414 
00415 static unsigned char sdl_std_cursor_mask_exchange[]= {0xe3,0x07,0xf7,0x0f,0xff,0x1f,0xff,0x3f,0x3f,0x38,0xff,0x30,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x0c,0xfe,0x1c,0xfc,0xfc,0xff,0xf8,0xff,0xf0,0xef,0xe0,0xc7,};
00416 static unsigned char sdl_std_cursor_exchange[]= {0xf1,0x03,0xfb,0x07,0x1f,0x0c,0x09,0x08,0x19,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x26,0x04,0x24,0x0c,0x3e,0xf8,0x37,0xf0,0x23,0x00,0x00,0x00,0x00,};
00417 #define sdl_std_cursor_WIDTH_exchange  16
00418 #define sdl_std_cursor_HEIGHT_exchange 16
00419 #define sdl_std_cursor_HOT_X_exchange  -6
00420 #define sdl_std_cursor_HOT_Y_exchange  -8
00421 
00422 static unsigned char sdl_std_cursor_mask_crosshair[]= {0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,};
00423 static unsigned char sdl_std_cursor_crosshair[]= {0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x7f,0xff,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,};
00424 #define sdl_std_cursor_WIDTH_crosshair  16
00425 #define sdl_std_cursor_HEIGHT_crosshair 16
00426 #define sdl_std_cursor_HOT_X_crosshair  -7
00427 #define sdl_std_cursor_HOT_Y_crosshair  -8
00428 
00429 static unsigned char sdl_std_cursor_mask_bottom_side[]= {0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xc0,0x01,0xcc,0x19,0xdc,0x1d,0xf8,0x0f,0xf0,0x07,0xe0,0x03,0xc0,0x01,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f,};
00430 static unsigned char sdl_std_cursor_bottom_side[]= {0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x44,0x04,0x48,0x02,0x50,0x01,0xe0,0x00,0x40,0x00,0x00,0x00,0xff,0x1f,0xff,0x1f,0x00,0x00,0x00,0x00,};
00431 #define sdl_std_cursor_WIDTH_bottom_side  15
00432 #define sdl_std_cursor_HEIGHT_bottom_side 16
00433 #define sdl_std_cursor_HOT_X_bottom_side  -6
00434 #define sdl_std_cursor_HOT_Y_bottom_side  -1
00435 
00436 static unsigned char sdl_std_cursor_mask_bottom_right_corner[]= {0x00,0xf0,0x00,0xf0,0x0c,0xf7,0x1c,0xf7,0x38,0xf7,0x70,0xf7,0xe0,0xf7,0xc0,0xf7,0xfc,0xf7,0xfc,0xf7,0xfc,0xf7,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,};
00437 static unsigned char sdl_std_cursor_bottom_right_corner[]= {0x00,0x30,0x00,0x30,0x04,0x31,0x08,0x31,0x10,0x31,0x20,0x31,0x40,0x31,0x80,0x31,0xfc,0x31,0x00,0x30,0x00,0x30,0x00,0x30,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,};
00438 #define sdl_std_cursor_WIDTH_bottom_right_corner  16
00439 #define sdl_std_cursor_HEIGHT_bottom_right_corner 16
00440 #define sdl_std_cursor_HOT_X_bottom_right_corner  -13
00441 #define sdl_std_cursor_HOT_Y_bottom_right_corner  -1
00442 
00443 static unsigned char sdl_std_cursor_mask_bottom_left_corner[]= {0x0f,0x00,0x0f,0x00,0xef,0x30,0xef,0x38,0xef,0x1c,0xef,0x0e,0xef,0x07,0xef,0x03,0xef,0x3f,0xef,0x3f,0xef,0x3f,0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,};
00444 static unsigned char sdl_std_cursor_bottom_left_corner[]= {0x03,0x00,0x03,0x00,0x23,0x08,0x23,0x04,0x23,0x02,0x23,0x01,0xa3,0x00,0x63,0x00,0xe3,0x0f,0x03,0x00,0x03,0x00,0x03,0x00,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,};
00445 #define sdl_std_cursor_WIDTH_bottom_left_corner  16
00446 #define sdl_std_cursor_HEIGHT_bottom_left_corner 16
00447 #define sdl_std_cursor_HOT_X_bottom_left_corner  0
00448 #define sdl_std_cursor_HOT_Y_bottom_left_corner  -1
00449 
00450 static unsigned char sdl_std_cursor_mask_arrow[]= {0x00,0xe0,0x00,0xf8,0x00,0xfe,0x80,0x7f,0xe0,0x7f,0xf8,0x3f,0xfc,0x3f,0xfc,0x1f,0xe0,0x1f,0xf0,0x0f,0xf8,0x0f,0x7c,0x07,0x3e,0x07,0x1f,0x02,0x0e,0x00,0x04,0x00,};
00451 static unsigned char sdl_std_cursor_arrow[]= {0x00,0x30,0x00,0x3c,0x00,0x1f,0xc0,0x1f,0xf0,0x0f,0xfc,0x0f,0xc0,0x07,0xe0,0x07,0x70,0x03,0x38,0x03,0x1c,0x01,0x0e,0x01,0x07,0x00,0x02,0x00,0x00,0x00,0x00,0x00,};
00452 #define sdl_std_cursor_WIDTH_arrow  16
00453 #define sdl_std_cursor_HEIGHT_arrow 16
00454 #define sdl_std_cursor_HOT_X_arrow  -13
00455 #define sdl_std_cursor_HOT_Y_arrow  -14
00456 /* end cursor data */
00457 
00458 
00459 static SDL_Cursor *sdl_std_cursor_array[(int)GHOST_kStandardCursorNumCursors]= {0};
00460 
00461 /* utility function mostly a copy of SDL_CreateCursor but allows us to change
00462  * color and supports blenders flipped bits */
00463 static SDL_Cursor *
00464 sdl_ghost_CreateCursor(const Uint8 *data,
00465                        const Uint8 *mask,
00466                        int w,
00467                        int h,
00468                        int hot_x,
00469                        int hot_y)
00470 {
00471     SDL_Surface *surface;
00472     SDL_Cursor *cursor;
00473     int x, y;
00474     Uint32 *pixel;
00475     Uint8 datab= 0, maskb= 0;
00476     const Uint32 black= 0xFF000000;
00477     const Uint32 white= 0xFFFFFFFF;
00478     const Uint32 transparent= 0x00000000;
00479 
00480     /* Make sure the width is a multiple of 8 */
00481     w= ((w + 7) & ~7);
00482 
00483     /* Create the surface from a bitmap */
00484         surface= SDL_CreateRGBSurface(0, w, h, 32,
00485                                       0x00FF0000,
00486                                       0x0000FF00,
00487                                       0x000000FF,
00488                                       0xFF000000);
00489     if (!surface) {
00490         return NULL;
00491     }
00492     for (y= 0; y < h; ++y) {
00493         pixel= (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
00494         for (x= 0; x < w; ++x) {
00495             if ((x % 8) == 0) {
00496                 datab= *data++;
00497                 maskb= *mask++;
00498 
00499                                 /* reverse bit order */
00500                                 datab= (datab * 0x0202020202ULL & 0x010884422010ULL) % 1023;
00501                                 maskb= (maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023;
00502             }
00503             if (maskb & 0x80) {
00504                 *pixel++= (datab & 0x80) ?  white : black;
00505             }
00506                         else {
00507                 *pixel++= (datab & 0x80) ? white : transparent;
00508             }
00509             datab <<= 1;
00510             maskb <<= 1;
00511         }
00512     }
00513 
00514     cursor= SDL_CreateColorCursor(surface, hot_x, hot_y);
00515 
00516     SDL_FreeSurface(surface);
00517 
00518     return cursor;
00519 }
00520 
00521 /* TODO, this is currently never freed but it wont leak either. */
00522 static void sdl_cursor_init(void)
00523 {
00524 
00525 #define DEF_CURSOR(name, ind) \
00526         assert(\
00527                 (\
00528                 sdl_std_cursor_array[(int)ind]= \
00529                                 sdl_ghost_CreateCursor(sdl_std_cursor_##name, \
00530                                 sdl_std_cursor_mask_##name, \
00531                                 sdl_std_cursor_WIDTH_##name, \
00532                                 sdl_std_cursor_HEIGHT_##name, \
00533                                 (sdl_std_cursor_WIDTH_##name + (sdl_std_cursor_HOT_X_##name)) - 1, \
00534                                 (sdl_std_cursor_HEIGHT_##name + (sdl_std_cursor_HOT_Y_##name)) - 1) \
00535                 ) != NULL) \
00536 
00537 
00538         DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault);
00539         DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow);
00540         DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow);
00541         DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); // TODO, replace this one.
00542         DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy);
00543         DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp);
00544         DEF_CURSOR(exchange, GHOST_kStandardCursorCycle);
00545         DEF_CURSOR(spraycan, GHOST_kStandardCursorSpray);
00546         DEF_CURSOR(watch, GHOST_kStandardCursorWait);
00547         DEF_CURSOR(xterm, GHOST_kStandardCursorText);
00548         DEF_CURSOR(crosshair, GHOST_kStandardCursorCrosshair);
00549         DEF_CURSOR(sb_v_double_arrow, GHOST_kStandardCursorUpDown);
00550         DEF_CURSOR(sb_h_double_arrow, GHOST_kStandardCursorLeftRight);
00551         DEF_CURSOR(top_side, GHOST_kStandardCursorTopSide);
00552         DEF_CURSOR(bottom_side, GHOST_kStandardCursorBottomSide);
00553         DEF_CURSOR(left_side, GHOST_kStandardCursorLeftSide);
00554         DEF_CURSOR(right_side, GHOST_kStandardCursorRightSide);
00555         DEF_CURSOR(top_left_corner, GHOST_kStandardCursorTopLeftCorner);
00556         DEF_CURSOR(top_right_corner, GHOST_kStandardCursorTopRightCorner);
00557         DEF_CURSOR(bottom_right_corner, GHOST_kStandardCursorBottomRightCorner);
00558         DEF_CURSOR(bottom_left_corner , GHOST_kStandardCursorBottomLeftCorner);
00559         DEF_CURSOR(arrow , GHOST_kStandardCursorCopy);
00560         //DEF_CURSOR(arrow, GHOST_kStandardCursorCustom);
00561         DEF_CURSOR(arrow, GHOST_kStandardCursorPencil);
00562 
00563 #undef DEF_CURSOR
00564 
00565 }
00566 
00567 
00568 
00569 GHOST_TSuccess
00570 GHOST_WindowSDL::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
00571 {
00572         return GHOST_kSuccess;
00573 }
00574 
00575 
00576 GHOST_TSuccess
00577 GHOST_WindowSDL::setWindowCursorShape(GHOST_TStandardCursor shape)
00578 {
00579         if(sdl_std_cursor_array[0] == NULL) {
00580                 sdl_cursor_init();
00581         }
00582 
00583         SDL_SetCursor(sdl_std_cursor_array[(int)shape]);
00584         return GHOST_kSuccess;
00585 }
00586 
00587 
00588 GHOST_TSuccess
00589 GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
00590                                             GHOST_TUns8 mask[16][2],
00591                                             int hotX,
00592                                             int hotY)
00593 {
00594         return setWindowCustomCursorShape((GHOST_TUns8 *)bitmap,
00595                                           (GHOST_TUns8 *)mask,
00596                                           16, 16,
00597                                           hotX, hotY,
00598                                           0, 1);
00599 }
00600 
00601 
00602 GHOST_TSuccess
00603 GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
00604                                             GHOST_TUns8 *mask,
00605                                             int sizex, int sizey,
00606                                             int hotX, int hotY,
00607                                             int fg_color, int bg_color)
00608 {
00609         if(m_sdl_custom_cursor) {
00610                 SDL_FreeCursor(m_sdl_custom_cursor);
00611         }
00612 
00613         m_sdl_custom_cursor= sdl_ghost_CreateCursor((const Uint8 *)bitmap,
00614                                                     (const Uint8 *)mask,
00615                                                     sizex, sizex,
00616                                                     hotX, hotY);
00617 
00618         SDL_SetCursor(m_sdl_custom_cursor);
00619         return GHOST_kSuccess;
00620 }
00621 
00622 
00623 GHOST_TSuccess
00624 GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
00625 {
00626         SDL_ShowCursor(visible);
00627         return GHOST_kSuccess;
00628 }