Skip to content

Persist window geometry and state - #906

Merged
david-vanderson merged 22 commits into
david-vanderson:mainfrom
foxnne:persist_window
Jun 15, 2026
Merged

david-vanderson merged 22 commits into
david-vanderson:mainfrom
foxnne:persist_window

Conversation

@foxnne

@foxnne foxnne commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Hey!

We recently talked about this a bit, and this is a hopefully working proof of concept that works both with the current version of fizzy and also generic DVUI apps. Currently only supports SDL3.

To test:

  1. Run zig build sdl3-app, change window size or maximize, and then close window
  2. Run zig build sdl3-app again and hopefully observe window return to previous size/position/state

I have only currently tested this on macOS, which needed some additional code to get apps to restore into exclusive fullscreen Spaces vs just window-sized-maximized.

I'm sure we will need some changes here but hopefully this is a decent start.

Notes:

  • The saved file is a window_geometry.zon file, which defaults to sdl's preference path subdirectoried into the app's title. An override was provided as well, so apps can have the window geometry file saved with their app's other settings/prefs files if wanted in another location.

@david-vanderson

Copy link
Copy Markdown
Owner

I'm having a bit of trouble understanding the pieces here, it seems like there is some duplication:

  • macOSZoomed seems only used in a context where macOSMaximized would work?
  • cocoa_window is unused? But the implementation is duplicated?

SDL_GetPrefPath("", title) I think is specifically discouraged in the SDL docs. We should require an org name to use this.

What is going on with all the retries and pending stuff? Can you walk me through the sequence here? What is the downside of waiting for the window to show and then doing it?

macosPairedSizes is interesting!

What is macosPreBeginSync for?

@foxnne

foxnne commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author
  • macOSZoomed seems only used in a context where macOSMaximized would work?

My apologies, I was trying to quickly get a proof of concept working and missed this. I've now removed redundant macOSZoomed, and just rely on macOSMaximized. This should be handled.

  • cocoa_window is unused? But the implementation is duplicated?

Another mistake, I've used cocoa_window now in the correct places and de-duplicated the implementation. This should be handled.

SDL_GetPrefPath("", title) I think is specifically discouraged in the SDL docs. We should require an org name to use this.

I originally had the same, and added a new org field, would this be the correct way to go? add default org "dvui" near title?

What is going on with all the retries and pending stuff? Can you walk me through the sequence here? What is the downside of waiting for the window to show and then doing it?

I've really been trying to fix things without needing too much complexity, but sadly it's been difficult, specifically dealing with loading into a fullscreen maximized "Space" on macOS, or handling apps with custom titlebar/windowing styling like fizzy has. SDL's events for entering and exiting these states are not reliable enough to do things like correctly update the app behind/underneath the titlebar traffic light buttons as the bar appears and disappears etc.

I'd recommend comparing current fizzy native editor with a current base DVUI app to see the differences in smoothness entering and exiting maximized states.

What is macosPreBeginSync for?

This is something I wanted to ask you probably a better way to handle, but for fizzy specifically, I needed some way of triggering SDL specific window styling code before each window.begin call. By the time AppFrame runs, begin() has already laid out with whatever sizes SDL had. This means its run each frame before window.begin during our transitions to and from exclusive Spaces on macOS, and allows apps with custom windowing code to update prior to showing the window or having to "snap" windows after rendering.

@david-vanderson

Copy link
Copy Markdown
Owner

Thanks, I totally understand going fast. Thanks for adding the org thing.

I'm digging into this - the first thing I tried to do was understand the macosPairedSizes thing, but it looks like that requires extra callbacks that fizzy is doing (fizzy_macos_window_resize_cb). Is it possible to deal with "painting during transitions" separately from "persisting the geometry" or are they tied together?

@david-vanderson

Copy link
Copy Markdown
Owner

@foxnne I pushed a commit trying to verify to myself what parts are needed for geometry saving. I am NOT giving up on rendering during the transitions, but I don't yet know if that can be done inside dvui, or is too complicated and we need to find the right api to allow fizzy to integrate that.

One thing for example - I added a global begin_hook that I think might be able to handle the macosPreBeginSync stuff (now that I moved where backend.begin is called to be before any pixel/window size calls). It also might be a way to do the restoreFn stuff as well but I'm less sure about that.

Also I don't think I've even gotten to just the geometry saving part yet, just got to a reasonable checkpoint.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

I think I'm agreeing with you, and I'm going to try to simplify this, probably at the expense of being able to load back into a fullscreen state. Upon thinking about it, I think thats where I was struggling the most, and I think it's honestly not something to try to support currently.

I apologize for the complexity of this, I'll try to ping you when I get this in a more reviewable state.

@foxnne
foxnne marked this pull request as draft June 15, 2026 12:52
@david-vanderson

Copy link
Copy Markdown
Owner

I think I'm close to having a decent split between dvui persisting the geometry but fizzy still doing the animating during resize. I will push a bit more and report where I got.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

I hope I didn't step on your toes! I just pushed a commit that removes a lot of the complexity added by trying to load into a fullscreen space seamlessly. This now should just instead load into the last non-maximized size, and I think that's probably the true desired behavior for windows, though the hook exists for apps that want to handle things themselves.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

