x11 mouse wheel horizontal direction

I’ve been noticing weirdness when updating my system sdl, and I managed to nail it down to this commit
I might be missing something, but this change seems wrong.

What I’m noticing after this commit (f.ex. in 3.4.6) is that when moving the fingers in touchpad from top left to bottom right, I get event.wheel.x > 0 but event.wheel.y < 0. I’d expect both to behave the same.

I agree with you, that is a bad commit. I don’t have a github account to do so, but this should be reported as a bug.

This looks like a user fighting natural scrolling vs reverse scrolling, it’s an optional setting in nearly all window managers/operating systems. Instead of changing their own mouse/touchpad settings, they decided to change SDL3’s default behavior to be broken for everyone else on X11.

To be fair, there is a field in the mousewheel event to indicate what type of scrolling is going on: event.wheel.direction, but when I flip my own OS scroll setting it does not change value. Maybe that is broken or I misunderstand its purpose? (Ubuntu, gnome, X11)

The mouse data reported by SDL Event should follow whatever the OS gives it, the game-coder should be responsible for setting their scroll inversion behavior in their own code, or preferably the player uses their own operating system’s mouse settings so that scrolling is consistent for their entire computer.
This should not be a behavior that changes on a player’s system because of a weekly system update of the SDL libs.

Behavior test:

#include <SDL3/SDL.h>

int main()
{
	SDL_Init(SDL_INIT_VIDEO);
	SDL_Window * window = SDL_CreateWindow("Scroll Left", 1000, 1000, SDL_WINDOW_RESIZABLE);
	SDL_Renderer * renderer = SDL_CreateRenderer(window, 0);
	SDL_SetRenderVSync(renderer, 1);

	SDL_FRect box = {100, 100, 50, 50};
	SDL_FRect box2 = {100, 100, 50, 50};
	SDL_FRect box3 = {100, 100, 50, 50};
	SDL_Color color = {255, 30, 30, 255};
	SDL_Color color2 = {30, 255, 30, 255};
	SDL_Color color3 = {30, 30, 255, 255};
	SDL_Color bg = {30, 30, 30, 255};
	
	bool run = true;
	while(run)
	{
		SDL_Event ev;
		while(SDL_PollEvent(&ev))
		{
			switch(ev.type)
			{
				case SDL_EVENT_MOUSE_WHEEL:
					box.x += ev.wheel.x;
					box.y += ev.wheel.y;
					box2.x = ev.wheel.mouse_x;
					box2.y = ev.wheel.mouse_y;
					box3.x = ev.wheel.integer_x;
					box3.y = ev.wheel.integer_y;
					if(ev.wheel.direction == SDL_MOUSEWHEEL_NORMAL)
					{
						SDL_Log("Scroll type: NORMAL");
					}
					else if(ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
					{
						SDL_Log("Scroll type: FLIPPED");

					}
					break;
				case SDL_EVENT_QUIT:
					run = false;
					break;
			}
		}
		SDL_SetRenderDrawColor(renderer, bg.r, bg.g, bg.b, bg.a);
		SDL_RenderClear(renderer);
		SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
		SDL_RenderRect(renderer, &box);
		SDL_SetRenderDrawColor(renderer, color2.r, color2.g, color2.b, color2.a);
		SDL_RenderRect(renderer, &box2);
		SDL_SetRenderDrawColor(renderer, color3.r, color3.g, color3.b, color3.a);
		SDL_RenderRect(renderer, &box3);
		SDL_RenderPresent(renderer);
	}
	SDL_Quit();
}

In the above code, the red box should follow the same rules as an object does in your web-browser on your system, but thanks to the commit on X11, the x-axis behavior is the opposite of y-axis behavior.

Edit: Apparently this is the preferred behavior per comments below.

This commit is correct. The x axis in the X11 smooth scrolling code should have been inverted to behave consistently with the X11 coarse scrolling and Wayland backends. This was a bug in the original smooth scrolling implementation that shipped in 3.4.

Using testmouse in the SDL test suite with a trackpad and this change:

  • With natural scrolling off, moving fingers up/right moves the scroll lines up/right
  • With natural scrolling on, moving fingers up/right moves the scroll lines down/left
  • Both coarse and smooth scroll events match on X11.
  • X11 and Wayland behavior match.

Note that X11 does not pass through normal/inverted scrolling information to apps, so there is no way for SDL to pass it through using the X11 backend. Only Mac and Wayland provide this information to apps, Windows and X do not.

well, the thing is testmouse itself has some weird sign handling

            if (event.wheel.x != 0.0f) {
                wheel_x_active = true;
                /* "positive to the right and negative to the left"  */
                wheel_x += event.wheel.x * 10.0f;
            }
            if (event.wheel.y != 0.0f) {
                wheel_y_active = true;
                /* "positive away from the user and negative towards the user" */
                wheel_y -= event.wheel.y * 10.0f;
            }

But, to be fair this is what the docs are saying: https://wiki.libsdl.org/SDL3/SDL_MouseWheelEvent

    float x;            /**< The amount scrolled horizontally, positive to the right and negative to the left */
    float y;            /**< The amount scrolled vertically, positive away from the user and negative toward the user */

and SDL2 says the same https://wiki.libsdl.org/SDL2/SDL_MouseWheelEvent , which I find odd but it’s documented!

Thanks for your reply Frank, and btw I see that you implemented the smooth scrolling but also seem a contributor. Thanks for that but for also for all your work in general!

So the origin for scrolling is never the same as the origin for mouse motion without another inversion? In what world is this the most intuitive option?
But thank you, I have confirmed on my side that the current behavior is consistent in both Wayland and X11 as indicated in test/testmouse.
Good methodology.
The consistent behavior for the same code across systems is what’s most important.
It’s so rare that I implement scrolling that I just know I’m going to grumble when I forget that I need to invert one axis, I’ll have to catch it and laugh at myself then.
I apologize for my earlier statements and assumptions.