src/video/windows/SDL_windowsmouse.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Oct 2012 18:59:56 -0700
changeset 6620 62fe18dc6841
parent 6350 19545983ac76
child 6675 20f3cdea0fd2
permissions -rw-r--r--
Added Windows message box implementation, but it needs a little work on layout.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINDOWS
    24 
    25 #include "SDL_assert.h"
    26 #include "SDL_windowsvideo.h"
    27 
    28 #include "../../events/SDL_mouse_c.h"
    29 
    30 
    31 HCURSOR SDL_cursor = NULL;
    32 
    33 
    34 static SDL_Cursor *
    35 WIN_CreateDefaultCursor()
    36 {
    37     SDL_Cursor *cursor;
    38 
    39     cursor = SDL_calloc(1, sizeof(*cursor));
    40     if (cursor) {
    41         cursor->driverdata = LoadCursor(NULL, IDC_ARROW);
    42     } else {
    43         SDL_OutOfMemory();
    44     }
    45 
    46     return cursor;
    47 }
    48 
    49 static SDL_Cursor *
    50 WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
    51 {
    52     SDL_Cursor *cursor;
    53     HICON hicon;
    54     HDC hdc;
    55     BITMAPV4HEADER bmh;
    56     LPVOID pixels;
    57     ICONINFO ii;
    58 
    59     SDL_zero(bmh);
    60     bmh.bV4Size = sizeof(bmh);
    61     bmh.bV4Width = surface->w;
    62     bmh.bV4Height = -surface->h; /* Invert the image */
    63     bmh.bV4Planes = 1;
    64     bmh.bV4BitCount = 32;
    65     bmh.bV4V4Compression = BI_BITFIELDS;
    66     bmh.bV4AlphaMask = 0xFF000000;
    67     bmh.bV4RedMask   = 0x00FF0000;
    68     bmh.bV4GreenMask = 0x0000FF00;
    69     bmh.bV4BlueMask  = 0x000000FF;
    70 
    71     hdc = GetDC(NULL);
    72     SDL_zero(ii);
    73     ii.fIcon = FALSE;
    74     ii.xHotspot = (DWORD)hot_x;
    75     ii.yHotspot = (DWORD)hot_y;
    76     ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0);
    77     ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, NULL);
    78     ReleaseDC(NULL, hdc);
    79 
    80     SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
    81     SDL_assert(surface->pitch == surface->w * 4);
    82     SDL_memcpy(pixels, surface->pixels, surface->h * surface->pitch);
    83 
    84     hicon = CreateIconIndirect(&ii);
    85 
    86     DeleteObject(ii.hbmColor);
    87     DeleteObject(ii.hbmMask);
    88 
    89     if (!hicon) {
    90         WIN_SetError("CreateIconIndirect()");
    91         return NULL;
    92     }
    93 
    94     cursor = SDL_calloc(1, sizeof(*cursor));
    95     if (cursor) {
    96         cursor->driverdata = hicon;
    97     } else {
    98         DestroyIcon(hicon);
    99         SDL_OutOfMemory();
   100     }
   101 
   102     return cursor;
   103 }
   104 
   105 static void
   106 WIN_FreeCursor(SDL_Cursor * cursor)
   107 {
   108     HICON hicon = (HICON)cursor->driverdata;
   109 
   110     DestroyIcon(hicon);
   111     SDL_free(cursor);
   112 }
   113 
   114 static int
   115 WIN_ShowCursor(SDL_Cursor * cursor)
   116 {
   117     if (cursor) {
   118         SDL_cursor = (HCURSOR)cursor->driverdata;
   119     } else {
   120         SDL_cursor = NULL;
   121     }
   122     if (SDL_GetMouseFocus() != NULL) {
   123         SetCursor(SDL_cursor);
   124     }
   125     return 0;
   126 }
   127 
   128 static void
   129 WIN_WarpMouse(SDL_Window * window, int x, int y)
   130 {
   131     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   132     POINT pt;
   133 
   134     pt.x = x;
   135     pt.y = y;
   136     ClientToScreen(hwnd, &pt);
   137     SetCursorPos(pt.x, pt.y);
   138 }
   139 
   140 static int
   141 WIN_SetRelativeMouseMode(SDL_bool enabled)
   142 {
   143     RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
   144 	HWND hWnd;
   145 	hWnd = GetActiveWindow();
   146 
   147 	rawMouse.hwndTarget = hWnd;
   148 	if(!enabled) {
   149 		rawMouse.dwFlags |= RIDEV_REMOVE;
   150 		rawMouse.hwndTarget = NULL;
   151 	}
   152 
   153 
   154 	/* (Un)register raw input for mice */
   155 	if(RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
   156 
   157 		/* Only return an error when registering. If we unregister and fail, then
   158 		it's probably that we unregistered twice. That's OK. */
   159 		if(enabled) {
   160 			SDL_Unsupported();
   161 			return -1;
   162 		}
   163 	}
   164 
   165 	if(enabled) {
   166 		LONG cx, cy;
   167 		RECT rect;
   168 		GetWindowRect(hWnd, &rect);
   169 
   170 		cx = (rect.left + rect.right) / 2;
   171 		cy = (rect.top + rect.bottom) / 2;
   172 
   173 		/* Make an absurdly small clip rect */
   174 		rect.left = cx-1;
   175 		rect.right = cx+1;
   176 		rect.top = cy-1;
   177 		rect.bottom = cy+1;
   178 
   179 		ClipCursor(&rect);
   180 	}
   181 	else
   182 		ClipCursor(NULL);
   183 
   184     return 0;
   185 }
   186 
   187 void
   188 WIN_InitMouse(_THIS)
   189 {
   190     SDL_Mouse *mouse = SDL_GetMouse();
   191 
   192     mouse->CreateCursor = WIN_CreateCursor;
   193     mouse->ShowCursor = WIN_ShowCursor;
   194     mouse->FreeCursor = WIN_FreeCursor;
   195     mouse->WarpMouse = WIN_WarpMouse;
   196     mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
   197 
   198     SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
   199 }
   200 
   201 void
   202 WIN_QuitMouse(_THIS)
   203 {
   204 }
   205 
   206 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   207 
   208 /* vi: set ts=4 sw=4 expandtab: */