comparison src/events/SDL_mouse.c @ 1670:eef792d31de8 SDL-1.3

Work in progress. :)
author Sam Lantinga <slouken@libsdl.org>
date Wed, 07 Jun 2006 16:10:28 +0000
parents 4da1ee79c9af
children 89f7510fe17a
comparison
equal deleted inserted replaced
1669:9857d21967bb 1670:eef792d31de8
23 23
24 /* General mouse handling code for SDL */ 24 /* General mouse handling code for SDL */
25 25
26 #include "SDL_events.h" 26 #include "SDL_events.h"
27 #include "SDL_events_c.h" 27 #include "SDL_events_c.h"
28 #include "../video/SDL_cursor_c.h" 28 #include "SDL_mouse_c.h"
29 #include "../video/SDL_sysvideo.h" 29
30 30
31 31 static int SDL_num_mice;
32 /* These are static for our mouse handling code */ 32 static int SDL_current_mouse;
33 static Sint16 SDL_MouseX = 0; 33 static SDL_Mouse *SDL_mice;
34 static Sint16 SDL_MouseY = 0;
35 static Sint16 SDL_DeltaX = 0;
36 static Sint16 SDL_DeltaY = 0;
37 static Uint8 SDL_ButtonState = 0;
38 34
39 35
40 /* Public functions */ 36 /* Public functions */
41 int 37 int
42 SDL_MouseInit(void) 38 SDL_MouseInit(void)
43 { 39 {
44 /* The mouse is at (0,0) */
45 SDL_MouseX = 0;
46 SDL_MouseY = 0;
47 SDL_DeltaX = 0;
48 SDL_DeltaY = 0;
49 SDL_ButtonState = 0;
50
51 /* That's it! */
52 return (0); 40 return (0);
41 }
42
43 int
44 SDL_AddMouse(SDL_WindowID focus, int x, int y, Uint8 buttonstate)
45 {
46 SDL_Mouse *new_mice;
47 int index;
48 SDL_Mouse *mouse;
49
50 new_mice =
51 (SDL_Mouse *) SDL_realloc(SDL_mice,
52 (SDL_num_mice + 1) * sizeof(*new_mice));
53 if (!new_mice) {
54 SDL_OutOfMemory();
55 return -1;
56 }
57
58 index = SDL_num_mice++;
59 mouse = &SDL_mice[index];
60 mouse->focus = focus;
61 mouse->x = x;
62 mouse->y = y;
63 mouse->xdelta = 0;
64 mouse->ydelta = 0;
65 mouse->buttonstate = buttonstate;
66
67 return index;
68 }
69
70 SDL_Mouse *
71 SDL_GetMouse(int index)
72 {
73 if (index < 0 || index >= SDL_num_mice) {
74 return NULL;
75 }
76 return &SDL_mice[index];
53 } 77 }
54 78
55 void 79 void
56 SDL_MouseQuit(void) 80 SDL_MouseQuit(void)
57 { 81 {
58 } 82 SDL_num_mice = 0;
59 83 SDL_current_mouse = 0;
60 /* We lost the mouse, so post button up messages for all pressed buttons */ 84
61 void 85 if (SDL_mice) {
62 SDL_ResetMouse(void) 86 SDL_free(SDL_mice);
63 { 87 SDL_mice = NULL;
64 Uint8 i; 88 }
65 for (i = 0; i < sizeof(SDL_ButtonState) * 8; ++i) { 89 }
66 if (SDL_ButtonState & SDL_BUTTON(i)) { 90
67 SDL_PrivateMouseButton(SDL_RELEASED, i, 0, 0); 91 int
68 } 92 SDL_GetNumMice(void)
69 } 93 {
94 return SDL_num_mice;
95 }
96
97 int
98 SDL_SelectMouse(int index)
99 {
100 if (index >= 0 && index < SDL_num_mice) {
101 SDL_current_mouse = index;
102 }
103 return SDL_current_mouse;
104 }
105
106 SDL_WindowID
107 SDL_GetMouseFocusWindow()
108 {
109 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
110
111 if (!mouse) {
112 return 0;
113 }
114 return mouse->focus;
70 } 115 }
71 116
72 Uint8 117 Uint8
73 SDL_GetMouseState(int *x, int *y) 118 SDL_GetMouseState(int *x, int *y)
74 { 119 {
120 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
121
122 if (!mouse) {
123 if (x) {
124 *x = 0;
125 }
126 if (y) {
127 *y = 0;
128 }
129 return 0;
130 }
131
75 if (x) { 132 if (x) {
76 *x = SDL_MouseX; 133 *x = mouse->x;
77 } 134 }
78 if (y) { 135 if (y) {
79 *y = SDL_MouseY; 136 *y = mouse->y;
80 } 137 }
81 return (SDL_ButtonState); 138 return mouse->buttonstate;
82 } 139 }
83 140
84 Uint8 141 Uint8
85 SDL_GetRelativeMouseState(int *x, int *y) 142 SDL_GetRelativeMouseState(int *x, int *y)
86 { 143 {
87 if (x) 144 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
88 *x = SDL_DeltaX; 145
89 if (y) 146 if (!mouse) {
90 *y = SDL_DeltaY; 147 if (x) {
91 SDL_DeltaX = 0; 148 *x = 0;
92 SDL_DeltaY = 0; 149 }
93 return (SDL_ButtonState); 150 if (y) {
94 } 151 *y = 0;
95 152 }
96 static void 153 return 0;
97 ClipOffset(Sint16 * x, Sint16 * y) 154 }
98 { 155
99 SDL_VideoDevice *_this = SDL_GetVideoDevice(); 156 if (x) {
100 157 *x = mouse->xdelta;
101 /* This clips absolute mouse coordinates when the apparent 158 }
102 display surface is smaller than the real display surface. 159 if (y) {
103 */ 160 *y = mouse->ydelta;
104 if (SDL_VideoSurface->offset) { 161 }
105 *y -= SDL_VideoSurface->offset / SDL_VideoSurface->pitch; 162 mouse->xdelta = 0;
106 *x -= (SDL_VideoSurface->offset % SDL_VideoSurface->pitch) / 163 mouse->ydelta = 0;
107 SDL_VideoSurface->format->BytesPerPixel; 164 return mouse->buttonstate;
108 } 165 }
109 } 166
110 167 int
111 /* These are global for SDL_eventloop.c */ 168 SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, int x,
112 int 169 int y)
113 SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y) 170 {
114 { 171 SDL_Mouse *mouse = SDL_GetMouse(index);
115 SDL_VideoDevice *_this = SDL_GetVideoDevice();
116 int posted; 172 int posted;
117 Uint16 X, Y; 173 int xrel;
118 Sint16 Xrel; 174 int yrel;
119 Sint16 Yrel; 175
120 176 if (!mouse) {
121 /* Don't handle mouse motion if there's no cursor surface */ 177 return 0;
122 if (SDL_VideoSurface == NULL) { 178 }
123 return (0); 179
124 } 180 if (windowID) {
125 181 mouse->focus = windowID;
126 /* Default buttonstate is the current one */ 182 }
127 if (!buttonstate) { 183
128 buttonstate = SDL_ButtonState;
129 }
130
131 Xrel = x;
132 Yrel = y;
133 if (relative) { 184 if (relative) {
134 /* Push the cursor around */ 185 /* Push the cursor around */
135 x = (SDL_MouseX + x); 186 xrel = x;
136 y = (SDL_MouseY + y); 187 yrel = y;
188 x = (mouse->x + xrel);
189 y = (mouse->y + yrel);
137 } else { 190 } else {
138 /* Do we need to clip {x,y} ? */ 191 xrel = x - mouse->x;
139 ClipOffset(&x, &y); 192 yrel = y - mouse->y;
140 }
141
142 /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */
143 if (x < 0)
144 X = 0;
145 else if (x >= SDL_VideoSurface->w)
146 X = SDL_VideoSurface->w - 1;
147 else
148 X = (Uint16) x;
149
150 if (y < 0)
151 Y = 0;
152 else if (y >= SDL_VideoSurface->h)
153 Y = SDL_VideoSurface->h - 1;
154 else
155 Y = (Uint16) y;
156
157 /* If not relative mode, generate relative motion from clamped X/Y.
158 This prevents lots of extraneous large delta relative motion when
159 the screen is windowed mode and the mouse is outside the window.
160 */
161 if (!relative) {
162 Xrel = X - SDL_MouseX;
163 Yrel = Y - SDL_MouseY;
164 } 193 }
165 194
166 /* Drop events that don't change state */ 195 /* Drop events that don't change state */
167 if (!Xrel && !Yrel) { 196 if (!xrel && !yrel) {
168 #if 0 197 #if 0
169 printf("Mouse event didn't change state - dropped!\n"); 198 printf("Mouse event didn't change state - dropped!\n");
170 #endif 199 #endif
171 return (0); 200 return 0;
172 } 201 }
173 202
174 /* Update internal mouse state */ 203 /* Update internal mouse state */
175 SDL_ButtonState = buttonstate; 204 mouse->xdelta += xrel;
176 SDL_MouseX = X; 205 mouse->ydelta += yrel;
177 SDL_MouseY = Y;
178 SDL_DeltaX += Xrel;
179 SDL_DeltaY += Yrel;
180 SDL_MoveCursor(SDL_MouseX, SDL_MouseY);
181 206
182 /* Post the event, if desired */ 207 /* Post the event, if desired */
183 posted = 0; 208 posted = 0;
184 if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) { 209 if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) {
185 SDL_Event event; 210 SDL_Event event;
186 SDL_memset(&event, 0, sizeof(event)); 211 event.motion.type = SDL_MOUSEMOTION;
187 event.type = SDL_MOUSEMOTION; 212 event.motion.which = (Uint8) index;
188 event.motion.state = buttonstate; 213 event.motion.state = mouse->buttonstate;
189 event.motion.x = X; 214 event.motion.x = mouse->x;
190 event.motion.y = Y; 215 event.motion.y = mouse->y;
191 event.motion.xrel = Xrel; 216 event.motion.xrel = xrel;
192 event.motion.yrel = Yrel; 217 event.motion.yrel = yrel;
218 event.motion.windowID = mouse->focus;
193 if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) { 219 if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
194 posted = 1; 220 posted = 1;
195 SDL_PushEvent(&event); 221 SDL_PushEvent(&event);
196 } 222 }
197 } 223 }
198 return (posted); 224 return posted;
199 } 225 }
200 226
201 int 227 int
202 SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, Sint16 y) 228 SDL_PrivateMouseButton(int index, SDL_WindowID windowID, Uint8 state,
203 { 229 Uint8 button)
204 SDL_VideoDevice *_this = SDL_GetVideoDevice(); 230 {
205 SDL_Event event; 231 SDL_Mouse *mouse = SDL_GetMouse(index);
206 int posted; 232 int posted;
207 int move_mouse; 233 Uint8 type;
208 Uint8 buttonstate; 234
209 235 if (!mouse) {
210 SDL_memset(&event, 0, sizeof(event)); 236 return 0;
211 237 }
212 /* Check parameters */ 238
213 if (x || y) { 239 if (windowID) {
214 ClipOffset(&x, &y); 240 mouse->focus = windowID;
215 move_mouse = 1; 241 }
216 /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */
217 if (x < 0)
218 x = 0;
219 else if (x >= SDL_VideoSurface->w)
220 x = SDL_VideoSurface->w - 1;
221
222 if (y < 0)
223 y = 0;
224 else if (y >= SDL_VideoSurface->h)
225 y = SDL_VideoSurface->h - 1;
226 } else {
227 move_mouse = 0;
228 }
229 if (!x)
230 x = SDL_MouseX;
231 if (!y)
232 y = SDL_MouseY;
233 242
234 /* Figure out which event to perform */ 243 /* Figure out which event to perform */
235 buttonstate = SDL_ButtonState;
236 switch (state) { 244 switch (state) {
237 case SDL_PRESSED: 245 case SDL_PRESSED:
238 event.type = SDL_MOUSEBUTTONDOWN; 246 if (mouse->buttonstate & SDL_BUTTON(button)) {
239 buttonstate |= SDL_BUTTON(button); 247 /* Ignore this event, no state change */
248 return 0;
249 }
250 type = SDL_MOUSEBUTTONDOWN;
251 mouse->buttonstate |= SDL_BUTTON(button);
240 break; 252 break;
241 case SDL_RELEASED: 253 case SDL_RELEASED:
242 event.type = SDL_MOUSEBUTTONUP; 254 if (!(mouse->buttonstate & SDL_BUTTON(button))) {
243 buttonstate &= ~SDL_BUTTON(button); 255 /* Ignore this event, no state change */
256 return 0;
257 }
258 type = SDL_MOUSEBUTTONUP;
259 mouse->buttonstate &= ~SDL_BUTTON(button);
244 break; 260 break;
245 default: 261 default:
246 /* Invalid state -- bail */ 262 /* Invalid state -- bail */
247 return (0); 263 return 0;
248 }
249
250 /* Update internal mouse state */
251 SDL_ButtonState = buttonstate;
252 if (move_mouse) {
253 SDL_MouseX = x;
254 SDL_MouseY = y;
255 SDL_MoveCursor(SDL_MouseX, SDL_MouseY);
256 } 264 }
257 265
258 /* Post the event, if desired */ 266 /* Post the event, if desired */
259 posted = 0; 267 posted = 0;
260 if (SDL_ProcessEvents[event.type] == SDL_ENABLE) { 268 if (SDL_ProcessEvents[type] == SDL_ENABLE) {
269 SDL_Event event;
270 event.type = type;
271 event.button.which = (Uint8) index;
261 event.button.state = state; 272 event.button.state = state;
262 event.button.button = button; 273 event.button.button = button;
263 event.button.x = x; 274 event.button.x = mouse->x;
264 event.button.y = y; 275 event.button.y = mouse->y;
276 event.button.windowID = windowID;
265 if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) { 277 if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
266 posted = 1; 278 posted = 1;
267 SDL_PushEvent(&event); 279 SDL_PushEvent(&event);
268 } 280 }
269 } 281 }
270 return (posted); 282 return posted;
271 } 283 }
272 284
273 /* vi: set ts=4 sw=4 expandtab: */ 285 /* vi: set ts=4 sw=4 expandtab: */