Skip to content

Leaving fullscreen doesn't fire SDL_EVENT_WINDOW_RESIZED or updates the value SDL_GetWindowSize returns #12870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wooster0 opened this issue Apr 21, 2025 · 5 comments
Assignees
Milestone

Comments

@wooster0
Copy link

#define SDL_MAIN_USE_CALLBACKS 1  
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>

static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
int width = 500;
int height = 500;

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
    SDL_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles");

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", width, height, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
        SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    if (event->type == SDL_EVENT_QUIT) {
        return SDL_APP_SUCCESS;  
    } else if (event-> type == SDL_EVENT_WINDOW_RESIZED) {
        printf("this is never fired after leaving fullscreen\n");
        width = event->window.data1;
        height = event->window.data2;
    }
    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppIterate(void *appstate)
{
    printf("%d, %d\n", width, height);
    SDL_Delay(20);
    return SDL_APP_CONTINUE; 
}

void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
}

You can trigger fullscreen here (it's going to look weird but ignore that) by pressing any key.
Before you trigger fullscreen you'll see it prints 500, 500 which is correct.
Then when you go into fullscreen it's going to print the correct fullscreen resolution.
But once you leave fullscreen after that, it keeps reporting the fullscreen resolution, which is obviously incorrect.
The output does not change if you use

    int w;
    int h;
    SDL_GetWindowSize(window, &w, &h);
    printf("%d, %d\n", w, h);

instead.
It simply never fires the relevant SDL_EVENT_WINDOW_RESIZED or updates the value SDL_GetWindowSize returns.
It does update after you resize the window just a little bit.

Not sure if this was already fixed by https://github.com/libsdl-org/sdl2-compat/pull/463/files (maybe irrelevant?) but reporting anyway. Going to test again once that PR makes it into my package manager's SDL3 package.

I'm on Linux, using SDL_VERSION=3002008.

@Sackzement
Copy link
Contributor

What distro and DE are you running?
How exactly do you trigger fullscreen?

I noticed that you don't draw the window, which can cause some visual and window event related issues.
Can you try?:

#define SDL_MAIN_USE_CALLBACKS 1  
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>

static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
int width = 500;
int height = 500;

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
    SDL_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles");

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", width, height, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
        SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    if (event->type == SDL_EVENT_QUIT) {
        return SDL_APP_SUCCESS;  
    } else if (event-> type == SDL_EVENT_WINDOW_RESIZED) {
        printf("this is never fired after leaving fullscreen\n");
        width = event->window.data1;
        height = event->window.data2;
    }
    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppIterate(void *appstate)
{
    printf("%d, %d\n", width, height);
    SDL_RenderPresent(renderer); // <=====================================================
    SDL_Delay(20);
    return SDL_APP_CONTINUE; 
}

void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
}

@wooster0
Copy link
Author

wooster0 commented Apr 22, 2025

Oh, sorry, I somehow forgot to include the actual code I used to reproduce this which included code to trigger fullscreen.
Here is an updated example, with code for triggering fullscreen (simply press any key) and a RenderClear to be less confusing:

#define SDL_MAIN_USE_CALLBACKS 1  
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>

static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
int width = 500;
int height = 500;

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
    SDL_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles");

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", width, height, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
        SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
        return SDL_APP_FAILURE;
    }

    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    if (event->type == SDL_EVENT_QUIT) {
        return SDL_APP_SUCCESS;  
    } else if (event-> type == SDL_EVENT_WINDOW_RESIZED) {
        printf("this is never fired after leaving fullscreen\n");
        width = event->window.data1;
        height = event->window.data2;
    } else if (event->type == SDL_EVENT_KEY_DOWN) {
        int flags = SDL_GetWindowFlags(window);
        if ((flags & SDL_WINDOW_FULLSCREEN) == 1) {
            SDL_SetWindowFullscreen(window, false);
        } else {
            SDL_SetWindowFullscreen(window, true);
        }
    }
    return SDL_APP_CONTINUE;  
}

SDL_AppResult SDL_AppIterate(void *appstate)
{
    printf("%d, %d\n", width, height);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    SDL_Delay(20);
    return SDL_APP_CONTINUE; 
}

void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
}

Again, same behavior here:
After running the program from a terminal, the window appears in the middle of the screen with a size of 500x500 and I consistently get 500, 500 printed in the terminal.
Then when pressing any key to trigger fullscreen (which works), I can't see the terminal but after pressing any key again to disable fullscreen, I see the terminal (still) printing 1920, 1080 the whole time.
It never goes back to printing 500, 500 until I trigger a different resize event by for example resizing the window just a little bit (or maximizing etc.); only once I do something like that, I finally get

this is never fired after leaving fullscreen
505, 500

Which means normal maximizing and un-maximizing triggers the event, but not leaving fullscreen.

I'm on Void, using Xfce.

@wooster0
Copy link
Author

wooster0 commented Apr 22, 2025

Also, not sure if this is related (though I wouldn't be surprised if it is) but, sometimes, when quitting the SDL program while in fullscreen (and using SDL_Quit()), I get this:

X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  40 (X_TranslateCoords)
  Resource id in failed request:  0x17d6ce6
  Serial number of failed request:  589
  Current serial number in output stream:  589

I don't get this if I leave fullscreen before exiting.

@Kontrabant
Copy link
Contributor

Ugh, Xfce places the window back where it was when leaving fullscreen, but doesn't reset the windowed size. Will have to add a quirk to for this.

@Kontrabant Kontrabant self-assigned this Apr 22, 2025
@Kontrabant Kontrabant added this to the 3.2.12 milestone Apr 22, 2025
@Kontrabant
Copy link
Contributor

Ah, so the root cause of this is that Xfce sends fullscreen events backwards from every other window manager in existence. Normally entering fullscreen first emits an event telling the client that the window is now fullscreen, followed by the new size. Instead, Xfce tells the client the new size before notifying it that it has entered fullscreen, resulting in the old windowed size being overwritten since the window isn't aware that it is fullscreen yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants