Skip to content
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

display.toggle_fullscreen does not work when toggling a maximized window to fullscreen #2380

Closed
QuetzalQatl opened this issue Dec 4, 2020 · 5 comments · Fixed by #3497
Closed

Comments

@QuetzalQatl
Copy link

Environment:
pygame 2.0.0 (SDL 2.0.12, python 3.7.9)

  • Operating system windows 7
  • Python version 3.7.9
  • SDL version 2.0.12
  • PyGame version 2.0.0:

Current behavior:

When toggling fullscreen from a windowed, maximized window, it tries to do it, fails, gives this warning:
Warning: re-creating window in toggle_fullscreen
then a windowed screen is displayed: that is not re-sizable

Expected behavior:

The same as non-maximized windows

Steps to reproduce:

Inspect the sample code: set isFullSreen to True if you want to start with a fullscreen (same behaviour)
Toggle fullscreen with F a couple of times: that works just fine.
then maximize the window, and press F to see the problem arise.

Test code

#!/usr/bin/env python3
import os
import pygame

pygame.init()

# find out & store desktopSize
pgdi=pygame.display.Info()
desktopSize=(pgdi.current_w, pgdi.current_h)

FPS = 100
clock = pygame.time.Clock()

screenWidth=160 # initial screen width when windowed
screenHeight=120

hor=0 # ball position on screen 
ver=0

# will make the first intance of the window appear in the middle of the screen.
# (consecutive instances will appear in the upper most left corner)
os.environ['SDL_VIDEO_CENTERED'] = '1' 

# flag to keep track of the question: is the window maximized or not
# should remain False at startup
maximized=False 

# choose to startup fullscreen or not.
# both options will work fine
isFullScreen=True 

# set up initial display:

# always make the non-fullscreen screen first, 
# so the fullscreen has something to toggle back to that is placed properly (as in not at 0,0 )
screen = pygame.display.set_mode((screenWidth,screenHeight), pygame.RESIZABLE) 

if isFullScreen:
    # set size to desktop 
    # not doing this takes much longer (about 4 seconds)
    # but doing this is near instantanious
    pygame.display.set_mode(desktopSize, pygame.RESIZABLE) 
    
    pygame.display.toggle_fullscreen() # now toggle fullscreen


done=False
while not done:
    for event in pygame.event.get():        
        if event.type == pygame.QUIT: 
            # like ctrl-break or the cross in the title bar
            done = True
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_q: 
            # pressing q will also quit the program
            done = True
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_f:
            # pressing f will toggle fullscreen
            
            isFullScreen=not isFullScreen # toggle fullscreen flag
            if isFullScreen: #toggling from not fullscreen to fullscreen
                # store size of windowed screen 
                # so we can reset it when toggling back
                screenWidth=screen.get_width()
                screenHeight=screen.get_height()
            
                # set the number of pixels to desktop size
                pygame.display.set_mode(desktopSize, pygame.RESIZABLE) 
                # then toggle that to fullscreen                
                pygame.display.toggle_fullscreen()                    
                    
            else: # toggling from fullscreen to not fullscreen
                pygame.display.toggle_fullscreen() 
                # restore to old size
                pygame.display.set_mode((screenWidth, screenHeight), pygame.RESIZABLE)
            
    # show some things on screen:        
    # paint background
    screen.fill((255, 0, 255))

    # slide ball position
    hor += 1
    hor = hor % screen.get_width()
    ver += hor % 2
    ver = ver % screen.get_height()
    
    # paint ball
    pygame.draw.circle(screen, (255, 255, 255), (hor, ver), 5)
        
    pygame.display.flip()
    clock.tick(FPS)

@robertpfeiffer
Copy link
Contributor

There was another bug about window maximing behaviour filed recently. I wrote the new toggle_fullscreen implementation, but unfortunately, I can't test on windows for the rest of the year. I'll try to see if your test case at least works as expected on X11 and wayland. toggle_fullscreen already tries to work around quirks in windows window management and upstream SDL2. Maybe the bug is in the handling of the windows special case (forgetting the flag), but again, I can't test this. Does this impact a game of yours?

Creating a resizeable window the size of the screen is not a good idea (for rather annoying reasons) on other window managers as well...

@QuetzalQatl
Copy link
Author

Yes, its the game engine I am writing for my own games that I want to make in the future.
All elements width etc on it are defined in promillages, that will re-render accordingly when the window size changes.
Which will not look nice on for example a 16x16 bmp stretched to 20x22. But I will make it look picture perfect on 1920x1080.

Most games will be like minesweeper: basic, rude forms, it does not have to be picture perfect, but it should allow the user to define the area on their screen they want to play on themselves (so they can open up other windows beside it as they please). Also: if they want, it should be able to go fullscreen/maximize/alt tab into and out off, anything they want to throw at it.

@Starbuck5
Copy link
Contributor

I've done some investigating.
I can't seem to get an SDL window at fullscreen with arbitrary width and height on windows. It always sets the resolution to the closest display mode.

The upside is that this function isn't completely broken: it works when the resolution of the window is the same as a display mode.
The downside is that I don't know if it's possible to fix this function up to spec.

@IFthenElse246
Copy link

I'm still having this issue, furthermore, at least on windows 11, it doesn't only happen if it is maximized, it seems to always happen as long as the window is resizeable.

@flodri
Copy link

flodri commented Aug 13, 2022

I fixed it in my framework as follow:
First I decorated pygame.display.set_mode to save the flags arg used in pygame.display.flags for now since I can't find a pygame equivalent of SDL_GetWindowFlags.
Then:

def fixed_toggle_fullscreen():
    if pygame.display.flags & pygame.FULLSCREEN == pygame.FULLSCREEN:
        pygame.display.set_mode(pygame.display.windowed_size,
                                flags=pygame.display.flags ^ pygame.FULLSCREEN)
    else:
        pygame.display.windowed_size = pygame.display.get_surface().get_size()
        pygame.display.set_mode(pygame.display.get_desktop_sizes()[0],
                                flags=pygame.display.flags | pygame.FULLSCREEN)
    pump_windowresized()
pygame.display.toggle_fulscreen = fixed_toggle_fullscreen

It works for me on windows (should work on linux too ?), including in an OPENGL context or with NOFRAME, whether the window is RESIZABLE, windowed maximized, at the original resolution or not.
So this might also be a fix for others issues (#3107, #2711).
But assuming this works for everyone I'm not sure how to go to make a PR for it since pygame.display.toggle_fulscreen is in c in src_c/display.c not in python.

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