david-vanderson/dvui

Window positioning

Closed this issue · 8 comments

iacore commented

Two problems:

  1. windows may be spawned outside of the viewport

example: (numbers are spawn order)

image

Suggestion: I think dvui should clip all windows inside the OS window, including on OS window resize.

  1. initial windows overlap each other completely. newly spawned windows do that too.

Suggestion: stagger the windows like

image

Thanks very much for the diagrams! You're right that new windows should never show outside the viewport so I'll fix that. I'm less sure how to fix the overlap issue, because that gets into window management which usually the application knows more about.

Can you tell me how you want to use floating windows?

iacore commented

I use floating windows to display bits of information. Said project is here.

For now, I care about

  • windows all inside viewport
  • Newly spawned window will appear somewhere empty. At least each one should spawn in a different place.

an ok strategy of spawning windows is to just put the new window to the right of the old one.
(See how Windows (Microsoft) show 100+ popups)

I've been playing around with your janet-graphical-repl project which is very cool!

I've committed some fixes for this, and I'll submit a pull request. Thank you!

iacore commented

so the problem is fixed partially.

here you can see the newly spawned window still overlap with existing ones perfectly. _000007v is covered many times.

Peek.2023-10-18.13-11.mp4

I recommend that new windows should spawn relative to the focused window, not screen center. Although this doesn't fix the problem in the video.

New windows can also be spawned in a random location. The chance of full overlap will be much lower.

I fixed that specific bug (sorry), but I'm not super happy with the results when there are lots of windows. I think you are right that spawning relative to the focused window (and nudging only away from the focused window) is probably the right way to go. I'll give it a go.

I've made that change. It seemed to be good to (by default) avoid both the previously focused window and the previously highest window. I left .window_avoid = .nudge there if you want to avoid all windows.

I think random location would not be a great default, but you can achieve that like this:

var nwin = dvui.FloatingWindowWidget.init(@src(), .{
    .open_flag = &open,
}, .{ .id_extra = i, .color_style = .window, .min_size_content = .{ .w = 200, .h = 60 } });

if (dvui.firstFrame(nwin.wd.id)) {
    dvui.dataSet(null, nwin.wd.id, "randomize", true);
} else if (dvui.dataGet(null, nwin.wd.id, "randomize", bool) != null) {
    dvui.dataRemove(null, nwin.wd.id, "randomize");

    var prng = std.rand.DefaultPrng.init(@truncate(std.math.absCast(dvui.frameTimeNS())));
    var rand = prng.random();
    nwin.wd.rect.x = rand.float(f32) * (dvui.windowRect().w - 24);
    nwin.wd.rect.y = rand.float(f32) * (dvui.windowRect().h - 24);
}

try nwin.install(.{});
defer nwin.deinit();
iacore commented

New bug: if multiple windows are spawned on the first frame, only one appear.

the other windows... I don't see them.

reproduction:

  • clone the REPL application -> debug-1 branch
  • zig build run -- imgfile
  • create some windows (typing 1 is fine)
  • click "Persist to File"
  • run the program again with zig build run -- imgfile

Previously the newly spawned windows all stack together. Not great, but at least I can see them. (You can try doing the same on main branch)

Terribly sorry about that. Thanks so much for testing. I've committed some fixes.

  • first problem was I accidentally made a new window's size have to be smaller than the previously focused, which combined with the others was preventing them from having a non-zero size
  • second problem was me not realizing the implications of multiple new windows showing up on the same frame

Let me know if it works for you now. Thank you!