Mercurial > sdl-ios-xcode
annotate src/video/SDL_cursor.c @ 1629:ef4a796e7f24
Fixed bug #55
From Christian Walther:
When writing my patch for #12, I ended up doing all sorts of changes to the way
application/window activating/deactivating is handled in the Quartz backend,
resulting in the attached patch. It does make the code a bit cleaner IMHO, but
as it might be regarded as a case of "if it ain't broken, don't fix it" I'd
like to hear other people's opinion about it. Please shout if some change
strikes you as unnecessary or wrong, and I'll explain the reasons behind it. As
far as I tested it, it does not introduce any new bugs, but I may well have
missed some.
- The most fundamental change (that triggered most of the others) is irrelevant
for the usual single-window SDL applications, it only affects the people who
are crazy enough to display other Cocoa windows alongside the SDL window (I'm
actually doing this currently, although the additional window only displays
debugging info and won't be present in the final product): Before, some things
were done on the application becoming active, some on the window becoming key,
and some on the window becoming main. Conceptually, all these actions belong to
the window becoming key, so that's what I implemented. However, since in a
single-window application these three events always happen together, the
previous implementation "ain't broken".
- This slightly changed the meaning of the SDL_APPMOUSEFOCUS flag from
SDL_GetAppState(): Before, it meant "window is main and mouse is inside window
(or mode is fullscreen)". Now, it means "window is key and mouse is inside
window (or mode is fullscreen)". It makes more sense to me that way. (See
http://developer.apple.com/documentation/Cocoa/Conceptual/WinPanel/Concepts/ChangingMainKeyWindow.html
for a discussion of what key and main windows are.) The other two flags are
unchanged: SDL_APPACTIVE = application is not hidden and window is not
minimized, SDL_APPINPUTFOCUS = window is key (or mode is fullscreen).
- As a side effect, the reorganization fixes the following two issues (and
maybe others) (but they could also be fixed in less invasive ways):
* A regression that was introduced in revision 1.42 of SDL_QuartzVideo.m
(http://libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzVideo.m.diff?r1=1.41&r2=1.42)
(from half-desirable to undesirable behavior):
Situation: While in windowed mode, hide the cursor using
SDL_ShowCursor(SDL_DISABLE), move the mouse outside of the window so that the
cursor becomes visible again, and SDL_SetVideoMode() to a fullscreen mode.
What happened before revision 1.42: The cursor is visible, but becomes
invisible as soon as the mouse is moved (half-desirable).
What happens in revision 1.42 and after (including current CVS): The cursor is
visible and stays visible (undesirable).
What happens after my patch: The cursor is invisible from the beginning
(desirable).
* When the cursor is hidden and grabbed, switch away from the application using
cmd-tab (which ungrabs and makes the cursor visible), move the cursor outside
of the SDL window, then cmd-tab back to the application. In 1.2.8 and in the
current CVS, the cursor is re-grabbed, but it stays visible (immovable in the
middle of the window). With my patch, the cursor is correctly re-grabbed and
hidden. (For some reason, it still doesn't work correctly if you switch back to
the application using the dock instead of cmd-tab. I haven't been able to
figure out why. I can step over [NSCursor hide] being called in the debugger,
but it seems to have no effect.)
- The patch includes my patch for #12 (it was easier to obtain using cvs diff
that way). If you apply both of them, you will end up with 6 duplicate lines in
SDL_QuartzEvents.m.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 13 Apr 2006 14:17:48 +0000 |
parents | 5f52867ba65c |
children | 782fd950bd46 37dab4a917c4 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library 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 GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
113
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
24 /* General cursor handling code for SDL */ | |
25 | |
26 #include "SDL_mutex.h" | |
27 #include "SDL_video.h" | |
28 #include "SDL_mouse.h" | |
29 #include "SDL_blit.h" | |
30 #include "SDL_sysvideo.h" | |
31 #include "SDL_cursor_c.h" | |
32 #include "SDL_pixels_c.h" | |
33 #include "default_cursor.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
34 #include "../events/SDL_sysevents.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
35 #include "../events/SDL_events_c.h" |
0 | 36 |
37 /* These are static for our cursor handling code */ | |
38 volatile int SDL_cursorstate = CURSOR_VISIBLE; | |
39 SDL_Cursor *SDL_cursor = NULL; | |
40 static SDL_Cursor *SDL_defcursor = NULL; | |
41 SDL_mutex *SDL_cursorlock = NULL; | |
42 | |
43 /* Public functions */ | |
44 void SDL_CursorQuit(void) | |
45 { | |
46 if ( SDL_cursor != NULL ) { | |
47 SDL_Cursor *cursor; | |
48 | |
49 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
50 if ( SDL_cursor != SDL_defcursor ) { | |
51 SDL_FreeCursor(SDL_cursor); | |
52 } | |
53 SDL_cursor = NULL; | |
54 if ( SDL_defcursor != NULL ) { | |
55 cursor = SDL_defcursor; | |
56 SDL_defcursor = NULL; | |
57 SDL_FreeCursor(cursor); | |
58 } | |
59 } | |
60 if ( SDL_cursorlock != NULL ) { | |
61 SDL_DestroyMutex(SDL_cursorlock); | |
62 SDL_cursorlock = NULL; | |
63 } | |
64 } | |
65 int SDL_CursorInit(Uint32 multithreaded) | |
66 { | |
67 /* We don't have mouse focus, and the cursor isn't drawn yet */ | |
1140
af8b0f9ac2f4
iPod Linux framebuffer support.
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
68 #ifndef IPOD |
0 | 69 SDL_cursorstate = CURSOR_VISIBLE; |
1140
af8b0f9ac2f4
iPod Linux framebuffer support.
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
70 #endif |
0 | 71 |
72 /* Create the default cursor */ | |
73 if ( SDL_defcursor == NULL ) { | |
74 SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask, | |
75 DEFAULT_CWIDTH, DEFAULT_CHEIGHT, | |
76 DEFAULT_CHOTX, DEFAULT_CHOTY); | |
77 SDL_SetCursor(SDL_defcursor); | |
78 } | |
79 | |
80 /* Create a lock if necessary */ | |
81 if ( multithreaded ) { | |
82 SDL_cursorlock = SDL_CreateMutex(); | |
83 } | |
84 | |
85 /* That's it! */ | |
86 return(0); | |
87 } | |
88 | |
89 /* Multi-thread support for cursors */ | |
90 #ifndef SDL_LockCursor | |
91 void SDL_LockCursor(void) | |
92 { | |
93 if ( SDL_cursorlock ) { | |
94 SDL_mutexP(SDL_cursorlock); | |
95 } | |
96 } | |
97 #endif | |
98 #ifndef SDL_UnlockCursor | |
99 void SDL_UnlockCursor(void) | |
100 { | |
101 if ( SDL_cursorlock ) { | |
102 SDL_mutexV(SDL_cursorlock); | |
103 } | |
104 } | |
105 #endif | |
106 | |
107 /* Software cursor drawing support */ | |
108 SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, | |
109 int w, int h, int hot_x, int hot_y) | |
110 { | |
111 SDL_VideoDevice *video = current_video; | |
112 int savelen; | |
113 int i; | |
114 SDL_Cursor *cursor; | |
115 | |
116 /* Make sure the width is a multiple of 8 */ | |
117 w = ((w+7)&~7); | |
118 | |
119 /* Sanity check the hot spot */ | |
120 if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) { | |
121 SDL_SetError("Cursor hot spot doesn't lie within cursor"); | |
122 return(NULL); | |
123 } | |
124 | |
125 /* Allocate memory for the cursor */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
126 cursor = (SDL_Cursor *)SDL_malloc(sizeof *cursor); |
0 | 127 if ( cursor == NULL ) { |
128 SDL_OutOfMemory(); | |
129 return(NULL); | |
130 } | |
131 savelen = (w*4)*h; | |
132 cursor->area.x = 0; | |
133 cursor->area.y = 0; | |
134 cursor->area.w = w; | |
135 cursor->area.h = h; | |
136 cursor->hot_x = hot_x; | |
137 cursor->hot_y = hot_y; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
138 cursor->data = (Uint8 *)SDL_malloc((w/8)*h*2); |
0 | 139 cursor->mask = cursor->data+((w/8)*h); |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
140 cursor->save[0] = (Uint8 *)SDL_malloc(savelen*2); |
0 | 141 cursor->save[1] = cursor->save[0] + savelen; |
142 cursor->wm_cursor = NULL; | |
143 if ( ! cursor->data || ! cursor->save[0] ) { | |
144 SDL_FreeCursor(cursor); | |
145 SDL_OutOfMemory(); | |
146 return(NULL); | |
147 } | |
148 for ( i=((w/8)*h)-1; i>=0; --i ) { | |
149 cursor->data[i] = data[i]; | |
150 cursor->mask[i] = mask[i] | data[i]; | |
151 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
152 SDL_memset(cursor->save[0], 0, savelen*2); |
0 | 153 |
154 /* If the window manager gives us a good cursor, we're done! */ | |
155 if ( video->CreateWMCursor ) { | |
156 cursor->wm_cursor = video->CreateWMCursor(video, data, mask, | |
157 w, h, hot_x, hot_y); | |
158 } else { | |
159 cursor->wm_cursor = NULL; | |
160 } | |
161 return(cursor); | |
162 } | |
163 | |
164 /* SDL_SetCursor(NULL) can be used to force the cursor redraw, | |
165 if this is desired for any reason. This is used when setting | |
166 the video mode and when the SDL window gains the mouse focus. | |
167 */ | |
168 void SDL_SetCursor (SDL_Cursor *cursor) | |
169 { | |
170 SDL_VideoDevice *video = current_video; | |
171 SDL_VideoDevice *this = current_video; | |
172 | |
173 /* Make sure that the video subsystem has been initialized */ | |
174 if ( ! video ) { | |
175 return; | |
176 } | |
177 | |
178 /* Prevent the event thread from moving the mouse */ | |
179 SDL_LockCursor(); | |
180 | |
181 /* Set the new cursor */ | |
182 if ( cursor && (cursor != SDL_cursor) ) { | |
183 /* Erase the current mouse position */ | |
184 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
185 SDL_EraseCursor(SDL_VideoSurface); | |
186 } else if ( video->MoveWMCursor ) { | |
187 /* If the video driver is moving the cursor directly, | |
188 it needs to hide the old cursor before (possibly) | |
189 showing the new one. (But don't erase NULL cursor) | |
190 */ | |
191 if ( SDL_cursor ) { | |
192 video->ShowWMCursor(this, NULL); | |
193 } | |
194 } | |
195 SDL_cursor = cursor; | |
196 } | |
197 | |
198 /* Draw the new mouse cursor */ | |
199 if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) { | |
200 /* Use window manager cursor if possible */ | |
201 if ( SDL_cursor->wm_cursor && | |
1296 | 202 video->ShowWMCursor(this, SDL_cursor->wm_cursor) ) { |
0 | 203 SDL_cursorstate &= ~CURSOR_USINGSW; |
1296 | 204 } else { |
0 | 205 SDL_cursorstate |= CURSOR_USINGSW; |
206 if ( video->ShowWMCursor ) { | |
207 video->ShowWMCursor(this, NULL); | |
208 } | |
209 { int x, y; | |
210 SDL_GetMouseState(&x, &y); | |
211 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
212 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
213 } | |
214 SDL_DrawCursor(SDL_VideoSurface); | |
215 } | |
216 } else { | |
217 /* Erase window manager mouse (cursor not visible) */ | |
218 if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) { | |
219 SDL_EraseCursor(SDL_VideoSurface); | |
220 } else { | |
221 if ( video ) { | |
222 video->ShowWMCursor(this, NULL); | |
223 } | |
224 } | |
225 } | |
226 SDL_UnlockCursor(); | |
227 } | |
228 | |
229 SDL_Cursor * SDL_GetCursor (void) | |
230 { | |
231 return(SDL_cursor); | |
232 } | |
233 | |
234 void SDL_FreeCursor (SDL_Cursor *cursor) | |
235 { | |
236 if ( cursor ) { | |
237 if ( cursor == SDL_cursor ) { | |
238 SDL_SetCursor(SDL_defcursor); | |
239 } | |
240 if ( cursor != SDL_defcursor ) { | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
241 SDL_VideoDevice *video = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
242 SDL_VideoDevice *this = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
243 |
0 | 244 if ( cursor->data ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
245 SDL_free(cursor->data); |
0 | 246 } |
247 if ( cursor->save[0] ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
248 SDL_free(cursor->save[0]); |
0 | 249 } |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
250 if ( video && cursor->wm_cursor ) { |
0 | 251 video->FreeWMCursor(this, cursor->wm_cursor); |
252 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
253 SDL_free(cursor); |
0 | 254 } |
255 } | |
256 } | |
257 | |
258 int SDL_ShowCursor (int toggle) | |
259 { | |
260 int showing; | |
261 | |
262 showing = (SDL_cursorstate & CURSOR_VISIBLE); | |
263 if ( toggle >= 0 ) { | |
264 SDL_LockCursor(); | |
265 if ( toggle ) { | |
266 SDL_cursorstate |= CURSOR_VISIBLE; | |
267 } else { | |
268 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
269 } | |
270 SDL_UnlockCursor(); | |
271 if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) { | |
272 SDL_VideoDevice *video = current_video; | |
273 SDL_VideoDevice *this = current_video; | |
274 | |
275 SDL_SetCursor(NULL); | |
276 if ( video && video->CheckMouseMode ) { | |
277 video->CheckMouseMode(this); | |
278 } | |
279 } | |
280 } else { | |
281 /* Query current state */ ; | |
282 } | |
283 return(showing ? 1 : 0); | |
284 } | |
285 | |
286 void SDL_WarpMouse (Uint16 x, Uint16 y) | |
287 { | |
288 SDL_VideoDevice *video = current_video; | |
289 SDL_VideoDevice *this = current_video; | |
290 | |
595
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
291 if ( !video || !SDL_PublicSurface ) { |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
292 SDL_SetError("A video mode must be set before warping mouse"); |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
293 return; |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
294 } |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
295 |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
296 /* If we have an offset video mode, offset the mouse coordinates */ |
1163
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
297 if (this->screen->pitch == 0) { |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
298 x += this->screen->offset / this->screen->format->BytesPerPixel; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
299 y += this->screen->offset; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
300 } else { |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
301 x += (this->screen->offset % this->screen->pitch) / |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
302 this->screen->format->BytesPerPixel; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
303 y += (this->screen->offset / this->screen->pitch); |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
304 } |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
305 |
0 | 306 /* This generates a mouse motion event */ |
307 if ( video->WarpWMCursor ) { | |
308 video->WarpWMCursor(this, x, y); | |
309 } else { | |
310 SDL_PrivateMouseMotion(0, 0, x, y); | |
311 } | |
312 } | |
313 | |
314 void SDL_MoveCursor(int x, int y) | |
315 { | |
316 SDL_VideoDevice *video = current_video; | |
317 | |
318 /* Erase and update the current mouse position */ | |
319 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
320 /* Erase and redraw mouse cursor in new position */ | |
321 SDL_LockCursor(); | |
322 SDL_EraseCursor(SDL_VideoSurface); | |
323 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
324 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
325 SDL_DrawCursor(SDL_VideoSurface); | |
326 SDL_UnlockCursor(); | |
327 } else if ( video->MoveWMCursor ) { | |
328 video->MoveWMCursor(video, x, y); | |
329 } | |
330 } | |
331 | |
332 /* Keep track of the current cursor colors */ | |
333 static int palette_changed = 1; | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
334 static Uint8 pixels8[2]; |
0 | 335 |
336 void SDL_CursorPaletteChanged(void) | |
337 { | |
338 palette_changed = 1; | |
339 } | |
340 | |
341 void SDL_MouseRect(SDL_Rect *area) | |
342 { | |
343 int clip_diff; | |
344 | |
345 *area = SDL_cursor->area; | |
346 if ( area->x < 0 ) { | |
347 area->w += area->x; | |
348 area->x = 0; | |
349 } | |
350 if ( area->y < 0 ) { | |
351 area->h += area->y; | |
352 area->y = 0; | |
353 } | |
354 clip_diff = (area->x+area->w)-SDL_VideoSurface->w; | |
355 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
356 area->w = area->w < clip_diff ? 0 : area->w-clip_diff; |
0 | 357 } |
358 clip_diff = (area->y+area->h)-SDL_VideoSurface->h; | |
359 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
360 area->h = area->h < clip_diff ? 0 : area->h-clip_diff; |
0 | 361 } |
362 } | |
363 | |
364 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) | |
365 { | |
366 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; | |
367 int i, w, h; | |
368 Uint8 *data, datab; | |
369 Uint8 *mask, maskb; | |
370 | |
371 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
372 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
373 switch (screen->format->BytesPerPixel) { | |
374 | |
375 case 1: { | |
376 Uint8 *dst; | |
377 int dstskip; | |
378 | |
379 if ( palette_changed ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
380 pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); |
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
381 pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); |
0 | 382 palette_changed = 0; |
383 } | |
384 dst = (Uint8 *)screen->pixels + | |
385 (SDL_cursor->area.y+area->y)*screen->pitch + | |
386 SDL_cursor->area.x; | |
387 dstskip = screen->pitch-area->w; | |
388 | |
389 for ( h=area->h; h; h-- ) { | |
390 for ( w=area->w/8; w; w-- ) { | |
391 maskb = *mask++; | |
392 datab = *data++; | |
393 for ( i=0; i<8; ++i ) { | |
394 if ( maskb & 0x80 ) { | |
395 *dst = pixels8[datab>>7]; | |
396 } | |
397 maskb <<= 1; | |
398 datab <<= 1; | |
399 dst++; | |
400 } | |
401 } | |
402 dst += dstskip; | |
403 } | |
404 } | |
405 break; | |
406 | |
407 case 2: { | |
408 Uint16 *dst; | |
409 int dstskip; | |
410 | |
411 dst = (Uint16 *)screen->pixels + | |
412 (SDL_cursor->area.y+area->y)*screen->pitch/2 + | |
413 SDL_cursor->area.x; | |
414 dstskip = (screen->pitch/2)-area->w; | |
415 | |
416 for ( h=area->h; h; h-- ) { | |
417 for ( w=area->w/8; w; w-- ) { | |
418 maskb = *mask++; | |
419 datab = *data++; | |
420 for ( i=0; i<8; ++i ) { | |
421 if ( maskb & 0x80 ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
422 *dst = (Uint16)pixels[datab>>7]; |
0 | 423 } |
424 maskb <<= 1; | |
425 datab <<= 1; | |
426 dst++; | |
427 } | |
428 } | |
429 dst += dstskip; | |
430 } | |
431 } | |
432 break; | |
433 | |
434 case 3: { | |
435 Uint8 *dst; | |
436 int dstskip; | |
437 | |
438 dst = (Uint8 *)screen->pixels + | |
439 (SDL_cursor->area.y+area->y)*screen->pitch + | |
440 SDL_cursor->area.x*3; | |
441 dstskip = screen->pitch-area->w*3; | |
442 | |
443 for ( h=area->h; h; h-- ) { | |
444 for ( w=area->w/8; w; w-- ) { | |
445 maskb = *mask++; | |
446 datab = *data++; | |
447 for ( i=0; i<8; ++i ) { | |
448 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
449 SDL_memset(dst,pixels[datab>>7],3); |
0 | 450 } |
451 maskb <<= 1; | |
452 datab <<= 1; | |
453 dst += 3; | |
454 } | |
455 } | |
456 dst += dstskip; | |
457 } | |
458 } | |
459 break; | |
460 | |
461 case 4: { | |
462 Uint32 *dst; | |
463 int dstskip; | |
464 | |
465 dst = (Uint32 *)screen->pixels + | |
466 (SDL_cursor->area.y+area->y)*screen->pitch/4 + | |
467 SDL_cursor->area.x; | |
468 dstskip = (screen->pitch/4)-area->w; | |
469 | |
470 for ( h=area->h; h; h-- ) { | |
471 for ( w=area->w/8; w; w-- ) { | |
472 maskb = *mask++; | |
473 datab = *data++; | |
474 for ( i=0; i<8; ++i ) { | |
475 if ( maskb & 0x80 ) { | |
476 *dst = pixels[datab>>7]; | |
477 } | |
478 maskb <<= 1; | |
479 datab <<= 1; | |
480 dst++; | |
481 } | |
482 } | |
483 dst += dstskip; | |
484 } | |
485 } | |
486 break; | |
487 } | |
488 } | |
489 | |
490 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) | |
491 { | |
492 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; | |
493 int h; | |
494 int x, minx, maxx; | |
495 Uint8 *data, datab = 0; | |
496 Uint8 *mask, maskb = 0; | |
497 Uint8 *dst; | |
498 int dstbpp, dstskip; | |
499 | |
500 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
501 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
502 dstbpp = screen->format->BytesPerPixel; | |
503 dst = (Uint8 *)screen->pixels + | |
504 (SDL_cursor->area.y+area->y)*screen->pitch + | |
505 SDL_cursor->area.x*dstbpp; | |
506 dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; | |
507 | |
508 minx = area->x; | |
509 maxx = area->x+area->w; | |
510 if ( screen->format->BytesPerPixel == 1 ) { | |
511 if ( palette_changed ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
512 pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); |
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
513 pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); |
0 | 514 palette_changed = 0; |
515 } | |
516 for ( h=area->h; h; h-- ) { | |
517 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
518 if ( (x%8) == 0 ) { | |
519 maskb = *mask++; | |
520 datab = *data++; | |
521 } | |
522 if ( (x >= minx) && (x < maxx) ) { | |
523 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
524 SDL_memset(dst, pixels8[datab>>7], dstbpp); |
0 | 525 } |
526 } | |
527 maskb <<= 1; | |
528 datab <<= 1; | |
529 dst += dstbpp; | |
530 } | |
531 dst += dstskip; | |
532 } | |
533 } else { | |
534 for ( h=area->h; h; h-- ) { | |
535 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
536 if ( (x%8) == 0 ) { | |
537 maskb = *mask++; | |
538 datab = *data++; | |
539 } | |
540 if ( (x >= minx) && (x < maxx) ) { | |
541 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
542 SDL_memset(dst, pixels[datab>>7], dstbpp); |
0 | 543 } |
544 } | |
545 maskb <<= 1; | |
546 datab <<= 1; | |
547 dst += dstbpp; | |
548 } | |
549 dst += dstskip; | |
550 } | |
551 } | |
552 } | |
553 | |
554 /* This handles the ugly work of converting the saved cursor background from | |
555 the pixel format of the shadow surface to that of the video surface. | |
556 This is only necessary when blitting from a shadow surface of a different | |
557 pixel format than the video surface, and using a software rendered cursor. | |
558 */ | |
559 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) | |
560 { | |
561 SDL_BlitInfo info; | |
562 SDL_loblit RunBlit; | |
563 | |
564 /* Make sure we can steal the blit mapping */ | |
565 if ( screen->map->dst != SDL_VideoSurface ) { | |
566 return; | |
567 } | |
568 | |
569 /* Set up the blit information */ | |
570 info.s_pixels = SDL_cursor->save[1]; | |
571 info.s_width = w; | |
572 info.s_height = h; | |
573 info.s_skip = 0; | |
574 info.d_pixels = SDL_cursor->save[0]; | |
575 info.d_width = w; | |
576 info.d_height = h; | |
577 info.d_skip = 0; | |
578 info.aux_data = screen->map->sw_data->aux_data; | |
579 info.src = screen->format; | |
580 info.table = screen->map->table; | |
581 info.dst = SDL_VideoSurface->format; | |
582 RunBlit = screen->map->sw_data->blit; | |
583 | |
584 /* Run the actual software blit */ | |
585 RunBlit(&info); | |
586 } | |
587 | |
588 void SDL_DrawCursorNoLock(SDL_Surface *screen) | |
589 { | |
590 SDL_Rect area; | |
591 | |
592 /* Get the mouse rectangle, clipped to the screen */ | |
593 SDL_MouseRect(&area); | |
594 if ( (area.w == 0) || (area.h == 0) ) { | |
595 return; | |
596 } | |
597 | |
598 /* Copy mouse background */ | |
599 { int w, h, screenbpp; | |
600 Uint8 *src, *dst; | |
601 | |
602 /* Set up the copy pointers */ | |
603 screenbpp = screen->format->BytesPerPixel; | |
604 if ( (screen == SDL_VideoSurface) || | |
605 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
606 dst = SDL_cursor->save[0]; | |
607 } else { | |
608 dst = SDL_cursor->save[1]; | |
609 } | |
610 src = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
611 area.x * screenbpp; | |
612 | |
613 /* Perform the copy */ | |
614 w = area.w*screenbpp; | |
615 h = area.h; | |
616 while ( h-- ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
617 SDL_memcpy(dst, src, w); |
0 | 618 dst += w; |
619 src += screen->pitch; | |
620 } | |
621 } | |
622 | |
623 /* Draw the mouse cursor */ | |
624 area.x -= SDL_cursor->area.x; | |
625 area.y -= SDL_cursor->area.y; | |
626 if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { | |
627 SDL_DrawCursorFast(screen, &area); | |
628 } else { | |
629 SDL_DrawCursorSlow(screen, &area); | |
630 } | |
631 } | |
632 | |
633 void SDL_DrawCursor(SDL_Surface *screen) | |
634 { | |
635 /* Lock the screen if necessary */ | |
636 if ( screen == NULL ) { | |
637 return; | |
638 } | |
639 if ( SDL_MUSTLOCK(screen) ) { | |
640 if ( SDL_LockSurface(screen) < 0 ) { | |
641 return; | |
642 } | |
643 } | |
644 | |
645 SDL_DrawCursorNoLock(screen); | |
646 | |
647 /* Unlock the screen and update if necessary */ | |
648 if ( SDL_MUSTLOCK(screen) ) { | |
649 SDL_UnlockSurface(screen); | |
650 } | |
651 if ( (screen == SDL_VideoSurface) && | |
652 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
653 SDL_VideoDevice *video = current_video; | |
654 SDL_VideoDevice *this = current_video; | |
655 SDL_Rect area; | |
656 | |
657 SDL_MouseRect(&area); | |
658 | |
659 /* This can be called before a video mode is set */ | |
660 if ( video->UpdateRects ) { | |
661 video->UpdateRects(this, 1, &area); | |
662 } | |
663 } | |
664 } | |
665 | |
666 void SDL_EraseCursorNoLock(SDL_Surface *screen) | |
667 { | |
668 SDL_Rect area; | |
669 | |
670 /* Get the mouse rectangle, clipped to the screen */ | |
671 SDL_MouseRect(&area); | |
672 if ( (area.w == 0) || (area.h == 0) ) { | |
673 return; | |
674 } | |
675 | |
676 /* Copy mouse background */ | |
677 { int w, h, screenbpp; | |
678 Uint8 *src, *dst; | |
679 | |
680 /* Set up the copy pointers */ | |
681 screenbpp = screen->format->BytesPerPixel; | |
682 if ( (screen == SDL_VideoSurface) || | |
683 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
684 src = SDL_cursor->save[0]; | |
685 } else { | |
686 src = SDL_cursor->save[1]; | |
687 } | |
688 dst = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
689 area.x * screenbpp; | |
690 | |
691 /* Perform the copy */ | |
692 w = area.w*screenbpp; | |
693 h = area.h; | |
694 while ( h-- ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
695 SDL_memcpy(dst, src, w); |
0 | 696 src += w; |
697 dst += screen->pitch; | |
698 } | |
699 | |
700 /* Perform pixel conversion on cursor background */ | |
701 if ( src > SDL_cursor->save[1] ) { | |
702 SDL_ConvertCursorSave(screen, area.w, area.h); | |
703 } | |
704 } | |
705 } | |
706 | |
707 void SDL_EraseCursor(SDL_Surface *screen) | |
708 { | |
709 /* Lock the screen if necessary */ | |
710 if ( screen == NULL ) { | |
711 return; | |
712 } | |
713 if ( SDL_MUSTLOCK(screen) ) { | |
714 if ( SDL_LockSurface(screen) < 0 ) { | |
715 return; | |
716 } | |
717 } | |
718 | |
719 SDL_EraseCursorNoLock(screen); | |
720 | |
721 /* Unlock the screen and update if necessary */ | |
722 if ( SDL_MUSTLOCK(screen) ) { | |
723 SDL_UnlockSurface(screen); | |
724 } | |
725 if ( (screen == SDL_VideoSurface) && | |
726 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
727 SDL_VideoDevice *video = current_video; | |
728 SDL_VideoDevice *this = current_video; | |
729 SDL_Rect area; | |
730 | |
731 SDL_MouseRect(&area); | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
732 if ( video->UpdateRects ) { |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
733 video->UpdateRects(this, 1, &area); |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
734 } |
0 | 735 } |
736 } | |
737 | |
738 /* Reset the cursor on video mode change | |
739 FIXME: Keep track of all cursors, and reset them all. | |
740 */ | |
741 void SDL_ResetCursor(void) | |
742 { | |
743 int savelen; | |
744 | |
745 if ( SDL_cursor ) { | |
746 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; | |
747 SDL_cursor->area.x = 0; | |
748 SDL_cursor->area.y = 0; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
749 SDL_memset(SDL_cursor->save[0], 0, savelen); |
0 | 750 } |
751 } |