src/video/wincommon/SDL_sysmouse.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 06 Jan 2006 13:20:10 +0000
changeset 1234 73676c1f56ee
parent 527 5c74ac147358
child 1251 86d0d01290ea
permissions -rw-r--r--
For sanity's sake, removed the '&' when passing copy_row array to asm.
     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@libsdl.org
    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 == GetCursor() )
    99 		SetCursor(NULL);
   100 	if ( cursor->curs != NULL )
   101 		DestroyCursor(cursor->curs);
   102 	if ( cursor->ands != NULL )
   103 		free(cursor->ands);
   104 	if ( cursor->xors != NULL )
   105 		free(cursor->xors);
   106 #endif /* !USE_STATIC_CURSOR */
   107 	free(cursor);
   108 }
   109 
   110 WMcursor *WIN_CreateWMCursor(_THIS,
   111 		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
   112 {
   113 #ifdef USE_STATIC_CURSOR
   114 	WMcursor *cursor;
   115 
   116 	/* Allocate the cursor */
   117 	cursor = (WMcursor *)malloc(sizeof(*cursor));
   118 	if ( cursor ) {
   119 		cursor->curs = LoadCursor(NULL, IDC_ARROW);
   120 	}
   121 	return(cursor);
   122 #else
   123 	WMcursor *cursor;
   124 	int allowed_x;
   125 	int allowed_y;
   126 	int run, pad, i;
   127 	Uint8 *aptr, *xptr;
   128 
   129 	/* Check to make sure the cursor size is okay */
   130 	allowed_x = GetSystemMetrics(SM_CXCURSOR);
   131 	allowed_y = GetSystemMetrics(SM_CYCURSOR);
   132 	if ( (w > allowed_x) || (h > allowed_y) ) {
   133 		SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
   134 							allowed_x, allowed_y);
   135 		return(NULL);
   136 	}
   137 
   138 	/* Allocate the cursor */
   139 	cursor = (WMcursor *)malloc(sizeof(*cursor));
   140 	if ( cursor == NULL ) {
   141 		SDL_SetError("Out of memory");
   142 		return(NULL);
   143 	}
   144 	cursor->curs = NULL;
   145 	cursor->ands = NULL;
   146 	cursor->xors = NULL;
   147 
   148 	/* Pad out to the normal cursor size */
   149 	run = PAD_BITS(w);
   150 	pad = PAD_BITS(allowed_x)-run;
   151 	aptr = cursor->ands = (Uint8 *)malloc((run+pad)*allowed_y);
   152 	xptr = cursor->xors = (Uint8 *)malloc((run+pad)*allowed_y);
   153 	if ( (aptr == NULL) || (xptr == NULL) ) {
   154 		WIN_FreeWMCursor(NULL, cursor);
   155 		SDL_OutOfMemory();
   156 		return(NULL);
   157 	}
   158 	for ( i=0; i<h; ++i ) {
   159 		memxor(xptr, data, mask, run);
   160 		xptr += run;
   161 		data += run;
   162 		memnot(aptr, mask, run);
   163 		mask += run;
   164 		aptr += run;
   165 		memset(xptr,  0, pad);
   166 		xptr += pad;
   167 		memset(aptr, ~0, pad);
   168 		aptr += pad;
   169 	}
   170 	pad += run;
   171 	for ( ; i<allowed_y; ++i ) {
   172 		memset(xptr,  0, pad);
   173 		xptr += pad;
   174 		memset(aptr, ~0, pad);
   175 		aptr += pad;
   176 	}
   177 
   178 	/* Create the cursor */
   179 	cursor->curs = CreateCursor(
   180 			(HINSTANCE)GetWindowLong(SDL_Window, GWL_HINSTANCE),
   181 					hot_x, hot_y, allowed_x, allowed_y, 
   182 						cursor->ands, cursor->xors);
   183 	if ( cursor->curs == NULL ) {
   184 		WIN_FreeWMCursor(NULL, cursor);
   185 		SDL_SetError("Windows couldn't create the requested cursor");
   186 		return(NULL);
   187 	}
   188 	return(cursor);
   189 #endif /* USE_STATIC_CURSOR */
   190 }
   191 
   192 int WIN_ShowWMCursor(_THIS, WMcursor *cursor)
   193 {
   194 	POINT mouse_pos;
   195 
   196 	/* The fullscreen cursor must be done in software with DirectInput */
   197 	if ( !this->screen || DDRAW_FULLSCREEN() ) {
   198 		return(0);
   199 	}
   200 
   201 	/* Set the window cursor to our cursor, if applicable */
   202 	if ( cursor != NULL ) {
   203 		SDL_hcursor = cursor->curs;
   204 	} else {
   205 		SDL_hcursor = NULL;
   206 	}
   207 	GetCursorPos(&mouse_pos);
   208 	if ( PtInRect(&SDL_bounds, mouse_pos) ) {
   209 		SetCursor(SDL_hcursor);
   210 	}
   211 	return(1);
   212 }
   213 
   214 void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
   215 {
   216 	if ( DDRAW_FULLSCREEN() ) {
   217 		SDL_PrivateMouseMotion(0, 0, x, y);
   218 	} else if ( mouse_relative) {
   219 		/*	RJR: March 28, 2000
   220 			leave physical cursor at center of screen if
   221 			mouse hidden and grabbed */
   222 		SDL_PrivateMouseMotion(0, 0, x, y);
   223 	} else {
   224 		POINT pt;
   225 		pt.x = x;
   226 		pt.y = y;
   227 		ClientToScreen(SDL_Window, &pt);
   228 		SetCursorPos(pt.x, pt.y);
   229 	}
   230 }
   231 
   232 /* Update the current mouse state and position */
   233 void WIN_UpdateMouse(_THIS)
   234 {
   235 	RECT rect;
   236 	POINT pt;
   237 
   238 	if ( ! DDRAW_FULLSCREEN() ) {
   239 		GetClientRect(SDL_Window, &rect);
   240 		GetCursorPos(&pt);
   241 		MapWindowPoints(NULL, SDL_Window, &pt, 1);
   242 		if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)){
   243 			SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   244 			SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
   245 		} else {
   246 			SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   247 		}
   248 	}
   249 }
   250 
   251 /* Check to see if we need to enter or leave mouse relative mode */
   252 void WIN_CheckMouseMode(_THIS)
   253 {
   254         /* If the mouse is hidden and input is grabbed, we use relative mode */
   255         if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
   256              (this->input_grab != SDL_GRAB_OFF) ) {
   257                 mouse_relative = 1;
   258         } else {
   259                 mouse_relative = 0;
   260         }
   261 }