src/video/wincommon/SDL_sysmouse.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@1433
    24
#define WIN32_LEAN_AND_MEAN
slouken@1433
    25
#include <windows.h>
slouken@0
    26
slouken@0
    27
#include "SDL_mouse.h"
slouken@1361
    28
#include "../../events/SDL_events_c.h"
slouken@1361
    29
#include "../SDL_cursor_c.h"
slouken@0
    30
#include "SDL_sysmouse_c.h"
slouken@0
    31
#include "SDL_lowvideo.h"
slouken@0
    32
slouken@0
    33
#ifdef _WIN32_WCE
slouken@0
    34
#define USE_STATIC_CURSOR
slouken@0
    35
#endif
slouken@0
    36
slouken@1662
    37
HCURSOR SDL_hcursor = NULL;     /* Exported for SDL_eventloop.c */
slouken@0
    38
slouken@0
    39
/* The implementation dependent data for the window manager cursor */
slouken@0
    40
/* For some reason when creating a windows cursor, the ands and xors memory
slouken@0
    41
   is not copied, so we need to keep track of it and free it when we are done
slouken@0
    42
   with the cursor.  If we free the memory prematurely, the app crashes. :-}
slouken@0
    43
*/
slouken@1662
    44
struct WMcursor
slouken@1662
    45
{
slouken@1662
    46
    HCURSOR curs;
slouken@0
    47
#ifndef USE_STATIC_CURSOR
slouken@1662
    48
    Uint8 *ands;
slouken@1662
    49
    Uint8 *xors;
slouken@0
    50
#endif
slouken@0
    51
};
slouken@0
    52
slouken@0
    53
/* Convert bits to padded bytes */
slouken@0
    54
#define PAD_BITS(bits)	((bits+7)/8)
slouken@0
    55
slouken@0
    56
#ifdef CURSOR_DEBUG
slouken@1662
    57
static void
slouken@1668
    58
PrintBITMAP(FILE * out, char *bits, int w, int h)
slouken@0
    59
{
slouken@1662
    60
    int i;
slouken@1662
    61
    unsigned char ch;
slouken@0
    62
slouken@1662
    63
    while (h-- > 0) {
slouken@1662
    64
        for (i = 0; i < w; ++i) {
slouken@1662
    65
            if ((i % 8) == 0)
slouken@1662
    66
                ch = *bits++;
slouken@1662
    67
            if (ch & 0x80)
slouken@1668
    68
                fprintf(out, "X");
slouken@1662
    69
            else
slouken@1668
    70
                fprintf(out, " ");
slouken@1662
    71
            ch <<= 1;
slouken@1662
    72
        }
slouken@1668
    73
        fprintf(out, "\n");
slouken@1662
    74
    }
slouken@0
    75
}
slouken@0
    76
#endif
slouken@0
    77
slouken@0
    78
#ifndef USE_STATIC_CURSOR
slouken@0
    79
/* Local functions to convert the SDL cursor mask into Windows format */
slouken@1662
    80
static void
slouken@1668
    81
memnot(Uint8 * dst, Uint8 * src, int len)
slouken@0
    82
{
slouken@1662
    83
    while (len-- > 0)
slouken@1662
    84
        *dst++ = ~*src++;
slouken@0
    85
}
slouken@1662
    86
static void
slouken@1668
    87
memxor(Uint8 * dst, Uint8 * src1, Uint8 * src2, int len)
slouken@0
    88
{
slouken@1662
    89
    while (len-- > 0)
slouken@1662
    90
        *dst++ = (*src1++) ^ (*src2++);
slouken@0
    91
}
slouken@0
    92
#endif /* !USE_STATIC_CURSOR */
slouken@0
    93
slouken@1662
    94
void
slouken@1668
    95
WIN_FreeWMCursor(_THIS, WMcursor * cursor)
slouken@0
    96
{
slouken@0
    97
#ifndef USE_STATIC_CURSOR
slouken@1668
    98
    if (cursor->curs == GetCursor())
slouken@1668
    99
        SetCursor(NULL);
slouken@1662
   100
    if (cursor->curs != NULL)
slouken@1668
   101
        DestroyCursor(cursor->curs);
slouken@1662
   102
    if (cursor->ands != NULL)
slouken@1668
   103
        SDL_free(cursor->ands);
slouken@1662
   104
    if (cursor->xors != NULL)
slouken@1668
   105
        SDL_free(cursor->xors);
slouken@0
   106
#endif /* !USE_STATIC_CURSOR */
slouken@1668
   107
    SDL_free(cursor);
slouken@0
   108
}
slouken@0
   109
slouken@1662
   110
