init
Parameters
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- gpa:std.mem.Allocator
- std.mem.Allocator
- backend_ctx:dvui.Backend
- dvui.Backend
- init_opts:InitOptions
- InitOptions
Source
Implementation
pub fn init(
src: std.builtin.SourceLocation,
gpa: std.mem.Allocator,
backend_ctx: dvui.Backend,
init_opts: InitOptions,
) !Self {
const hashval = if (dvui.current_window) |cw|
cw.data().id.extendId(src, init_opts.id_extra)
else
dvui.Id.extendId(null, src, init_opts.id_extra);
var self = Self{
.gpa = gpa,
._arena = if (init_opts.arena) |a| a else .init(gpa),
._lifo_arena = .init(gpa),
._widget_stack = .init(gpa),
.wd = WidgetData{
.src = src,
.id = hashval,
.init_options = .{ .subwindow = true },
.options = .{ .name = "Window", .role = .window },
// Unused
.min_size = .{},
// Set in `begin`
.rect = undefined,
// Set in `begin`
.parent = undefined,
},
// Set in `begin`
.current_parent = undefined,
.theme = undefined, // set below
.open_flag = init_opts.open_flag,
.backend = backend_ctx,
.accesskit = .{},
};
if (init_opts.theme) |t| {
self.themeSet(t);
} else switch (init_opts.color_scheme orelse backend_ctx.preferredColorScheme() orelse .light) {
.light => self.themeSet(Theme.builtin.adwaita_light),
.dark => self.themeSet(Theme.builtin.adwaita_dark),
}
try self.initEvents();
self.button_order = init_opts.button_order orelse switch (builtin.os.tag) {
.windows => .ok_cancel,
else => .cancel_ok,
};
const kb = init_opts.keybinds orelse blk: {
if (builtin.os.tag.isDarwin()) {
break :blk .mac;
} else {
break :blk .windows;
}
};
if (kb == .windows or kb == .mac) {
try self.keybinds.putNoClobber(self.gpa, "activate", .{ .key = .enter, .also = "activate_1" });
try self.keybinds.putNoClobber(self.gpa, "activate_1", .{ .key = .space });
try self.keybinds.putNoClobber(self.gpa, "next_widget", .{ .key = .tab, .shift = false });
try self.keybinds.putNoClobber(self.gpa, "prev_widget", .{ .key = .tab, .shift = true });
}
switch (kb) {
.none => {},
.windows => {
// zig fmt: off
try self.keybinds.putNoClobber(self.gpa, "cut", .{ .key = .x, .control = true });
try self.keybinds.putNoClobber(self.gpa, "copy", .{ .key = .c, .control = true, .also = "copy_1" });
try self.keybinds.putNoClobber(self.gpa, "copy_1", .{ .key = .insert, .control = true, .shift = false, .alt = false, .command = false });
try self.keybinds.putNoClobber(self.gpa, "paste", .{ .key = .v, .control = true, .also = "paste_1" });
try self.keybinds.putNoClobber(self.gpa, "paste_1", .{ .key = .insert, .control = false, .shift = true, .alt = false, .command = false });
try self.keybinds.putNoClobber(self.gpa, "select_all", .{ .key = .a, .control = true });
// use with mod.matchBind
try self.keybinds.putNoClobber(self.gpa, "ctrl/cmd", .{ .control = true });
try self.keybinds.putNoClobber(self.gpa, "text_start", .{ .key = .home, .shift = false, .control = true });
try self.keybinds.putNoClobber(self.gpa, "text_end", .{ .key = .end, .shift = false, .control = true });
try self.keybinds.putNoClobber(self.gpa, "text_start_select", .{ .key = .home, .shift = true, .control = true });
try self.keybinds.putNoClobber(self.gpa, "text_end_select", .{ .key = .end, .shift = true, .control = true });
try self.keybinds.putNoClobber(self.gpa, "line_start", .{ .key = .home, .shift = false, .control = false });
try self.keybinds.putNoClobber(self.gpa, "line_end", .{ .key = .end, .shift = false, .control = false });
try self.keybinds.putNoClobber(self.gpa, "line_start_select", .{ .key = .home, .shift = true, .control = false });
try self.keybinds.putNoClobber(self.gpa, "line_end_select", .{ .key = .end, .shift = true, .control = false });
try self.keybinds.putNoClobber(self.gpa, "word_left", .{ .key = .left, .shift = false, .control = true });
try self.keybinds.putNoClobber(self.gpa, "word_right", .{ .key = .right, .shift = false, .control = true });
try self.keybinds.putNoClobber(self.gpa, "word_left_select", .{ .key = .left, .shift = true, .control = true });
try self.keybinds.putNoClobber(self.gpa, "word_right_select", .{ .key = .right, .shift = true, .control = true });
try self.keybinds.putNoClobber(self.gpa, "char_left", .{ .key = .left, .shift = false, .control = false });
try self.keybinds.putNoClobber(self.gpa, "char_right", .{ .key = .right, .shift = false, .control = false });
try self.keybinds.putNoClobber(self.gpa, "char_left_select", .{ .key = .left, .shift = true, .control = false });
try self.keybinds.putNoClobber(self.gpa, "char_right_select", .{ .key = .right, .shift = true, .control = false });
try self.keybinds.putNoClobber(self.gpa, "char_up", .{ .key = .up, .shift = false });
try self.keybinds.putNoClobber(self.gpa, "char_down", .{ .key = .down, .shift = false });
try self.keybinds.putNoClobber(self.gpa, "char_up_select", .{ .key = .up, .shift = true });
try self.keybinds.putNoClobber(self.gpa, "char_down_select", .{ .key = .down, .shift = true });
try self.keybinds.putNoClobber(self.gpa, "delete_prev_word", .{ .key = .backspace, .control = true });
try self.keybinds.putNoClobber(self.gpa, "delete_next_word", .{ .key = .delete, .control = true });
// zig fmt: on
},
.mac => {
// zig fmt: off
try self.keybinds.putNoClobber(self.gpa, "cut", .{ .key = .x, .command = true });
try self.keybinds.putNoClobber(self.gpa, "copy", .{ .key = .c, .command = true });
try self.keybinds.putNoClobber(self.gpa, "paste", .{ .key = .v, .command = true });
try self.keybinds.putNoClobber(self.gpa, "select_all", .{ .key = .a, .command = true });
// use with mod.matchBind
try self.keybinds.putNoClobber(self.gpa, "ctrl/cmd", .{ .command = true });
try self.keybinds.putNoClobber(self.gpa, "text_start", .{ .key = .up, .shift = false, .command = true });
try self.keybinds.putNoClobber(self.gpa, "text_end", .{ .key = .down, .shift = false, .command = true });
try self.keybinds.putNoClobber(self.gpa, "text_start_select", .{ .key = .up, .shift = true, .command = true });
try self.keybinds.putNoClobber(self.gpa, "text_end_select", .{ .key = .down, .shift = true, .command = true });
try self.keybinds.putNoClobber(self.gpa, "line_start", .{ .key = .left, .shift = false, .command = true });
try self.keybinds.putNoClobber(self.gpa, "line_end", .{ .key = .right, .shift = false, .command = true });
try self.keybinds.putNoClobber(self.gpa, "line_start_select", .{ .key = .left, .shift = true, .command = true });
try self.keybinds.putNoClobber(self.gpa, "line_end_select", .{ .key = .right, .shift = true, .command = true });
try self.keybinds.putNoClobber(self.gpa, "word_left", .{ .key = .left, .shift = false, .alt = true });
try self.keybinds.putNoClobber(self.gpa, "word_right", .{ .key = .right, .shift = false, .alt = true });
try self.keybinds.putNoClobber(self.gpa, "word_left_select", .{ .key = .left, .shift = true, .alt = true });
try self.keybinds.putNoClobber(self.gpa, "word_right_select", .{ .key = .right, .shift = true, .alt = true });
try self.keybinds.putNoClobber(self.gpa, "char_left", .{ .key = .left, .shift = false, .alt = false });
try self.keybinds.putNoClobber(self.gpa, "char_right", .{ .key = .right, .shift = false, .alt = false });
try self.keybinds.putNoClobber(self.gpa, "char_left_select", .{ .key = .left, .shift = true, .alt = false });
try self.keybinds.putNoClobber(self.gpa, "char_right_select", .{ .key = .right, .shift = true, .alt = false });
try self.keybinds.putNoClobber(self.gpa, "char_up", .{ .key = .up, .shift = false, .command = false });
try self.keybinds.putNoClobber(self.gpa, "char_down", .{ .key = .down, .shift = false, .command = false });
try self.keybinds.putNoClobber(self.gpa, "char_up_select", .{ .key = .up, .shift = true, .command = false });
try self.keybinds.putNoClobber(self.gpa, "char_down_select", .{ .key = .down, .shift = true, .command = false });
try self.keybinds.putNoClobber(self.gpa, "delete_prev_word", .{ .key = .backspace, .alt = true });
try self.keybinds.putNoClobber(self.gpa, "delete_next_word", .{ .key = .delete, .alt = true });
// zig fmt: on
},
}
const winSize = self.backend.windowSize();
const pxSize = self.backend.pixelSize();
const sysContentScale = self.backend.contentScale();
// Even on hidpi screens I see slight flattening of the sides of glyphs
// when snap_to_pixels is false, so we are going to default on for now.
//const total_scale = self.content_scale * pxSize.w / winSize.w;
//if (total_scale >= 2.0) {
// self.snap_to_pixels = false;
//}
log.info("window logical {f} pixels {f} pixel scale {d} initial content scale {d} snap_to_pixels {any} accesskit {any}\n", .{ winSize, pxSize, pxSize.w / winSize.w, sysContentScale, self.snap_to_pixels, dvui.accesskit_enabled });
errdefer self.deinit();
self.subwindows.focused_id = self.data().id;
self.frame_time_ns = 1;
if (dvui.useFreeType) {
dvui.Font.FreeType.intToError(c.FT_Init_FreeType(&dvui.ft2lib)) catch |err| {
dvui.log.err("freetype error {any} trying to init freetype library\n", .{err});
return error.freetypeError;
};
}
return self;
}