Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
297 lines (265 loc) · 8.98 KB

SDL_x11mouse.c

File metadata and controls

297 lines (265 loc) · 8.98 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Apr 26, 2001
Apr 26, 2001
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Apr 26, 2001
Apr 26, 2001
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Apr 26, 2001
Apr 26, 2001
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
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Apr 26, 2001
Apr 26, 2001
14
Feb 1, 2006
Feb 1, 2006
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
Apr 26, 2001
Apr 26, 2001
18
19
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Apr 26, 2001
Apr 26, 2001
21
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
23
24
25
26
27
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "SDL_mouse.h"
Feb 16, 2006
Feb 16, 2006
28
29
#include "../../events/SDL_events_c.h"
#include "../SDL_cursor_c.h"
Apr 26, 2001
Apr 26, 2001
30
31
32
33
34
#include "SDL_x11dga_c.h"
#include "SDL_x11mouse_c.h"
/* The implementation dependent data for the window manager cursor */
May 28, 2006
May 28, 2006
35
36
37
struct WMcursor
{
Cursor x_cursor;
Apr 26, 2001
Apr 26, 2001
38
39
40
};
May 28, 2006
May 28, 2006
41
void
May 29, 2006
May 29, 2006
42
X11_FreeWMCursor(_THIS, WMcursor * cursor)
Apr 26, 2001
Apr 26, 2001
43
{
May 28, 2006
May 28, 2006
44
if (SDL_Display != NULL) {
May 29, 2006
May 29, 2006
45
46
47
48
SDL_Lock_EventThread();
XFreeCursor(SDL_Display, cursor->x_cursor);
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
May 28, 2006
May 28, 2006
49
}
May 29, 2006
May 29, 2006
50
SDL_free(cursor);
Apr 26, 2001
Apr 26, 2001
51
52
}
May 28, 2006
May 28, 2006
53
WMcursor *
May 29, 2006
May 29, 2006
54
55
56
X11_CreateWMCursor(_THIS,
Uint8 * data, Uint8 * mask, int w, int h, int hot_x,
int hot_y)
Apr 26, 2001
Apr 26, 2001
57
{
May 28, 2006
May 28, 2006
58
59
60
61
62
63
64
65
66
67
68
WMcursor *cursor;
XGCValues GCvalues;
GC GCcursor;
XImage *data_image, *mask_image;
Pixmap data_pixmap, mask_pixmap;
int clen, i;
char *x_data, *x_mask;
static XColor black = { 0, 0, 0, 0 };
static XColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
/* Allocate the cursor memory */
May 29, 2006
May 29, 2006
69
cursor = (WMcursor *) SDL_malloc(sizeof(WMcursor));
May 28, 2006
May 28, 2006
70
if (cursor == NULL) {
May 29, 2006
May 29, 2006
71
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
72
73
74
75
76
return (NULL);
}
/* Mix the mask and the data */
clen = (w / 8) * h;
May 29, 2006
May 29, 2006
77
x_data = (char *) SDL_malloc(clen);
May 28, 2006
May 28, 2006
78
if (x_data == NULL) {
May 29, 2006
May 29, 2006
79
80
SDL_free(cursor);
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
81
82
return (NULL);
}
May 29, 2006
May 29, 2006
83
x_mask = (char *) SDL_malloc(clen);
May 28, 2006
May 28, 2006
84
if (x_mask == NULL) {
May 29, 2006
May 29, 2006
85
86
87
SDL_free(cursor);
SDL_free(x_data);
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
88
89
90
91
92
93
94
95
96
97
98
99
return (NULL);
}
for (i = 0; i < clen; ++i) {
/* The mask is OR'd with the data to turn inverted color
pixels black since inverted color cursors aren't supported
under X11.
*/
x_mask[i] = data[i] | mask[i];
x_data[i] = data[i];
}
/* Prevent the event thread from running while we use the X server */
May 29, 2006
May 29, 2006
100
SDL_Lock_EventThread();
May 28, 2006
May 28, 2006
101
102
/* Create the data image */
May 29, 2006
May 29, 2006
103
104
105
data_image = XCreateImage(SDL_Display,
DefaultVisual(SDL_Display, SDL_Screen),
1, XYBitmap, 0, x_data, w, h, 8, w / 8);
May 28, 2006
May 28, 2006
106
107
data_image->byte_order = MSBFirst;
data_image->bitmap_bit_order = MSBFirst;
May 29, 2006
May 29, 2006
108
data_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1);
May 28, 2006
May 28, 2006
109
110
/* Create the data mask */
May 29, 2006
May 29, 2006
111
112
113
mask_image = XCreateImage(SDL_Display,
DefaultVisual(SDL_Display, SDL_Screen),
1, XYBitmap, 0, x_mask, w, h, 8, w / 8);
May 28, 2006
May 28, 2006
114
115
mask_image->byte_order = MSBFirst;
mask_image->bitmap_bit_order = MSBFirst;
May 29, 2006
May 29, 2006
116
mask_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1);
May 28, 2006
May 28, 2006
117
118
119
120
121
122
/* Create the graphics context */
GCvalues.function = GXcopy;
GCvalues.foreground = ~0;
GCvalues.background = 0;
GCvalues.plane_mask = AllPlanes;
May 29, 2006
May 29, 2006
123
124
125
GCcursor = XCreateGC(SDL_Display, data_pixmap,
(GCFunction | GCForeground | GCBackground |
GCPlaneMask), &GCvalues);
May 28, 2006
May 28, 2006
126
127
/* Blit the images to the pixmaps */
May 29, 2006
May 29, 2006
128
129
130
131
132
XPutImage(SDL_Display, data_pixmap, GCcursor, data_image,
0, 0, 0, 0, w, h);
XPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image,
0, 0, 0, 0, w, h);
XFreeGC(SDL_Display, GCcursor);
May 28, 2006
May 28, 2006
133
/* These free the x_data and x_mask memory pointers */
May 29, 2006
May 29, 2006
134
135
XDestroyImage(data_image);
XDestroyImage(mask_image);
May 28, 2006
May 28, 2006
136
137
/* Create the cursor */
May 29, 2006
May 29, 2006
138
139
140
141
142
cursor->x_cursor = XCreatePixmapCursor(SDL_Display, data_pixmap,
mask_pixmap, &black, &white,
hot_x, hot_y);
XFreePixmap(SDL_Display, data_pixmap);
XFreePixmap(SDL_Display, mask_pixmap);
May 28, 2006
May 28, 2006
143
144
/* Release the event thread */
May 29, 2006
May 29, 2006
145
146
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
May 28, 2006
May 28, 2006
147
148
return (cursor);
Apr 26, 2001
Apr 26, 2001
149
150
}
May 28, 2006
May 28, 2006
151
int
May 29, 2006
May 29, 2006
152
X11_ShowWMCursor(_THIS, WMcursor * cursor)
Apr 26, 2001
Apr 26, 2001
153
{
May 28, 2006
May 28, 2006
154
155
156
157
158
159
160
/* Don't do anything if the display is gone */
if (SDL_Display == NULL) {
return (0);
}
/* Set the X11 cursor cursor, or blank if cursor is NULL */
if (SDL_Window) {
May 29, 2006
May 29, 2006
161
SDL_Lock_EventThread();
May 28, 2006
May 28, 2006
162
163
if (cursor == NULL) {
if (SDL_BlankCursor != NULL) {
May 29, 2006
May 29, 2006
164
165
XDefineCursor(SDL_Display, SDL_Window,
SDL_BlankCursor->x_cursor);
May 28, 2006
May 28, 2006
166
167
}
} else {
May 29, 2006
May 29, 2006
168
XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor);
May 28, 2006
May 28, 2006
169
}
May 29, 2006
May 29, 2006
170
171
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
May 28, 2006
May 28, 2006
172
173
}
return (1);
Apr 26, 2001
Apr 26, 2001
174
175
}
May 28, 2006
May 28, 2006
176
void
May 29, 2006
May 29, 2006
177
X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
Apr 26, 2001
Apr 26, 2001
178
{
May 28, 2006
May 28, 2006
179
if (using_dga & DGA_MOUSE) {
May 29, 2006
May 29, 2006
180
SDL_PrivateMouseMotion(0, 0, x, y);
May 28, 2006
May 28, 2006
181
182
183
184
} else if (mouse_relative) {
/* RJR: March 28, 2000
leave physical cursor at center of screen if
mouse hidden and grabbed */
May 29, 2006
May 29, 2006
185
SDL_PrivateMouseMotion(0, 0, x, y);
May 28, 2006
May 28, 2006
186
} else {
May 29, 2006
May 29, 2006
187
188
189
190
SDL_Lock_EventThread();
XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y);
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
May 28, 2006
May 28, 2006
191
}
Apr 26, 2001
Apr 26, 2001
192
193
194
195
196
197
198
}
/* Sets the mouse acceleration from a string of the form:
2/1/0
The first number is the numerator, followed by the acceleration
denumenator and threshold.
*/
May 28, 2006
May 28, 2006
199
static void
May 29, 2006
May 29, 2006
200
SetMouseAccel(_THIS, const char *accel_param)
Apr 26, 2001
Apr 26, 2001
201
{
May 28, 2006
May 28, 2006
202
203
204
205
206
int i;
size_t len;
int accel_value[3];
char *mouse_param, *mouse_param_buf, *pin;
May 29, 2006
May 29, 2006
207
208
len = SDL_strlen(accel_param) + 1;
mouse_param_buf = SDL_stack_alloc(char, len);
May 28, 2006
May 28, 2006
209
210
211
if (!mouse_param_buf) {
return;
}
May 29, 2006
May 29, 2006
212
SDL_strlcpy(mouse_param_buf, accel_param, len);
May 28, 2006
May 28, 2006
213
214
215
mouse_param = mouse_param_buf;
for (i = 0; (i < 3) && mouse_param; ++i) {
May 29, 2006
May 29, 2006
216
pin = SDL_strchr(mouse_param, '/');
May 28, 2006
May 28, 2006
217
218
219
if (pin) {
*pin = '\0';
}
May 29, 2006
May 29, 2006
220
accel_value[i] = atoi(mouse_param);
May 28, 2006
May 28, 2006
221
222
223
224
225
226
227
if (pin) {
mouse_param = pin + 1;
} else {
mouse_param = NULL;
}
}
if (mouse_param_buf) {
May 29, 2006
May 29, 2006
228
229
230
XChangePointerControl(SDL_Display, True, True,
accel_value[0], accel_value[1], accel_value[2]);
SDL_free(mouse_param_buf);
May 28, 2006
May 28, 2006
231
}
Apr 26, 2001
Apr 26, 2001
232
233
234
}
/* Check to see if we need to enter or leave mouse relative mode */
May 28, 2006
May 28, 2006
235
void
May 29, 2006
May 29, 2006
236
X11_CheckMouseModeNoLock(_THIS)
Apr 26, 2001
Apr 26, 2001
237
{
May 28, 2006
May 28, 2006
238
239
240
241
242
243
244
245
246
const Uint8 full_focus =
(SDL_APPACTIVE | SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS);
char *env_override;
int enable_relative = 1;
/* Allow the user to override the relative mouse mode.
They almost never want to do this, as it seriously affects
applications that rely on continuous relative mouse motion.
*/
May 29, 2006
May 29, 2006
247
env_override = SDL_getenv("SDL_MOUSE_RELATIVE");
May 28, 2006
May 28, 2006
248
if (env_override) {
May 29, 2006
May 29, 2006
249
enable_relative = atoi(env_override);
May 28, 2006
May 28, 2006
250
251
252
253
254
255
}
/* If the mouse is hidden and input is grabbed, we use relative mode */
if (enable_relative &&
!(SDL_cursorstate & CURSOR_VISIBLE) &&
(SDL_CurrentWindow.input_grab != SDL_GRAB_OFF) &&
May 29, 2006
May 29, 2006
256
(SDL_GetAppState() & full_focus) == full_focus) {
May 28, 2006
May 28, 2006
257
if (!mouse_relative) {
May 29, 2006
May 29, 2006
258
X11_EnableDGAMouse(this);
May 28, 2006
May 28, 2006
259
260
261
if (!(using_dga & DGA_MOUSE)) {
char *xmouse_accel;
May 29, 2006
May 29, 2006
262
SDL_GetMouseState(&mouse_last.x, &mouse_last.y);
May 28, 2006
May 28, 2006
263
/* Use as raw mouse mickeys as possible */
May 29, 2006
May 29, 2006
264
265
266
267
268
XGetPointerControl(SDL_Display,
&mouse_accel.numerator,
&mouse_accel.denominator,
&mouse_accel.threshold);
xmouse_accel = SDL_getenv("SDL_VIDEO_X11_MOUSEACCEL");
May 28, 2006
May 28, 2006
269
if (xmouse_accel) {
May 29, 2006
May 29, 2006
270
SetMouseAccel(this, xmouse_accel);
May 28, 2006
May 28, 2006
271
272
273
274
275
276
277
}
}
mouse_relative = 1;
}
} else {
if (mouse_relative) {
if (using_dga & DGA_MOUSE) {
May 29, 2006
May 29, 2006
278
X11_DisableDGAMouse(this);
May 28, 2006
May 28, 2006
279
} else {
May 29, 2006
May 29, 2006
280
281
282
283
XChangePointerControl(SDL_Display, True, True,
mouse_accel.numerator,
mouse_accel.denominator,
mouse_accel.threshold);
May 28, 2006
May 28, 2006
284
285
286
287
}
mouse_relative = 0;
}
}
Apr 26, 2001
Apr 26, 2001
288
}
May 28, 2006
May 28, 2006
289
void
May 29, 2006
May 29, 2006
290
X11_CheckMouseMode(_THIS)
Apr 26, 2001
Apr 26, 2001
291
{
May 29, 2006
May 29, 2006
292
293
294
SDL_Lock_EventThread();
X11_CheckMouseModeNoLock(this);
SDL_Unlock_EventThread();
Apr 26, 2001
Apr 26, 2001
295
}
May 28, 2006
May 28, 2006
296
297
/* vi: set ts=4 sw=4 expandtab: */