pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
862 stars 141 forks source link

while loop freezes when i move the window (2760) #1418

Open GalacticEmperor1 opened 1 year ago

GalacticEmperor1 commented 1 year ago

Issue №2760 opened by kusleikar at 2021-10-09 23:10:05

to reproduce simply increment a number when you inside a while loop and move the window.

import sys import pygame

pygame.init()

screen = pygame.display.set_mode((800,400)) clock = pygame.time.Clock()

x = 1 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() print(x) pygame.display.update() clock.tick(60) x += 1


Comments

*kusleikar commented at 2021-10-09 23:13:56*

typically it should keep printing x and incrementing x, but when i grab the window and move it, it stops.


*MyreMylar commented at 2021-10-10 08:52:01*

Hello,

This happens on Windows largely because of decisions made by Microsoft about what should happen when you are moving a window (i.e. applications operations should be paused until you stop moving the window). Basically windows pauses a programs main thread (the one that handles OS messages) while you are moving the window.

I'm not sure if there is anything we could do to adjust it at the python level as most workarounds I've seen for SDL (the C library underlying pygame) involve using multiple threads in a way that almost certainly wouldn't work well performance wise with python's GIL (the global interpreter lock that makes switching execution frequently between threads both running python code very slow). Anyway, whatever the possibility of it any fix would definitely not be simple.

In my opinion it is better for users to treat it as a fact of life on the windows platform and handle it in your programs. The simplest workaround for most common game application bugs is just to constrain your time delta values to a range of normal operation so that it doesn't grow hugely when the application is paused by the windows messaging system.


*kusleikar commented at 2021-10-10 14:51:36*

I did manage to fix the problem by running a thread and handling the window using ctypes.windll to keep an active message loop running. But, there is an option in SDL, https://wiki.libsdl.org/SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP . So I was wondering if that can be enabled when compiling the source under a windows platform. I also made a search to find this in this repository and you guys don't seem to have that anywhere.


*MyreMylar commented at 2021-10-10 19:35:01*

Did you try:

import os
os.environ['SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP'] = "0"

?

(AFAICT setting it this way doesn't do anything)

Obviously we wouldn't want to activate this by default.


*kusleikar commented at 2021-10-11 00:08:42*

I did, but what worked for me was passing the window handle that you get when you call get_wm_info() to effectively create a message loop for the current window.


*BozakJay commented at 2021-11-23 20:23:48*

I did, but what worked for me was passing the window handle that you get when you call get_wm_info() to effectively create a message loop for the current window.

can you share your solution? I'm stuck with the same issue.


*kusleikar commented at 2021-11-23 21:12:22*

Implement the message loop for your window handle in python using ctypes. Again, this is not something you should be doing that's why I moved to Qt, but pyglet is another alternative you could use if you understand classes intuitively. Or just install Linux, simple fix.


*BozakJay commented at 2021-11-23 21:36:39*

thanks for the reply, I think I'll try Pyglet before Qt.


*Starbuck5 commented at 2021-12-13 08:45:47*

There is an SDL issue open about this, which shows people have been discussing this since the beginning of time (or 2013 at least). https://github.com/libsdl-org/SDL/issues/1059

It looks like some sort of optional solution might come soon though, which is cool.

But in the current state of the world, this is a "can't fix" on our end, so I'm going to close this issue.

nitori commented 9 months ago

Sorry to dig this up, but according to https://github.com/libsdl-org/SDL/issues/1059 - which was mentioned in the last comment - the issue was fixed with SDL 2.30.

If that's correct, it should now be possible to fix it on pygame's end, right? I don't know how to do that myself, so I thought to at least point it out.

Greetings Nitori

oddbookworm commented 9 months ago

You pointing this out is appreciated! Unfortunately, SDL 2.30 hasn't released yet, so we can't incorporate that yet either. I'm also not sure that doing so would be the best idea (at least for pygame-ce 2.xx.xx). That behavior has been unchanged for years, and it's possible that someone's project uses that behavior for whatever functionality they've implemented. We tend to be more conservative when it comes to backwards compatiblity. However, I definitely think that it would be less of an issue if/when pygame-ce 3.0.0 becomes a thing and backcompat-breaking might be a larger option. I'd like to hear opinions from the steering council however @Starbuck5 @ankith26 @MyreMylar

I am also reopening this because it was originally closed as "we can't fix it", but now it looks like it's an option

ankith26 commented 9 months ago

okay so I looked around, and it still looks like a "we can't easily fix it" to me. What SDL 2.30.x does is basically send events on a timer while the window is in the "modal state" or whatever. So it's still up to the application on what to do about this event, the existing game loop based code won't just magically start working. Now, these events must be handled on a separate thread and that thread can do any updating, which is always a tricky thing.

TL:DR TO fix this we could expose new pygame side API, but it would still need changes in user code