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

Add window example #2626

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Starbuck5
Copy link
Member

Task for #2603

@Starbuck5 Starbuck5 added the window pygame.Window label Dec 23, 2023
@Starbuck5 Starbuck5 requested a review from a team as a code owner December 23, 2023 09:41
Copy link
Member

@ankith26 ankith26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work on the example! 😎
Seeing this example in action has gotten me more interested in Window 😄 as it demonstrates new cool stuff and also serves as a good way to test things in action

I added a couple of reviews, some reviews for the example, and also a few API reviews that I noticed while playing around with the example.


if event.key == pygame.K_1:
for win, _ in windows_and_surfaces:
win.size -= pygame.Vector2(WIN_GROW_SPEED, WIN_GROW_SPEED)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API comment

Continuously pressing 1 leads to the error
ValueError: width or height should not be less than or equal to zero

Interestingly, this issue does not happen for the "main window" which has minimum_size set to some larger than (0, 0). In that case, the size is implicitly capped with no python errors raised.

This could be an API inconsistency? I'd like an error to be not raised here and it should just cap at (0, 0)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear reading your comment whether you see the minimum_size of the window is explicitly set to contain the instruction text.

It would happen to the main window if it was ever told to do a negative size there. Which it can't because the minimum size dimensions are higher than WIN_GROW_SPEED.

I agree it shouldn't be possible to crash the example by messing around with it, but I'm not sure what the best solution would be.

surface.blit(rendered_instructions, centered_rect)
win.flip()

clock.tick(144)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be a small and nice addition to set FPS in the title for the main window, also serves as a demonstration of the title property.

Also how about something like window.id in the titles for all windows?

pygame.init()
pygame.key.set_repeat(500, 100)

main_window = pygame.Window("demo window", (500, 500), resizable=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could the main window also be always_on_top?

Another trivial note, how about setting an icon with set_icon?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least on Windows, the spawned windows spawn in the center of the main window (I'm not controlling the spawn point). So if the main window was always_on_top it would seem like the spawn window command does nothing, because the other windows would not be visible unless you move the main window with the mouse.

I was looking around the examples data folder for art to use for this, (icons, backgrounds), and none of it spoke to me. I don't feel the need to set an icon in this example.


if event.key == pygame.K_2:
for win, _ in windows_and_surfaces:
win.size += pygame.Vector2(WIN_GROW_SPEED, WIN_GROW_SPEED)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might also be a good idea to cap it to some upper bound? Perhaps using the maximum_size property?

try:
event.window.opacity = 1.0
except pygame.error:
pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a event.window.focus() here?

instructions = """Welcome to the window demo!
Controls:
m.) maximize main window
n.) minimize main window
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to maximise/minimise, could also two keys for add/remove full screen?

win.opacity = UNHOVERED_OPACITY
except pygame.error:
pass
windows_and_surfaces.append((win, win.get_surface()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API comment

This has gotten me thinking about the API. As a user, I think it would be much neater if we could do something like win.surface and not have to explicitly track the output of win.get_surface. Even helps conceptually to show that "this surface instance is a special window-surface tied to the window"

Copy link
Member Author

@Starbuck5 Starbuck5 Dec 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I think I could be calling get_surface() every time I need the surface. I'm just not sure how that works SDL-side.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also why I thought of subclassing window, issue raised as #2625. In this demo it would be nice to store the color of the window with the window. (Store arbitrary things in instance of class, subclass)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, SDL stores the surface in the window struct (both in SDL2 and SDL3), and if the surface needs updating it updates the surface, so for most of the calls to this function it is just a cheap struct member access.

On the python side, we could basically the change this get_surface to a property.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a commit on a branch I made on top of yours, implementing my idea: 6b620f1

I also updated this example to see/test the property in action


if event.key == pygame.K_RIGHT:
for win, _ in windows_and_surfaces:
win.position += pygame.Vector2(WIN_MOVE_SPEED, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API comment

SMH my head, window.position is also broken under direct wayland

Nothing moves when I press the arrow keys. 😢

All these "direct wayland" issues are fine/ignorable for now because these issues don't happen under XWayland which SDL2 picks by default, but this could be a problem in the SDL3 era if SDL3 devs decide to do wayland-default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is by design. Wayland does not want applications to know this for API design and security reasons. There is nothing SDL3 can do about it short of sending patches to KDE and GNOME and sway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I need to add try/except pygame.error blocks around them then? I did it for opacity given your previous report.

I'm also unsure if we really want to raise an exception if the operation is not supported. We could return True/False about success?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the position is silently ignored by SDL, like always_on_top. Only opacity explicitly errors.

I think for this example, we should not have this position-moving thing as a highlight, and make it more low-key somehow?

Copy link
Member

@ankith26 ankith26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example also reveals memory leaks 😓

Open task manager while this example is running and play around with this example. Every time a new window is spawned the memory usage goes up as expected, but closing the window does not reduce the memory consumption

Similarly everytime the window is resized memory usage increases, even when downsizing.

These memory leaks are not insignificant, I believe entire window surfaces are being leaked, so depending on the window size and display resolutions we may be leaking a lot.

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

Successfully merging this pull request may close these issues.

3 participants