mirror of https://github.com/libsdl-org/SDL
mouse: Make pointer warp emulation via relative mode available to all platforms
Move the Wayland pointer warp emulation code up to the SDL mouse layer, and activate it when a client attempts to warp a hidden mouse cursor when the hint is set. testrelative adds the ability to test the warp emulation activation/deactivation with the --warp parameter and 'c' key for toggling cursor visibility.
This commit is contained in:
parent
92667e3066
commit
66eb2ea443
|
@ -3596,3 +3596,7 @@ typedef SDL_JoystickGUID, SDL_GUID;
|
|||
- SDL_OnApplicationDidBecomeActive
|
||||
+ SDL_OnApplicationDidEnterForeground
|
||||
(...)
|
||||
@@
|
||||
@@
|
||||
- SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP
|
||||
+ SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE
|
||||
|
|
|
@ -806,6 +806,7 @@ The following hints have been renamed:
|
|||
* SDL_HINT_LINUX_HAT_DEADZONES => SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES
|
||||
* SDL_HINT_LINUX_JOYSTICK_CLASSIC => SDL_HINT_JOYSTICK_LINUX_CLASSIC
|
||||
* SDL_HINT_LINUX_JOYSTICK_DEADZONES => SDL_HINT_JOYSTICK_LINUX_DEADZONES
|
||||
* SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP => SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE
|
||||
|
||||
The following functions have been removed:
|
||||
* SDL_ClearHints() - replaced with SDL_ResetHints()
|
||||
|
|
|
@ -2190,6 +2190,36 @@ extern "C" {
|
|||
*/
|
||||
#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
|
||||
|
||||
/**
|
||||
* A variable controlling whether warping a hidden mouse cursor will activate
|
||||
* relative mouse mode.
|
||||
*
|
||||
* When this hint is set and the mouse cursor is hidden, SDL will emulate mouse
|
||||
* warps using relative mouse mode. This can provide smoother and more reliable
|
||||
* mouse motion for some older games, which continuously calculate the distance
|
||||
* travelled by the mouse pointer and warp it back to the center of the window,
|
||||
* rather than using relative mouse motion.
|
||||
*
|
||||
* Note that relative mouse mode may have different mouse acceleration behavior
|
||||
* than pointer warps.
|
||||
*
|
||||
* If your game or application needs to warp the mouse cursor while hidden for
|
||||
* other purposes, such as drawing a software cursor, it should disable this hint.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": Attempts to warp the mouse will always be made.
|
||||
* - "1": Some mouse warps will be emulated by forcing relative mouse mode. (default)
|
||||
*
|
||||
* If not set, this is automatically enabled unless an application uses
|
||||
* relative mouse mode directly.
|
||||
*
|
||||
* This hint can be set anytime.
|
||||
*
|
||||
* \since This hint is available since SDL 3.0.0.
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE "SDL_MOUSE_EMULATE_WARP_WITH_RELATIVE"
|
||||
|
||||
/**
|
||||
* Allow mouse click events when clicking to focus an SDL window.
|
||||
*
|
||||
|
@ -3063,34 +3093,6 @@ extern "C" {
|
|||
*/
|
||||
#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
|
||||
|
||||
/**
|
||||
* Enable or disable hidden mouse pointer warp emulation, needed by some older
|
||||
* games.
|
||||
*
|
||||
* Wayland requires the pointer confinement protocol to warp the mouse, but
|
||||
* that is just a hint that the compositor is free to ignore, and warping the
|
||||
* the pointer to or from regions outside of the focused window is prohibited.
|
||||
* When this hint is set and the pointer is hidden, SDL will emulate mouse
|
||||
* warps using relative mouse mode. This is required for some older games
|
||||
* (such as Source engine games), which warp the mouse to the centre of the
|
||||
* screen rather than using relative mouse motion. Note that relative mouse
|
||||
* mode may have different mouse acceleration behaviour than pointer warps.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": Attempts to warp the mouse will be made, if the appropriate protocol
|
||||
* is available.
|
||||
* - "1": Some mouse warps will be emulated by forcing relative mouse mode.
|
||||
*
|
||||
* If not set, this is automatically enabled unless an application uses
|
||||
* relative mouse mode directly.
|
||||
*
|
||||
* This hint can be set anytime.
|
||||
*
|
||||
* \since This hint is available since SDL 3.0.0.
|
||||
*/
|
||||
#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP"
|
||||
|
||||
/**
|
||||
* A variable controlling whether video mode emulation is enabled under
|
||||
* Wayland.
|
||||
|
|
|
@ -119,6 +119,18 @@ static void SDLCALL SDL_MouseRelativeSystemScaleChanged(void *userdata, const ch
|
|||
mouse->enable_relative_system_scale = SDL_GetStringBoolean(hint, SDL_FALSE);
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_MouseWarpEmulationChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
|
||||
mouse->warp_emulation_hint = SDL_GetStringBoolean(hint, SDL_TRUE);
|
||||
|
||||
if (!mouse->warp_emulation_hint && mouse->warp_emulation_active) {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
|
@ -211,6 +223,9 @@ int SDL_PreInitMouse(void)
|
|||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
|
||||
SDL_MouseRelativeSystemScaleChanged, mouse);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
|
||||
SDL_MouseWarpEmulationChanged, mouse);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
|
||||
SDL_TouchMouseEventsChanged, mouse);
|
||||
|
||||
|
@ -724,7 +739,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_
|
|||
float xrel = 0.0f;
|
||||
float yrel = 0.0f;
|
||||
|
||||
if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
|
||||
if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
|
||||
/* We're not in relative mode, so all mouse events are global mouse events */
|
||||
mouseID = SDL_GLOBAL_MOUSE_ID;
|
||||
}
|
||||
|
@ -1132,6 +1147,9 @@ void SDL_QuitMouse(void)
|
|||
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
|
||||
SDL_MouseRelativeSystemScaleChanged, mouse);
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
|
||||
SDL_MouseWarpEmulationChanged, mouse);
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
|
||||
SDL_TouchMouseEventsChanged, mouse);
|
||||
|
||||
|
@ -1253,9 +1271,24 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool
|
|||
}
|
||||
}
|
||||
|
||||
static void SDL_EnableWarpEmulation(SDL_Mouse *mouse)
|
||||
{
|
||||
if (!mouse->cursor_shown && mouse->warp_emulation_hint && !mouse->warp_emulation_prohibited) {
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) {
|
||||
mouse->warp_emulation_active = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Disable attempts at enabling warp emulation until further notice. */
|
||||
mouse->warp_emulation_prohibited = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WarpMouseInWindow(SDL_Window *window, float x, float y)
|
||||
{
|
||||
SDL_PerformWarpMouseInWindow(window, x, y, SDL_FALSE);
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_EnableWarpEmulation(mouse);
|
||||
|
||||
SDL_PerformWarpMouseInWindow(window, x, y, mouse->warp_emulation_active);
|
||||
}
|
||||
|
||||
int SDL_WarpMouseGlobal(float x, float y)
|
||||
|
@ -1284,6 +1317,18 @@ int SDL_SetRelativeMouseMode(SDL_bool enabled)
|
|||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Window *focusWindow = SDL_GetKeyboardFocus();
|
||||
|
||||
if (enabled) {
|
||||
if (mouse->warp_emulation_active) {
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If the app has used relative mode before, it probably shouldn't
|
||||
* also be emulating it using repeated mouse warps, so disable
|
||||
* mouse warp emulation by default.
|
||||
*/
|
||||
mouse->warp_emulation_prohibited = SDL_TRUE;
|
||||
}
|
||||
|
||||
if (enabled == mouse->relative_mode) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1642,6 +1687,12 @@ int SDL_ShowCursor(void)
|
|||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->warp_emulation_active) {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
mouse->warp_emulation_prohibited = SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!mouse->cursor_shown) {
|
||||
mouse->cursor_shown = SDL_TRUE;
|
||||
SDL_SetCursor(NULL);
|
||||
|
|
|
@ -92,6 +92,9 @@ typedef struct
|
|||
SDL_bool relative_mode_warp;
|
||||
SDL_bool relative_mode_warp_motion;
|
||||
SDL_bool relative_mode_cursor_visible;
|
||||
SDL_bool warp_emulation_hint;
|
||||
SDL_bool warp_emulation_active;
|
||||
SDL_bool warp_emulation_prohibited;
|
||||
int relative_mode_clip_interval;
|
||||
SDL_bool enable_normal_speed_scale;
|
||||
float normal_speed_scale;
|
||||
|
|
|
@ -171,10 +171,6 @@ struct SDL_WaylandInput
|
|||
|
||||
struct SDL_WaylandTabletInput *tablet;
|
||||
|
||||
/* are we forcing relative mouse mode? */
|
||||
SDL_bool cursor_visible;
|
||||
SDL_bool relative_mode_override;
|
||||
SDL_bool warp_emulation_prohibited;
|
||||
SDL_bool keyboard_is_virtual;
|
||||
|
||||
/* Current SDL modifier flags */
|
||||
|
|
|
@ -624,14 +624,8 @@ static int Wayland_ShowCursor(SDL_Cursor *cursor)
|
|||
if (input->cursor_shape) {
|
||||
Wayland_SetSystemCursorShape(input, data->cursor_data.system.id);
|
||||
|
||||
input->cursor_visible = SDL_TRUE;
|
||||
input->current_cursor = data;
|
||||
|
||||
if (input->relative_mode_override) {
|
||||
Wayland_input_disable_relative_pointer(input);
|
||||
input->relative_mode_override = SDL_FALSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if (!wayland_get_system_cursor(d, data, &scale)) {
|
||||
return -1;
|
||||
|
@ -662,18 +656,10 @@ static int Wayland_ShowCursor(SDL_Cursor *cursor)
|
|||
} else {
|
||||
wl_surface_damage(data->surface, 0, 0, SDL_MAX_SINT32, SDL_MAX_SINT32);
|
||||
}
|
||||
|
||||
wl_surface_commit(data->surface);
|
||||
|
||||
input->cursor_visible = SDL_TRUE;
|
||||
input->current_cursor = data;
|
||||
|
||||
if (input->relative_mode_override) {
|
||||
Wayland_input_disable_relative_pointer(input);
|
||||
input->relative_mode_override = SDL_FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
input->cursor_visible = SDL_FALSE;
|
||||
input->current_cursor = NULL;
|
||||
wl_pointer_set_cursor(pointer, input->pointer_enter_serial, NULL, 0, 0);
|
||||
}
|
||||
|
@ -688,40 +674,33 @@ static int Wayland_WarpMouse(SDL_Window *window, float x, float y)
|
|||
SDL_WindowData *wind = window->internal;
|
||||
struct SDL_WaylandInput *input = d->input;
|
||||
|
||||
if (input->cursor_visible || (input->warp_emulation_prohibited && !d->relative_mouse_mode)) {
|
||||
if (d->pointer_constraints) {
|
||||
const SDL_bool toggle_lock = !wind->locked_pointer;
|
||||
if (d->pointer_constraints) {
|
||||
const SDL_bool toggle_lock = !wind->locked_pointer;
|
||||
|
||||
/* The pointer confinement protocol allows setting a hint to warp the pointer,
|
||||
* but only when the pointer is locked.
|
||||
*
|
||||
* Lock the pointer, set the position hint, unlock, and hope for the best.
|
||||
*/
|
||||
if (toggle_lock) {
|
||||
Wayland_input_lock_pointer(input, window);
|
||||
}
|
||||
if (wind->locked_pointer) {
|
||||
const wl_fixed_t f_x = wl_fixed_from_double(x / wind->pointer_scale.x);
|
||||
const wl_fixed_t f_y = wl_fixed_from_double(y / wind->pointer_scale.y);
|
||||
zwp_locked_pointer_v1_set_cursor_position_hint(wind->locked_pointer, f_x, f_y);
|
||||
wl_surface_commit(wind->surface);
|
||||
}
|
||||
if (toggle_lock) {
|
||||
Wayland_input_unlock_pointer(input, window);
|
||||
}
|
||||
|
||||
/* NOTE: There is a pending warp event under discussion that should replace this when available.
|
||||
* https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/340
|
||||
*/
|
||||
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y);
|
||||
} else {
|
||||
return SDL_SetError("wayland: mouse warp failed; compositor lacks support for the required zwp_pointer_confinement_v1 protocol");
|
||||
/* The pointer confinement protocol allows setting a hint to warp the pointer,
|
||||
* but only when the pointer is locked.
|
||||
*
|
||||
* Lock the pointer, set the position hint, unlock, and hope for the best.
|
||||
*/
|
||||
if (toggle_lock) {
|
||||
Wayland_input_lock_pointer(input, window);
|
||||
}
|
||||
} else if (input->warp_emulation_prohibited) {
|
||||
return SDL_Unsupported();
|
||||
} else if (!d->relative_mouse_mode) {
|
||||
Wayland_input_enable_relative_pointer(input);
|
||||
input->relative_mode_override = SDL_TRUE;
|
||||
if (wind->locked_pointer) {
|
||||
const wl_fixed_t f_x = wl_fixed_from_double(x / wind->pointer_scale.x);
|
||||
const wl_fixed_t f_y = wl_fixed_from_double(y / wind->pointer_scale.y);
|
||||
zwp_locked_pointer_v1_set_cursor_position_hint(wind->locked_pointer, f_x, f_y);
|
||||
wl_surface_commit(wind->surface);
|
||||
}
|
||||
if (toggle_lock) {
|
||||
Wayland_input_unlock_pointer(input, window);
|
||||
}
|
||||
|
||||
/* NOTE: There is a pending warp event under discussion that should replace this when available.
|
||||
* https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/340
|
||||
*/
|
||||
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y);
|
||||
} else {
|
||||
return SDL_SetError("wayland: mouse warp failed; compositor lacks support for the required zwp_pointer_confinement_v1 protocol");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -749,29 +728,12 @@ static int Wayland_SetRelativeMouseMode(SDL_bool enabled)
|
|||
SDL_VideoData *data = vd->internal;
|
||||
|
||||
if (enabled) {
|
||||
/* Disable mouse warp emulation if it's enabled. */
|
||||
if (data->input->relative_mode_override) {
|
||||
data->input->relative_mode_override = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If the app has used relative mode before, it probably shouldn't
|
||||
* also be emulating it using repeated mouse warps, so disable
|
||||
* mouse warp emulation by default.
|
||||
*/
|
||||
data->input->warp_emulation_prohibited = SDL_TRUE;
|
||||
return Wayland_input_enable_relative_pointer(data->input);
|
||||
} else {
|
||||
return Wayland_input_disable_relative_pointer(data->input);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL Wayland_EmulateMouseWarpChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
struct SDL_WaylandInput *input = (struct SDL_WaylandInput *)userdata;
|
||||
|
||||
input->warp_emulation_prohibited = !SDL_GetStringBoolean(hint, !input->warp_emulation_prohibited);
|
||||
}
|
||||
|
||||
/* Wayland doesn't support getting the true global cursor position, but it can
|
||||
* be faked well enough for what most applications use it for: querying the
|
||||
* global cursor coordinates and transforming them to the window-relative
|
||||
|
@ -862,7 +824,6 @@ void Wayland_InitMouse(void)
|
|||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_VideoDevice *vd = SDL_GetVideoDevice();
|
||||
SDL_VideoData *d = vd->internal;
|
||||
struct SDL_WaylandInput *input = d->input;
|
||||
|
||||
mouse->CreateCursor = Wayland_CreateCursor;
|
||||
mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
|
||||
|
@ -873,9 +834,6 @@ void Wayland_InitMouse(void)
|
|||
mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
|
||||
mouse->GetGlobalMouseState = Wayland_GetGlobalMouseState;
|
||||
|
||||
input->relative_mode_override = SDL_FALSE;
|
||||
input->cursor_visible = SDL_TRUE;
|
||||
|
||||
SDL_HitTestResult r = SDL_HITTEST_NORMAL;
|
||||
while (r <= SDL_HITTEST_RESIZE_LEFT) {
|
||||
switch (r) {
|
||||
|
@ -918,26 +876,17 @@ void Wayland_InitMouse(void)
|
|||
#endif
|
||||
|
||||
SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP,
|
||||
Wayland_EmulateMouseWarpChanged, input);
|
||||
}
|
||||
|
||||
void Wayland_FiniMouse(SDL_VideoData *data)
|
||||
{
|
||||
struct SDL_WaylandInput *input = data->input;
|
||||
int i;
|
||||
|
||||
Wayland_FreeCursorThemes(data);
|
||||
|
||||
#ifdef SDL_USE_LIBDBUS
|
||||
Wayland_DBusFinishCursorProperties();
|
||||
#endif
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP,
|
||||
Wayland_EmulateMouseWarpChanged, input);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(sys_cursors); i++) {
|
||||
for (int i = 0; i < SDL_arraysize(sys_cursors); i++) {
|
||||
Wayland_FreeCursor(sys_cursors[i]);
|
||||
sys_cursors[i] = NULL;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
/* Simple program: Test relative mouse motion */
|
||||
|
||||
#include <SDL3/SDL_test.h>
|
||||
#include <SDL3/SDL_test_common.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
|
@ -21,16 +22,47 @@
|
|||
|
||||
static SDLTest_CommonState *state;
|
||||
static int i, done;
|
||||
static float mouseX, mouseY;
|
||||
static SDL_FRect rect;
|
||||
static SDL_Event event;
|
||||
static SDL_bool warp;
|
||||
|
||||
static void DrawRects(SDL_Renderer *renderer)
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||
rect.x = mouseX;
|
||||
rect.y = mouseY;
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
if (SDL_GetRelativeMouseMode()) {
|
||||
SDLTest_DrawString(renderer, 0.f, 0.f, "Relative Mode: Enabled");
|
||||
} else {
|
||||
SDLTest_DrawString(renderer, 0.f, 0.f, "Relative Mode: Disabled");
|
||||
}
|
||||
}
|
||||
|
||||
static void CenterMouse()
|
||||
{
|
||||
/* Warp the mouse back to the center of the window with input focus to use the
|
||||
* center point for calculating future motion deltas.
|
||||
*
|
||||
* NOTE: DO NOT DO THIS IN REAL APPS/GAMES!
|
||||
*
|
||||
* This is an outdated method of handling relative pointer motion, and
|
||||
* may not work properly, if at all, on some platforms. It is here *only*
|
||||
* for testing the warp emulation code path internal to SDL.
|
||||
*
|
||||
* Relative mouse mode should be used instead!
|
||||
*/
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
if (window) {
|
||||
int w, h;
|
||||
float cx, cy;
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
cx = (float)w / 2.f;
|
||||
cy = (float)h / 2.f;
|
||||
|
||||
SDL_WarpMouseInWindow(window, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
static void loop(void)
|
||||
|
@ -39,21 +71,46 @@ static void loop(void)
|
|||
while (SDL_PollEvent(&event)) {
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
if (warp) {
|
||||
/* This should activate relative mode for warp emulation, unless disabled via a hint. */
|
||||
CenterMouse();
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_C) {
|
||||
/* If warp emulation is active, showing the cursor should turn
|
||||
* relative mode off, and it should re-activate after a warp
|
||||
* when hidden again.
|
||||
*/
|
||||
if (SDL_CursorVisible()) {
|
||||
SDL_HideCursor();
|
||||
} else {
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
{
|
||||
mouseX += event.motion.xrel;
|
||||
mouseY += event.motion.yrel;
|
||||
rect.x += event.motion.xrel;
|
||||
rect.y += event.motion.yrel;
|
||||
|
||||
if (warp) {
|
||||
CenterMouse();
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
SDL_Rect viewport;
|
||||
SDL_Renderer *renderer = state->renderers[i];
|
||||
if (state->windows[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
|
@ -85,7 +142,6 @@ static void loop(void)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
/* Enable standard application logging */
|
||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
||||
|
||||
|
@ -96,8 +152,27 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
/* Parse commandline */
|
||||
if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
|
||||
return 1;
|
||||
for (i = 1; i < argc;) {
|
||||
int consumed;
|
||||
|
||||
consumed = SDLTest_CommonArg(state, i);
|
||||
if (consumed == 0) {
|
||||
consumed = -1;
|
||||
if (SDL_strcasecmp(argv[i], "--warp") == 0) {
|
||||
warp = SDL_TRUE;
|
||||
consumed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (consumed < 0) {
|
||||
static const char *options[] = {
|
||||
"[--warp]",
|
||||
NULL
|
||||
};
|
||||
SDLTest_CommonLogUsage(state, argv[0], options);
|
||||
return 1;
|
||||
}
|
||||
i += consumed;
|
||||
}
|
||||
|
||||
if (!SDLTest_CommonInit(state)) {
|
||||
|
@ -112,8 +187,17 @@ int main(int argc, char *argv[])
|
|||
SDL_RenderClear(renderer);
|
||||
}
|
||||
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
|
||||
return 3;
|
||||
/* If warp mode is activated, the cursor will be repeatedly warped back to
|
||||
* the center of the window to simulate the behavior of older games. The cursor
|
||||
* is initially hidden in this case to trigger the warp emulation unless it has
|
||||
* been explicitly disabled via a hint.
|
||||
*
|
||||
* Otherwise, try to activate relative mode.
|
||||
*/
|
||||
if (warp) {
|
||||
SDL_HideCursor();
|
||||
} else if (SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
|
||||
return 3; /* Relative mode failed, just exit. */
|
||||
}
|
||||
|
||||
rect.x = DEFAULT_WINDOW_WIDTH / 2;
|
||||
|
|
Loading…
Reference in New Issue