Last active
December 6, 2017 16:03
-
-
Save DanielGibson/f357c2f86734f8be39c8a758b1f900e3 to your computer and use it in GitHub Desktop.
test sdl relative mouse input with mouse warping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gcc -Wall -o warptest `sdl2-config --cflags` sdl-warptest.c `sdl2-config --libs` | |
#include <stdio.h> | |
#include <SDL.h> | |
// set to 1 to use SDL_GetMouseState() and SDL_WarpMouseInWindow() for custom relative mode | |
// 0 uses SDL2s relative mode, while enforcing SDL2's internal warping with SDL_HINT_MOUSE_RELATIVE_MODE_WARP | |
#define DO_WARP_YOURSELF 0 | |
static FILE* outfile = NULL; | |
static void UpdateWinTitle(int accumX, int accumY, SDL_Window* win) | |
{ | |
char buf[128]; | |
snprintf(buf, 128, "Accumulated: X: %d Y: %d\n", accumX, accumY); | |
SDL_SetWindowTitle(win, buf); | |
} | |
static void my_SDL_LogOutputFunction(void* userdata, | |
int category, | |
SDL_LogPriority priority, | |
const char* message) | |
{ | |
fprintf(outfile, "#SDL: %s\n", message); | |
fflush(outfile); | |
} | |
int main(int argc, char** argv) | |
{ | |
outfile = stdout; // if you can't use stdout on windows, you could fopen() a text file here for logging | |
SDL_version ver; | |
SDL_GetVersion(&ver); | |
fprintf(outfile, "SDL Version: %d.%d.%d\n", (int)ver.major, (int)ver.minor, (int)ver.patch); | |
SDL_LogSetOutputFunction(my_SDL_LogOutputFunction, NULL); | |
SDL_Init(SDL_INIT_VIDEO); | |
SDL_Window* win = SDL_CreateWindow("Move your mouse!", 100, 100, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); | |
//SDL_SetWindowGrab(win, 1); | |
SDL_Surface* winSurf = SDL_GetWindowSurface(win); | |
Uint32 grey = SDL_MapRGB(winSurf->format, 127, 127, 127); | |
// accum* holds the sum of all relative movements and is shown in window title | |
int accumX = 0, accumY = 0; | |
#if DO_WARP_YOURSELF | |
SDL_WarpMouseInWindow(win, 320, 240); | |
#else | |
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); | |
SDL_SetRelativeMouseMode(1); | |
#endif | |
int keepRunning = 1; | |
while(keepRunning) { | |
winSurf = SDL_GetWindowSurface(win); | |
SDL_FillRect(winSurf, NULL, grey); | |
SDL_UpdateWindowSurface(win); | |
SDL_Delay(10); | |
SDL_Event ev; | |
while(SDL_PollEvent(&ev)) { | |
switch(ev.type) { | |
case SDL_KEYDOWN: | |
if(ev.key.keysym.sym == SDLK_q || ev.key.keysym.sym == SDLK_ESCAPE) { | |
fprintf(outfile, "You pressed Q or Esc - bye!\n"); | |
keepRunning = 0; | |
} | |
break; | |
case SDL_MOUSEMOTION: | |
if(ev.motion.xrel > 0) | |
fprintf(outfile, "> Mouse motion: rel: %d %d pos: %d %d\n", (int)ev.motion.xrel, (int)ev.motion.yrel, (int)ev.motion.x, (int)ev.motion.y); | |
else | |
fprintf(outfile, "<<< Mouse motion: rel: %d %d pos: %d %d\n", (int)ev.motion.xrel, (int)ev.motion.yrel, (int)ev.motion.x, (int)ev.motion.y); | |
fflush(outfile); | |
#if ! DO_WARP_YOURSELF | |
accumX += ev.motion.xrel; | |
accumY += ev.motion.yrel; | |
UpdateWinTitle(accumX, accumY, win); | |
#endif | |
break; | |
} | |
} | |
#if DO_WARP_YOURSELF | |
int x,y, w,h; | |
SDL_GetMouseState(&x, &y); | |
SDL_GetWindowSize(win, &w, &h); | |
x -= w/2; | |
y -= h/2; | |
SDL_WarpMouseInWindow(win, w/2, h/2); | |
fprintf(outfile, "rel Mouse Position: %d %d\n", x, y); | |
if(x != 0 || y != 0) { | |
accumX += x; | |
accumY += y; | |
UpdateWinTitle(accumX, accumY, win); | |
} | |
#endif | |
fprintf(outfile, "### end of frame ###\n"); | |
fflush(outfile); | |
} | |
SDL_DestroyWindow(win); | |
SDL_Quit(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in src/events/SDL_mouse.c added some SDL_Log() calls to SDL_PrivateSendMouseMotion(): | |
#include "SDL_log.h" | |
static int | |
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) | |
{ | |
SDL_Mouse *mouse = SDL_GetMouse(); | |
int posted; | |
int xrel; | |
int yrel; | |
if (mouseID == SDL_TOUCH_MOUSEID && !mouse->touch_mouse_events) { | |
return 0; | |
} | |
if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) { | |
int center_x = 0, center_y = 0; | |
SDL_GetWindowSize(window, ¢er_x, ¢er_y); | |
center_x /= 2; | |
center_y /= 2; | |
if (x == center_x && y == center_y) { | |
SDL_Log("## Resetting mouse->last* to %d %d\n", center_x, center_y); | |
mouse->last_x = center_x; // possible fix for the issue: move this .. | |
mouse->last_y = center_y; // and this line before the if(x == center_x && y == center_y) | |
return 0; | |
} | |
SDL_Log("## Warping mouse to %d %d\n", center_x, center_y); | |
SDL_WarpMouseInWindow(window, center_x, center_y); | |
} | |
if (relative) { | |
if (mouse->relative_mode) { | |
x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x); | |
y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y); | |
} else { | |
x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x); | |
y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y); | |
} | |
xrel = x; | |
yrel = y; | |
x = (mouse->last_x + xrel); | |
y = (mouse->last_y + yrel); | |
} else { | |
xrel = x - mouse->last_x; | |
yrel = y - mouse->last_y; | |
} | |
SDL_Log("# x,y: %d/%d rel: %d/%d, last: %d/%d\n", x, y, xrel, yrel, mouse->last_x, mouse->last_y); | |
SDL_Log("# relative: %d mouse->relative_mode: %d\n", relative, mouse->relative_mode); | |
/* Drop events that don't change state */ | |
if (!xrel && !yrel) { | |
#ifdef DEBUG_MOUSE | |
printf("Mouse event didn't change state - dropped!\n"); | |
#endif | |
return 0; | |
} | |
/* Ignore relative motion when first positioning the mouse */ | |
if (!mouse->has_position) { | |
xrel = 0; | |
yrel = 0; | |
mouse->has_position = SDL_TRUE; | |
} | |
/* Ignore relative motion positioning the first touch */ | |
if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) { | |
xrel = 0; | |
yrel = 0; | |
} | |
/* Update internal mouse coordinates */ | |
if (!mouse->relative_mode) { | |
mouse->x = x; | |
mouse->y = y; | |
} else { | |
mouse->x += xrel; | |
mouse->y += yrel; | |
} | |
/* make sure that the pointers find themselves inside the windows, | |
unless we have the mouse captured. */ | |
if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { | |
int x_max = 0, y_max = 0; | |
/* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */ | |
SDL_GetWindowSize(mouse->focus, &x_max, &y_max); | |
--x_max; | |
--y_max; | |
if (mouse->x > x_max) { | |
mouse->x = x_max; | |
} | |
if (mouse->x < 0) { | |
mouse->x = 0; | |
} | |
if (mouse->y > y_max) { | |
mouse->y = y_max; | |
} | |
if (mouse->y < 0) { | |
mouse->y = 0; | |
} | |
} | |
mouse->xdelta += xrel; | |
mouse->ydelta += yrel; | |
/* Move the mouse cursor, if needed */ | |
if (mouse->cursor_shown && !mouse->relative_mode && | |
mouse->MoveCursor && mouse->cur_cursor) { | |
mouse->MoveCursor(mouse->cur_cursor); | |
} | |
/* Post the event, if desired */ | |
posted = 0; | |
if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { | |
SDL_Event event; | |
event.motion.type = SDL_MOUSEMOTION; | |
event.motion.windowID = mouse->focus ? mouse->focus->id : 0; | |
event.motion.which = mouseID; | |
event.motion.state = mouse->buttonstate; | |
event.motion.x = mouse->x; | |
event.motion.y = mouse->y; | |
event.motion.xrel = xrel; | |
event.motion.yrel = yrel; | |
posted = (SDL_PushEvent(&event) > 0); | |
} | |
if (relative) { | |
mouse->last_x = mouse->x; | |
mouse->last_y = mouse->y; | |
} else { | |
/* Use unclamped values if we're getting events outside the window */ | |
mouse->last_x = x; | |
mouse->last_y = y; | |
} | |
return posted; | |
} | |
// ... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment