src/video/windows/SDL_windowsmouse.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Mar 2011 13:59:52 -0800
changeset 5472 674d45edfaeb
parent 5421 f8588afb6486
child 5535 96594ac5fd1a
permissions -rw-r--r--
We can assume ARGB surface format when creating cursors (enforced by higher level API)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 Sam Lantinga
     4 
     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.
     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     Lesser General Public License for more details.
    14 
    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
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #include "SDL_config.h"
    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     SDL_Unsupported();
   144     return -1;
   145 }
   146 
   147 void
   148 WIN_InitMouse(_THIS)
   149 {
   150     SDL_Mouse *mouse = SDL_GetMouse();
   151 
   152     mouse->CreateCursor = WIN_CreateCursor;
   153     mouse->ShowCursor = WIN_ShowCursor;
   154     mouse->FreeCursor = WIN_FreeCursor;
   155     mouse->WarpMouse = WIN_WarpMouse;
   156     mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
   157 
   158     SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
   159 }
   160 
   161 void
   162 WIN_QuitMouse(_THIS)
   163 {
   164 }
   165 
   166 /* vi: set ts=4 sw=4 expandtab: */