2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 #define WIN32_LEAN_AND_MEAN
27 #include "SDL_mouse.h"
28 #include "../../events/SDL_events_c.h"
29 #include "../SDL_cursor_c.h"
30 #include "SDL_sysmouse_c.h"
31 #include "SDL_lowvideo.h"
34 #define USE_STATIC_CURSOR
37 HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */
39 /* The implementation dependent data for the window manager cursor */
40 /* For some reason when creating a windows cursor, the ands and xors memory
41 is not copied, so we need to keep track of it and free it when we are done
42 with the cursor. If we free the memory prematurely, the app crashes. :-}
46 #ifndef USE_STATIC_CURSOR
52 /* Convert bits to padded bytes */
53 #define PAD_BITS(bits) ((bits+7)/8)
56 static void PrintBITMAP(FILE *out, char *bits, int w, int h)
62 for ( i=0; i<w; ++i ) {
76 #ifndef USE_STATIC_CURSOR
77 /* Local functions to convert the SDL cursor mask into Windows format */
78 static void memnot(Uint8 *dst, Uint8 *src, int len)
83 static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
86 *dst++ = (*src1++)^(*src2++);
88 #endif /* !USE_STATIC_CURSOR */
90 void WIN_FreeWMCursor(_THIS, WMcursor *cursor)
92 #ifndef USE_STATIC_CURSOR
93 if ( cursor->curs == GetCursor() )
95 if ( cursor->curs != NULL )
96 DestroyCursor(cursor->curs);
97 if ( cursor->ands != NULL )
98 SDL_free(cursor->ands);
99 if ( cursor->xors != NULL )
100 SDL_free(cursor->xors);
101 #endif /* !USE_STATIC_CURSOR */
105 WMcursor *WIN_CreateWMCursor(_THIS,
106 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
108 #ifdef USE_STATIC_CURSOR
111 /* Allocate the cursor */
112 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
114 cursor->curs = LoadCursor(NULL, IDC_ARROW);
124 /* Check to make sure the cursor size is okay */
125 allowed_x = GetSystemMetrics(SM_CXCURSOR);
126 allowed_y = GetSystemMetrics(SM_CYCURSOR);
127 if ( (w > allowed_x) || (h > allowed_y) ) {
128 SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
129 allowed_x, allowed_y);
133 /* Allocate the cursor */
134 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
135 if ( cursor == NULL ) {
136 SDL_SetError("Out of memory");
143 /* Pad out to the normal cursor size */
145 pad = PAD_BITS(allowed_x)-run;
146 aptr = cursor->ands = (Uint8 *)SDL_malloc((run+pad)*allowed_y);
147 xptr = cursor->xors = (Uint8 *)SDL_malloc((run+pad)*allowed_y);
148 if ( (aptr == NULL) || (xptr == NULL) ) {
149 WIN_FreeWMCursor(NULL, cursor);
153 for ( i=0; i<h; ++i ) {
154 memxor(xptr, data, mask, run);
157 memnot(aptr, mask, run);
160 SDL_memset(xptr, 0, pad);
162 SDL_memset(aptr, ~0, pad);
166 for ( ; i<allowed_y; ++i ) {
167 SDL_memset(xptr, 0, pad);
169 SDL_memset(aptr, ~0, pad);
173 /* Create the cursor */
174 cursor->curs = CreateCursor(
175 (HINSTANCE)GetWindowLongPtr(SDL_Window, GWLP_HINSTANCE),
176 hot_x, hot_y, allowed_x, allowed_y,
177 cursor->ands, cursor->xors);
178 if ( cursor->curs == NULL ) {
179 WIN_FreeWMCursor(NULL, cursor);
180 SDL_SetError("Windows couldn't create the requested cursor");
184 #endif /* USE_STATIC_CURSOR */
187 int WIN_ShowWMCursor(_THIS, WMcursor *cursor)
191 if ( !this->screen ) {
195 /* Set the window cursor to our cursor, if applicable */
196 if ( cursor != NULL ) {
197 SDL_hcursor = cursor->curs;
201 GetCursorPos(&mouse_pos);
202 if ( PtInRect(&SDL_bounds, mouse_pos) ) {
203 SetCursor(SDL_hcursor);
208 void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
210 if ( mouse_relative) {
211 /* RJR: March 28, 2000
212 leave physical cursor at center of screen if
213 mouse hidden and grabbed */
214 SDL_PrivateMouseMotion(0, 0, x, y);
218 /* With DirectInput the position doesn't follow
219 * the cursor, so it is set manually */
221 SDL_PrivateMouseMotion(0, 0, x, y);
226 ClientToScreen(SDL_Window, &pt);
227 SetCursorPos(pt.x, pt.y);
231 /* Update the current mouse state and position */
232 void WIN_UpdateMouse(_THIS)
236 /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event
237 * handler a chance to install a TRACKMOUSEEVENT */
238 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
241 ScreenToClient(SDL_Window, &pt);
242 SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
245 /* Check to see if we need to enter or leave mouse relative mode */
246 void WIN_CheckMouseMode(_THIS)
249 /* If the mouse is hidden and input is grabbed, we use relative mode */
250 if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
251 (this->input_grab != SDL_GRAB_OFF) ) {