mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-24 08:15:21 +00:00
macos: unhide cursor on clipboard confirmation
This commit is contained in:
@@ -34,6 +34,9 @@ struct ClipboardConfirmationView: View {
|
||||
/// Optional delegate to get results. If this is nil, then this view will never close on its own.
|
||||
weak var delegate: ClipboardConfirmationViewDelegate? = nil
|
||||
|
||||
/// Used to track if we should rehide on disappear
|
||||
@State private var cursorHiddenCount: UInt = 0
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
@@ -65,6 +68,25 @@ struct ClipboardConfirmationView: View {
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
.onAppear {
|
||||
// I can't find a better way to handle this. There is no API to detect
|
||||
// if the cursor is hidden and OTHER THINGS do unhide the cursor. So we
|
||||
// try to unhide it completely here and hope for the best. Issue #1516.
|
||||
cursorHiddenCount = Cursor.unhideCompletely()
|
||||
|
||||
// If we didn't unhide anything, we just send an unhide to be safe.
|
||||
// I don't think the count can go negative on NSCursor so this handles
|
||||
// scenarios cursor is hidden outside of our own NSCursor usage.
|
||||
if (cursorHiddenCount == 0) {
|
||||
_ = Cursor.unhide()
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
// Rehide if we unhid
|
||||
for _ in 0..<cursorHiddenCount {
|
||||
Cursor.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func onCancel() {
|
||||
|
||||
@@ -59,6 +59,21 @@ extension Ghostty {
|
||||
|
||||
@EnvironmentObject private var ghostty: Ghostty.App
|
||||
|
||||
// The visibility state of the mouse pointer
|
||||
private var pointerVisibililty: BackportVisibility {
|
||||
// If our window or surface loses focus we always bring it back
|
||||
if (!windowFocus || !surfaceFocus) {
|
||||
return .visible
|
||||
}
|
||||
|
||||
// If we have window focus then it depends on surface state
|
||||
if (surfaceView.pointerVisible) {
|
||||
return .visible
|
||||
} else {
|
||||
return .hidden
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
let center = NotificationCenter.default
|
||||
|
||||
@@ -82,7 +97,7 @@ extension Ghostty {
|
||||
.focusedValue(\.ghosttySurfaceView, surfaceView)
|
||||
.focusedValue(\.ghosttySurfaceCellSize, surfaceView.cellSize)
|
||||
#if canImport(AppKit)
|
||||
.backport.pointerVisibility(surfaceView.pointerVisible ? .visible : .hidden)
|
||||
.backport.pointerVisibility(pointerVisibililty)
|
||||
.backport.pointerStyle(surfaceView.pointerStyle)
|
||||
.onReceive(pubBecomeKey) { notification in
|
||||
guard let window = notification.object as? NSWindow else { return }
|
||||
|
||||
38
macos/Sources/Helpers/Cursor.swift
Normal file
38
macos/Sources/Helpers/Cursor.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
import Cocoa
|
||||
|
||||
/// This helps manage the stateful nature of NSCursor hiding and unhiding.
|
||||
class Cursor {
|
||||
private static var counter: UInt = 0
|
||||
|
||||
static var isVisible: Bool {
|
||||
counter == 0
|
||||
}
|
||||
|
||||
static func hide() {
|
||||
counter += 1
|
||||
NSCursor.hide()
|
||||
}
|
||||
|
||||
/// Unhide the cursor. Returns true if the cursor was previously hidden.
|
||||
static func unhide() -> Bool {
|
||||
// Its always safe to call unhide when the counter is zero because it
|
||||
// won't go negative.
|
||||
NSCursor.unhide()
|
||||
|
||||
if (counter > 0) {
|
||||
counter -= 1
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
static func unhideCompletely() -> UInt {
|
||||
let counter = self.counter
|
||||
for _ in 0..<counter {
|
||||
assert(unhide())
|
||||
}
|
||||
assert(self.counter == 0)
|
||||
return counter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user