mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-19 22:10:29 +00:00
macos: drag preview is an image of the surface
This commit is contained in:
@@ -5,6 +5,7 @@ extension Ghostty {
|
||||
/// Only appears when hovering in the top region of the surface.
|
||||
struct SurfaceGrabHandle: View {
|
||||
private let handleHeight: CGFloat = 10
|
||||
private let previewScale: CGFloat = 0.2
|
||||
|
||||
let surfaceView: SurfaceView
|
||||
|
||||
@@ -34,7 +35,35 @@ extension Ghostty {
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.draggable(surfaceView)
|
||||
.draggable(surfaceView) {
|
||||
SurfaceDragPreview(surfaceView: surfaceView, scale: previewScale)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A miniature preview of the surface view for drag operations that updates periodically.
|
||||
private struct SurfaceDragPreview: View {
|
||||
let surfaceView: SurfaceView
|
||||
let scale: CGFloat
|
||||
|
||||
var body: some View {
|
||||
// We need to use a TimelineView to ensure that this doesn't
|
||||
// cache forever. This will NOT let the view live update while
|
||||
// being dragged; macOS doesn't seem to allow that. But it will
|
||||
// make sure on new drags the screenshot is updated.
|
||||
TimelineView(.periodic(from: .now, by: 1.0 / 30.0)) { _ in
|
||||
if let snapshot = surfaceView.asImage {
|
||||
Image(nsImage: snapshot)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(
|
||||
width: snapshot.size.width * scale,
|
||||
height: snapshot.size.height * scale
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||
.shadow(radius: 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
macos/Sources/Ghostty/Surface View/SurfaceView+Image.swift
Normal file
28
macos/Sources/Ghostty/Surface View/SurfaceView+Image.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
#if canImport(AppKit)
|
||||
import AppKit
|
||||
#elseif canImport(UIKit)
|
||||
import UIKit
|
||||
#endif
|
||||
|
||||
extension Ghostty.SurfaceView {
|
||||
#if canImport(AppKit)
|
||||
/// A snapshot image of the current surface view.
|
||||
var asImage: NSImage? {
|
||||
guard let bitmapRep = bitmapImageRepForCachingDisplay(in: bounds) else {
|
||||
return nil
|
||||
}
|
||||
cacheDisplay(in: bounds, to: bitmapRep)
|
||||
let image = NSImage(size: bounds.size)
|
||||
image.addRepresentation(bitmapRep)
|
||||
return image
|
||||
}
|
||||
#elseif canImport(UIKit)
|
||||
/// A snapshot image of the current surface view.
|
||||
var asImage: UIImage? {
|
||||
let renderer = UIGraphicsImageRenderer(bounds: bounds)
|
||||
return renderer.image { _ in
|
||||
drawHierarchy(in: bounds, afterScreenUpdates: true)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -2213,6 +2213,7 @@ extension Ghostty.SurfaceView {
|
||||
|
||||
return NSAttributedString(string: plainString, attributes: attributes)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Caches a value for some period of time, evicting it automatically when that time expires.
|
||||
|
||||
Reference in New Issue
Block a user