diff --git a/src/runtime/root.zig b/src/runtime/root.zig index 93fc05de..ba84fb32 100644 --- a/src/runtime/root.zig +++ b/src/runtime/root.zig @@ -837,12 +837,13 @@ pub const Runtime = struct { const app_info = self.options.platform.app_info; const startup_window = app_info.resolvedStartupWindow(0); const window_id = startup_window.id; - const frame_value = geometry.RectF.init( + const manifest_frame = geometry.RectF.init( shell_window.x orelse 0, shell_window.y orelse 0, shell_window.width, shell_window.height, ); + const startup_frame = startupWindowFrame(startup_window.default_frame, manifest_frame); const runtime_index = if (self.findWindowIndexById(window_id)) |index| index else try self.reserveWindow( window_id, @@ -856,16 +857,16 @@ pub const Runtime = struct { self.windows[runtime_index].info.label = try copyInto(&self.windows[runtime_index].label_storage, shell_window.label); self.windows[runtime_index].info.title = try copyInto(&self.windows[runtime_index].title_storage, shell_window.title orelse app_info.resolvedWindowTitle()); - self.windows[runtime_index].info.frame = frame_value; + self.windows[runtime_index].info.frame = startup_frame; self.windows[runtime_index].source = try self.copySource(runtime_index, source); if (!self.windows[runtime_index].main_frame_set) { - self.windows[runtime_index].main_frame = geometry.RectF.init(0, 0, frame_value.width, frame_value.height); + self.windows[runtime_index].main_frame = geometry.RectF.init(0, 0, startup_frame.width, startup_frame.height); } self.next_window_id = @max(self.next_window_id, window_id + 1); try self.options.platform.services.loadWindowWebView(window_id, source); try self.applyMainWebViewState(window_id); - try self.createShellViews(window_id, shell_window.views, frame_value); + try self.createShellViews(window_id, shell_window.views, self.shellBoundsForWindow(window_id)); } fn applyMainWebViewState(self: *Runtime, window_id: platform.WindowId) anyerror!void { @@ -1104,6 +1105,16 @@ pub const Runtime = struct { return geometry.RectF.init(0, 0, frame_value.width, frame_value.height); } + fn startupWindowFrame(native_frame: geometry.RectF, manifest_frame: geometry.RectF) geometry.RectF { + const default_frame = (platform.WindowOptions{}).default_frame; + if (!rectsEqual(native_frame, default_frame)) return native_frame; + return manifest_frame; + } + + fn rectsEqual(a: geometry.RectF, b: geometry.RectF) bool { + return a.x == b.x and a.y == b.y and a.width == b.width and a.height == b.height; + } + fn bindShellViews(self: *Runtime, window_id: platform.WindowId, views: []const app_manifest.ShellView) !void { if (self.findShellLayoutIndex(window_id)) |index| { self.shell_layouts[index].views = views; @@ -4053,6 +4064,75 @@ test "runtime lays out created shell windows with native returned bounds" { try std.testing.expectEqual(@as(f32, 1200), host.views[2].frame.width); } +test "runtime lays out startup shell windows with native configured bounds" { + const TestApp = struct { + const scene_views = [_]app_manifest.ShellView{ + .{ .label = "toolbar", .kind = .toolbar, .edge = .top, .height = 50 }, + .{ .label = "main", .kind = .webview, .url = "zero://app/main.html", .fill = true }, + .{ .label = "statusbar", .kind = .statusbar, .edge = .bottom, .height = 40 }, + }; + const scene_windows = [_]app_manifest.ShellWindow{.{ + .label = "main", + .title = "Startup", + .width = 900, + .height = 600, + .views = &scene_views, + }}; + + fn scene(context: *anyopaque) anyerror!app_manifest.ShellConfig { + _ = context; + return .{ .windows = &scene_windows }; + } + + fn app(self: *@This()) App { + return .{ + .context = self, + .name = "startup-native-bounds", + .source = platform.WebViewSource.html("