mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-22 23:35:20 +00:00
macos: show secure input overlay when it is enabled
This commit is contained in:
@@ -12,7 +12,7 @@ import OSLog
|
||||
// it. You have to yield secure input on application deactivation (because
|
||||
// it'll affect other apps) and reacquire on reactivation, and every enable
|
||||
// needs to be balanced with a disable.
|
||||
class SecureInput {
|
||||
class SecureInput : ObservableObject {
|
||||
static let shared = SecureInput()
|
||||
|
||||
private static let logger = Logger(
|
||||
@@ -31,7 +31,7 @@ class SecureInput {
|
||||
private var scoped: [ObjectIdentifier: Bool] = [:]
|
||||
|
||||
// This is set to true when we've successfully called EnableSecureInput.
|
||||
private var enabled: Bool = false
|
||||
@Published private(set) var enabled: Bool = false
|
||||
|
||||
// This is true if we want to enable secure input. We want to enable
|
||||
// secure input if its enabled globally or any of the scoped objects are
|
||||
|
||||
67
macos/Sources/Features/Secure Input/SecureInputOverlay.swift
Normal file
67
macos/Sources/Features/Secure Input/SecureInputOverlay.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SecureInputOverlay: View {
|
||||
// Animations
|
||||
@State private var shadowAngle: Angle = .degrees(0)
|
||||
@State private var shadowWidth: CGFloat = 6
|
||||
|
||||
// Popover explainer text
|
||||
@State private var isPopover = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "lock.shield.fill")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25, height: 25)
|
||||
.foregroundColor(.primary)
|
||||
.padding(5)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(.background)
|
||||
.innerShadow(
|
||||
using: RoundedRectangle(cornerRadius: 12),
|
||||
stroke: AngularGradient(
|
||||
gradient: Gradient(colors: [.cyan, .blue, .yellow, .blue, .cyan]),
|
||||
center: .center,
|
||||
angle: shadowAngle
|
||||
),
|
||||
width: shadowWidth
|
||||
)
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.stroke(Color.gray, lineWidth: 1)
|
||||
)
|
||||
.onTapGesture {
|
||||
isPopover = true
|
||||
}
|
||||
.padding(.top, 10)
|
||||
.padding(.trailing, 10)
|
||||
.popover(isPresented: $isPopover, arrowEdge: .bottom) {
|
||||
Text("""
|
||||
Secure Input is active. Secure Input is a macOS security feature that
|
||||
prevents applications from reading keyboard events. Ghostty turns
|
||||
this on manually if `Ghostty > Secure Keyboard Entry` is enabled or
|
||||
automatically when at a password prompt.
|
||||
""")
|
||||
.padding(.all)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.onAppear {
|
||||
withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) {
|
||||
shadowAngle = .degrees(360)
|
||||
}
|
||||
|
||||
withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: true)) {
|
||||
shadowWidth = 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,9 @@ extension Ghostty {
|
||||
// True if we're hovering over the left URL view, so we can show it on the right.
|
||||
@State private var isHoveringURLLeft: Bool = false
|
||||
|
||||
// Observe SecureInput to detect when its enabled
|
||||
@ObservedObject private var secureInput = SecureInput.shared
|
||||
|
||||
@EnvironmentObject private var ghostty: Ghostty.App
|
||||
|
||||
var body: some View {
|
||||
@@ -197,6 +200,14 @@ extension Ghostty {
|
||||
}
|
||||
}
|
||||
|
||||
// If we have secure input enabled and we're the focused surface and window
|
||||
// then we want to show the secure input overlay.
|
||||
if (secureInput.enabled &&
|
||||
surfaceFocus &&
|
||||
windowFocus) {
|
||||
SecureInputOverlay()
|
||||
}
|
||||
|
||||
// If our surface is not healthy, then we render an error view over it.
|
||||
if (!surfaceView.healthy) {
|
||||
Rectangle().fill(ghostty.config.backgroundColor)
|
||||
|
||||
18
macos/Sources/Helpers/View+Extension.swift
Normal file
18
macos/Sources/Helpers/View+Extension.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
func innerShadow<S: Shape, ST: ShapeStyle>(
|
||||
using shape: S = Rectangle(),
|
||||
stroke: ST = Color.black,
|
||||
width: CGFloat = 6,
|
||||
blur: CGFloat = 6
|
||||
) -> some View {
|
||||
return self
|
||||
.overlay(
|
||||
shape
|
||||
.stroke(stroke, lineWidth: width)
|
||||
.blur(radius: blur)
|
||||
.mask(shape)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user