Home | History | Annotate | Download | only in events
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 (at) 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 
    269