comparison src/video/wincommon/SDL_sysmouse.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children e30a8ce27c22
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@devolution.com
21 */
22
23 #ifdef SAVE_RCSID
24 static char rcsid =
25 "@(#) $Id$";
26 #endif
27
28 #include <stdlib.h>
29 #include <windows.h>
30
31 #include "SDL_error.h"
32 #include "SDL_mouse.h"
33 #include "SDL_sysmouse_c.h"
34 #include "SDL_events_c.h"
35 #include "SDL_cursor_c.h"
36 #include "SDL_lowvideo.h"
37
38 #ifdef _WIN32_WCE
39 #define USE_STATIC_CURSOR
40 #endif
41
42 HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */
43
44 /* The implementation dependent data for the window manager cursor */
45 /* For some reason when creating a windows cursor, the ands and xors memory
46 is not copied, so we need to keep track of it and free it when we are done
47 with the cursor. If we free the memory prematurely, the app crashes. :-}
48 */
49 struct WMcursor {
50 HCURSOR curs;
51 #ifndef USE_STATIC_CURSOR
52 Uint8 *ands;
53 Uint8 *xors;
54 #endif
55 };
56
57 /* Convert bits to padded bytes */
58 #define PAD_BITS(bits) ((bits+7)/8)
59
60 #ifdef CURSOR_DEBUG
61 static void PrintBITMAP(FILE *out, char *bits, int w, int h)
62 {
63 int i;
64 unsigned char ch;
65
66 while ( h-- > 0 ) {
67 for ( i=0; i<w; ++i ) {
68 if ( (i%8) == 0 )
69 ch = *bits++;
70 if ( ch&0x80 )
71 fprintf(out, "X");
72 else
73 fprintf(out, " ");
74 ch <<= 1;
75 }
76 fprintf(out, "\n");
77 }
78 }
79 #endif
80
81 #ifndef USE_STATIC_CURSOR
82 /* Local functions to convert the SDL cursor mask into Windows format */
83 static void memnot(Uint8 *dst, Uint8 *src, int len)
84 {
85 while ( len-- > 0 )
86 *dst++ = ~*src++;
87 }
88 static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
89 {
90 while ( len-- > 0 )
91 *dst++ = (*src1++)^(*src2++);
92 }
93 #endif /* !USE_STATIC_CURSOR */
94
95 void WIN_FreeWMCursor(_THIS, WMcursor *cursor)
96 {
97 #ifndef USE_STATIC_CURSOR
98 if ( cursor->curs != NULL )
99 DestroyCursor(cursor->curs);
100 if ( cursor->ands != NULL )
101 free(cursor->ands);
102 if ( cursor->xors != NULL )
103 free(cursor->xors);
104 #endif /* !USE_STATIC_CURSOR */
105 free(cursor);
106 }
107
108 WMcursor *WIN_CreateWMCursor(_THIS,
109 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
110 {
111 #ifdef USE_STATIC_CURSOR
112 WMcursor *cursor;
113
114 /* Allocate the cursor */
115 cursor = (WMcursor *)malloc(sizeof(*cursor));
116 if ( cursor ) {
117 cursor->curs = LoadCursor(NULL, IDC_ARROW);
118 }
119 return(cursor);
120 #else
121 WMcursor *cursor;
122 int allowed_x;
123 int allowed_y;
124 int run, pad, i;
125 Uint8 *aptr, *xptr;
126
127 /* Check to make sure the cursor size is okay */
128 allowed_x = GetSystemMetrics(SM_CXCURSOR);
129 allowed_y = GetSystemMetrics(SM_CYCURSOR);
130 if ( (w > allowed_x) || (h > allowed_y) ) {
131 SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
132 allowed_x, allowed_y);
133 return(NULL);
134 }
135
136 /* Allocate the cursor */
137 cursor = (WMcursor *)malloc(sizeof(*cursor));
138 if ( cursor == NULL ) {
139 SDL_SetError("Out of memory");
140 return(NULL);
141 }
142 cursor->curs = NULL;
143 cursor->ands = NULL;
144 cursor->xors = NULL;
145
146 /* Pad out to the normal cursor size */
147 run = PAD_BITS(w);
148 pad = PAD_BITS(allowed_x)-run;
149 aptr = cursor->ands = (Uint8 *)malloc((run+pad)*allowed_y);
150 xptr = cursor->xors = (Uint8 *)malloc((run+pad)*allowed_y);
151 if ( (aptr == NULL) || (xptr == NULL) ) {
152 WIN_FreeWMCursor(NULL, cursor);
153 SDL_OutOfMemory();
154 return(NULL);
155 }
156 for ( i=0; i<h; ++i ) {
157 memxor(xptr, data, mask, run);
158 xptr += run;
159 data += run;
160 memnot(aptr, mask, run);
161 mask += run;
162 aptr += run;
163 memset(xptr, 0, pad);
164 xptr += pad;
165 memset(aptr, ~0, pad);
166 aptr += pad;
167 }
168 pad += run;
169 for ( ; i<allowed_y; ++i ) {
170 memset(xptr, 0, pad);
171 xptr += pad;
172 memset(aptr, ~0, pad);
173 aptr += pad;
174 }
175
176 /* Create the cursor */
177 cursor->curs = CreateCursor(
178 (HINSTANCE)GetWindowLong(SDL_Window, GWL_HINSTANCE),
179 hot_x, hot_y, allowed_x, allowed_y,
180 cursor->ands, cursor->xors);
181 if ( cursor->curs == NULL ) {
182 WIN_FreeWMCursor(NULL, cursor);
183 SDL_SetError("Windows couldn't create the requested cursor");
184 return(NULL);
185 }
186 return(cursor);
187 #endif /* USE_STATIC_CURSOR */
188 }
189
190 int WIN_ShowWMCursor(_THIS, WMcursor *cursor)
191 {
192 POINT mouse_pos;
193
194 /* The fullscreen cursor must be done in software with DirectInput */
195 if ( !this->screen || DIRECTX_FULLSCREEN() ) {
196 return(0);
197 }
198
199 /* Set the window cursor to our cursor, if applicable */
200 if ( cursor != NULL ) {
201 SDL_hcursor = cursor->curs;
202 } else {
203 SDL_hcursor = NULL;
204 }
205 GetCursorPos(&mouse_pos);
206 if ( PtInRect(&SDL_bounds, mouse_pos) ) {
207 SetCursor(SDL_hcursor);
208 }
209 return(1);
210 }
211
212 void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
213 {
214 POINT pt;
215
216 if ( DIRECTX_FULLSCREEN() ) {
217 x += (this->screen->offset % this->screen->pitch) /
218 this->screen->format->BytesPerPixel;
219 y += (this->screen->offset / this->screen->pitch);
220 SDL_PrivateMouseMotion(0, 0, x, y);
221 } else if ( mouse_relative) {
222 /* RJR: March 28, 2000
223 leave physical cursor at center of screen if
224 mouse hidden and grabbed */
225 SDL_PrivateMouseMotion(0, 0, x, y);
226 } else {
227 pt.x = x;
228 pt.y = y;
229 ClientToScreen(SDL_Window, &pt);
230 SetCursorPos(pt.x, pt.y);
231 }
232 }
233
234 /* Update the current mouse state and position */
235 void WIN_UpdateMouse(_THIS)
236 {
237 RECT rect;
238 POINT pt;
239
240 if ( ! DIRECTX_FULLSCREEN() ) {
241 GetClientRect(SDL_Window, &rect);
242 GetCursorPos(&pt);
243 MapWindowPoints(NULL, SDL_Window, &pt, 1);
244 if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)){
245 SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
246 SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
247 } else {
248 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
249 }
250 }
251 }
252
253 /* Check to see if we need to enter or leave mouse relative mode */
254 void WIN_CheckMouseMode(_THIS)
255 {
256 /* If the mouse is hidden and input is grabbed, we use relative mode */
257 if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
258 (this->input_grab != SDL_GRAB_OFF) ) {
259 mouse_relative = 1;
260 } else {
261 mouse_relative = 0;
262 }
263 }