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,
macos_non_native_fullscreen: configpkg.NonNativeFullscreen,
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 {
var arena = ArenaAllocator.init(alloc_gpa);
@ -156,6 +158,8 @@ const DerivedConfig = struct {
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
.macos_non_native_fullscreen = config.@"macos-non-native-fullscreen",
.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
// 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.
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
self.screen_size = new_screen_size;
self.screen_size = size;
// Mail the renderer so that it can update the GPU and re-render
_ = self.renderer_thread.mailbox.push(.{
.resize = .{
.screen_size = self.screen_size,
.padding = self.padding,
},
}, .{ .forever = {} });
try self.queueRender();
@ -1192,16 +1203,50 @@ pub fn scrollCallback(
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 y_dpi = content_scale.y * font.face.default_dpi;
// Update our font size which is dependent on the DPI
const size = size: {
var size = self.font_size;
size.xdpi = @intFromFloat(x_dpi);
size.ydpi = @intFromFloat(y_dpi);
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);
// 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.

View File

@ -350,7 +350,10 @@ pub const Surface = struct {
.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 {

View File

@ -1048,9 +1048,14 @@ pub fn changeConfig(self: *Metal, config: *DerivedConfig) !void {
}
/// Resize the screen.
pub fn setScreenSize(self: *Metal, dim: renderer.ScreenSize) !void {
// Store our screen size
pub fn setScreenSize(
self: *Metal,
dim: renderer.ScreenSize,
pad: renderer.Padding,
) !void {
// Store our sizes
self.screen_size = dim;
self.padding.explicit = pad;
// Recalculate the rows/columns. This can't fail since we just set
// 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
/// 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();
defer if (single_threaded_draw) self.draw_mutex.unlock();
// Store our screen size
self.screen_size = dim;
self.padding.explicit = pad;
// Recalculate the rows/columns.
const grid_size = self.gridSize(dim);

View File

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

View File

@ -20,9 +20,15 @@ pub const Message = union(enum) {
/// the size changes.
font_size: font.face.DesiredSize,
/// Change the screen size.
/// Changes the screen size.
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.
change_config: struct {
alloc: Allocator,

View File

@ -143,6 +143,14 @@ pub const Padding = struct {
.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" {