This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_sysmouse.c
274 lines (246 loc) · 7.19 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 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
11
12
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
13
Lesser General Public License for more details.
14
15
16
17
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
18
19
Sam Lantinga
20
slouken@libsdl.org
21
*/
22
#include "SDL_config.h"
23
24
25
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
26
27
#include "SDL_mouse.h"
28
29
#include "../../events/SDL_events_c.h"
#include "../SDL_cursor_c.h"
30
31
32
33
34
35
36
#include "SDL_sysmouse_c.h"
#include "SDL_lowvideo.h"
#ifdef _WIN32_WCE
#define USE_STATIC_CURSOR
#endif
37
HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */
38
39
40
41
42
43
/* 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. :-}
*/
44
45
46
struct WMcursor
{
HCURSOR curs;
47
#ifndef USE_STATIC_CURSOR
48
49
Uint8 *ands;
Uint8 *xors;
50
51
52
53
54
55
56
#endif
};
/* Convert bits to padded bytes */
#define PAD_BITS(bits) ((bits+7)/8)
#ifdef CURSOR_DEBUG
57
58
static void
PrintBITMAP(FILE * out, char *bits, int w, int h)
59
{
60
61
int i;
unsigned char ch;
62
63
64
65
66
67
68
69
70
71
72
73
74
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");
}
75
76
77
78
79
}
#endif
#ifndef USE_STATIC_CURSOR
/* Local functions to convert the SDL cursor mask into Windows format */
80
81
static void
memnot(Uint8 * dst, Uint8 * src, int len)
82
{
83
84
while (len-- > 0)
*dst++ = ~*src++;
85
}
86
87
static void
memxor(Uint8 * dst, Uint8 * src1, Uint8 * src2, int len)
88
{
89
90
while (len-- > 0)
*dst++ = (*src1++) ^ (*src2++);
91
92
93
}
#endif /* !USE_STATIC_CURSOR */
94
95
void
WIN_FreeWMCursor(_THIS, WMcursor * cursor)
96
97
{
#ifndef USE_STATIC_CURSOR
98
99
100
101
102
103
104
105
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);
106
#endif /* !USE_STATIC_CURSOR */
107
SDL_free(cursor);
108
109
}
110
111
112
113
WMcursor *
WIN_CreateWMCursor(_THIS,
Uint8 * data, Uint8 * mask, int w, int h, int hot_x,
int hot_y)
114
115
{
#ifdef USE_STATIC_CURSOR
116
WMcursor *cursor;
117
118
119
120
121
122
123
/* Allocate the cursor */
cursor = (WMcursor *) SDL_malloc(sizeof(*cursor));
if (cursor) {
cursor->curs = LoadCursor(NULL, IDC_ARROW);
}
return (cursor);
124
#else
125
126
127
128
129
WMcursor *cursor;
int allowed_x;
int allowed_y;
int run, pad, i;
Uint8 *aptr, *xptr;
130
131
132
133
134
135
136
137
138
/* 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);
}
139
140
141
142
143
144
145
146
147
148
/* 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;
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* 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;
}
179
180
181
182
183
184
185
186
187
188
189
190
191
/* 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);
192
193
194
#endif /* USE_STATIC_CURSOR */
}
195
196
int
WIN_ShowWMCursor(_THIS, WMcursor * cursor)
197
{
198
POINT mouse_pos;
199
200
201
202
203
/* The fullscreen cursor must be done in software with DirectInput */
if (!this->screen || DDRAW_FULLSCREEN()) {
return (0);
}
204
205
206
207
208
209
210
211
212
213
214
215
/* 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);
216
217
}
218
219
void
WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
220
{
221
222
223
224
225
226
227
228
229
230
231
232
233
234
if (DDRAW_FULLSCREEN()) {
SDL_PrivateMouseMotion(0, 0, x, y);
} else 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;
pt.x = x;
pt.y = y;
ClientToScreen(SDL_Window, &pt);
SetCursorPos(pt.x, pt.y);
}
235
236
237
}
/* Update the current mouse state and position */
238
239
void
WIN_UpdateMouse(_THIS)
240
{
241
242
RECT rect;
POINT pt;
243
244
245
246
247
248
249
250
251
252
253
254
if (!DDRAW_FULLSCREEN()) {
GetClientRect(SDL_Window, &rect);
GetCursorPos(&pt);
MapWindowPoints(NULL, SDL_Window, &pt, 1);
if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)) {
SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
SDL_PrivateMouseMotion(0, 0, (Sint16) pt.x, (Sint16) pt.y);
} else {
SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
}
}
255
256
257
}
/* Check to see if we need to enter or leave mouse relative mode */
258
259
void
WIN_CheckMouseMode(_THIS)
260
{
261
262
263
264
265
266
267
268
#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;
}
269
#else
270
mouse_relative = 0;
271
#endif
272
}
273
274
/* vi: set ts=4 sw=4 expandtab: */