[Linux] SDL2 reports wrong display size when using Wayland

I have an issue on a fresh install of Ubuntu 22.04.04 on a laptop where any of the SDL2 (v2.0.20) functions to get the monitor size reports 1360x768 instead of 1366x768. If I disable Wayland and use X11, it returns the correct values. Ubuntu itself reports 1366x768, so I think this may be an issue with SDL2.

Is this a known issue? It’s a pretty serious issue as my fullscreen mouse coordinate conversion depends on these values being correct. I don’t know how I can write a workaround for this…

Perhaps XWayland is being used? Try running the application with SDL_VIDEODRIVER=wayland.

SDL_GetCurrentVideoDriver returns "x11". Forcing it to use wayland by doing SDL_VideoInit("wayland") results in major issues like no mouse/keyboard input.

Kinda strange, as Wayland really seems to be used in the OS itself.

What function are you using to get the display size?
I’m thinking perhaps what you are getting back is the size of the renderer view which may be shrunk because of window borders or the docker/activities/tool bar.
Is the window in full-screen mode when you request the information?

See this link for querying specifically for the screen size → c++ - How to get screen size in SDL - Stack Overflow

Yeah, XWayland is used here.

Pretty old, can you test it with fresh SDL? I believe that SDL still has some problems with Wayland, for me the display sizes is crazy when the desktop scaling is enabled.

I compiled SDL v2.31.0 on Ubuntu, and I get the same issue (display width is reported as 1360 instead of 1366).

Here’s the code I use to get the display size:

SDL_DisplayMode dm;

int32_t di = SDL_GetWindowDisplayIndex(video.window);
if (di < 0)
	di = 0; // return display index 0 (default) on error

SDL_GetDesktopDisplayMode(di, &dm);
video.displayW = dm.w;
video.displayH = dm.h;

It works fine on Windows, and on another laptop with the same Ubuntu version.

Have you tried to force Wayland?

Yup, yesterday I wrote that I forced wayland but that it resulted in severe problems like no keyboard/mouse input.

So your code is reporting correctly on a different laptop with the same OS.
(…and when you say it works fine on Windows, I’m assuming this is on the current problem laptop?)
What are the key differences between these two laptops?

  • AMD VS Intel
  • NVIDIA vs stock graphics
  • is the problem laptop perhaps very new (built in the last year)?
  • is there another monitor attached to your problem system?

My current thoughts are perhaps MESA drivers vs NVIDIA hardware, but I would expect other programs would be having issues too.

The laptop that reports the wrong display size (in SDL2) in Ubuntu is a Lenovo G500 from late 2012 with an Intel i3-3110M CPU + Intel HD Graphics 4000 iGPU. No dedicated GPU. Its display is the built-in 1366x768 panel, no external monitor connected.

I haven’t tested Windows on this machine yet, but I’m pretty sure it would report the display size correctly with SDL2.

// I’m testing something, I think it might be a red-herring, but I’ll post back in 20 minutes.

Here’s my thought: if you are starting in fullscreen mode and checking for display size after window creation, perhaps letterboxing is occurring to match your original window size, and displaymode is reporting that difference.

That’s what I’m testing right now.

Edit: No, I couldn’t replicate the problem like that.

Well, the reported display size was correct on a different laptop that ran the same version of Ubuntu and SDL2. I’m starting to think that it’s because of old GPU drivers or something. That laptop had an Intel i5-8250U, Intel UHD Graphics 620 iGPU and a 1920x1080 built-in panel, though. Also, why should the reported desktop display size (using SDL_GetDesktopDisplayMode) depend on how I created the window?

It shouldn’t, and in my tests it doesn’t, that was the red-herring I mentioned. It was just something I hadn’t tested before, sorry for that.

Can we see your code (or a shortened sample of it that replicates the problem) so we can test it on our devices?

#include <stdio.h>
#include <SDL2/SDL.h>

int main(int argc, char *argv[])
{
	SDL_Init(SDL_INIT_VIDEO);
	
	SDL_DisplayMode dm;
	SDL_GetDesktopDisplayMode(0, &dm); // 0 = default display
	
	char text[512];
	sprintf(text, "Display size: %dx%d", dm.w, dm.h);
	SDL_ShowSimpleMessageBox(0, "SDL2 display size", text, NULL);

	SDL_Quit();
	return 0;
}

Screenshot from 2024-03-18 19-00-29

Screenshot from 2024-03-18 19-02-13
EDIT: Yes, I have tried to disable that “fractional scaling” option.

OK, Here’s some code from SDL2/SDL_DisplayMode - SDL Wiki, does the resolution that you want show up on the list when you run it?

#include <SDL2/SDL.h>

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_DisplayMode mode;
       	SDL_GetDisplayMode(0, 0, &mode);
	SDL_Log("There are a total of %d displayModes for the main screen", SDL_GetNumDisplayModes(0));
	SDL_Log("Setting current displayMode to largest available resolution");

	static int display_in_use = 0; /* Only using first display */

	int i, display_mode_count;
	Uint32 f;

	SDL_Log("SDL_GetNumVideoDisplays(): %i", SDL_GetNumVideoDisplays());

	display_mode_count = SDL_GetNumDisplayModes(display_in_use);
	if (display_mode_count < 1)
	{
		SDL_Log("SDL_GetNumDisplayModes failed: %s", SDL_GetError());
		return 1;
	}
	SDL_Log("SDL_GetNumDisplayModes: %i", display_mode_count);

	for (i = 0; i < display_mode_count; ++i)
	{
		if (SDL_GetDisplayMode(display_in_use, i, &mode) != 0) 
		{
			SDL_Log("SDL_GetDisplayMode failed: %s", SDL_GetError());
			return 1;
		}
		f = mode.format;
		
		SDL_Log("Mode %i\tbpp %i\t%s\t%i x %i", i, SDL_BITSPERPIXEL(f), SDL_GetPixelFormatName(f), mode.w, mode.h);
	}
	SDL_Quit();
}

If it is in the list, then I think the next thing to do is to try using SDL_SetWindowDisplayMode.
If not, then at least we find out if the 1366x768 is a detectable option or not.

I’m not sure why this is relevant, I’m not trying to change the resolution, I’m trying to run a program in windowed fullscreen mode and get the actual display coordinates so that I can do some calculations. An incorrect value makes a big difference, and it makes me unable to get stuff to work right.

SDL is set up in a way that it tries to determine what resolution it thinks best fits the current situation. It’s possible that the 1360x768 display mode is being picked even though 1366x768 is also available.

If you run the code above we can determine whether 1366x768 is detected as an available option in SDL for that laptop. I’m pretty certain it will be. If it is, then you can specify that you want that mode.

He’s talking about “windowed fullscreen mode”, which I assume is what you get when using SDL_WINDOW_FULLSCREEN_DESKTOP, and that shouldn’t lead to a change in resolution.

SDL2/SDL_WindowFlags - SDL Wiki
SDL_WINDOW_FULLSCREEN_DESKTOP - fullscreen window at the current desktop resolution

I use SDL_WINDOW_FULLSCREEN_DESKTOP indeed. Also, if I enter that mode, even SDL_WindowGetSize() will report the same erroneous width value.