Browse Source

Make Add to desktop create true desktop widgets.

Route Add to desktop to desktop widget instances and set widget panels to desktop-level, non-focusable behavior so they no longer appear as standard app windows.

Made-with: Cursor
huzaifahayat12 3 tháng trước cách đây
mục cha
commit
b75f4e75ec

+ 15 - 24
google_apps/AppTileView.swift

@@ -158,27 +158,25 @@ struct AppTileView: View {
     }
 
     private func addToDesktop() {
-        guard let url = app.webURL else {
-            showAlert(title: "Unavailable", message: "This tile doesn’t have a web link to create a desktop shortcut.")
+        let widgetVariants = WidgetTemplates.variants(for: app)
+        guard let variant = widgetVariants.first else {
+            showAlert(title: "Unavailable", message: "No desktop widget is available for this app.")
             return
         }
 
-        guard let desktopURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first else {
-            showAlert(title: "Error", message: "Couldn’t find your Desktop folder.")
-            return
-        }
-
-        let fileName = sanitizedFileName(app.name).isEmpty ? "Shortcut" : sanitizedFileName(app.name)
-        let targetURL = desktopURL.appendingPathComponent("\(fileName).webloc")
+        var updated = decodeUUIDSet(from: widgetAppIDsData)
+        updated.insert(app.id)
+        widgetAppIDsData = encodeUUIDSet(updated)
 
-        let payload: [String: Any] = ["URL": url.absoluteString]
-        do {
-            let data = try PropertyListSerialization.data(fromPropertyList: payload, format: .xml, options: 0)
-            try data.write(to: targetURL, options: .atomic)
-            showAlert(title: "Created", message: "Desktop shortcut created: \(targetURL.lastPathComponent)")
-        } catch {
-            showAlert(title: "Error", message: "Couldn’t create the desktop shortcut.")
-        }
+        let instance = WidgetInstance(
+            appID: app.id,
+            variantID: variant.id,
+            size: variant.size,
+            origin: nil
+        )
+        DesktopWidgetWindowManager.shared.show(instance: instance, appProvider: { id in
+            id == app.id ? app : nil
+        })
     }
 
     private func decodeUUIDSet(from dataString: String) -> Set<UUID> {
@@ -201,13 +199,6 @@ struct AppTileView: View {
         }
     }
 
-    private func sanitizedFileName(_ input: String) -> String {
-        let invalid = CharacterSet(charactersIn: "/:\\?%*|\"<>")
-        let cleaned = input.components(separatedBy: invalid).joined(separator: " ")
-        return cleaned.trimmingCharacters(in: .whitespacesAndNewlines)
-            .replacingOccurrences(of: "  +", with: " ", options: .regularExpression)
-    }
-
     private func showAlert(title: String, message: String) {
         let alert = NSAlert()
         alert.messageText = title

+ 15 - 25
google_apps/LauncherRootView.swift

@@ -593,35 +593,25 @@ private struct PanelAppRowView: View {
     }
 
     private func addToDesktop() {
-        guard let url = app.webURL else {
-            showAlert(title: "Unavailable", message: "This tile doesn’t have a web link to create a desktop shortcut.")
+        let variants = WidgetTemplates.variants(for: app)
+        guard let variant = variants.first else {
+            showAlert(title: "Unavailable", message: "No desktop widget is available for this app.")
             return
         }
 
-        guard let desktopURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first else {
-            showAlert(title: "Error", message: "Couldn’t find your Desktop folder.")
-            return
-        }
-
-        let fileName = sanitizedFileName(app.name).isEmpty ? "Shortcut" : sanitizedFileName(app.name)
-        let targetURL = desktopURL.appendingPathComponent("\(fileName).webloc")
-
-        let payload: [String: Any] = ["URL": url.absoluteString]
-        do {
-            let data = try PropertyListSerialization.data(fromPropertyList: payload, format: .xml, options: 0)
-            try data.write(to: targetURL, options: .atomic)
-            showAlert(title: "Created", message: "Desktop shortcut created: \(targetURL.lastPathComponent)")
-        } catch {
-            showAlert(title: "Error", message: "Couldn’t create the desktop shortcut.")
-        }
-    }
+        var updated = decodeUUIDSetGlobal(from: widgetAppIDsData)
+        updated.insert(app.id)
+        widgetAppIDsData = encodeUUIDSetGlobal(updated)
 
-    private func sanitizedFileName(_ input: String) -> String {
-        let invalid = CharacterSet(charactersIn: "/:\\?%*|\"<>")
-        let cleaned = input.components(separatedBy: invalid).joined(separator: " ")
-        return cleaned
-            .trimmingCharacters(in: .whitespacesAndNewlines)
-            .replacingOccurrences(of: "  +", with: " ", options: .regularExpression)
+        let instance = WidgetInstance(
+            appID: app.id,
+            variantID: variant.id,
+            size: variant.size,
+            origin: nil
+        )
+        DesktopWidgetWindowManager.shared.show(instance: instance, appProvider: { id in
+            id == app.id ? app : nil
+        })
     }
 
     private func showAlert(title: String, message: String) {

+ 11 - 3
google_apps/Widgets/DesktopWidgetWindowManager.swift

@@ -57,7 +57,7 @@ final class DesktopWidgetWindowManager {
 
     private func makePanel(for instance: WidgetInstance, app: LauncherApp, variant: WidgetVariant) -> NSPanel {
         let size = panelSize(for: variant.size)
-        let panel = NSPanel(
+        let panel = DesktopWidgetPanel(
             contentRect: NSRect(x: 0, y: 0, width: size.width, height: size.height),
             styleMask: [.nonactivatingPanel, .borderless],
             backing: .buffered,
@@ -66,16 +66,19 @@ final class DesktopWidgetWindowManager {
 
         panel.isReleasedWhenClosed = false
         panel.isFloatingPanel = false
-        panel.becomesKeyOnlyIfNeeded = true
+        panel.becomesKeyOnlyIfNeeded = false
         panel.isMovable = true
-        panel.level = .normal
+        panel.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.desktopIconWindow)))
         panel.hasShadow = true
         panel.isOpaque = false
         panel.backgroundColor = .clear
         panel.isMovableByWindowBackground = true
         panel.hidesOnDeactivate = false
+        panel.ignoresMouseEvents = false
         panel.collectionBehavior = [
             .canJoinAllSpaces,
+            .stationary,
+            .ignoresCycle,
         ]
 
         let root = DesktopWidgetHostView(
@@ -196,6 +199,11 @@ final class DesktopWidgetWindowManager {
     }
 }
 
+private final class DesktopWidgetPanel: NSPanel {
+    override var canBecomeKey: Bool { false }
+    override var canBecomeMain: Bool { false }
+}
+
 private struct DesktopWidgetHostView: View {
     let app: LauncherApp
     let variant: WidgetVariant