WMcursor *
slouken@1668
   111
WIN_CreateWMCursor(_THIS,
slouken@1668
   112
                   Uint8 * data, Uint8 * mask, int w, int h, int hot_x,
slouken@1668
   113
                   int hot_y)
slouken@0
   114
{
slouken@0
   115
#ifdef USE_STATIC_CURSOR
slouken@1662
   116
    WMcursor *cursor;
slouken@0
   117
slouken@1662
   118
    /* Allocate the cursor */
slouken@1668
   119
    cursor = (WMcursor *) SDL_malloc(sizeof(*cursor));
slouken@1662
   120
    if (cursor) {
slouken@1668
   121
        cursor->curs = LoadCursor(NULL, IDC_ARROW);
slouken@1662
   122
    }
slouken@1662
   123
    return (cursor);
slouken@0
   124
#else
slouken@1662
   125
    WMcursor *cursor;
slouken@1662
   126
    int allowed_x;
slouken@1662
   127
    int allowed_y;
slouken@1662
   128
    int run, pad, i;
slouken@1662
   129
    Uint8 *aptr, *xptr;
slouken@0
   130
slouken@1662
   131
    /* Check to make sure the cursor size is okay */
slouken@1668
   132
    allowed_x = GetSystemMetrics(SM_CXCURSOR);
slouken@1668
   133
    allowed_y = GetSystemMetrics(SM_CYCURSOR);
slouken@1662
   134
    if ((w > allowed_x) || (h > allowed_y)) {
slouken@1668
   135
        SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
slouken@1668
   136
                     allowed_x, allowed_y);
slouken@1662
   137
        return (NULL);
slouken@1662
   138
    }
slouken@0
   139
slouken@1662
   140
    /* Allocate the cursor */
slouken@1668
   141
    cursor = (WMcursor *) SDL_malloc(sizeof(*cursor));
slouken@1662
   142
    if (cursor == NULL) {
slouken@1668
   143
        SDL_SetError("Out of memory");
slouken@1662
   144
        return (NULL);
slouken@1662
   145
    }
slouken@1662
   146
    cursor->curs = NULL;
slouken@1662
   147
    cursor->ands = NULL;
slouken@1662
   148
    cursor->xors = NULL;
slouken@0
   149
slouken@1662
   150
    /* Pad out to the normal cursor size */
slouken@1668
   151
    run = PAD_BITS(w);
slouken@1668
   152
    pad = PAD_BITS(allowed_x) - run;
slouken@1668
   153
    aptr = cursor->ands = (Uint8 *) SDL_malloc((run + pad) * allowed_y);
slouken@1668
   154
    xptr = cursor->xors = (Uint8 *) SDL_malloc((run + pad) * allowed_y);
slouken@1662
   155
    if ((aptr == NULL) || (xptr == NULL)) {
slouken@1668
   156
        WIN_FreeWMCursor(NULL, cursor);
slouken@1668
   157
        SDL_OutOfMemory();
slouken@1662
   158
        return (NULL);
slouken@1662
   159
    }
slouken@1662
   160
    for (i = 0; i < h; ++i) {
slouken@1668
   161
        memxor(xptr, data, mask, run);
slouken@1662
   162
        xptr += run;
slouken@1662
   163
        data += run;
slouken@1668
   164
        memnot(aptr, mask, run);
slouken@1662
   165
        mask += run;
slouken@1662
   166
        aptr += run;
slouken@1668
   167
        SDL_memset(xptr, 0, pad);
slouken@1662
   168
        xptr += pad;
slouken@1668
   169
        SDL_memset(aptr, ~0, pad);
slouken@1662
   170
        aptr += pad;
slouken@1662
   171
    }
slouken@1662
   172
    pad += run;
slouken@1662
   173
    for (; i < allowed_y; ++i) {
slouken@1668
   174
        SDL_memset(xptr, 0, pad);
slouken@1662
   175
        xptr += pad;
slouken@1668
   176
        SDL_memset(aptr, ~0, pad);
slouken@1662
   177
        aptr += pad;
slouken@1662
   178
    }
slouken@0
   179
slouken@1662
   180
    /* Create the cursor */
slouken@1668
   181
    cursor->curs = CreateCursor((HINSTANCE)
slouken@1668
   182
                                GetWindowLongPtr(SDL_Window,
slouken@1668
   183
                                                 GWLP_HINSTANCE), hot_x,
slouken@1668
   184
                                hot_y, allowed_x, allowed_y, cursor->ands,
slouken@1668
   185
                                cursor->xors);
