ClangFormat: apply to source, most of intern
[blender.git] / intern / ghost / intern / GHOST_WindowSDL.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup GHOST
19  */
20
21 #include "GHOST_WindowSDL.h"
22 #include "SDL_mouse.h"
23 #include "glew-mx.h"
24
25 #include "GHOST_ContextSDL.h"
26
27 #include <assert.h>
28
29 GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
30                                  const STR_String &title,
31                                  GHOST_TInt32 left,
32                                  GHOST_TInt32 top,
33                                  GHOST_TUns32 width,
34                                  GHOST_TUns32 height,
35                                  GHOST_TWindowState state,
36                                  const GHOST_TEmbedderWindowID parentWindow,
37                                  GHOST_TDrawingContextType type,
38                                  const bool stereoVisual,
39                                  const bool exclusive,
40                                  const GHOST_TUns16 numOfAASamples)
41     : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
42       m_system(system),
43       m_valid_setup(false),
44       m_invalid_window(false),
45       m_sdl_custom_cursor(NULL)
46 {
47
48   /* creating the window _must_ come after setting attributes */
49   m_sdl_win = SDL_CreateWindow(title,
50                                left,
51                                top,
52                                width,
53                                height,
54                                SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
55
56   /* now set up the rendering context. */
57   if (setDrawingContextType(type) == GHOST_kSuccess) {
58     m_valid_setup = true;
59     GHOST_PRINT("Created window\n");
60   }
61
62   if (exclusive) {
63     SDL_RaiseWindow(m_sdl_win);
64   }
65
66   setTitle(title);
67 }
68
69 GHOST_WindowSDL::~GHOST_WindowSDL()
70 {
71   if (m_sdl_custom_cursor) {
72     SDL_FreeCursor(m_sdl_custom_cursor);
73   }
74
75   releaseNativeHandles();
76
77   SDL_DestroyWindow(m_sdl_win);
78 }
79
80 GHOST_Context *GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type)
81 {
82   if (type == GHOST_kDrawingContextTypeOpenGL) {
83     GHOST_Context *context = new GHOST_ContextSDL(m_wantStereoVisual,
84                                                   m_wantNumOfAASamples,
85                                                   m_sdl_win,
86                                                   0,  // profile bit
87                                                   3,
88                                                   3,
89                                                   GHOST_OPENGL_SDL_CONTEXT_FLAGS,
90                                                   GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
91
92     if (context->initializeDrawingContext())
93       return context;
94     else
95       delete context;
96   }
97
98   return NULL;
99 }
100
101 GHOST_TSuccess GHOST_WindowSDL::invalidate(void)
102 {
103   if (m_invalid_window == false) {
104     m_system->addDirtyWindow(this);
105     m_invalid_window = true;
106   }
107
108   return GHOST_kSuccess;
109 }
110
111 GHOST_TSuccess GHOST_WindowSDL::setState(GHOST_TWindowState state)
112 {
113   switch (state) {
114     case GHOST_kWindowStateNormal:
115       SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
116       SDL_RestoreWindow(m_sdl_win);
117       break;
118     case GHOST_kWindowStateMaximized:
119       SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
120       SDL_MaximizeWindow(m_sdl_win);
121       break;
122     case GHOST_kWindowStateMinimized:
123       SDL_MinimizeWindow(m_sdl_win);
124       break;
125     case GHOST_kWindowStateFullScreen:
126       SDL_SetWindowFullscreen(m_sdl_win, SDL_TRUE);
127       break;
128     default:
129       break;
130   }
131
132   return GHOST_kSuccess;
133 }
134
135 GHOST_TWindowState GHOST_WindowSDL::getState() const
136 {
137   Uint32 flags = SDL_GetWindowFlags(m_sdl_win);
138
139   if (flags & SDL_WINDOW_FULLSCREEN)
140     return GHOST_kWindowStateFullScreen;
141   else if (flags & SDL_WINDOW_MAXIMIZED)
142     return GHOST_kWindowStateMaximized;
143   else if (flags & SDL_WINDOW_MINIMIZED)
144     return GHOST_kWindowStateMinimized;
145   return GHOST_kWindowStateNormal;
146 }
147
148 bool GHOST_WindowSDL::getValid() const
149 {
150   return GHOST_Window::getValid() && m_valid_setup;
151 }
152
153 void GHOST_WindowSDL::setTitle(const STR_String &title)
154 {
155   SDL_SetWindowTitle(m_sdl_win, title.ReadPtr());
156 }
157
158 void GHOST_WindowSDL::getTitle(STR_String &title) const
159 {
160   title = SDL_GetWindowTitle(m_sdl_win);
161 }
162
163 void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const
164 {
165   getClientBounds(bounds);
166 }
167
168 void GHOST_WindowSDL::getClientBounds(GHOST_Rect &bounds) const
169 {
170   int x, y, w, h;
171   SDL_GetWindowSize(m_sdl_win, &w, &h);
172   SDL_GetWindowPosition(m_sdl_win, &x, &y);
173
174   bounds.m_l = x;
175   bounds.m_r = x + w;
176   bounds.m_t = y;
177   bounds.m_b = y + h;
178 }
179
180 GHOST_TSuccess GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width)
181 {
182   int height;
183   SDL_GetWindowSize(m_sdl_win, NULL, &height);
184   SDL_SetWindowSize(m_sdl_win, width, height);
185   return GHOST_kSuccess;
186 }
187
188 GHOST_TSuccess GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height)
189 {
190   int width;
191   SDL_GetWindowSize(m_sdl_win, &width, NULL);
192   SDL_SetWindowSize(m_sdl_win, width, height);
193   return GHOST_kSuccess;
194 }
195
196 GHOST_TSuccess GHOST_WindowSDL::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
197 {
198   SDL_SetWindowSize(m_sdl_win, width, height);
199   return GHOST_kSuccess;
200 }
201
202 void GHOST_WindowSDL::screenToClient(GHOST_TInt32 inX,
203                                      GHOST_TInt32 inY,
204                                      GHOST_TInt32 &outX,
205                                      GHOST_TInt32 &outY) const
206 {
207   /* XXXSDL_WEAK_ABS_COORDS */
208   int x_win, y_win;
209   SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
210
211   outX = inX - x_win;
212   outY = inY - y_win;
213 }
214 void GHOST_WindowSDL::clientToScreen(GHOST_TInt32 inX,
215                                      GHOST_TInt32 inY,
216                                      GHOST_TInt32 &outX,
217                                      GHOST_TInt32 &outY) const
218 {
219   /* XXXSDL_WEAK_ABS_COORDS */
220   int x_win, y_win;
221   SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
222
223   outX = inX + x_win;
224   outY = inY + y_win;
225 }
226
227 /* mouse cursor */
228 static unsigned char sdl_std_cursor_mask_xterm[] = {
229     0xef, 0x01, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
230     0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xef, 0x01,
231 };
232 static unsigned char sdl_std_cursor_xterm[] = {
233     0x00, 0x77, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
234     0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00,
235 };
236 #define sdl_std_cursor_WIDTH_xterm 9
237 #define sdl_std_cursor_HEIGHT_xterm 16
238 #define sdl_std_cursor_HOT_X_xterm -3
239 #define sdl_std_cursor_HOT_Y_xterm -7
240
241 static unsigned char sdl_std_cursor_mask_watch[] = {
242     0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
243     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0x1f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
244 };
245 static unsigned char sdl_std_cursor_watch[] = {
246     0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0xfc, 0x0f, 0x86, 0x18, 0x83, 0x30, 0x81, 0xe0, 0xc1, 0xe1,
247     0xc1, 0xe1, 0x21, 0xe0, 0x13, 0x30, 0x06, 0x18, 0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07,
248 };
249 #define sdl_std_cursor_WIDTH_watch 16
250 #define sdl_std_cursor_HEIGHT_watch 16
251 #define sdl_std_cursor_HOT_X_watch -15
252 #define sdl_std_cursor_HOT_Y_watch -7
253
254 static unsigned char sdl_std_cursor_mask_umbrella[] = {
255     0xe8, 0x76, 0xfb, 0xdf, 0xfd, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0x79, 0xc0, 0x01,
256     0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0x80, 0x03,
257 };
258 static unsigned char sdl_std_cursor_umbrella[] = {
259     0x88, 0x04, 0x20, 0x0a, 0xc9, 0x32, 0xf2, 0x09, 0x4c, 0x06, 0x43, 0x18, 0x40, 0x00, 0x40, 0x00,
260     0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x01, 0x40, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
261 };
262 #define sdl_std_cursor_WIDTH_umbrella 16
263 #define sdl_std_cursor_HEIGHT_umbrella 16
264 #define sdl_std_cursor_HOT_X_umbrella -7
265 #define sdl_std_cursor_HOT_Y_umbrella -12
266
267 static unsigned char sdl_std_cursor_mask_top_side[] = {
268     0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f,
269     0xdc, 0x1d, 0xcc, 0x19, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
270 };
271 static unsigned char sdl_std_cursor_top_side[] = {
272     0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x50, 0x01, 0x48, 0x02, 0x44, 0x04,
273     0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
274 };
275 #define sdl_std_cursor_WIDTH_top_side 15
276 #define sdl_std_cursor_HEIGHT_top_side 16
277 #define sdl_std_cursor_HOT_X_top_side -6
278 #define sdl_std_cursor_HOT_Y_top_side -14
279
280 static unsigned char sdl_std_cursor_mask_top_right_corner[] = {
281     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7,
282     0xc0, 0xf7, 0xe0, 0xf7, 0x70, 0xf7, 0x38, 0xf7, 0x1c, 0xf7, 0x0c, 0xf7, 0x00, 0xf0, 0x00, 0xf0,
283 };
284 static unsigned char sdl_std_cursor_top_right_corner[] = {
285     0xff, 0x3f, 0xff, 0x3f, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0xfc, 0x31, 0x80, 0x31, 0x40, 0x31,
286     0x20, 0x31, 0x10, 0x31, 0x08, 0x31, 0x04, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
287 };
288 #define sdl_std_cursor_WIDTH_top_right_corner 16
289 #define sdl_std_cursor_HEIGHT_top_right_corner 16
290 #define sdl_std_cursor_HOT_X_top_right_corner -13
291 #define sdl_std_cursor_HOT_Y_top_right_corner -14
292
293 static unsigned char sdl_std_cursor_mask_top_left_corner[] = {
294     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xef, 0x3f, 0xef, 0x3f, 0xef, 0x3f,
295     0xef, 0x03, 0xef, 0x07, 0xef, 0x0e, 0xef, 0x1c, 0xef, 0x38, 0xef, 0x30, 0x0f, 0x00, 0x0f, 0x00,
296 };
297 static unsigned char sdl_std_cursor_top_left_corner[] = {
298     0xff, 0x3f, 0xff, 0x3f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xe3, 0x0f, 0x63, 0x00, 0xa3, 0x00,
299     0x23, 0x01, 0x23, 0x02, 0x23, 0x04, 0x23, 0x08, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
300 };
301 #define sdl_std_cursor_WIDTH_top_left_corner 16
302 #define sdl_std_cursor_HEIGHT_top_left_corner 16
303 #define sdl_std_cursor_HOT_X_top_left_corner 0
304 #define sdl_std_cursor_HOT_Y_top_left_corner -14
305
306 static unsigned char sdl_std_cursor_mask_spraycan[] = {
307     0x00, 0x0c, 0x18, 0x0d, 0x7c, 0x0d, 0x7c, 0x0d, 0x7e, 0x0d, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
308     0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
309 };
310 static unsigned char sdl_std_cursor_spraycan[] = {
311     0x00, 0x06, 0x80, 0x00, 0x2c, 0x06, 0x9e, 0x00, 0x16, 0x06, 0x3f, 0x00, 0x21, 0x00, 0x27, 0x00,
312     0x25, 0x00, 0x27, 0x00, 0x25, 0x00, 0x27, 0x00, 0x27, 0x00, 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00,
313 };
314 #define sdl_std_cursor_WIDTH_spraycan 12
315 #define sdl_std_cursor_HEIGHT_spraycan 16
316 #define sdl_std_cursor_HOT_X_spraycan -9
317 #define sdl_std_cursor_HOT_Y_spraycan -14
318
319 static unsigned char sdl_std_cursor_mask_sb_v_double_arrow[] = {
320     0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x7c, 0x00, 0x7c,
321     0x00, 0x7c, 0x00, 0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00,
322 };
323 static unsigned char sdl_std_cursor_sb_v_double_arrow[] = {
324     0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28,
325     0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00,
326 };
327 #define sdl_std_cursor_WIDTH_sb_v_double_arrow 9
328 #define sdl_std_cursor_HEIGHT_sb_v_double_arrow 15
329 #define sdl_std_cursor_HOT_X_sb_v_double_arrow -3
330 #define sdl_std_cursor_HOT_Y_sb_v_double_arrow -8
331
332 static unsigned char sdl_std_cursor_mask_sb_h_double_arrow[] = {
333     0x18,
334     0x0c,
335     0x1c,
336     0x1c,
337     0xfe,
338     0x3f,
339     0xff,
340     0x7f,
341     0xff,
342     0x7f,
343     0xff,
344     0x7f,
345     0xfe,
346     0x3f,
347     0x1c,
348     0x1c,
349     0x18,
350     0x0c,
351 };
352 static unsigned char sdl_std_cursor_sb_h_double_arrow[] = {0x00,
353                                                            0x00,
354                                                            0x08,
355                                                            0x08,
356                                                            0x0c,
357                                                            0x18,
358                                                            0xfe,
359                                                            0x3f,
360                                                            0x0f,
361                                                            0x78,
362                                                            0xfe,
363                                                            0x3f,
364                                                            0x0c,
365                                                            0x18,
366                                                            0x08,
367                                                            0x08,
368                                                            0x00,
369                                                            0x00};
370 #define sdl_std_cursor_WIDTH_sb_h_double_arrow 15
371 #define sdl_std_cursor_HEIGHT_sb_h_double_arrow 9
372 #define sdl_std_cursor_HOT_X_sb_h_double_arrow -7
373 #define sdl_std_cursor_HOT_Y_sb_h_double_arrow -4
374
375 static unsigned char sdl_std_cursor_mask_right_side[] = {
376     0x00, 0xf0, 0x00, 0xf0, 0xc0, 0xf0, 0xc0, 0xf1, 0x80, 0xf3, 0x00, 0xf7, 0xff, 0xff, 0xff,
377     0xff, 0xff, 0xff, 0x00, 0xf7, 0x80, 0xf3, 0xc0, 0xf1, 0xc0, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
378 };
379 static unsigned char sdl_std_cursor_right_side[] = {
380     0x00, 0x30, 0x00, 0x30, 0x40, 0x30, 0x80, 0x30, 0x00, 0x31, 0x00, 0x32, 0xff, 0x37, 0x00,
381     0x32, 0x00, 0x31, 0x80, 0x30, 0x40, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
382 };
383 #define sdl_std_cursor_WIDTH_right_side 16
384 #define sdl_std_cursor_HEIGHT_right_side 15
385 #define sdl_std_cursor_HOT_X_right_side -13
386 #define sdl_std_cursor_HOT_Y_right_side -7
387
388 static unsigned char sdl_std_cursor_mask_right_ptr[] = {
389     0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x03, 0xf0, 0x03, 0xf8, 0x03, 0xfc, 0x03, 0xfe, 0x03,
390     0xff, 0x03, 0xff, 0x03, 0xf8, 0x03, 0xbc, 0x03, 0x3c, 0x03, 0x1e, 0x00, 0x1e, 0x00, 0x0c, 0x00,
391 };
392 static unsigned char sdl_std_cursor_right_ptr[] = {
393     0x00, 0x80, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0xff,
394     0x00, 0xf8, 0x00, 0xd8, 0x00, 0x8c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
395 };
396 #define sdl_std_cursor_WIDTH_right_ptr 10
397 #define sdl_std_cursor_HEIGHT_right_ptr 16
398 #define sdl_std_cursor_HOT_X_right_ptr -7
399 #define sdl_std_cursor_HOT_Y_right_ptr -14
400
401 static unsigned char sdl_std_cursor_mask_question_arrow[] = {
402     0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xff, 0x07, 0x8f, 0x07, 0x9f, 0x07, 0xde, 0x07, 0xfc, 0x03,
403     0xf8, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00,
404 };
405 static unsigned char sdl_std_cursor_question_arrow[] = {
406     0x7c, 0x00, 0xfe, 0x00, 0xc7, 0x01, 0x83, 0x01, 0x87, 0x01, 0xc6, 0x01, 0xe0, 0x00, 0x78, 0x00,
407     0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0xee, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00,
408 };
409 #define sdl_std_cursor_WIDTH_question_arrow 11
410 #define sdl_std_cursor_HEIGHT_question_arrow 16
411 #define sdl_std_cursor_HOT_X_question_arrow -4
412 #define sdl_std_cursor_HOT_Y_question_arrow -8
413
414 static unsigned char sdl_std_cursor_mask_pirate[] = {
415     0xf0, 0x03, 0xf8, 0x07, 0xfc, 0x0f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xf1, 0x83,
416     0xf1, 0xe3, 0xf3, 0xf3, 0xef, 0x39, 0x1e, 0x1e, 0xe0, 0x01, 0xfe, 0xc7, 0xff, 0xff, 0x0f, 0x7c,
417 };
418 static unsigned char sdl_std_cursor_pirate[] = {
419     0xe0, 0x01, 0xf0, 0x03, 0xf8, 0x07, 0xcc, 0x0c, 0xcc, 0x0c, 0xf8, 0x07, 0xf0, 0x03, 0xe0, 0x01,
420     0xe1, 0x21, 0xe1, 0x61, 0xc2, 0x10, 0x1c, 0x0e, 0xe0, 0x01, 0xf8, 0x47, 0x0f, 0x7c, 0x01, 0x20,
421 };
422 #define sdl_std_cursor_WIDTH_pirate 16
423 #define sdl_std_cursor_HEIGHT_pirate 16
424 #define sdl_std_cursor_HOT_X_pirate -7
425 #define sdl_std_cursor_HOT_Y_pirate -4
426
427 static unsigned char sdl_std_cursor_mask_left_side[] = {
428     0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x03, 0x8f, 0x03, 0xcf, 0x01, 0xef, 0x00, 0xff, 0xff, 0xff,
429     0xff, 0xff, 0xff, 0xef, 0x00, 0xcf, 0x01, 0x8f, 0x03, 0x0f, 0x03, 0x0f, 0x00, 0x0f, 0x00,
430 };
431 static unsigned char sdl_std_cursor_left_side[] = {
432     0x03, 0x00, 0x03, 0x00, 0x83, 0x00, 0x43, 0x00, 0x23, 0x00, 0x13, 0x00, 0xfb, 0x3f, 0x13,
433     0x00, 0x23, 0x00, 0x43, 0x00, 0x83, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
434 };
435 #define sdl_std_cursor_WIDTH_left_side 16
436 #define sdl_std_cursor_HEIGHT_left_side 15
437 #define sdl_std_cursor_HOT_X_left_side 0
438 #define sdl_std_cursor_HOT_Y_left_side -7
439
440 static unsigned char sdl_std_cursor_mask_left_ptr[] = {
441     0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01,
442     0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, 0xf7, 0x00, 0xf3, 0x00, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x00,
443 };
444 static unsigned char sdl_std_cursor_left_ptr[] = {
445     0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x7e, 0x00, 0xfe, 0x00,
446     0xfe, 0x00, 0x3e, 0x00, 0x36, 0x00, 0x62, 0x00, 0x60, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00,
447 };
448 #define sdl_std_cursor_WIDTH_left_ptr 10
449 #define sdl_std_cursor_HEIGHT_left_ptr 16
450 #define sdl_std_cursor_HOT_X_left_ptr -8
451 #define sdl_std_cursor_HOT_Y_left_ptr -14
452
453 static unsigned char sdl_std_cursor_mask_exchange[] = {
454     0xe3, 0x07, 0xf7, 0x0f, 0xff, 0x1f, 0xff, 0x3f, 0x3f, 0x38, 0xff, 0x30, 0xff, 0x00, 0xff, 0x00,
455     0x00, 0xff, 0x00, 0xff, 0x0c, 0xfe, 0x1c, 0xfc, 0xfc, 0xff, 0xf8, 0xff, 0xf0, 0xef, 0xe0, 0xc7,
456 };
457 static unsigned char sdl_std_cursor_exchange[] = {
458     0xf1, 0x03, 0xfb, 0x07, 0x1f, 0x0c, 0x09, 0x08, 0x19, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
459     0x00, 0x3f, 0x00, 0x26, 0x04, 0x24, 0x0c, 0x3e, 0xf8, 0x37, 0xf0, 0x23, 0x00, 0x00, 0x00, 0x00,
460 };
461 #define sdl_std_cursor_WIDTH_exchange 16
462 #define sdl_std_cursor_HEIGHT_exchange 16
463 #define sdl_std_cursor_HOT_X_exchange -6
464 #define sdl_std_cursor_HOT_Y_exchange -8
465
466 static unsigned char sdl_std_cursor_mask_crosshair[] = {
467     0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff,
468     0xff, 0xff, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
469 };
470 static unsigned char sdl_std_cursor_crosshair[] = {
471     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7f, 0xff,
472     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
473 };
474 #define sdl_std_cursor_WIDTH_crosshair 16
475 #define sdl_std_cursor_HEIGHT_crosshair 16
476 #define sdl_std_cursor_HOT_X_crosshair -7
477 #define sdl_std_cursor_HOT_Y_crosshair -8
478
479 static unsigned char sdl_std_cursor_mask_bottom_side[] = {
480     0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xcc, 0x19, 0xdc, 0x1d,
481     0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
482 };
483 static unsigned char sdl_std_cursor_bottom_side[] = {
484     0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x44, 0x04, 0x48, 0x02,
485     0x50, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
486 };
487 #define sdl_std_cursor_WIDTH_bottom_side 15
488 #define sdl_std_cursor_HEIGHT_bottom_side 16
489 #define sdl_std_cursor_HOT_X_bottom_side -6
490 #define sdl_std_cursor_HOT_Y_bottom_side -1
491
492 static unsigned char sdl_std_cursor_mask_bottom_right_corner[] = {
493     0x00, 0xf0, 0x00, 0xf0, 0x0c, 0xf7, 0x1c, 0xf7, 0x38, 0xf7, 0x70, 0xf7, 0xe0, 0xf7, 0xc0, 0xf7,
494     0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
495 };
496 static unsigned char sdl_std_cursor_bottom_right_corner[] = {
497     0x00, 0x30, 0x00, 0x30, 0x04, 0x31, 0x08, 0x31, 0x10, 0x31, 0x20, 0x31, 0x40, 0x31, 0x80, 0x31,
498     0xfc, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0xff, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
499 };
500 #define sdl_std_cursor_WIDTH_bottom_right_corner 16
501 #define sdl_std_cursor_HEIGHT_bottom_right_corner 16
502 #define sdl_std_cursor_HOT_X_bottom_right_corner -13
503 #define sdl_std_cursor_HOT_Y_bottom_right_corner -1
504
505 static unsigned char sdl_std_cursor_mask_bottom_left_corner[] = {
506     0x0f, 0x00, 0x0f, 0x00, 0xef, 0x30, 0xef, 0x38, 0xef, 0x1c, 0xef, 0x0e, 0xef, 0x07, 0xef, 0x03,
507     0xef, 0x3f, 0xef, 0x3f, 0xef, 0x3f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
508 };
509 static unsigned char sdl_std_cursor_bottom_left_corner[] = {
510     0x03, 0x00, 0x03, 0x00, 0x23, 0x08, 0x23, 0x04, 0x23, 0x02, 0x23, 0x01, 0xa3, 0x00, 0x63, 0x00,
511     0xe3, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
512 };
513 #define sdl_std_cursor_WIDTH_bottom_left_corner 16
514 #define sdl_std_cursor_HEIGHT_bottom_left_corner 16
515 #define sdl_std_cursor_HOT_X_bottom_left_corner 0
516 #define sdl_std_cursor_HOT_Y_bottom_left_corner -1
517
518 static unsigned char sdl_std_cursor_mask_arrow[] = {
519     0x00, 0xe0, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x1f,
520     0xe0, 0x1f, 0xf0, 0x0f, 0xf8, 0x0f, 0x7c, 0x07, 0x3e, 0x07, 0x1f, 0x02, 0x0e, 0x00, 0x04, 0x00,
521 };
522 static unsigned char sdl_std_cursor_arrow[] = {
523     0x00, 0x30, 0x00, 0x3c, 0x00, 0x1f, 0xc0, 0x1f, 0xf0, 0x0f, 0xfc, 0x0f, 0xc0, 0x07, 0xe0, 0x07,
524     0x70, 0x03, 0x38, 0x03, 0x1c, 0x01, 0x0e, 0x01, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
525 };
526 #define sdl_std_cursor_WIDTH_arrow 16
527 #define sdl_std_cursor_HEIGHT_arrow 16
528 #define sdl_std_cursor_HOT_X_arrow -13
529 #define sdl_std_cursor_HOT_Y_arrow -14
530 /* end cursor data */
531
532 static SDL_Cursor *sdl_std_cursor_array[(int)GHOST_kStandardCursorNumCursors] = {0};
533
534 /* utility function mostly a copy of SDL_CreateCursor but allows us to change
535  * color and supports blenders flipped bits */
536 static SDL_Cursor *sdl_ghost_CreateCursor(
537     const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
538 {
539   SDL_Surface *surface;
540   SDL_Cursor *cursor;
541   int x, y;
542   Uint32 *pixel;
543   Uint8 datab = 0, maskb = 0;
544   const Uint32 black = 0xFF000000;
545   const Uint32 white = 0xFFFFFFFF;
546   const Uint32 transparent = 0x00000000;
547
548   /* Make sure the width is a multiple of 8 */
549   w = ((w + 7) & ~7);
550
551   /* Create the surface from a bitmap */
552   surface = SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
553   if (!surface) {
554     return NULL;
555   }
556   for (y = 0; y < h; ++y) {
557     pixel = (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch);
558     for (x = 0; x < w; ++x) {
559       if ((x % 8) == 0) {
560         datab = *data++;
561         maskb = *mask++;
562
563         /* reverse bit order */
564         datab = (datab * 0x0202020202ULL & 0x010884422010ULL) % 1023;
565         maskb = (maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023;
566       }
567       if (maskb & 0x80) {
568         *pixel++ = (datab & 0x80) ? white : black;
569       }
570       else {
571         *pixel++ = (datab & 0x80) ? white : transparent;
572       }
573       datab <<= 1;
574       maskb <<= 1;
575     }
576   }
577
578   cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
579
580   SDL_FreeSurface(surface);
581
582   return cursor;
583 }
584
585 /* TODO, this is currently never freed but it wont leak either. */
586 static void sdl_cursor_init(void)
587 {
588
589 #define DEF_CURSOR(name, ind) \
590   { \
591     sdl_std_cursor_array[(int)ind] = sdl_ghost_CreateCursor( \
592         sdl_std_cursor_##name, \
593         sdl_std_cursor_mask_##name, \
594         sdl_std_cursor_WIDTH_##name, \
595         sdl_std_cursor_HEIGHT_##name, \
596         (sdl_std_cursor_WIDTH_##name + (sdl_std_cursor_HOT_X_##name)) - 1, \
597         (sdl_std_cursor_HEIGHT_##name + (sdl_std_cursor_HOT_Y_##name)) - 1); \
598     assert(sdl_std_cursor_array[(int)ind] != NULL); \
599   } \
600   (void)0
601
602   DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault);
603   DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow);
604   DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow);
605   DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo);  // TODO, replace this one.
606   DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy);
607   DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp);
608   DEF_CURSOR(exchange, GHOST_kStandardCursorCycle);
609   DEF_CURSOR(spraycan, GHOST_kStandardCursorSpray);
610   DEF_CURSOR(watch, GHOST_kStandardCursorWait);
611   DEF_CURSOR(xterm, GHOST_kStandardCursorText);
612   DEF_CURSOR(crosshair, GHOST_kStandardCursorCrosshair);
613   DEF_CURSOR(sb_v_double_arrow, GHOST_kStandardCursorUpDown);
614   DEF_CURSOR(sb_h_double_arrow, GHOST_kStandardCursorLeftRight);
615   DEF_CURSOR(top_side, GHOST_kStandardCursorTopSide);
616   DEF_CURSOR(bottom_side, GHOST_kStandardCursorBottomSide);
617   DEF_CURSOR(left_side, GHOST_kStandardCursorLeftSide);
618   DEF_CURSOR(right_side, GHOST_kStandardCursorRightSide);
619   DEF_CURSOR(top_left_corner, GHOST_kStandardCursorTopLeftCorner);
620   DEF_CURSOR(top_right_corner, GHOST_kStandardCursorTopRightCorner);
621   DEF_CURSOR(bottom_right_corner, GHOST_kStandardCursorBottomRightCorner);
622   DEF_CURSOR(bottom_left_corner, GHOST_kStandardCursorBottomLeftCorner);
623   DEF_CURSOR(arrow, GHOST_kStandardCursorCopy);
624   //DEF_CURSOR(arrow, GHOST_kStandardCursorCustom);
625   DEF_CURSOR(arrow, GHOST_kStandardCursorPencil);
626
627 #undef DEF_CURSOR
628 }
629
630 GHOST_TSuccess GHOST_WindowSDL::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
631 {
632   return GHOST_kSuccess;
633 }
634
635 GHOST_TSuccess GHOST_WindowSDL::setWindowCursorShape(GHOST_TStandardCursor shape)
636 {
637   if (sdl_std_cursor_array[0] == NULL) {
638     sdl_cursor_init();
639   }
640
641   SDL_SetCursor(sdl_std_cursor_array[(int)shape]);
642   return GHOST_kSuccess;
643 }
644
645 GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
646                                                            GHOST_TUns8 mask[16][2],
647                                                            int hotX,
648                                                            int hotY)
649 {
650   return setWindowCustomCursorShape(
651       (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask, 16, 16, hotX, hotY, 0, 1);
652 }
653
654 GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
655                                                            GHOST_TUns8 *mask,
656                                                            int sizex,
657                                                            int sizey,
658                                                            int hotX,
659                                                            int hotY,
660                                                            int fg_color,
661                                                            int bg_color)
662 {
663   if (m_sdl_custom_cursor) {
664     SDL_FreeCursor(m_sdl_custom_cursor);
665   }
666
667   m_sdl_custom_cursor = sdl_ghost_CreateCursor(
668       (const Uint8 *)bitmap, (const Uint8 *)mask, sizex, sizex, hotX, hotY);
669
670   SDL_SetCursor(m_sdl_custom_cursor);
671   return GHOST_kSuccess;
672 }
673
674 GHOST_TSuccess GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
675 {
676   SDL_ShowCursor(visible);
677   return GHOST_kSuccess;
678 }
679
680 GHOST_TUns16 GHOST_WindowSDL::getDPIHint()
681 {
682   int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win);
683   if (displayIndex < 0) {
684     return 96;
685   }
686
687   float ddpi;
688   if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) {
689     return 96;
690   }
691
692   return (int)ddpi;
693 }