mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macOS: inherit font size when creating new tab
This is one part of #281.
This commit is contained in:
@ -233,6 +233,7 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
GHOSTTY_BINDING_COPY_TO_CLIPBOARD,
|
GHOSTTY_BINDING_COPY_TO_CLIPBOARD,
|
||||||
GHOSTTY_BINDING_PASTE_FROM_CLIPBOARD,
|
GHOSTTY_BINDING_PASTE_FROM_CLIPBOARD,
|
||||||
|
GHOSTTY_BINDING_NEW_TAB,
|
||||||
} ghostty_binding_action_e;
|
} ghostty_binding_action_e;
|
||||||
|
|
||||||
// Fully defined types. This MUST be kept in sync with equivalent Zig
|
// Fully defined types. This MUST be kept in sync with equivalent Zig
|
||||||
@ -242,6 +243,7 @@ typedef struct {
|
|||||||
void *userdata;
|
void *userdata;
|
||||||
void *nsview;
|
void *nsview;
|
||||||
double scale_factor;
|
double scale_factor;
|
||||||
|
uint8_t font_size;
|
||||||
} ghostty_surface_config_s;
|
} ghostty_surface_config_s;
|
||||||
|
|
||||||
typedef void (*ghostty_runtime_wakeup_cb)(void *);
|
typedef void (*ghostty_runtime_wakeup_cb)(void *);
|
||||||
@ -254,6 +256,7 @@ typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
|
|||||||
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
||||||
typedef void (*ghostty_runtime_goto_tab_cb)(void *, int32_t);
|
typedef void (*ghostty_runtime_goto_tab_cb)(void *, int32_t);
|
||||||
typedef void (*ghostty_runtime_toggle_fullscreen_cb)(void *, bool);
|
typedef void (*ghostty_runtime_toggle_fullscreen_cb)(void *, bool);
|
||||||
|
typedef void (*ghostty_runtime_new_tab_cb)(void *, uint8_t);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *userdata;
|
void *userdata;
|
||||||
@ -268,6 +271,7 @@ typedef struct {
|
|||||||
ghostty_runtime_focus_split_cb focus_split_cb;
|
ghostty_runtime_focus_split_cb focus_split_cb;
|
||||||
ghostty_runtime_goto_tab_cb goto_tab_cb;
|
ghostty_runtime_goto_tab_cb goto_tab_cb;
|
||||||
ghostty_runtime_toggle_fullscreen_cb toggle_fullscreen_cb;
|
ghostty_runtime_toggle_fullscreen_cb toggle_fullscreen_cb;
|
||||||
|
ghostty_runtime_new_tab_cb new_tab_cb;
|
||||||
} ghostty_runtime_config_s;
|
} ghostty_runtime_config_s;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import OSLog
|
import OSLog
|
||||||
import GhosttyKit
|
import GhosttyKit
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
||||||
@ -24,6 +25,22 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
|||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
windowManager = PrimaryWindowManager(ghostty: self.ghostty)
|
windowManager = PrimaryWindowManager(ghostty: self.ghostty)
|
||||||
|
|
||||||
|
// Register self as observer for the NewTab notification that
|
||||||
|
// is triggered via callback from Zig code.
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(onNewTab),
|
||||||
|
name: Ghostty.Notification.ghosttyNewTab,
|
||||||
|
object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
// Clean up the observer.
|
||||||
|
NotificationCenter.default.removeObserver(
|
||||||
|
self,
|
||||||
|
name: Ghostty.Notification.ghosttyNewTab,
|
||||||
|
object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
@ -81,13 +98,30 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func newTab(_ sender: Any?) {
|
@IBAction func newTab(_ sender: Any?) {
|
||||||
if let existingWindow = windowManager.mainWindow {
|
if windowManager.mainWindow != nil {
|
||||||
windowManager.addNewTab(to: existingWindow)
|
guard let surface = focusedSurface() else { return }
|
||||||
|
ghostty.newTab(surface: surface)
|
||||||
} else {
|
} else {
|
||||||
windowManager.addNewWindow()
|
windowManager.addNewWindow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func onNewTab(notification: SwiftUI.Notification) {
|
||||||
|
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
|
guard let window = surfaceView.window else { return }
|
||||||
|
|
||||||
|
let fontSizeAny = notification.userInfo?[Ghostty.Notification.NewTabKey]
|
||||||
|
let fontSize = fontSizeAny as? UInt8
|
||||||
|
|
||||||
|
if fontSize != nil {
|
||||||
|
// Add the new tab to the window with the given font size.
|
||||||
|
windowManager.addNewTab(to: window, withFontSize: fontSize)
|
||||||
|
} else {
|
||||||
|
// No font size specified, just add new tab.
|
||||||
|
windowManager.addNewTab(to: window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func closeWindow(_ sender: Any) {
|
@IBAction func closeWindow(_ sender: Any) {
|
||||||
guard let currentWindow = NSApp.keyWindow else { return }
|
guard let currentWindow = NSApp.keyWindow else { return }
|
||||||
currentWindow.close()
|
currentWindow.close()
|
||||||
|
@ -11,6 +11,9 @@ struct PrimaryView: View {
|
|||||||
// We need this to report back up the app controller which surface in this view is focused.
|
// We need this to report back up the app controller which surface in this view is focused.
|
||||||
let focusedSurfaceWrapper: FocusedSurfaceWrapper
|
let focusedSurfaceWrapper: FocusedSurfaceWrapper
|
||||||
|
|
||||||
|
// TODO: Document this
|
||||||
|
let fontSize: UInt8?
|
||||||
|
|
||||||
// We need access to our window to know if we're the key window to determine
|
// We need access to our window to know if we're the key window to determine
|
||||||
// if we show the quit confirmation or not.
|
// if we show the quit confirmation or not.
|
||||||
@State private var window: NSWindow?
|
@State private var window: NSWindow?
|
||||||
@ -71,7 +74,7 @@ struct PrimaryView: View {
|
|||||||
self.appDelegate.confirmQuit = $0
|
self.appDelegate.confirmQuit = $0
|
||||||
})
|
})
|
||||||
|
|
||||||
Ghostty.TerminalSplit(onClose: Self.closeWindow)
|
Ghostty.TerminalSplit(onClose: Self.closeWindow, fontSize: self.fontSize)
|
||||||
.ghosttyApp(ghostty.app!)
|
.ghosttyApp(ghostty.app!)
|
||||||
.background(WindowAccessor(window: $window))
|
.background(WindowAccessor(window: $window))
|
||||||
.onReceive(gotoTab) { onGotoTab(notification: $0) }
|
.onReceive(gotoTab) { onGotoTab(notification: $0) }
|
||||||
|
@ -16,7 +16,7 @@ class FocusedSurfaceWrapper {
|
|||||||
class PrimaryWindow: NSWindow {
|
class PrimaryWindow: NSWindow {
|
||||||
var focusedSurfaceWrapper: FocusedSurfaceWrapper = FocusedSurfaceWrapper()
|
var focusedSurfaceWrapper: FocusedSurfaceWrapper = FocusedSurfaceWrapper()
|
||||||
|
|
||||||
static func create(ghostty: Ghostty.AppState, appDelegate: AppDelegate) -> PrimaryWindow {
|
static func create(ghostty: Ghostty.AppState, appDelegate: AppDelegate, fontSize: UInt8? = nil) -> PrimaryWindow {
|
||||||
let window = PrimaryWindow(
|
let window = PrimaryWindow(
|
||||||
contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
|
contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
|
||||||
styleMask: [.titled, .closable, .miniaturizable, .resizable],
|
styleMask: [.titled, .closable, .miniaturizable, .resizable],
|
||||||
@ -27,7 +27,9 @@ class PrimaryWindow: NSWindow {
|
|||||||
window.contentView = NSHostingView(rootView: PrimaryView(
|
window.contentView = NSHostingView(rootView: PrimaryView(
|
||||||
ghostty: ghostty,
|
ghostty: ghostty,
|
||||||
appDelegate: appDelegate,
|
appDelegate: appDelegate,
|
||||||
focusedSurfaceWrapper: window.focusedSurfaceWrapper))
|
focusedSurfaceWrapper: window.focusedSurfaceWrapper,
|
||||||
|
fontSize: fontSize
|
||||||
|
))
|
||||||
|
|
||||||
// We do want to cascade when new windows are created
|
// We do want to cascade when new windows are created
|
||||||
window.windowController?.shouldCascadeWindows = true
|
window.windowController?.shouldCascadeWindows = true
|
||||||
|
@ -14,6 +14,7 @@ class PrimaryWindowController: NSWindowController {
|
|||||||
override func newWindowForTab(_ sender: Any?) {
|
override func newWindowForTab(_ sender: Any?) {
|
||||||
guard let window = self.window else { preconditionFailure("Expected window to be loaded") }
|
guard let window = self.window else { preconditionFailure("Expected window to be loaded") }
|
||||||
guard let manager = self.windowManager else { return }
|
guard let manager = self.windowManager else { return }
|
||||||
|
// TODO: We need to call to Zig code here so we can get the surface
|
||||||
manager.addNewTab(to: window)
|
manager.addNewTab(to: window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,16 +61,16 @@ class PrimaryWindowManager {
|
|||||||
newWindow.makeKeyAndOrderFront(nil)
|
newWindow.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addNewTab(to window: NSWindow) {
|
func addNewTab(to window: NSWindow, withFontSize fontSize: UInt8? = nil) {
|
||||||
guard let controller = createWindowController() else { return }
|
guard let controller = createWindowController(withFontSize: fontSize) else { return }
|
||||||
guard let newWindow = addManagedWindow(windowController: controller)?.window else { return }
|
guard let newWindow = addManagedWindow(windowController: controller)?.window else { return }
|
||||||
window.addTabbedWindow(newWindow, ordered: .above)
|
window.addTabbedWindow(newWindow, ordered: .above)
|
||||||
newWindow.makeKeyAndOrderFront(nil)
|
newWindow.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createWindowController() -> PrimaryWindowController? {
|
private func createWindowController(withFontSize fontSize: UInt8? = nil) -> PrimaryWindowController? {
|
||||||
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return nil }
|
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return nil }
|
||||||
let window = PrimaryWindow.create(ghostty: ghostty, appDelegate: appDelegate)
|
let window = PrimaryWindow.create(ghostty: ghostty, appDelegate: appDelegate, fontSize: fontSize)
|
||||||
Self.lastCascadePoint = window.cascadeTopLeft(from: Self.lastCascadePoint)
|
Self.lastCascadePoint = window.cascadeTopLeft(from: Self.lastCascadePoint)
|
||||||
let controller = PrimaryWindowController(window: window)
|
let controller = PrimaryWindowController(window: window)
|
||||||
controller.windowManager = self
|
controller.windowManager = self
|
||||||
|
@ -64,7 +64,8 @@ extension Ghostty {
|
|||||||
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
|
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
|
||||||
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
|
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
|
||||||
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) },
|
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) },
|
||||||
toggle_fullscreen_cb: { userdata, nonNativeFullscreen in AppState.toggleFullscreen(userdata, useNonNativeFullscreen: nonNativeFullscreen) }
|
toggle_fullscreen_cb: { userdata, nonNativeFullscreen in AppState.toggleFullscreen(userdata, useNonNativeFullscreen: nonNativeFullscreen) },
|
||||||
|
new_tab_cb: { userdata, fontSize in AppState.newTab(userdata, fontSize: fontSize) }
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create the ghostty app.
|
// Create the ghostty app.
|
||||||
@ -137,6 +138,10 @@ extension Ghostty {
|
|||||||
ghostty_surface_request_close(surface)
|
ghostty_surface_request_close(surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTab(surface: ghostty_surface_t) {
|
||||||
|
ghostty_surface_binding_action(surface, GHOSTTY_BINDING_NEW_TAB, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func split(surface: ghostty_surface_t, direction: ghostty_split_direction_e) {
|
func split(surface: ghostty_surface_t, direction: ghostty_split_direction_e) {
|
||||||
ghostty_surface_split(surface, direction)
|
ghostty_surface_split(surface, direction)
|
||||||
}
|
}
|
||||||
@ -258,6 +263,17 @@ extension Ghostty {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func newTab(_ userdata: UnsafeMutableRawPointer?, fontSize: UInt8) {
|
||||||
|
guard let surface = self.surfaceUserdata(from: userdata) else { return }
|
||||||
|
NotificationCenter.default.post(
|
||||||
|
name: Notification.ghosttyNewTab,
|
||||||
|
object: surface,
|
||||||
|
userInfo: [
|
||||||
|
Notification.NewTabKey: fontSize,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the GhosttyState from the given userdata value.
|
/// Returns the GhosttyState from the given userdata value.
|
||||||
static private func appState(fromSurface userdata: UnsafeMutableRawPointer?) -> AppState? {
|
static private func appState(fromSurface userdata: UnsafeMutableRawPointer?) -> AppState? {
|
||||||
let surfaceView = Unmanaged<SurfaceView>.fromOpaque(userdata!).takeUnretainedValue()
|
let surfaceView = Unmanaged<SurfaceView>.fromOpaque(userdata!).takeUnretainedValue()
|
||||||
|
@ -8,10 +8,11 @@ extension Ghostty {
|
|||||||
struct TerminalSplit: View {
|
struct TerminalSplit: View {
|
||||||
@Environment(\.ghosttyApp) private var app
|
@Environment(\.ghosttyApp) private var app
|
||||||
let onClose: (() -> Void)?
|
let onClose: (() -> Void)?
|
||||||
|
let fontSize: UInt8?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let app = app {
|
if let app = app {
|
||||||
TerminalSplitRoot(app: app, onClose: onClose)
|
TerminalSplitRoot(app: app, onClose: onClose, fontSize: fontSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,9 +68,9 @@ extension Ghostty {
|
|||||||
@Published var surface: SurfaceView
|
@Published var surface: SurfaceView
|
||||||
|
|
||||||
/// Initialize a new leaf which creates a new terminal surface.
|
/// Initialize a new leaf which creates a new terminal surface.
|
||||||
init(_ app: ghostty_app_t) {
|
init(_ app: ghostty_app_t, _ fontSize: UInt8?) {
|
||||||
self.app = app
|
self.app = app
|
||||||
self.surface = SurfaceView(app)
|
self.surface = SurfaceView(app, fontSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ extension Ghostty {
|
|||||||
// Initially, both topLeft and bottomRight are in the "nosplit"
|
// Initially, both topLeft and bottomRight are in the "nosplit"
|
||||||
// state since this is a new split.
|
// state since this is a new split.
|
||||||
self.topLeft = .noSplit(from)
|
self.topLeft = .noSplit(from)
|
||||||
self.bottomRight = .noSplit(.init(app))
|
self.bottomRight = .noSplit(.init(app, nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,12 +142,14 @@ extension Ghostty {
|
|||||||
@State private var node: SplitNode
|
@State private var node: SplitNode
|
||||||
@State private var requestClose: Bool = false
|
@State private var requestClose: Bool = false
|
||||||
let onClose: (() -> Void)?
|
let onClose: (() -> Void)?
|
||||||
|
let fontSize: UInt8?
|
||||||
|
|
||||||
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle: String?
|
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle: String?
|
||||||
|
|
||||||
init(app: ghostty_app_t, onClose: (() ->Void)? = nil) {
|
init(app: ghostty_app_t, onClose: (() ->Void)? = nil, fontSize: UInt8? = nil) {
|
||||||
self.onClose = onClose
|
self.onClose = onClose
|
||||||
_node = State(wrappedValue: SplitNode.noSplit(.init(app)))
|
self.fontSize = fontSize
|
||||||
|
_node = State(wrappedValue: SplitNode.noSplit(.init(app, fontSize)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -78,6 +78,10 @@ extension Ghostty.Notification {
|
|||||||
/// Goto tab. Has tab index in the userinfo.
|
/// Goto tab. Has tab index in the userinfo.
|
||||||
static let ghosttyGotoTab = Notification.Name("com.mitchellh.ghostty.gotoTab")
|
static let ghosttyGotoTab = Notification.Name("com.mitchellh.ghostty.gotoTab")
|
||||||
static let GotoTabKey = ghosttyGotoTab.rawValue
|
static let GotoTabKey = ghosttyGotoTab.rawValue
|
||||||
|
|
||||||
|
/// New tab. Has font size of currently focused surface in the userinfo.
|
||||||
|
static let ghosttyNewTab = Notification.Name("com.mitchellh.ghostty.newTab")
|
||||||
|
static let NewTabKey = ghosttyNewTab.rawValue
|
||||||
|
|
||||||
/// Toggle fullscreen of current window
|
/// Toggle fullscreen of current window
|
||||||
static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
|
static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
|
||||||
|
@ -24,7 +24,7 @@ extension Ghostty {
|
|||||||
@StateObject private var surfaceView: SurfaceView
|
@StateObject private var surfaceView: SurfaceView
|
||||||
|
|
||||||
init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) {
|
init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) {
|
||||||
_surfaceView = StateObject(wrappedValue: SurfaceView(app))
|
_surfaceView = StateObject(wrappedValue: SurfaceView(app, nil))
|
||||||
self.content = content
|
self.content = content
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ extension Ghostty {
|
|||||||
// so we'll use that to tell ghostty to refresh.
|
// so we'll use that to tell ghostty to refresh.
|
||||||
override var wantsUpdateLayer: Bool { return true }
|
override var wantsUpdateLayer: Bool { return true }
|
||||||
|
|
||||||
init(_ app: ghostty_app_t) {
|
init(_ app: ghostty_app_t, _ fontSize: UInt8?) {
|
||||||
self.markedText = NSMutableAttributedString()
|
self.markedText = NSMutableAttributedString()
|
||||||
|
|
||||||
// Initialize with some default frame size. The important thing is that this
|
// Initialize with some default frame size. The important thing is that this
|
||||||
@ -149,7 +149,8 @@ extension Ghostty {
|
|||||||
var surface_cfg = ghostty_surface_config_s(
|
var surface_cfg = ghostty_surface_config_s(
|
||||||
userdata: Unmanaged.passUnretained(self).toOpaque(),
|
userdata: Unmanaged.passUnretained(self).toOpaque(),
|
||||||
nsview: Unmanaged.passUnretained(self).toOpaque(),
|
nsview: Unmanaged.passUnretained(self).toOpaque(),
|
||||||
scale_factor: NSScreen.main!.backingScaleFactor)
|
scale_factor: NSScreen.main!.backingScaleFactor,
|
||||||
|
font_size: fontSize ?? 0)
|
||||||
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
|
||||||
|
@ -70,6 +70,10 @@ pub const App = struct {
|
|||||||
|
|
||||||
/// Toggle fullscreen for current window.
|
/// Toggle fullscreen for current window.
|
||||||
toggle_fullscreen: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
|
toggle_fullscreen: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
|
||||||
|
|
||||||
|
/// New tab with desired font size in points
|
||||||
|
/// TODO: u8 should be something that's nullable
|
||||||
|
new_tab: ?*const fn (SurfaceUD, u8) callconv(.C) void = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
core_app: *CoreApp,
|
core_app: *CoreApp,
|
||||||
@ -166,6 +170,9 @@ pub const Surface = struct {
|
|||||||
|
|
||||||
/// The scale factor of the screen.
|
/// The scale factor of the screen.
|
||||||
scale_factor: f64 = 1,
|
scale_factor: f64 = 1,
|
||||||
|
|
||||||
|
/// The font size to inherit. If 0, default font size will be used.
|
||||||
|
font_size: u8 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
||||||
@ -191,6 +198,13 @@ pub const Surface = struct {
|
|||||||
var config = try apprt.surface.newConfig(app.core_app, app.config);
|
var config = try apprt.surface.newConfig(app.core_app, app.config);
|
||||||
defer config.deinit();
|
defer config.deinit();
|
||||||
|
|
||||||
|
// Overwrite the config for this new surface if we need to set a font
|
||||||
|
// size based on parent.
|
||||||
|
// TODO: Is this super hacky?
|
||||||
|
if (opts.font_size != 0) {
|
||||||
|
config.@"font-size" = opts.font_size;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize our surface right away. We're given a view that is
|
// Initialize our surface right away. We're given a view that is
|
||||||
// ready to use.
|
// ready to use.
|
||||||
try self.core_surface.init(
|
try self.core_surface.init(
|
||||||
@ -580,6 +594,22 @@ pub const Surface = struct {
|
|||||||
func(self.opts.userdata, nonNativeFullscreen);
|
func(self.opts.userdata, nonNativeFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn newTab(self: *const Surface) !void {
|
||||||
|
const func = self.app.opts.new_tab orelse {
|
||||||
|
log.info("runtime embedder does not support new_tab", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Do we check this here? Or do we check this in embedder?
|
||||||
|
//
|
||||||
|
const font_size: u8 = font_size: {
|
||||||
|
if (!self.app.config.@"window-inherit-font-size") break :font_size 0;
|
||||||
|
break :font_size @intCast(self.core_surface.font_size.points);
|
||||||
|
};
|
||||||
|
|
||||||
|
func(self.opts.userdata, font_size);
|
||||||
|
}
|
||||||
|
|
||||||
/// The cursor position from the host directly is in screen coordinates but
|
/// The cursor position from the host directly is in screen coordinates but
|
||||||
/// all our interface works in pixels.
|
/// all our interface works in pixels.
|
||||||
fn cursorPosToPixels(self: *const Surface, pos: apprt.CursorPos) !apprt.CursorPos {
|
fn cursorPosToPixels(self: *const Surface, pos: apprt.CursorPos) !apprt.CursorPos {
|
||||||
@ -804,6 +834,7 @@ pub const CAPI = struct {
|
|||||||
const action: input.Binding.Action = switch (key) {
|
const action: input.Binding.Action = switch (key) {
|
||||||
.copy_to_clipboard => .{ .copy_to_clipboard = {} },
|
.copy_to_clipboard => .{ .copy_to_clipboard = {} },
|
||||||
.paste_from_clipboard => .{ .paste_from_clipboard = {} },
|
.paste_from_clipboard => .{ .paste_from_clipboard = {} },
|
||||||
|
.new_tab => .{ .new_tab = {} },
|
||||||
};
|
};
|
||||||
|
|
||||||
ptr.core_surface.performBindingAction(action) catch |err| {
|
ptr.core_surface.performBindingAction(action) catch |err| {
|
||||||
|
@ -276,6 +276,7 @@ pub const Action = union(enum) {
|
|||||||
pub const Key = enum(c_int) {
|
pub const Key = enum(c_int) {
|
||||||
copy_to_clipboard,
|
copy_to_clipboard,
|
||||||
paste_from_clipboard,
|
paste_from_clipboard,
|
||||||
|
new_tab,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trigger is the associated key state that can trigger an action.
|
/// Trigger is the associated key state that can trigger an action.
|
||||||
|
Reference in New Issue
Block a user