slouken@1662
   186
    if (cursor->curs == NULL) {
slouken@1668
   187
        WIN_FreeWMCursor(NULL, cursor);
slouken@1668
   188
        SDL_SetError("Windows couldn't create the requested cursor");
slouken@1662
   189
        return (NULL);
slouken@1662
   190
    }
slouken@1662
   191
    return (cursor);
slouken@0
   192
#endif /* USE_STATIC_CURSOR */
slouken@0
   193
}
slouken@0
   194
slouken@1662
   195
int
slouken@1668
   196
WIN_ShowWMCursor(_THIS, WMcursor * cursor)
slouken@0
   197
{
slouken@1662
   198
    POINT mouse_pos;
slouken@0
   199
slouken@1662
   200
    /* The fullscreen cursor must be done in software with DirectInput */
slouken@1668
   201
    if (!this->screen || DDRAW_FULLSCREEN()) {
slouken@1662
   202
        return (0);
slouken@1662
   203
    }
slouken@0
   204
slouken@1662
   205
    /* Set the window cursor to our cursor, if applicable */
slouken@1662
   206
    if (cursor != NULL) {
slouken@1662
   207
        SDL_hcursor = cursor->curs;
slouken@1662
   208
    } else {
slouken@1662
   209
        SDL_hcursor = NULL;
slouken@1662
   210
    }
slouken@1668
   211
    GetCursorPos(&mouse_pos);
slouken@1668
   212
    if (PtInRect(&SDL_bounds, mouse_pos)) {
slouken@1668
   213
        SetCursor(SDL_hcursor);
slouken@1662
   214
    }
slouken@1662
   215
    return (1);
slouken@0
   216
}
slouken@0
   217
slouken@1662
   218
void
slouken@1668
   219
WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
slouken@0
   220
{
slouken@1668
   221
    if (DDRAW_FULLSCREEN()) {
slouken@1668
   222
        SDL_PrivateMouseMotion(0, 0, x, y);
slouken@1662
   223
    } else if (mouse_relative) {
slouken@1662
   224
        /*      RJR: March 28, 2000
slouken@1662
   225
           leave physical cursor at center of screen if
slouken@1662
   226
           mouse hidden and grabbed */
slouken@1668
   227
        SDL_PrivateMouseMotion(0, 0, x, y);
slouken@1662
   228
    } else {
slouken@1662
   229
        POINT pt;
slouken@1662
   230
        pt.x = x;
slouken@1662
   231
        pt.y = y;
slouken@1668
   232
        ClientToScreen(SDL_Window, &pt);
slouken@1668
   233
        SetCursorPos(pt.x, pt.y);
slouken@1662
   234
    }
slouken@0
   235
}
slouken@0
   236
slouken@0
   237
/* Update the current mouse state and position */
slouken@1662
   238
void
slouken@1668
   239
WIN_UpdateMouse(_THIS)
slouken@0
   240
{
slouken@1662
   241
    RECT rect;
slouken@1662
   242
    POINT pt;
slouken@0
   243
slouken@1668
   244
    if (!DDRAW_FULLSCREEN()) {
slouken@1668
   245
        GetClientRect(SDL_Window, &rect);
slouken@1668
   246
        GetCursorPos(&pt);
slouken@1668
   247
        MapWindowPoints(NULL, SDL_Window, &pt, 1);
slouken@1668
   248
        if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)) {
slouken@1668
   249
            SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
slouken@1668
   250
            SDL_PrivateMouseMotion(0, 0, (Sint16) pt.x, (Sint16) pt.y);
slouken@1662
   251
        } else {
slouken@1668
   252
            SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
slouken@1662
   253
        }
slouken@1662
   254
    }
slouken@0
   255
}
slouken@0
   256
slouken@0
   257
/* Check to see if we need to enter or leave mouse relative mode */
slouken@1662
   258
void
slouken@1668
   259
WIN_CheckMouseMode(_THIS)
slouken@0
   260
{
slouken@1662
   261
#ifndef _WIN32_WCE
slouken@1662
   262
    /* If the mouse is hidden and input is grabbed, we use relative mode */
slouken@1662
   263
    if (!(SDL_cursorstate & CURSOR_VISIBLE) &&
slouken@1662
   264
        (this->input_grab != SDL_GRAB_OFF)) {
slouken@1662
   265
        mouse_relative = 1;
slouken@1662
   266
    } else {
slouken@1662
   267
        mouse_relative = 0;
slouken@1662
   268
    }
icculus@1251
   269
#else
slouken@1662
   270
    mouse_relative = 0;
icculus@1251
   271
#endif
slouken@0
   272
}
slouken@1662
   273
slouken@1662
   274
/* vi: set ts=4 sw=4 expandtab: */