Okay, I've also made a change to how/when window geometry is saved. Before, it was just saved on a successful app close in deinit, which would miss scenarios such as:

  1. Open window
  2. Make window smaller
  3. Enter fullscreen
  4. Close window
  5. Open window

In this state and I'm sure plenty of others, the smaller pre-maximized state is never saved.

Instead, I've opted to track the geometry as dirty when events change it, and save the zon file on the first non-resize/move event such that hopefully we don't miss any window sizes but also avoid trying to write to disk during a resize.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

@david-vanderson Okay, I think I'm a bit happier with where this is now.

Please let me know of any other areas you feel could be simplified or removed if needed. With this current code, the dvui sdl3-app example seems to behave as expected, other than a small quirk with opening the app after it was closed at screen-size, but not "maximized" (in its own Space in macOS):

The window doesn't seem to reopen full sized, but slightly smaller horizontally. I couldn't find any reason this is happening in our code, and seems to be a quirk with opening a full size window on macOS without it being "maximized"?

@david-vanderson

Copy link
Copy Markdown
Owner

@david-vanderson Okay, I think I'm a bit happier with where this is now.

Please let me know of any other areas you feel could be simplified or removed if needed. With this current code, the dvui sdl3-app example seems to behave as expected, other than a small quirk with opening the app after it was closed at screen-size, but not "maximized" (in its own Space in macOS):

The window doesn't seem to reopen full sized, but slightly smaller horizontally. I couldn't find any reason this is happening in our code, and seems to be a quirk with opening a full size window on macOS without it being "maximized"?

Do you mean slightly smaller vertically? I saw something like that with fizzy but not with the sdl3-app, where restarting from a maximized (not fullscreen) would make the window be shorter and lower than expected by about the height of the window titlebar.

Okay, I've also made a change to how/when window geometry is saved. Before, it was just saved on a successful app close in deinit, which would miss scenarios such as:

I think sdl3-app is working for this scenario? But a double-check would be appreciated, maybe I'm not understanding how to reproduce it?

I'm still working on how fizzy should interact to be able to override this stuff.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

Do you mean slightly smaller vertically? I saw something like that with fizzy but not with the sdl3-app, where restarting from a maximized (not fullscreen) would make the window be shorter and lower than expected by about the height of the window titlebar.

Yes, but this is fizzy-specific, for the titlebar issue. But with the regular sdl3-app, I if I close a maximized (not fullscreen) window and reopen it, its slightly smaller horizontally (maybe about 10 px?). I can't seem to reproduce the horizontal issue with fizzy, but it makes sense fizzy has a titlebar spacing issue since fizzy sometimes hides and sometimes shows the titlebar spacing.

I think sdl3-app is working for this scenario? But a double-check would be appreciated, maybe I'm not understanding how to reproduce it?

Was this before? because my recent push fixed this. Current behavior for me works both with sdl3-app and fizzy for all scenarios, save for the strange slightly smaller window on restore from maximized, which I'm okay with.

@david-vanderson

Copy link
Copy Markdown
Owner

But with the regular sdl3-app, I if I close a maximized (not fullscreen) window and reopen it, its slightly smaller horizontally (maybe about 10 px?).

That is weird and I haven't been able to see it (with either sdl3-app or fizzy), but I'll keep an eye out.

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

I'm happy with the behavior of everything as is now, I think all that I see left is removing debug logs, but I'll leave this up to you and please let me know if you'd prefer i make any further changes

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

Oh I thought I had removed state from WindowGeometry since we no longer need to track that

@david-vanderson

Copy link
Copy Markdown
Owner

I'm happy now with how it works on sdl3-app. But I'm not sure we've solved it for fizzy. I pushed fizzyedit/fizzy#184 for how I'm trying to run it with this branch.

Can you test that and tell me what you see?

Two things are confusing to me:

  • it doesn't seem to matter if I pass .hidden to dvui or not?
  • zooming fizzy (or fullscreening) causes dvui to record a "normal" geometry at about the maximized size
    • this doesn't happen in sdl3-app, I assume because fizzy is running the sdl event loop

Any ideas here?

@foxnne

foxnne commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

I'm happy now with how it works on sdl3-app. But I'm not sure we've solved it for fizzy. I pushed fizzyedit/fizzy#184 for how I'm trying to run it with this branch.
Any ideas here?

I see the same things, but no worries, I'm working on another branch with other changes, and I am up to date with what you have here and I can make any of this work for me :) thank you for the changes you made here that unblock me, and add this functionality.

@foxnne
foxnne marked this pull request as ready for review June 15, 2026 19:07
This catches a problem on Linux x11:
* load maximized
* click window to return from maximized
* close and reopen
* window is maximized

When returning from maximized trackGeometry still sees the window as
"maximized".

So call trackGeometry in deinit just before saving the information.
@david-vanderson

Copy link
Copy Markdown
Owner

Good. I'm very happy with this. Especially nice when I am iterating on something that requires a certain window size.

I'm sure we'll need some more tweaks for this, but this is a great step in the right direction.

Thank you!

@david-vanderson
david-vanderson merged commit d1dc2b6 into david-vanderson:main Jun 15, 2026
6 checks passed
@foxnne

foxnne commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

Thank you for this!

nat3Github pushed a commit to nat3Github/zig-lib-dvui-dev-fork that referenced this pull request Aug 28, 2026
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

Successfully merging this pull request may close these issues.

2 participants