Apptag/ApptagApp.swift
@@ -67,6 +67,7 @@ private var lastShowDockIcon: Bool? private var statusMenuScreenForNextOverlay: NSScreen? private var overlayGeneration = 0 private var overlayAvoidsSpaceSwitch = false private var suppressReopenUntil = Date.distantPast private struct OverlayPlacementContext { @@ -269,9 +270,8 @@ let showDock = UserDefaults.standard.bool(forKey: Self.showDockIconKey) lastShowDockIcon = showDock let shouldStayAccessoryForCurrentFullscreenSpace = avoidSpaceSwitch && isOverlayVisible && !isSettingsVisible let shouldStayAccessoryForCurrentFullscreenSpace = isOverlayVisible && (avoidSpaceSwitch || overlayAvoidsSpaceSwitch) let desiredPolicy: NSApplication.ActivationPolicy = shouldStayAccessoryForCurrentFullscreenSpace ? .accessory : (requiresForegroundOwnership @@ -784,6 +784,7 @@ let placement = overlayPlacementContextForNextOverlay(preferredScreen: preferredScreen) let shouldAvoidSpaceSwitch = placement.map { hasFullscreenWindowOnScreen($0.screen) } ?? false if let overlayWindow, overlayWindow.isVisible { overlayAvoidsSpaceSwitch = shouldAvoidSpaceSwitch moveOverlayToCurrentPlacement(preferredScreen: preferredScreen) overlayWindow.level = currentOverlayLevel refreshLauncherChromeState(activate: !shouldAvoidSpaceSwitch, avoidSpaceSwitch: shouldAvoidSpaceSwitch) @@ -839,6 +840,7 @@ existingWindow.orderOut(nil) overlayWindow = nil } overlayAvoidsSpaceSwitch = shouldAvoidSpaceSwitch let window = makeOverlayWindow( on: placement.screen, @@ -1098,6 +1100,7 @@ overlayWindow?.orderOut(nil) removeOverlayKeyMonitor() removeQuickSearchExternalMouseMonitor() overlayAvoidsSpaceSwitch = false refreshLauncherChromeState() NotificationCenter.default.post(name: .tagLauncherOverlayDidHide, object: nil) if discardWindow { @@ -1203,7 +1206,10 @@ private func showQuickSearchFromGlobalHotkey() { if overlayWindow?.isVisible == true { refreshLauncherChromeState(activate: true) refreshLauncherChromeState( activate: !overlayAvoidsSpaceSwitch, avoidSpaceSwitch: overlayAvoidsSpaceSwitch ) requestQuickSearch(source: QuickSearchOpenSource.globalVisible) return } @@ -1299,12 +1305,20 @@ var behavior = window.collectionBehavior behavior.remove(.canJoinAllSpaces) if overlayAvoidsSpaceSwitch { behavior.remove(.moveToActiveSpace) behavior.formUnion([.fullScreenAuxiliary, .stationary, .transient, .ignoresCycle]) } else { behavior.formUnion([.fullScreenAuxiliary, .moveToActiveSpace]) } window.collectionBehavior = behavior window.makeKeyAndOrderFront(nil) window.orderFrontRegardless() settingsWindow = window refreshLauncherChromeState(activate: true) refreshLauncherChromeState( activate: !overlayAvoidsSpaceSwitch, avoidSpaceSwitch: overlayAvoidsSpaceSwitch ) } private func attachSettingsWindow(_ window: NSWindow, to overlayWindow: NSWindow) { @@ -1454,6 +1468,13 @@ } private func promoteOverlayToForegroundInput() { if overlayAvoidsSpaceSwitch { refreshLauncherChromeState(activate: false, avoidSpaceSwitch: true) guard let overlayWindow else { return } overlayWindow.makeKeyAndOrderFront(nil) overlayWindow.orderFrontRegardless() return } beginLauncherForegroundOwnership() guard let overlayWindow else { return } overlayWindow.makeKeyAndOrderFront(nil) @@ -1551,7 +1572,11 @@ @objc private func openPreferences(_ sender: Any? = nil) { TagDatabase.flushPendingCategorySchemeBackupBatch() if overlayAvoidsSpaceSwitch { refreshLauncherChromeState(activate: false, avoidSpaceSwitch: true) } else { beginLauncherForegroundOwnership() } // Don't hide overlay — keep it visible for real-time setting preview. if let overlayWindow, overlayWindow.isVisible { overlayWindow.makeKeyAndOrderFront(nil) Release/AppStore-7.6.0-20260524.1849/APP_STORE_CONNECT_METADATA.md
Release/AppStore-7.6.0-20260524.1849/BUILD_SIGN_UPLOAD.md
File was renamed from Release/AppStore-7.6.0-20260524.1652/BUILD_SIGN_UPLOAD.md @@ -50,7 +50,7 @@ APP_STORE=1 \ CODESIGN_IDENTITY="3rd Party Mac Developer Application: <TEAM NAME> (<TEAMID>)" \ APP_BUILD=20260524.1652 \ APP_BUILD=20260524.1849 \ bash build.sh productbuild \ Release/AppStore-7.6.0-20260524.1849/FIRST_TIME_MAC_APP_STORE_TODO.md
Release/AppStore-7.6.0-20260524.1849/QA_RELEASE_EVIDENCE.md
File was renamed from Release/AppStore-7.6.0-20260524.1652/QA_RELEASE_EVIDENCE.md @@ -3,7 +3,7 @@ ## Local Build - Version: `7.6.0` - Build: `20260524.1652` - Build: `20260524.1849` - App path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.app` - DMG path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.dmg` - App executable size: `1.4M` @@ -12,8 +12,8 @@ ## Hashes ```text 1bf3e53410e18778038c310e1ed083cd89c27b781cc87942dd3dd9fb57d73cb2 build/TagLauncher.dmg 13e74a774662dfec88e69b5f51e5c51c5c46e3e5f8884cbf8cbab5cd44c4442d build/TagLauncher.app/Contents/MacOS/TagLauncher dc5bc9cf90b9e04a9e4fda155b757e6e0af681ff1b79bf109552ae0c3ce2a193 build/TagLauncher.dmg a59f08f214bd4ac667197f6b2f2672aaf4a57c1fdd9872ea385099e84f18fa57 build/TagLauncher.app/Contents/MacOS/TagLauncher ``` ## Commands Run @@ -42,6 +42,8 @@ - Fullscreen Space overlay appears above the current fullscreen app. - Fullscreen Space overlay is checked with `showDockIcon=true` and `showDockIcon=false`. - Fullscreen Space overlay bounds must match the fullscreen target display and remain stable across repeated samples. - Fullscreen Space Quick Search opens from app grid without switching away from the current fullscreen app. - Fullscreen Space Settings opens from app grid without switching away from the current fullscreen app. - Split View fullscreen geometry is checked for 50/50 and 33/67 split layouts, while ordinary side-by-side desktop windows are rejected. - App grid claims foreground, hides Dock, and keeps menu bar visible. - Settings floats above app grid. Release/AppStore-7.6.0-20260524.1849/README.md
File was renamed from Release/AppStore-7.6.0-20260524.1652/README.md @@ -8,9 +8,9 @@ - Platform: macOS / Mac App Store - Bundle ID: `com.taglauncher.app` - Version: `7.6.0` - Local QA build: `20260524.1652` - Local QA build: `20260524.1849` - Source branch at preparation time: `main` - Release folder: `Release/AppStore-7.6.0-20260524.1652` - Release folder: `Release/AppStore-7.6.0-20260524.1849` ## What Changed For This Release @@ -23,6 +23,7 @@ - Added an About-page Help PDF button that opens the online PDF matching the current app language, plus a copy-link button. - Hardened fullscreen Space presentation so the app grid stays above the current fullscreen app instead of moving to another Space. - Added Split View fullscreen detection so two apps sharing one fullscreen Space also keep the app grid on the current Space. - Kept Quick Search and Settings inside the same fullscreen/Split View Space session instead of activating TagLauncher and sliding to another Space. - Expanded window QA to cover fullscreen Space behavior with Dock icon both enabled and disabled, including stability checks. - Strengthened the window logic QA script to cover fullscreen Space, duplicate Dock tiles, repeated self-launch, force quit layering, Settings/file panel layering, Quick Search, and two-display pointer-following behavior. Scripts/window_logic_qa.sh
@@ -93,6 +93,26 @@ osascript -e 'tell application "System Events" to keystroke "w" using {command down}' } close_settings_window() { osascript <<'OSA' >/dev/null 2>&1 || true tell application "System Events" tell process "TagLauncher" repeat 20 times repeat with windowRef in windows try if (name of windowRef as text) is not "" then click button 1 of windowRef return end if end try end repeat delay 0.1 end repeat end tell end tell OSA } dismiss_reopen_dialog() { osascript <<'OSA' >/dev/null 2>&1 || true tell application "System Events" @@ -438,6 +458,20 @@ fail("TagLauncher layer \(tag[0].layer) is not above fullscreen target layer \(target.layer)") } print("PASS fullscreen overlay above target: overlayLayer=\(tag[0].layer) targetLayer=\(target.layer)") case "fullscreen-settings": guard tag.count == 2 else { fail("fullscreen settings expected 2 TagLauncher windows, got \(tag.count)") } assertTagLayer(tag) guard let target = windows.first(where: { $0.name == "TagLauncherFullscreenQATargetFullscreen" }) else { fail("fullscreen target disappeared after opening settings; TagLauncher likely switched to another Space") } guard !tag[0].name.isEmpty, tag[1].name.isEmpty else { fail("fullscreen settings order wrong: \(tag.map(\.name))") } guard tag.allSatisfy({ $0.layer > target.layer }) else { fail("TagLauncher settings stack is not above fullscreen target") } print("PASS fullscreen settings above target: tagLayers=\(tag.map(\.layer)) targetLayer=\(target.layer)") case "split-geometry": func isSingleFullscreenWindow(_ windowFrame: CGRect, on screenFrame: CGRect) -> Bool { @@ -797,6 +831,20 @@ send_main_hotkey wait_swift_assert fullscreen-overlay assert_fullscreen_overlay_stable log "==> QA fullscreen Space: quick search from appgrid does not switch Space" send_keycode 49 sleep 0.4 assert_fullscreen_overlay_stable send_keycode 53 sleep 0.3 wait_swift_assert fullscreen-overlay log "==> QA fullscreen Space: settings from appgrid does not switch Space" send_cmd_comma sleep 0.7 wait_swift_assert fullscreen-settings close_settings_window sleep 0.5 wait_swift_assert fullscreen-overlay send_keycode 53 sleep 0.4 wait_swift_assert no-overlay