diff --git a/mac/MOUSE_CLICK_DEBUG.md b/mac/MOUSE_CLICK_DEBUG.md deleted file mode 100644 index abd7b427..00000000 --- a/mac/MOUSE_CLICK_DEBUG.md +++ /dev/null @@ -1,82 +0,0 @@ -# Mouse Click Debug Guide for VibeTunnel Screen Capture - -## Problem -Mouse clicks are not working correctly in the screen capture feature. The coordinate system conversion might be incorrect. - -## Changes Made - -1. **Added Environment Variable Controls**: - - `VIBETUNNEL_FLIP_Y` - Set to "false" to disable Y-coordinate flipping - - `VIBETUNNEL_USE_WARP` - Set to "true" to use CGWarpMouseCursorPosition instead of CGEvent - -2. **Enhanced Debug Logging**: - - Extensive coordinate transformation logging - - Screen information for all displays - - Mouse position before and after moves - - Capture mode and filter information - -3. **Improved Mouse Movement**: - - Added mouse move before click (already implemented) - - Option to use CGWarpMouseCursorPosition for more direct cursor control - - Proper multi-monitor support with screen-relative Y-flipping - -## Testing Instructions - -### 1. Test Default Behavior (Y-flipping enabled) -```bash -./build/Build/Products/Debug/VibeTunnel.app/Contents/MacOS/VibeTunnel -``` - -### 2. Test Without Y-Coordinate Flipping -```bash -VIBETUNNEL_FLIP_Y=false ./build/Build/Products/Debug/VibeTunnel.app/Contents/MacOS/VibeTunnel -``` - -### 3. Test With CGWarpMouseCursorPosition -```bash -VIBETUNNEL_USE_WARP=true ./build/Build/Products/Debug/VibeTunnel.app/Contents/MacOS/VibeTunnel -``` - -### 4. Test Both Options -```bash -VIBETUNNEL_FLIP_Y=false VIBETUNNEL_USE_WARP=true ./build/Build/Products/Debug/VibeTunnel.app/Contents/MacOS/VibeTunnel -``` - -## What to Look For in Logs - -Use `./scripts/vtlog.sh -f -c ScreencapService` to monitor logs and look for: - -1. **Coordinate Transformation**: - - `🔍 [DEBUG] calculateClickLocation - Input: x=XXX, y=YYY` - - `🔍 [DEBUG] Configuration: shouldFlipY=true/false, useWarpCursor=true/false` - - `🔍 [DEBUG] Y-coordinate flipping DISABLED` (when VIBETUNNEL_FLIP_Y=false) - -2. **Mouse Position**: - - `🖱️ Current mouse position: (XXX, YYY)` - - `🖱️ [DEBUG] Mouse position after move: (XXX, YYY)` - -3. **Final Coordinates**: - - `🎯 [DEBUG] Final coordinates: x=XXX, y=YYY` - - `🔍 [DEBUG] Direct pixel coordinates (no Y-flip): x=XXX, y=YYY` - -4. **Errors**: - - `❌ [DEBUG] CGWarpMouseCursorPosition failed` - - `🔐 [DEBUG] Accessibility permission status: false` - -## Possible Issues - -1. **Accessibility Permission**: Ensure VibeTunnel has accessibility permission in System Settings > Privacy & Security > Accessibility - -2. **Coordinate Systems**: - - SCDisplay uses top-left origin (0,0 at top-left) - - NSScreen uses bottom-left origin (0,0 at bottom-left) - - The Y-flipping might not be needed if SCDisplay coordinates are already converted - -3. **Multi-Monitor**: The code now properly handles multi-monitor setups by finding which screen contains the click point - -## Next Steps - -1. Test each configuration and observe where the mouse actually clicks -2. Check if clicks work better with `VIBETUNNEL_FLIP_Y=false` -3. Compare logged coordinates with expected click positions -4. If still not working, the debug logs will show exactly what coordinates are being used \ No newline at end of file diff --git a/mac/VibeTunnel/Core/Services/Screencap/CaptureConfigurationBuilder.swift b/mac/VibeTunnel/Core/Services/Screencap/CaptureConfigurationBuilder.swift index 2974c577..bb706a9e 100644 --- a/mac/VibeTunnel/Core/Services/Screencap/CaptureConfigurationBuilder.swift +++ b/mac/VibeTunnel/Core/Services/Screencap/CaptureConfigurationBuilder.swift @@ -278,26 +278,29 @@ public final class CaptureConfigurationBuilder { return limitedDimensions } - + private func limitTo4K(width: Int, height: Int) -> (width: Int, height: Int) { - let max4KWidth = 3840 - let max4KHeight = 2160 - + let max4KWidth = 3_840 + let max4KHeight = 2_160 + // If already within 4K bounds, return as is if width <= max4KWidth && height <= max4KHeight { return (width, height) } - + // Calculate scale factor to fit within 4K bounds while maintaining aspect ratio let widthScale = Double(max4KWidth) / Double(width) let heightScale = Double(max4KHeight) / Double(height) let scale = min(widthScale, heightScale) - + let scaledWidth = Int(Double(width) * scale) let scaledHeight = Int(Double(height) * scale) - - logger.info("🔽 Scaling down from \(width)x\(height) to \(scaledWidth)x\(scaledHeight) (scale: \(String(format: "%.2f", scale)))") - + + logger + .info( + "🔽 Scaling down from \(width)x\(height) to \(scaledWidth)x\(scaledHeight) (scale: \(String(format: "%.2f", scale)))" + ) + return (width: scaledWidth, height: scaledHeight) } diff --git a/mac/VibeTunnel/Core/Services/Screencap/CoordinateTransformer.swift b/mac/VibeTunnel/Core/Services/Screencap/CoordinateTransformer.swift index 614b6af9..9718022b 100644 --- a/mac/VibeTunnel/Core/Services/Screencap/CoordinateTransformer.swift +++ b/mac/VibeTunnel/Core/Services/Screencap/CoordinateTransformer.swift @@ -288,7 +288,6 @@ public final class CoordinateTransformer { return CGPoint(x: clampedX, y: clampedY) } - } // MARK: - Helper Extensions diff --git a/mac/VibeTunnel/Core/Services/SystemPermissionManager.swift b/mac/VibeTunnel/Core/Services/SystemPermissionManager.swift index a166209d..8d53605a 100644 --- a/mac/VibeTunnel/Core/Services/SystemPermissionManager.swift +++ b/mac/VibeTunnel/Core/Services/SystemPermissionManager.swift @@ -124,20 +124,20 @@ final class SystemPermissionManager { requestPermission(permission) } } - + /// Force a permission recheck (useful when user manually changes settings) func forcePermissionRecheck() { logger.info("Force permission recheck requested") - + // Clear any cached values permissions[.accessibility] = false permissions[.screenRecording] = false permissions[.appleScript] = false - + // Immediate check Task { @MainActor in await checkAllPermissions() - + // Double-check after a delay to catch any async updates try? await Task.sleep(for: .milliseconds(500)) await checkAllPermissions() @@ -282,7 +282,7 @@ final class SystemPermissionManager { // First check the API let apiResult = AXIsProcessTrusted() logger.debug("AXIsProcessTrusted returned: \(apiResult)") - + // More comprehensive test - try to get focused application and its windows // This definitely requires accessibility permission let systemElement = AXUIElementCreateSystemWide() @@ -292,7 +292,7 @@ final class SystemPermissionManager { kAXFocusedApplicationAttribute as CFString, &focusedApp ) - + if appResult == .success, let app = focusedApp { // Try to get windows from the app - this definitely needs accessibility var windows: CFTypeRef? @@ -301,10 +301,10 @@ final class SystemPermissionManager { kAXWindowsAttribute as CFString, &windows ) - + let hasAccess = windowResult == .success logger.debug("Comprehensive accessibility test result: \(hasAccess), can get windows: \(windows != nil)") - + if hasAccess { logger.debug("Accessibility permission verified through comprehensive test") return true @@ -320,7 +320,7 @@ final class SystemPermissionManager { logger.debug("API reports true but cannot access UI elements") } } - + return false } diff --git a/mac/VibeTunnel/Presentation/Views/Settings/AdvancedSettingsView.swift b/mac/VibeTunnel/Presentation/Views/Settings/AdvancedSettingsView.swift index 8b7416fc..1d02d500 100644 --- a/mac/VibeTunnel/Presentation/Views/Settings/AdvancedSettingsView.swift +++ b/mac/VibeTunnel/Presentation/Views/Settings/AdvancedSettingsView.swift @@ -46,7 +46,7 @@ struct AdvancedSettingsView: View { .foregroundColor(.orange) Text("VT update available") .foregroundColor(.secondary) - + Button("Update") { Task { await cliInstaller.install() diff --git a/mac/VibeTunnel/Presentation/Views/Welcome/VTCommandPageView.swift b/mac/VibeTunnel/Presentation/Views/Welcome/VTCommandPageView.swift index 4ca690d6..aa658771 100644 --- a/mac/VibeTunnel/Presentation/Views/Welcome/VTCommandPageView.swift +++ b/mac/VibeTunnel/Presentation/Views/Welcome/VTCommandPageView.swift @@ -60,7 +60,7 @@ struct VTCommandPageView: View { Text("CLI tool is outdated") .foregroundColor(.secondary) } - + Button("Update VT Command Line Tool") { Task { await cliInstaller.install() diff --git a/mac/VibeTunnel/Utilities/CLIInstaller.swift b/mac/VibeTunnel/Utilities/CLIInstaller.swift index 19031fba..26146f9f 100644 --- a/mac/VibeTunnel/Utilities/CLIInstaller.swift +++ b/mac/VibeTunnel/Utilities/CLIInstaller.swift @@ -81,7 +81,7 @@ final class CLIInstaller { isInstalled = isCorrectlyInstalled logger.info("CLIInstaller: vt script installed: \(self.isInstalled)") - + // If installed, check if it's outdated if isInstalled { checkScriptVersion() @@ -265,29 +265,29 @@ final class CLIInstaller { alert.alertStyle = .critical alert.runModal() } - + // MARK: - Script Version Detection - + /// Calculates SHA256 hash of a file private func calculateHash(for filePath: String) -> String? { guard let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else { return nil } - + let hash = SHA256.hash(data: data) return hash.compactMap { String(format: "%02x", $0) }.joined() } - + /// Gets the hash of the bundled vt script private func getBundledScriptHash() -> String? { guard let scriptPath = Bundle.main.path(forResource: "vt", ofType: nil) else { logger.error("CLIInstaller: Bundled vt script not found") return nil } - + return calculateHash(for: scriptPath) } - + /// Checks if the installed script is outdated compared to bundled version func checkScriptVersion() { Task { @MainActor in @@ -295,13 +295,13 @@ final class CLIInstaller { logger.error("CLIInstaller: Failed to get bundled script hash") return } - + // Check both possible installation paths let pathsToCheck = [ vtTargetPath, "/opt/homebrew/bin/vt" ] - + var installedHash: String? for path in pathsToCheck where FileManager.default.fileExists(atPath: path) { if let hash = calculateHash(for: path) { @@ -309,9 +309,9 @@ final class CLIInstaller { break } } - + // Update outdated status - if let installedHash = installedHash { + if let installedHash { self.isOutdated = (installedHash != bundledHash) logger.info("CLIInstaller: Script version check - outdated: \(self.isOutdated)") logger.debug("CLIInstaller: Bundled hash: \(bundledHash), Installed hash: \(installedHash)") diff --git a/mac/VibeTunnel/VibeTunnelApp.swift b/mac/VibeTunnel/VibeTunnelApp.swift index 59d49a1c..68baa677 100644 --- a/mac/VibeTunnel/VibeTunnelApp.swift +++ b/mac/VibeTunnel/VibeTunnelApp.swift @@ -197,15 +197,16 @@ final class AppDelegate: NSObject, NSApplicationDelegate, @preconcurrency UNUser // Check CLI installation status let cliInstaller = CLIInstaller() cliInstaller.checkInstallationStatus() - + // Show welcome screen when version changes OR when vt script is outdated let storedWelcomeVersion = UserDefaults.standard.integer(forKey: AppConstants.UserDefaultsKeys.welcomeVersion) - + // Small delay to allow CLI check to complete DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in // Show welcome if version is different from current OR if vt script is outdated - if (storedWelcomeVersion < AppConstants.currentWelcomeVersion || cliInstaller.isOutdated) - && !isRunningInTests && !isRunningInPreview { + if (storedWelcomeVersion < AppConstants.currentWelcomeVersion || cliInstaller.isOutdated) + && !isRunningInTests && !isRunningInPreview + { self?.showWelcomeScreen() } }