🚀 First official release of ShotScreen with complete feature set: ✨ Core Features: - Advanced screenshot capture system - Multi-monitor support - Professional UI/UX design - Automated update system with Sparkle - Apple notarized & code signed 🛠 Technical Excellence: - Native Swift macOS application - Professional build & deployment pipeline - Comprehensive error handling - Memory optimized performance 📦 Distribution Ready: - Professional DMG packaging - Apple notarization complete - No security warnings for users - Ready for public distribution This is the foundation release that establishes ShotScreen as a premium screenshot tool for macOS.
186 lines
8.0 KiB
Swift
186 lines
8.0 KiB
Swift
//
|
|
// DesktopIconManager.swift
|
|
// ScreenShot
|
|
//
|
|
// Created by [Your Name/AI] on [Current Date].
|
|
// Copyright © 2025 [Your Name/AI]. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import ScreenCaptureKit
|
|
|
|
@available(macOS 12.3, *)
|
|
class DesktopIconManager {
|
|
|
|
static let shared = DesktopIconManager()
|
|
|
|
private init() {
|
|
// Private constructor for singleton
|
|
}
|
|
|
|
func logFinderWindowDetails(windows: [SCWindow]) {
|
|
NSLog("🕵️♂️ DesktopIconManager: Logging details for Finder windows...")
|
|
let finderWindows = windows.filter { $0.owningApplication?.bundleIdentifier == "com.apple.finder" }
|
|
|
|
if finderWindows.isEmpty {
|
|
NSLog("🕵️♂️ No Finder windows found in the provided list.")
|
|
return
|
|
}
|
|
|
|
NSLog("🕵️♂️ Found \(finderWindows.count) Finder windows:")
|
|
for (index, window) in finderWindows.enumerated() {
|
|
let appName = window.owningApplication?.applicationName ?? "Unknown"
|
|
let bundleID = window.owningApplication?.bundleIdentifier ?? "Unknown"
|
|
|
|
NSLog(" --------------------------------------------------")
|
|
NSLog(" 🕵️♂️ Finder Window [\(index)] Details:")
|
|
NSLog(" --------------------------------------------------")
|
|
NSLog(" Title: '\(window.title ?? "N/A")'")
|
|
NSLog(" App Name: \(appName)")
|
|
NSLog(" Bundle ID: \(bundleID)")
|
|
NSLog(" Window ID: \(window.windowID)")
|
|
NSLog(" Layer: \(window.windowLayer)")
|
|
NSLog(" Frame (SCK Coords): \(NSStringFromRect(window.frame))")
|
|
NSLog(" Is OnScreen: \(window.isOnScreen)")
|
|
if #available(macOS 13.1, *) {
|
|
NSLog(" Is Active: \(window.isActive)")
|
|
} else {
|
|
NSLog(" Is Active: (N/A on this macOS version)")
|
|
}
|
|
NSLog(" --------------------------------------------------")
|
|
}
|
|
}
|
|
|
|
/// Checks if desktop icon hiding is currently enabled in user settings
|
|
/// - Returns: true if desktop icons should be hidden during screenshots
|
|
func isDesktopIconHidingEnabled() -> Bool {
|
|
return SettingsManager.shared.hideDesktopIconsDuringScreenshot
|
|
}
|
|
|
|
/// Checks if desktop widget hiding is currently enabled in user settings
|
|
/// - Returns: true if desktop widgets should be hidden during screenshots
|
|
func isDesktopWidgetHidingEnabled() -> Bool {
|
|
return SettingsManager.shared.hideDesktopWidgetsDuringScreenshot
|
|
}
|
|
|
|
/// Detects desktop widgets from available windows
|
|
/// This function identifies widgets based on various criteria such as bundle identifiers and window characteristics
|
|
/// - Parameter windows: Array of SCWindow objects to analyze
|
|
/// - Returns: Array of SCWindow objects that are likely desktop widgets
|
|
func detectDesktopWidgets(from windows: [SCWindow]) -> [SCWindow] {
|
|
guard isDesktopWidgetHidingEnabled() else {
|
|
NSLog("🔄 DesktopIconManager: Widget hiding is disabled, returning empty array")
|
|
return []
|
|
}
|
|
|
|
NSLog("🔍 DesktopIconManager: Starting widget detection...")
|
|
var potentialWidgets: [SCWindow] = []
|
|
|
|
// Known widget bundle identifiers (based on research)
|
|
let knownWidgetBundleIdentifiers = [
|
|
"com.apple.controlcenter",
|
|
"com.apple.notificationcenter",
|
|
"com.apple.dashboard",
|
|
"com.apple.widget",
|
|
"com.apple.WidgetKit",
|
|
"com.apple.widgets"
|
|
]
|
|
|
|
// Widget-like window characteristics
|
|
let widgetWindowTitles = [
|
|
"Widget",
|
|
"Dashboard",
|
|
"Control Center",
|
|
"Notification",
|
|
"Today"
|
|
]
|
|
|
|
for window in windows {
|
|
let bundleId = window.owningApplication?.bundleIdentifier ?? ""
|
|
let appName = window.owningApplication?.applicationName ?? ""
|
|
let windowTitle = window.title ?? ""
|
|
let windowLayer = window.windowLayer
|
|
|
|
var isWidget = false
|
|
var detectionReason = ""
|
|
|
|
// Check 1: Known widget bundle identifiers
|
|
if knownWidgetBundleIdentifiers.contains(where: { bundleId.contains($0) }) {
|
|
isWidget = true
|
|
detectionReason = "Known widget bundle ID: \(bundleId)"
|
|
}
|
|
|
|
// Check 2: Widget-like window titles
|
|
if !isWidget && widgetWindowTitles.contains(where: { windowTitle.contains($0) }) {
|
|
isWidget = true
|
|
detectionReason = "Widget-like window title: '\(windowTitle)'"
|
|
}
|
|
|
|
// Check 3: Window layer characteristics (widgets often appear on specific layers)
|
|
// Widgets may appear on desktop-level layers (often higher than normal windows)
|
|
if !isWidget && windowLayer > 25 && windowLayer < 1000 {
|
|
// Additional checks for this layer range
|
|
if appName.lowercased().contains("widget") ||
|
|
bundleId.lowercased().contains("widget") ||
|
|
windowTitle.lowercased().contains("widget") {
|
|
isWidget = true
|
|
detectionReason = "High window layer (\(windowLayer)) with widget-related naming"
|
|
}
|
|
}
|
|
|
|
// Check 4: Window size characteristics (many widgets are small, square-ish windows)
|
|
let frame = window.frame
|
|
if !isWidget && frame.width > 0 && frame.height > 0 {
|
|
let aspectRatio = frame.width / frame.height
|
|
let area = frame.width * frame.height
|
|
|
|
// Small to medium sized windows with square-ish aspect ratios
|
|
if area < 50000 && aspectRatio >= 0.5 && aspectRatio <= 2.0 {
|
|
if bundleId.contains("apple") && (
|
|
windowTitle.isEmpty ||
|
|
windowTitle.count < 3 ||
|
|
bundleId.contains("notification") ||
|
|
bundleId.contains("control")
|
|
) {
|
|
isWidget = true
|
|
detectionReason = "Small Apple window with widget characteristics (area: \(Int(area)), ratio: \(String(format: "%.2f", aspectRatio)))"
|
|
}
|
|
}
|
|
}
|
|
|
|
if isWidget {
|
|
potentialWidgets.append(window)
|
|
NSLog("📱 Widget detected: \(detectionReason)")
|
|
NSLog(" App: \(appName) (\(bundleId))")
|
|
NSLog(" Title: '\(windowTitle)'")
|
|
NSLog(" Layer: \(windowLayer)")
|
|
NSLog(" Frame: \(NSStringFromRect(frame))")
|
|
}
|
|
}
|
|
|
|
NSLog("🔍 DesktopIconManager: Found \(potentialWidgets.count) potential desktop widgets")
|
|
return potentialWidgets
|
|
}
|
|
|
|
/// Legacy placeholder for future window filtering functionality
|
|
/// Note: The main desktop icon filtering logic is now handled in ScreenCaptureKitProvider.getDesktopIconWindows()
|
|
/// which respects the hideDesktopIconsDuringScreenshot setting from SettingsManager
|
|
func shouldExcludeWindowForDesktopIconHiding(_ window: SCWindow) -> Bool {
|
|
// Desktop icon filtering is now handled in ScreenCaptureKitProvider.getDesktopIconWindows()
|
|
// This method is kept for potential future advanced filtering logic
|
|
return false
|
|
}
|
|
|
|
/// Determines if a window should be excluded for widget hiding
|
|
/// - Parameter window: The window to check
|
|
/// - Returns: true if the window should be excluded (i.e., it's a widget and widget hiding is enabled)
|
|
func shouldExcludeWindowForWidgetHiding(_ window: SCWindow) -> Bool {
|
|
guard isDesktopWidgetHidingEnabled() else {
|
|
return false
|
|
}
|
|
|
|
// Use the widget detection logic to determine if this single window is a widget
|
|
let widgets = detectDesktopWidgets(from: [window])
|
|
return !widgets.isEmpty
|
|
}
|
|
} |