content scale change events should also impact viewport padding

This calculates the new padding pixel values and propogates those
changes to the renderer.
This commit is contained in:
Mitchell Hashimoto
2023-09-02 10:59:50 -07:00
parent 6c7ccae848
commit 22eb533473
7 changed files with 83 additions and 11 deletions

View File

@ -139,6 +139,8 @@ const DerivedConfig = struct {
mouse_interval: u64, mouse_interval: u64,
macos_non_native_fullscreen: configpkg.NonNativeFullscreen, macos_non_native_fullscreen: configpkg.NonNativeFullscreen,
macos_option_as_alt: configpkg.OptionAsAlt, macos_option_as_alt: configpkg.OptionAsAlt,
window_padding_x: u32,
window_padding_y: u32,
pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig { pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig {
var arena = ArenaAllocator.init(alloc_gpa); var arena = ArenaAllocator.init(alloc_gpa);
@ -156,6 +158,8 @@ const DerivedConfig = struct {
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms .mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
.macos_non_native_fullscreen = config.@"macos-non-native-fullscreen", .macos_non_native_fullscreen = config.@"macos-non-native-fullscreen",
.macos_option_as_alt = config.@"macos-option-as-alt", .macos_option_as_alt = config.@"macos-option-as-alt",
.window_padding_x = config.@"window-padding-x",
.window_padding_y = config.@"window-padding-y",
// Assignments happen sequentially so we have to do this last // Assignments happen sequentially so we have to do this last
// so that the memory is captured from allocs above. // so that the memory is captured from allocs above.
@ -871,12 +875,19 @@ pub fn sizeCallback(self: *Surface, size: apprt.SurfaceSize) !void {
// changed, so we just return. // changed, so we just return.
if (self.screen_size.equals(new_screen_size)) return; if (self.screen_size.equals(new_screen_size)) return;
try self.resize(new_screen_size);
}
fn resize(self: *Surface, size: renderer.ScreenSize) !void {
// Save our screen size // Save our screen size
self.screen_size = new_screen_size; self.screen_size = size;
// Mail the renderer so that it can update the GPU and re-render // Mail the renderer so that it can update the GPU and re-render
_ = self.renderer_thread.mailbox.push(.{ _ = self.renderer_thread.mailbox.push(.{
.screen_size = self.screen_size, .resize = .{
.screen_size = self.screen_size,
.padding = self.padding,
},
}, .{ .forever = {} }); }, .{ .forever = {} });
try self.queueRender(); try self.queueRender();
@ -1192,16 +1203,50 @@ pub fn scrollCallback(
try self.queueRender(); try self.queueRender();
} }
pub fn contentScaleCallback(self: *Surface, content_scale: apprt.ContentScale) void { /// This is called when the content scale of the surface changes. The surface
/// can then update any DPI-sensitive state.
pub fn contentScaleCallback(self: *Surface, content_scale: apprt.ContentScale) !void {
// Calculate the new DPI
const x_dpi = content_scale.x * font.face.default_dpi; const x_dpi = content_scale.x * font.face.default_dpi;
const y_dpi = content_scale.y * font.face.default_dpi; const y_dpi = content_scale.y * font.face.default_dpi;
// Update our font size which is dependent on the DPI
const size = size: { const size = size: {
var size = self.font_size; var size = self.font_size;
size.xdpi = @intFromFloat(x_dpi); size.xdpi = @intFromFloat(x_dpi);
size.ydpi = @intFromFloat(y_dpi); size.ydpi = @intFromFloat(y_dpi);
break :size size; break :size size;
}; };
// If our DPI didn't actually change, save a lot of work by doing nothing.
if (size.xdpi == self.font_size.xdpi and size.ydpi == self.font_size.ydpi) {
return;
}
self.setFontSize(size); self.setFontSize(size);
// Update our padding which is dependent on DPI.
self.padding = padding: {
const padding_x: u32 = padding_x: {
const padding_x: f32 = @floatFromInt(self.config.window_padding_x);
break :padding_x @intFromFloat(@floor(padding_x * x_dpi / 72));
};
const padding_y: u32 = padding_y: {
const padding_y: f32 = @floatFromInt(self.config.window_padding_y);
break :padding_y @intFromFloat(@floor(padding_y * y_dpi / 72));
};
break :padding .{
.top = padding_y,
.bottom = padding_y,
.right = padding_x,
.left = padding_x,
};
};
// Force a resize event because the change in padding will affect
// pixel-level changes to the renderer and viewport.
try self.resize(self.screen_size);
} }
/// The type of action to report for a mouse event. /// The type of action to report for a mouse event.

View File

@ -350,7 +350,10 @@ pub const Surface = struct {
.y = @floatCast(y), .y = @floatCast(y),
}; };
self.core_surface.contentScaleCallback(self.content_scale); self.core_surface.contentScaleCallback(self.content_scale) catch |err| {
log.err("error in content scale callback err={}", .{err});
return;
};
} }
pub fn updateSize(self: *Surface, width: u32, height: u32) void { pub fn updateSize(self: *Surface, width: u32, height: u32) void {

View File

@ -1048,9 +1048,14 @@ pub fn changeConfig(self: *Metal, config: *DerivedConfig) !void {
} }
/// Resize the screen. /// Resize the screen.
pub fn setScreenSize(self: *Metal, dim: renderer.ScreenSize) !void { pub fn setScreenSize(
// Store our screen size self: *Metal,
dim: renderer.ScreenSize,
pad: renderer.Padding,
) !void {
// Store our sizes
self.screen_size = dim; self.screen_size = dim;
self.padding.explicit = pad;
// Recalculate the rows/columns. This can't fail since we just set // Recalculate the rows/columns. This can't fail since we just set
// the screen size above. // the screen size above.

View File

@ -1427,12 +1427,17 @@ pub fn changeConfig(self: *OpenGL, config: *DerivedConfig) !void {
/// Set the screen size for rendering. This will update the projection /// Set the screen size for rendering. This will update the projection
/// used for the shader so that the scaling of the grid is correct. /// used for the shader so that the scaling of the grid is correct.
pub fn setScreenSize(self: *OpenGL, dim: renderer.ScreenSize) !void { pub fn setScreenSize(
self: *OpenGL,
dim: renderer.ScreenSize,
pad: renderer.Padding,
) !void {
if (single_threaded_draw) self.draw_mutex.lock(); if (single_threaded_draw) self.draw_mutex.lock();
defer if (single_threaded_draw) self.draw_mutex.unlock(); defer if (single_threaded_draw) self.draw_mutex.unlock();
// Store our screen size // Store our screen size
self.screen_size = dim; self.screen_size = dim;
self.padding.explicit = pad;
// Recalculate the rows/columns. // Recalculate the rows/columns.
const grid_size = self.gridSize(dim); const grid_size = self.gridSize(dim);

View File

@ -252,8 +252,8 @@ fn drainMailbox(self: *Thread) !void {
try self.renderer.setFontSize(size); try self.renderer.setFontSize(size);
}, },
.screen_size => |size| { .resize => |v| {
try self.renderer.setScreenSize(size); try self.renderer.setScreenSize(v.screen_size, v.padding);
}, },
.change_config => |config| { .change_config => |config| {

View File

@ -20,8 +20,14 @@ pub const Message = union(enum) {
/// the size changes. /// the size changes.
font_size: font.face.DesiredSize, font_size: font.face.DesiredSize,
/// Change the screen size. /// Changes the screen size.
screen_size: renderer.ScreenSize, resize: struct {
/// The full screen (drawable) size. This does NOT include padding.
screen_size: renderer.ScreenSize,
/// The explicit padding values.
padding: renderer.Padding,
},
/// The derived configuration to update the renderer with. /// The derived configuration to update the renderer with.
change_config: struct { change_config: struct {

View File

@ -143,6 +143,14 @@ pub const Padding = struct {
.left = self.left + other.left, .left = self.left + other.left,
}; };
} }
/// Equality test between two paddings.
pub fn eql(self: Padding, other: Padding) bool {
return self.top == other.top and
self.bottom == other.bottom and
self.right == other.right and
self.left == other.left;
}
}; };
test "Padding balanced on zero" { test "Padding balanced on zero" {