summaryrefslogtreecommitdiff
path: root/src/video/wincommon/SDL_sysmouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video/wincommon/SDL_sysmouse.c')
-rw-r--r--src/video/wincommon/SDL_sysmouse.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/video/wincommon/SDL_sysmouse.c b/src/video/wincommon/SDL_sysmouse.c
new file mode 100644
index 0000000..b53bf9c
--- /dev/null
+++ b/src/video/wincommon/SDL_sysmouse.c
@@ -0,0 +1,259 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "SDL_mouse.h"
+#include "../../events/SDL_events_c.h"
+#include "../SDL_cursor_c.h"
+#include "SDL_sysmouse_c.h"
+#include "SDL_lowvideo.h"
+
+#ifdef _WIN32_WCE
+#define USE_STATIC_CURSOR
+#endif
+
+HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */
+
+/* The implementation dependent data for the window manager cursor */
+/* For some reason when creating a windows cursor, the ands and xors memory
+ is not copied, so we need to keep track of it and free it when we are done
+ with the cursor. If we free the memory prematurely, the app crashes. :-}
+*/
+struct WMcursor {
+ HCURSOR curs;
+#ifndef USE_STATIC_CURSOR
+ Uint8 *ands;
+ Uint8 *xors;
+#endif
+};
+
+/* Convert bits to padded bytes */
+#define PAD_BITS(bits) ((bits+7)/8)
+
+#ifdef CURSOR_DEBUG
+static void PrintBITMAP(FILE *out, char *bits, int w, int h)
+{
+ int i;
+ unsigned char ch;
+
+ while ( h-- > 0 ) {
+ for ( i=0; i<w; ++i ) {
+ if ( (i%8) == 0 )
+ ch = *bits++;
+ if ( ch&0x80 )
+ fprintf(out, "X");
+ else
+ fprintf(out, " ");
+ ch <<= 1;
+ }
+ fprintf(out, "\n");
+ }
+}
+#endif
+
+#ifndef USE_STATIC_CURSOR
+/* Local functions to convert the SDL cursor mask into Windows format */
+static void memnot(Uint8 *dst, Uint8 *src, int len)
+{
+ while ( len-- > 0 )
+ *dst++ = ~*src++;
+}
+static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
+{
+ while ( len-- > 0 )
+ *dst++ = (*src1++)^(*src2++);
+}
+#endif /* !USE_STATIC_CURSOR */
+
+void WIN_FreeWMCursor(_THIS, WMcursor *cursor)
+{
+#ifndef USE_STATIC_CURSOR
+ if ( cursor->curs == GetCursor() )
+ SetCursor(NULL);
+ if ( cursor->curs != NULL )
+ DestroyCursor(cursor->curs);
+ if ( cursor->ands != NULL )
+ SDL_free(cursor->ands);
+ if ( cursor->xors != NULL )
+ SDL_free(cursor->xors);
+#endif /* !USE_STATIC_CURSOR */
+ SDL_free(cursor);
+}
+
+WMcursor *WIN_CreateWMCursor(_THIS,
+ Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
+{
+#ifdef USE_STATIC_CURSOR
+ WMcursor *cursor;
+
+ /* Allocate the cursor */
+ cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
+ if ( cursor ) {
+ cursor->curs = LoadCursor(NULL, IDC_ARROW);
+ }
+ return(cursor);
+#else
+ WMcursor *cursor;
+ int allowed_x;
+ int allowed_y;
+ int run, pad, i;
+ Uint8 *aptr, *xptr;
+
+ /* Check to make sure the cursor size is okay */
+ allowed_x = GetSystemMetrics(SM_CXCURSOR);
+ allowed_y = GetSystemMetrics(SM_CYCURSOR);
+ if ( (w > allowed_x) || (h > allowed_y) ) {
+ SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
+ allowed_x, allowed_y);
+ return(NULL);
+ }
+
+ /* Allocate the cursor */
+ cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
+ if ( cursor == NULL ) {
+ SDL_SetError("Out of memory");
+ return(NULL);
+ }
+ cursor->curs = NULL;
+ cursor->ands = NULL;
+ cursor->xors = NULL;
+
+ /* Pad out to the normal cursor size */
+ run = PAD_BITS(w);
+ pad = PAD_BITS(allowed_x)-run;
+ aptr = cursor->ands = (Uint8 *)SDL_malloc((run+pad)*allowed_y);
+ xptr = cursor->xors = (Uint8 *)SDL_malloc((run+pad)*allowed_y);
+ if ( (aptr == NULL) || (xptr == NULL) ) {
+ WIN_FreeWMCursor(NULL, cursor);
+ SDL_OutOfMemory();
+ return(NULL);
+ }
+ for ( i=0; i<h; ++i ) {
+ memxor(xptr, data, mask, run);
+ xptr += run;
+ data += run;
+ memnot(aptr, mask, run);
+ mask += run;
+ aptr += run;
+ SDL_memset(xptr, 0, pad);
+ xptr += pad;
+ SDL_memset(aptr, ~0, pad);
+ aptr += pad;
+ }
+ pad += run;
+ for ( ; i<allowed_y; ++i ) {
+ SDL_memset(xptr, 0, pad);
+ xptr += pad;
+ SDL_memset(aptr, ~0, pad);
+ aptr += pad;
+ }
+
+ /* Create the cursor */
+ cursor->curs = CreateCursor(
+ (HINSTANCE)GetWindowLongPtr(SDL_Window, GWLP_HINSTANCE),
+ hot_x, hot_y, allowed_x, allowed_y,
+ cursor->ands, cursor->xors);
+ if ( cursor->curs == NULL ) {
+ WIN_FreeWMCursor(NULL, cursor);
+ SDL_SetError("Windows couldn't create the requested cursor");
+ return(NULL);
+ }
+ return(cursor);
+#endif /* USE_STATIC_CURSOR */
+}
+
+int WIN_ShowWMCursor(_THIS, WMcursor *cursor)
+{
+ POINT mouse_pos;
+
+ if ( !this->screen ) {
+ return(0);
+ }
+
+ /* Set the window cursor to our cursor, if applicable */
+ if ( cursor != NULL ) {
+ SDL_hcursor = cursor->curs;
+ } else {
+ SDL_hcursor = NULL;
+ }
+ GetCursorPos(&mouse_pos);
+ if ( PtInRect(&SDL_bounds, mouse_pos) ) {
+ SetCursor(SDL_hcursor);
+ }
+ return(1);
+}
+
+void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
+{
+ if ( mouse_relative) {
+ /* RJR: March 28, 2000
+ leave physical cursor at center of screen if
+ mouse hidden and grabbed */
+ SDL_PrivateMouseMotion(0, 0, x, y);
+ } else {
+ POINT pt;
+
+ /* With DirectInput the position doesn't follow
+ * the cursor, so it is set manually */
+ if ( DINPUT() ) {
+ SDL_PrivateMouseMotion(0, 0, x, y);
+ }
+
+ pt.x = x;
+ pt.y = y;
+ ClientToScreen(SDL_Window, &pt);
+ SetCursorPos(pt.x, pt.y);
+ }
+}
+
+/* Update the current mouse state and position */
+void WIN_UpdateMouse(_THIS)
+{
+ POINT pt;
+
+ /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event
+ * handler a chance to install a TRACKMOUSEEVENT */
+ SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
+
+ GetCursorPos(&pt);
+ ScreenToClient(SDL_Window, &pt);
+ SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
+}
+
+/* Check to see if we need to enter or leave mouse relative mode */
+void WIN_CheckMouseMode(_THIS)
+{
+#ifndef _WIN32_WCE
+ /* If the mouse is hidden and input is grabbed, we use relative mode */
+ if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
+ (this->input_grab != SDL_GRAB_OFF) ) {
+ mouse_relative = 1;
+ } else {
+ mouse_relative = 0;
+ }
+#else
+ mouse_relative = 0;
+#endif
+}