svn merge -r38300:38400 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / intern / ghost / intern / GHOST_WindowSDL.cpp
1 /*
2  * $Id: GHOST_WindowSDL.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_WindowSDL.cpp
25  *  \ingroup GHOST
26  */
27
28 #include "GHOST_WindowSDL.h"
29 #include "SDL_mouse.h"
30 #include <assert.h>
31
32 static SDL_GLContext s_firstContext= NULL;
33
34 GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
35                                  const STR_String& title,
36                                  GHOST_TInt32 left,
37                                  GHOST_TInt32 top,
38                                  GHOST_TUns32 width,
39                                  GHOST_TUns32 height,
40                                  GHOST_TWindowState state,
41                                  const GHOST_TEmbedderWindowID parentWindow,
42                                  GHOST_TDrawingContextType type,
43                                  const bool stereoVisual,
44                                  const GHOST_TUns16 numOfAASamples
45                                  )
46     :
47       GHOST_Window(width,height,state,type,stereoVisual,numOfAASamples),
48       m_system (system),
49       m_invalid_window(false),
50       m_sdl_custom_cursor(NULL)
51 {
52         m_sdl_win= SDL_CreateWindow(title,
53                                     left,
54                                     top,
55                                     width,
56                                     height,
57                                     SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
58
59         //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
60         //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
61         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
62         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
63         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
64         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
65         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
66         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
67
68         m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win);
69
70         //fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
71         //      theEvent->error_code, theEvent->request_code) ;
72
73         setTitle(title);
74 }
75
76 GHOST_WindowSDL::~GHOST_WindowSDL()
77 {
78         if(m_sdl_custom_cursor) {
79                 SDL_FreeCursor(m_sdl_custom_cursor);
80         }
81
82         if (m_sdl_glcontext != s_firstContext) {
83                 SDL_GL_DeleteContext(m_sdl_glcontext);
84         }
85
86         SDL_DestroyWindow(m_sdl_win);
87 }
88
89
90 GHOST_TSuccess
91 GHOST_WindowSDL::installDrawingContext(GHOST_TDrawingContextType type)
92 {
93         // only support openGL for now.
94         GHOST_TSuccess success;
95         switch (type) {
96         case GHOST_kDrawingContextTypeOpenGL:
97                 m_sdl_glcontext= SDL_GL_CreateContext(m_sdl_win);
98
99                 if (m_sdl_glcontext != NULL) {
100                         if (!s_firstContext) {
101                                 s_firstContext= m_sdl_glcontext;
102                         }
103
104                         success= (SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext) < 0) ?
105                                     GHOST_kFailure : GHOST_kSuccess;
106                 }
107                 else {
108                         success= GHOST_kFailure;
109                 }
110
111                 break;
112
113         case GHOST_kDrawingContextTypeNone:
114                 success= GHOST_kSuccess;
115                 break;
116
117         default:
118                 success= GHOST_kFailure;
119         }
120         return success;
121 }
122
123
124 GHOST_TSuccess
125 GHOST_WindowSDL::invalidate(void)
126 {
127         // So the idea of this function is to generate an expose event
128         // for the window.
129         // Unfortunately X does not handle expose events for you and
130         // it is the client's job to refresh the dirty part of the window.
131         // We need to queue up invalidate calls and generate GHOST events
132         // for them in the system.
133
134         // We implement this by setting a boolean in this class to concatenate
135         // all such calls into a single event for this window.
136
137         // At the same time we queue the dirty windows in the system class
138         // and generate events for them at the next processEvents call.
139
140         if (m_invalid_window == false) {
141                 m_system->addDirtyWindow(this);
142                 m_invalid_window= true;
143         }
144
145         return GHOST_kSuccess;
146 }
147
148
149 GHOST_TSuccess
150 GHOST_WindowSDL::swapBuffers()
151 {
152         if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
153                 SDL_GL_SwapWindow(m_sdl_win);
154                 return GHOST_kSuccess;
155         }
156         else {
157                 return GHOST_kFailure;
158         }
159 }
160
161
162 GHOST_TSuccess
163 GHOST_WindowSDL::activateDrawingContext()
164 {
165         if (m_sdl_glcontext !=NULL) {
166                 int status=SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext);
167                 (void)status;
168                 return GHOST_kSuccess;
169         }
170         return GHOST_kFailure;
171 }
172
173
174 GHOST_TSuccess
175 GHOST_WindowSDL::removeDrawingContext()
176 {
177         GHOST_TSuccess success;
178
179         if (m_sdl_glcontext != NULL) {
180                 SDL_GL_DeleteContext(m_sdl_glcontext);
181                 success= GHOST_kSuccess;
182         }
183         else {
184                 success= GHOST_kFailure;
185         }
186         return success;
187 }
188
189
190 GHOST_TSuccess
191 GHOST_WindowSDL::setState(GHOST_TWindowState state)
192 {
193         switch(state) {
194         case GHOST_kWindowStateNormal:
195                 SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
196                 SDL_RestoreWindow(m_sdl_win);
197                 break;
198         case GHOST_kWindowStateMaximized:
199                 SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
200                 SDL_MaximizeWindow(m_sdl_win);
201                 break;
202         case GHOST_kWindowStateMinimized:
203                 SDL_MinimizeWindow(m_sdl_win);
204                 break;
205         case GHOST_kWindowStateFullScreen:
206                 SDL_SetWindowFullscreen(m_sdl_win, SDL_TRUE);
207                 break;
208         default:
209                 break;
210         }
211
212         return GHOST_kSuccess;
213 }
214
215
216 GHOST_TWindowState
217 GHOST_WindowSDL::getState() const
218 {
219         Uint32 flags= SDL_GetWindowFlags(m_sdl_win);
220
221         if(flags & SDL_WINDOW_FULLSCREEN)      return GHOST_kWindowStateFullScreen;
222         else if(flags & SDL_WINDOW_MAXIMIZED)  return GHOST_kWindowStateMaximized;
223         else if(flags & SDL_WINDOW_MINIMIZED)  return GHOST_kWindowStateMinimized;
224         return GHOST_kWindowStateNormal;
225 }
226
227
228 void
229 GHOST_WindowSDL::setTitle(const STR_String& title)
230 {
231         SDL_SetWindowTitle(m_sdl_win, title.ReadPtr());
232 }
233
234
235 void
236 GHOST_WindowSDL::getTitle(STR_String& title) const
237 {
238         title= SDL_GetWindowTitle(m_sdl_win);
239 }
240
241
242 void
243 GHOST_WindowSDL::getWindowBounds(GHOST_Rect& bounds) const
244 {
245         getClientBounds(bounds);
246 }
247
248
249 void
250 GHOST_WindowSDL::getClientBounds(GHOST_Rect& bounds) const
251 {
252         int x, y, w, h;
253         SDL_GetWindowSize(m_sdl_win, &w, &h);
254         SDL_GetWindowPosition(m_sdl_win, &x, &y);
255
256         bounds.m_l= x;
257         bounds.m_r= x + w;
258         bounds.m_t= y;
259         bounds.m_b= y + h;
260 }
261
262 GHOST_TSuccess
263 GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width)
264 {
265         int height;
266         SDL_GetWindowSize(m_sdl_win, NULL, &height);
267         SDL_SetWindowSize(m_sdl_win, width, height);
268         return GHOST_kSuccess;
269 }
270
271 GHOST_TSuccess
272 GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height)
273 {
274         int width;
275         SDL_GetWindowSize(m_sdl_win, &width, NULL);
276         SDL_SetWindowSize(m_sdl_win, width, height);
277         return GHOST_kSuccess;
278 }
279
280 GHOST_TSuccess
281 GHOST_WindowSDL::setClientSize(GHOST_TUns32 width,
282                                               GHOST_TUns32 height)
283 {
284         SDL_SetWindowSize(m_sdl_win, width, height);
285         return GHOST_kSuccess;
286 }
287
288 void
289 GHOST_WindowSDL::screenToClient( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const
290 {
291         /* XXXSDL_WEAK_ABS_COORDS */
292         int x_win, y_win;
293         SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
294
295         outX = inX - x_win;
296         outY = inY - y_win;
297 }
298 void
299 GHOST_WindowSDL::clientToScreen( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const
300 {
301         /* XXXSDL_WEAK_ABS_COORDS */
302         int x_win, y_win;
303         SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
304
305         outX = inX + x_win;
306         outY = inY + y_win;
307 }
308
309 /* mouse cursor */
310 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,};
311 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,};
312 #define sdl_std_cursor_WIDTH_xterm  9
313 #define sdl_std_cursor_HEIGHT_xterm 16
314 #define sdl_std_cursor_HOT_X_xterm  -3
315 #define sdl_std_cursor_HOT_Y_xterm  -7
316
317 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,};
318 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,};
319 #define sdl_std_cursor_WIDTH_watch  16
320 #define sdl_std_cursor_HEIGHT_watch 16
321 #define sdl_std_cursor_HOT_X_watch  -15
322 #define sdl_std_cursor_HOT_Y_watch  -7
323
324 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,};
325 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,};
326 #define sdl_std_cursor_WIDTH_umbrella  16
327 #define sdl_std_cursor_HEIGHT_umbrella 16
328 #define sdl_std_cursor_HOT_X_umbrella  -7
329 #define sdl_std_cursor_HOT_Y_umbrella  -12
330
331 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,};
332 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,};
333 #define sdl_std_cursor_WIDTH_top_side  15
334 #define sdl_std_cursor_HEIGHT_top_side 16
335 #define sdl_std_cursor_HOT_X_top_side  -6
336 #define sdl_std_cursor_HOT_Y_top_side  -14
337
338 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,};
339 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,};
340 #define sdl_std_cursor_WIDTH_top_right_corner  16
341 #define sdl_std_cursor_HEIGHT_top_right_corner 16
342 #define sdl_std_cursor_HOT_X_top_right_corner  -13
343 #define sdl_std_cursor_HOT_Y_top_right_corner  -14
344
345 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,};
346 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,};
347 #define sdl_std_cursor_WIDTH_top_left_corner  16
348 #define sdl_std_cursor_HEIGHT_top_left_corner 16
349 #define sdl_std_cursor_HOT_X_top_left_corner  0
350 #define sdl_std_cursor_HOT_Y_top_left_corner  -14
351
352 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,};
353 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,};
354 #define sdl_std_cursor_WIDTH_spraycan  12
355 #define sdl_std_cursor_HEIGHT_spraycan 16
356 #define sdl_std_cursor_HOT_X_spraycan  -9
357 #define sdl_std_cursor_HOT_Y_spraycan  -14
358
359 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,};
360 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,};
361 #define sdl_std_cursor_WIDTH_sb_v_double_arrow  9
362 #define sdl_std_cursor_HEIGHT_sb_v_double_arrow 15
363 #define sdl_std_cursor_HOT_X_sb_v_double_arrow  -3
364 #define sdl_std_cursor_HOT_Y_sb_v_double_arrow  -8
365
366 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,};
367 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};
368 #define sdl_std_cursor_WIDTH_sb_h_double_arrow  15
369 #define sdl_std_cursor_HEIGHT_sb_h_double_arrow 9
370 #define sdl_std_cursor_HOT_X_sb_h_double_arrow  -7
371 #define sdl_std_cursor_HOT_Y_sb_h_double_arrow  -4
372
373 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,};
374 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,};
375 #define sdl_std_cursor_WIDTH_right_side  16
376 #define sdl_std_cursor_HEIGHT_right_side 15
377 #define sdl_std_cursor_HOT_X_right_side  -13
378 #define sdl_std_cursor_HOT_Y_right_side  -7
379
380 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,};
381 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,};
382 #define sdl_std_cursor_WIDTH_right_ptr  10
383 #define sdl_std_cursor_HEIGHT_right_ptr 16
384 #define sdl_std_cursor_HOT_X_right_ptr  -7
385 #define sdl_std_cursor_HOT_Y_right_ptr  -14
386
387 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,};
388 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,};
389 #define sdl_std_cursor_WIDTH_question_arrow  11
390 #define sdl_std_cursor_HEIGHT_question_arrow 16
391 #define sdl_std_cursor_HOT_X_question_arrow  -4
392 #define sdl_std_cursor_HOT_Y_question_arrow  -8
393
394 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,};
395 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,};
396 #define sdl_std_cursor_WIDTH_pirate  16
397 #define sdl_std_cursor_HEIGHT_pirate 16
398 #define sdl_std_cursor_HOT_X_pirate  -7
399 #define sdl_std_cursor_HOT_Y_pirate  -4
400
401 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,};
402 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,};
403 #define sdl_std_cursor_WIDTH_left_side  16
404 #define sdl_std_cursor_HEIGHT_left_side 15
405 #define sdl_std_cursor_HOT_X_left_side  0
406 #define sdl_std_cursor_HOT_Y_left_side  -7
407
408 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,};
409 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,};
410 #define sdl_std_cursor_WIDTH_left_ptr  10
411 #define sdl_std_cursor_HEIGHT_left_ptr 16
412 #define sdl_std_cursor_HOT_X_left_ptr  -8
413 #define sdl_std_cursor_HOT_Y_left_ptr  -14
414
415 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,};
416 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,};
417 #define sdl_std_cursor_WIDTH_exchange  16
418 #define sdl_std_cursor_HEIGHT_exchange 16
419 #define sdl_std_cursor_HOT_X_exchange  -6
420 #define sdl_std_cursor_HOT_Y_exchange  -8
421
422 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,};
423 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,};
424 #define sdl_std_cursor_WIDTH_crosshair  16
425 #define sdl_std_cursor_HEIGHT_crosshair 16
426 #define sdl_std_cursor_HOT_X_crosshair  -7
427 #define sdl_std_cursor_HOT_Y_crosshair  -8
428
429 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,};
430 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,};
431 #define sdl_std_cursor_WIDTH_bottom_side  15
432 #define sdl_std_cursor_HEIGHT_bottom_side 16
433 #define sdl_std_cursor_HOT_X_bottom_side  -6
434 #define sdl_std_cursor_HOT_Y_bottom_side  -1
435
436 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,};
437 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,};
438 #define sdl_std_cursor_WIDTH_bottom_right_corner  16
439 #define sdl_std_cursor_HEIGHT_bottom_right_corner 16
440 #define sdl_std_cursor_HOT_X_bottom_right_corner  -13
441 #define sdl_std_cursor_HOT_Y_bottom_right_corner  -1
442
443 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,};
444 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,};
445 #define sdl_std_cursor_WIDTH_bottom_left_corner  16
446 #define sdl_std_cursor_HEIGHT_bottom_left_corner 16
447 #define sdl_std_cursor_HOT_X_bottom_left_corner  0
448 #define sdl_std_cursor_HOT_Y_bottom_left_corner  -1
449
450 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,};
451 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,};
452 #define sdl_std_cursor_WIDTH_arrow  16
453 #define sdl_std_cursor_HEIGHT_arrow 16
454 #define sdl_std_cursor_HOT_X_arrow  -13
455 #define sdl_std_cursor_HOT_Y_arrow  -14
456 /* end cursor data */
457
458
459 static SDL_Cursor *sdl_std_cursor_array[(int)GHOST_kStandardCursorNumCursors]= {0};
460
461 /* utility function mostly a copy of SDL_CreateCursor but allows us to change
462  * color and supports blenders flipped bits */
463 static SDL_Cursor *
464 sdl_ghost_CreateCursor(const Uint8 *data,
465                        const Uint8 *mask,
466                        int w,
467                        int h,
468                        int hot_x,
469                        int hot_y)
470 {
471     SDL_Surface *surface;
472     SDL_Cursor *cursor;
473     int x, y;
474     Uint32 *pixel;
475     Uint8 datab= 0, maskb= 0;
476     const Uint32 black= 0xFF000000;
477     const Uint32 white= 0xFFFFFFFF;
478     const Uint32 transparent= 0x00000000;
479
480     /* Make sure the width is a multiple of 8 */
481     w= ((w + 7) & ~7);
482
483     /* Create the surface from a bitmap */
484         surface= SDL_CreateRGBSurface(0, w, h, 32,
485                                       0x00FF0000,
486                                       0x0000FF00,
487                                       0x000000FF,
488                                       0xFF000000);
489     if (!surface) {
490         return NULL;
491     }
492     for (y= 0; y < h; ++y) {
493         pixel= (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
494         for (x= 0; x < w; ++x) {
495             if ((x % 8) == 0) {
496                 datab= *data++;
497                 maskb= *mask++;
498
499                                 /* reverse bit order */
500                                 datab= (datab * 0x0202020202ULL & 0x010884422010ULL) % 1023;
501                                 maskb= (maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023;
502             }
503             if (maskb & 0x80) {
504                 *pixel++= (datab & 0x80) ?  white : black;
505             }
506                         else {
507                 *pixel++= (datab & 0x80) ? white : transparent;
508             }
509             datab <<= 1;
510             maskb <<= 1;
511         }
512     }
513
514     cursor= SDL_CreateColorCursor(surface, hot_x, hot_y);
515
516     SDL_FreeSurface(surface);
517
518     return cursor;
519 }
520
521 /* TODO, this is currently never freed but it wont leak either. */
522 static void sdl_cursor_init(void)
523 {
524
525 #define DEF_CURSOR(name, ind) \
526         assert(\
527                 (\
528                 sdl_std_cursor_array[(int)ind]= \
529                                 sdl_ghost_CreateCursor(sdl_std_cursor_##name, \
530                                 sdl_std_cursor_mask_##name, \
531                                 sdl_std_cursor_WIDTH_##name, \
532                                 sdl_std_cursor_HEIGHT_##name, \
533                                 (sdl_std_cursor_WIDTH_##name + (sdl_std_cursor_HOT_X_##name)) - 1, \
534                                 (sdl_std_cursor_HEIGHT_##name + (sdl_std_cursor_HOT_Y_##name)) - 1) \
535                 ) != NULL) \
536
537
538         DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault);
539         DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow);
540         DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow);
541         DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); // TODO, replace this one.
542         DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy);
543         DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp);
544         DEF_CURSOR(exchange, GHOST_kStandardCursorCycle);
545         DEF_CURSOR(spraycan, GHOST_kStandardCursorSpray);
546         DEF_CURSOR(watch, GHOST_kStandardCursorWait);
547         DEF_CURSOR(xterm, GHOST_kStandardCursorText);
548         DEF_CURSOR(crosshair, GHOST_kStandardCursorCrosshair);
549         DEF_CURSOR(sb_v_double_arrow, GHOST_kStandardCursorUpDown);
550         DEF_CURSOR(sb_h_double_arrow, GHOST_kStandardCursorLeftRight);
551         DEF_CURSOR(top_side, GHOST_kStandardCursorTopSide);
552         DEF_CURSOR(bottom_side, GHOST_kStandardCursorBottomSide);
553         DEF_CURSOR(left_side, GHOST_kStandardCursorLeftSide);
554         DEF_CURSOR(right_side, GHOST_kStandardCursorRightSide);
555         DEF_CURSOR(top_left_corner, GHOST_kStandardCursorTopLeftCorner);
556         DEF_CURSOR(top_right_corner, GHOST_kStandardCursorTopRightCorner);
557         DEF_CURSOR(bottom_right_corner, GHOST_kStandardCursorBottomRightCorner);
558         DEF_CURSOR(bottom_left_corner , GHOST_kStandardCursorBottomLeftCorner);
559         DEF_CURSOR(arrow , GHOST_kStandardCursorCopy);
560         //DEF_CURSOR(arrow, GHOST_kStandardCursorCustom);
561         DEF_CURSOR(arrow, GHOST_kStandardCursorPencil);
562
563 #undef DEF_CURSOR
564
565 }
566
567
568
569 GHOST_TSuccess
570 GHOST_WindowSDL::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
571 {
572         return GHOST_kSuccess;
573 }
574
575
576 GHOST_TSuccess
577 GHOST_WindowSDL::setWindowCursorShape(GHOST_TStandardCursor shape)
578 {
579         if(sdl_std_cursor_array[0] == NULL) {
580                 sdl_cursor_init();
581         }
582
583         SDL_SetCursor(sdl_std_cursor_array[(int)shape]);
584         return GHOST_kSuccess;
585 }
586
587
588 GHOST_TSuccess
589 GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
590                                             GHOST_TUns8 mask[16][2],
591                                             int hotX,
592                                             int hotY)
593 {
594         return setWindowCustomCursorShape((GHOST_TUns8 *)bitmap,
595                                           (GHOST_TUns8 *)mask,
596                                           16, 16,
597                                           hotX, hotY,
598                                           0, 1);
599 }
600
601
602 GHOST_TSuccess
603 GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
604                                             GHOST_TUns8 *mask,
605                                             int sizex, int sizey,
606                                             int hotX, int hotY,
607                                             int fg_color, int bg_color)
608 {
609         if(m_sdl_custom_cursor) {
610                 SDL_FreeCursor(m_sdl_custom_cursor);
611         }
612
613         m_sdl_custom_cursor= sdl_ghost_CreateCursor((const Uint8 *)bitmap,
614                                                     (const Uint8 *)mask,
615                                                     sizex, sizex,
616                                                     hotX, hotY);
617
618         SDL_SetCursor(m_sdl_custom_cursor);
619         return GHOST_kSuccess;
620 }
621
622
623 GHOST_TSuccess
624 GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
625 {
626         SDL_ShowCursor(visible);
627         return GHOST_kSuccess;
628 }