<3/products/browser/Sources/GhostBrowser/

BrowserChrome.swift

import AppKit
import SwiftUI
import WebKit

/// Shared hover, press and cursor feedback for the browser chrome controls.
struct ChromeButtonStyle: ButtonStyle {
    var selected = false
    var cornerRadius: CGFloat = 7

    func makeBody(configuration: Configuration) -> some View {
        ChromeButtonBody(configuration: configuration, selected: selected, cornerRadius: cornerRadius)
    }

    private struct ChromeButtonBody: View {
        let configuration: ButtonStyle.Configuration
        let selected: Bool
        let cornerRadius: CGFloat
        @State private var hovered = false
        @Environment(\.isEnabled) private var isEnabled
        @Environment(\.accessibilityReduceMotion) private var reduceMotion

        private var opacity: Double {
            guard isEnabled else { return 0 }
            if configuration.isPressed { return selected ? 0.22 : 0.16 }
            if hovered { return selected ? 0.17 : 0.08 }
            return selected ? 0.12 : 0
        }

        var body: some View {
            configuration.label
                .foregroundStyle(Color.primary.opacity(!isEnabled ? 0.25 : selected || hovered || configuration.isPressed ? 1 : 0.72))
                .background(Color.primary.opacity(opacity), in: RoundedRectangle(cornerRadius: cornerRadius))
                .overlay {
                    RoundedRectangle(cornerRadius: cornerRadius)
                        .strokeBorder(Color.primary.opacity(selected ? 0.08 : 0), lineWidth: 1)
                        .allowsHitTesting(false)
                }
                .contentShape(RoundedRectangle(cornerRadius: cornerRadius))
                .onHover { hovered = $0 }
                .animation(reduceMotion ? nil : .easeOut(duration: 0.12), value: hovered)
                .modifier(ChromePointer())
        }
    }
}

private struct ChromePointer: ViewModifier {
    @Environment(\.isEnabled) private var isEnabled

    func body(content: Content) -> some View {
        if !isEnabled {
            content
        } else if #available(macOS 15, *) {
            content.pointerStyle(.link)
        } else {
            content.background(LegacyCursorRegion())
        }
    }
}

/// Cursor rectangles let AppKit restore the cursor when a tab moves or disappears.
private struct LegacyCursorRegion: NSViewRepresentable {
    final class CursorView: NSView {
        override func resetCursorRects() {
            super.resetCursorRects()
            addCursorRect(visibleRect, cursor: .pointingHand)
        }
        override func hitTest(_ point: NSPoint) -> NSView? { nil }
    }
    func makeNSView(context: Context) -> CursorView { CursorView() }
    func updateNSView(_ view: CursorView, context: Context) {
        view.window?.invalidateCursorRects(for: view)
    }
}

/// Keep WebKit's native link hit-testing and action. The UI delegate routes its
/// new-window request into a Ghost tab, including links in frames and images.
final class BrowserWebView: WKWebView {
    override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
        super.willOpenMenu(menu, with: event)
        for item in menu.items where item.identifier?.rawValue == "WKMenuItemIdentifierOpenLinkInNewWindow" {
            item.title = "Open Link in New Tab"
        }
    }
}