macos: correct scale factor propagated

This commit is contained in:
Mitchell Hashimoto
2023-02-17 21:45:52 -08:00
parent 57551e3990
commit 074664398a
5 changed files with 67 additions and 7 deletions

View File

@ -53,6 +53,8 @@ int ghostty_app_tick(ghostty_app_t);
ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*); ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*);
void ghostty_surface_free(ghostty_surface_t); void ghostty_surface_free(ghostty_surface_t);
void ghostty_surface_refresh(ghostty_surface_t);
void ghostty_surface_set_content_scale(ghostty_surface_t, double, double);
void ghostty_surface_set_size(ghostty_surface_t, uint32_t, uint32_t); void ghostty_surface_set_size(ghostty_surface_t, uint32_t, uint32_t);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -33,6 +33,10 @@ class TerminalSurfaceView_Real: NSView, ObservableObject {
// We need to support being a first responder so that we can get input events // We need to support being a first responder so that we can get input events
override var acceptsFirstResponder: Bool { return true } override var acceptsFirstResponder: Bool { return true }
// I don't thikn we need this but this lets us know we should redraw our layer
// so we'll use that to tell ghostty to refresh.
override var wantsUpdateLayer: Bool { return true }
private var surface: ghostty_surface_t? = nil private var surface: ghostty_surface_t? = nil
private var error: Error? = nil private var error: Error? = nil
@ -45,7 +49,7 @@ class TerminalSurfaceView_Real: NSView, ObservableObject {
// Setup our surface. This will also initialize all the terminal IO. // Setup our surface. This will also initialize all the terminal IO.
var surface_cfg = ghostty_surface_config_s( var surface_cfg = ghostty_surface_config_s(
nsview: Unmanaged.passUnretained(self).toOpaque(), nsview: Unmanaged.passUnretained(self).toOpaque(),
scale_factor: 1.0) scale_factor: NSScreen.main!.backingScaleFactor)
guard let surface = ghostty_surface_new(app, &surface_cfg) else { guard let surface = ghostty_surface_new(app, &surface_cfg) else {
self.error = AppError.surfaceCreateError self.error = AppError.surfaceCreateError
return return
@ -62,16 +66,44 @@ class TerminalSurfaceView_Real: NSView, ObservableObject {
super.resize(withOldSuperviewSize: oldSize) super.resize(withOldSuperviewSize: oldSize)
if let surface = self.surface { if let surface = self.surface {
ghostty_surface_set_size(surface, UInt32(self.bounds.size.width), UInt32(self.bounds.size.height)) // Ghostty wants to know the actual framebuffer size...
let fbFrame = self.convertToBacking(self.frame);
ghostty_surface_set_size(surface, UInt32(fbFrame.size.width), UInt32(fbFrame.size.height))
} }
} }
override func viewDidChangeBackingProperties() {
guard let surface = self.surface else { return }
// Detect our X/Y scale factor so we can update our surface
let fbFrame = self.convertToBacking(self.frame)
let xScale = fbFrame.size.width / self.frame.size.width
let yScale = fbFrame.size.height / self.frame.size.height
ghostty_surface_set_content_scale(surface, xScale, yScale)
// When our scale factor changes, so does our fb size so we send that too
ghostty_surface_set_size(surface, UInt32(fbFrame.size.width), UInt32(fbFrame.size.height))
}
override func updateLayer() {
guard let surface = self.surface else { return }
ghostty_surface_refresh(surface);
}
override func mouseDown(with event: NSEvent) { override func mouseDown(with event: NSEvent) {
print("Mouse down: \(event)") print("Mouse down: \(event)")
} }
override func keyDown(with event: NSEvent) { override func keyDown(with event: NSEvent) {
print("Key down: \(event)") print("Key down: \(event)")
self.interpretKeyEvents([event])
}
override func doCommand(by selector: Selector) {
// This currently just prevents NSBeep from interpretKeyEvents but in the future
// we may want to make some of this work.
// print("SEL: \(selector)")
} }
} }

View File

@ -397,9 +397,19 @@ pub const CAPI = struct {
if (ptr) |v| v.app.closeWindow(v); if (ptr) |v| v.app.closeWindow(v);
} }
/// Tell the surface that it needs to schedule a render
export fn ghostty_surface_refresh(win: *Window) void {
win.window.refresh();
}
/// Update the size of a surface. This will trigger resize notifications /// Update the size of a surface. This will trigger resize notifications
/// to the pty and the renderer. /// to the pty and the renderer.
export fn ghostty_surface_set_size(win: *Window, w: u32, h: u32) void { export fn ghostty_surface_set_size(win: *Window, w: u32, h: u32) void {
win.window.updateSize(w, h); win.window.updateSize(w, h);
} }
/// Update the content scale of the surface.
export fn ghostty_surface_set_content_scale(win: *Window, x: f64, y: f64) void {
win.window.updateContentScale(x, y);
}
}; };

View File

@ -49,8 +49,8 @@ pub const App = struct {
pub const Window = struct { pub const Window = struct {
nsview: objc.Object, nsview: objc.Object,
scale_factor: f64,
core_win: *CoreWindow, core_win: *CoreWindow,
content_scale: apprt.ContentScale,
size: apprt.WindowSize, size: apprt.WindowSize,
pub const Options = extern struct { pub const Options = extern struct {
@ -67,7 +67,10 @@ pub const Window = struct {
return .{ return .{
.core_win = core_win, .core_win = core_win,
.nsview = objc.Object.fromId(opts.nsview), .nsview = objc.Object.fromId(opts.nsview),
.scale_factor = opts.scale_factor, .content_scale = .{
.x = @floatCast(f32, opts.scale_factor),
.y = @floatCast(f32, opts.scale_factor),
},
.size = .{ .width = 800, .height = 600 }, .size = .{ .width = 800, .height = 600 },
}; };
} }
@ -77,8 +80,7 @@ pub const Window = struct {
} }
pub fn getContentScale(self: *const Window) !apprt.ContentScale { pub fn getContentScale(self: *const Window) !apprt.ContentScale {
_ = self; return self.content_scale;
return apprt.ContentScale{ .x = 1, .y = 1 };
} }
pub fn getSize(self: *const Window) !apprt.WindowSize { pub fn getSize(self: *const Window) !apprt.WindowSize {
@ -115,6 +117,20 @@ pub const Window = struct {
return false; return false;
} }
pub fn refresh(self: *Window) void {
self.core_win.refreshCallback() catch |err| {
log.err("error in refresh callback err={}", .{err});
return;
};
}
pub fn updateContentScale(self: *Window, x: f64, y: f64) void {
self.content_scale = .{
.x = @floatCast(f32, x),
.y = @floatCast(f32, y),
};
}
pub fn updateSize(self: *Window, width: u32, height: u32) void { pub fn updateSize(self: *Window, width: u32, height: u32) void {
self.size = .{ self.size = .{
.width = width, .width = width,

View File

@ -326,7 +326,7 @@ pub fn finalizeWindowInit(self: *const Metal, win: apprt.runtime.Window) !void {
apprt.embedded => .{ apprt.embedded => .{
.view = win.nsview, .view = win.nsview,
.scaleFactor = win.scale_factor, .scaleFactor = @floatCast(f64, win.content_scale.x),
}, },
else => @compileError("unsupported apprt for metal"), else => @compileError("unsupported apprt for metal"),