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