### C# VNC Client Implementation Source: https://context7.com/royalapplications/royalvnc/llms.txt Demonstrates a complete C# VNC client implementation, including settings configuration, connection, event handling for authentication and state changes, framebuffer updates, input simulation, and proper disposal. Ensure the RoyalApps.RoyalVNCKit NuGet package is installed. ```csharp using RoyalApps.RoyalVNCKit; // Define settings using the IVncSettings interface readonly struct MyVncSettings : IVncSettings { public string Hostname { get; init; } public ushort Port { get; init; } public InputMode InputMode { get; init; } public ColorDepth ColorDepth { get; init; } public bool IsClipboardRedirectionEnabled { get; init; } public bool IsDebugLoggingEnabled { get; init; } public bool IsScalingEnabled { get; init; } public bool IsShared { get; init; } public bool UseDisplayLink { get; init; } public VncFrameEncodingType[]? FrameEncodings { get; init; } } class VncClient : IDisposable { private VncConnection? _connection; private VncConnectionDelegate? _delegate; public void Connect(string hostname, string password) { var settings = new MyVncSettings { Hostname = hostname, Port = 5900, IsDebugLoggingEnabled = false, IsShared = true, IsScalingEnabled = false, UseDisplayLink = false, InputMode = InputMode.None, IsClipboardRedirectionEnabled = false, ColorDepth = ColorDepth.Bits24, FrameEncodings = null // Use default encodings }; using var vncSettings = new VncSettings(settings); _connection = new VncConnection(vncSettings); // Set up event handlers _delegate = new VncConnectionDelegate(); _delegate.AuthenticationRequested = (conn, request) => { if (request.RequiresPassword) request.Password = password; if (request.RequiresUsername) request.Username = "admin"; return true; // Continue authentication }; _delegate.ConnectionStateChanged = (conn, state) => { Console.WriteLine($"Connection state: {state.Status}"); if (state.DisplayErrorToUser) Console.WriteLine($"Error: {state.ErrorDescription}"); }; _delegate.FramebufferCreated = (conn, fb) => Console.WriteLine($"Framebuffer: {fb.Width}x{fb.Height}"); _delegate.FramebufferUpdated = (conn, fb, region) => Console.WriteLine($"Updated region: {region.X},{region.Y} {region.Width}x{region.Height}"); _connection.Delegate = _delegate; _connection.Connect(); } public void SendInput() { if (_connection is null) return; // Send keyboard input _connection.SendKeyDown(KeySymbol.XK_a); _connection.SendKeyUp(KeySymbol.XK_a); // Send mouse input _connection.SendMouseMove(100, 100); _connection.SendMouseButtonDown(100, 100, MouseButton.Left); _connection.SendMouseButtonUp(100, 100, MouseButton.Left); } public void Disconnect() { _connection?.Disconnect(); } public void Dispose() { _delegate?.Dispose(); _connection?.Dispose(); } } // Usage using var client = new VncClient(); client.Connect("192.168.1.100", "password123"); // Wait for connection and interact... while (client.Status != ConnectionStatus.Disconnected) { Thread.Sleep(500); } ``` -------------------------------- ### Initiate VNC Connection Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Call VNCConnection.connect() to start the connection process asynchronously. Connection state updates are delivered to the delegate's connection(_:stateDidChange:) method. ```swift connection.connect() ``` -------------------------------- ### Initialize VNCConnection Settings Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Create an instance of VNCConnection.Settings with configuration parameters for the target host. Properties must be set in the initializer. Use .default for frameEncodings if no customization is needed. Set isDebugLoggingEnabled to true for debugging, but be aware of performance impact. ```swift let settings = VNCConnection.Settings( isDebugLoggingEnabled: true, hostname: "targethost", port: 5900, isShared: true, isScalingEnabled: true, useDisplayLink: true, inputMode: .forwardKeyboardShortcutsEvenIfInUseLocally, isClipboardRedirectionEnabled: true, colorDepth: .depth24Bit, frameEncodings: .default ) ``` -------------------------------- ### Configure VNC Connection Settings Source: https://context7.com/royalapplications/royalvnc/llms.txt Use `VNCConnection.Settings` to define connection parameters. All properties are set during initialization. Consider enabling debug logging only for troubleshooting as it impacts performance. ```swift import RoyalVNCKit // Create connection settings with full configuration let settings = VNCConnection.Settings( isDebugLoggingEnabled: false, // Enable for troubleshooting (impacts performance) hostname: "192.168.1.100", // VNC server hostname or IP port: 5900, // Standard VNC port isShared: true, // Allow other clients to connect simultaneously isScalingEnabled: true, // Enable desktop scaling to fit view useDisplayLink: true, // Use display link for smooth rendering (macOS) inputMode: .forwardKeyboardShortcutsEvenIfInUseLocally, // Forward keyboard shortcuts isClipboardRedirectionEnabled: true, // Enable clipboard sync between local and remote colorDepth: .depth24Bit, // Color depth: .depth8Bit, .depth16Bit, or .depth24Bit frameEncodings: .default // Use default encoding order: Tight, Zlib, ZRLE, Hextile, CoRRE, RRE ) // Custom frame encoding order (optional) let customSettings = VNCConnection.Settings( isDebugLoggingEnabled: false, hostname: "vnc.example.com", port: 5901, isShared: false, isScalingEnabled: false, useDisplayLink: false, inputMode: .none, isClipboardRedirectionEnabled: false, colorDepth: .depth16Bit, frameEncodings: [.tight, .zrle, .hextile] // Prioritize specific encodings ) ``` -------------------------------- ### Send Input Events to VNC Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Demonstrates how to convert characters to key codes and send keyboard and mouse input events to the remote host. ```swift // Convert the string "abc" into VNCKeyCode's let keyCodes = VNCKeyCode.keyCodesFrom(characters: "abc") // Press keys required for printing "abc" for keyCode in keyCodes { connection.keyDown(keyCode) connection.keyUp(keyCode) } // Press return/enter key connection.keyDown(.return) connection.keyUp(.return) // Press Left Mouse Button at x: 10, y: 15 connection.mouseButtonDown(.left, x: 10, y: 15) connection.mouseButtonUp(.left, x: 10, y: 15) ``` -------------------------------- ### Implement VNCCAFramebufferView in a macOS View Controller Source: https://context7.com/royalapplications/royalvnc/llms.txt Demonstrates setting up a VNC connection and initializing the VNCCAFramebufferView within an NSViewController. ```swift #if os(macOS) import AppKit import RoyalVNCKit class VNCViewController: NSViewController, VNCConnectionDelegate { private var connection: VNCConnection? private var framebufferView: VNCCAFramebufferView? func setupConnection() { let settings = VNCConnection.Settings( isDebugLoggingEnabled: false, hostname: "192.168.1.50", port: 5900, isShared: true, isScalingEnabled: true, useDisplayLink: true, inputMode: .forwardKeyboardShortcutsEvenIfInUseLocally, isClipboardRedirectionEnabled: true, colorDepth: .depth24Bit, frameEncodings: .default ) connection = VNCConnection(settings: settings) connection?.delegate = self connection?.connect() } // VNCConnectionDelegate - handle framebuffer creation func connection(_ connection: VNCConnection, didCreateFramebuffer framebuffer: VNCFramebuffer) { DispatchQueue.main.async { [weak self] in guard let self = self else { return } // Create the framebuffer view with Metal rendering let fbView = VNCCAFramebufferView( frame: self.view.bounds, framebuffer: framebuffer, connection: connection, connectionDelegate: self // Forward other delegate calls to us ) // Add to view hierarchy fbView.autoresizingMask = [.width, .height] self.view.addSubview(fbView) self.framebufferView = fbView // Make it first responder for keyboard input self.view.window?.makeFirstResponder(fbView) } } // VNCConnectionDelegate - other required methods func connection(_ connection: VNCConnection, stateDidChange connectionState: VNCConnection.ConnectionState) { print("State: \(connectionState.status)") } func connection(_ connection: VNCConnection, credentialFor authenticationType: VNCAuthenticationType, completion: @escaping (VNCCredential?) -> Void) { let credential = VNCPasswordCredential(password: "mypassword") completion(credential) } func connection(_ connection: VNCConnection, didResizeFramebuffer framebuffer: VNCFramebuffer) {} func connection(_ connection: VNCConnection, didUpdateFramebuffer framebuffer: VNCFramebuffer, x: UInt16, y: UInt16, width: UInt16, height: UInt16) {} func connection(_ connection: VNCConnection, didUpdateCursor cursor: VNCCursor) {} } #endif ``` -------------------------------- ### Handle Framebuffer Creation Source: https://context7.com/royalapplications/royalvnc/llms.txt This callback is invoked when the VNC server creates the initial framebuffer. Use this to set up your view for displaying the remote desktop. ```swift // Called when framebuffer is created (initial connection) func connection(_ connection: VNCConnection, didCreateFramebuffer framebuffer: VNCFramebuffer) { print("Framebuffer created: \(framebuffer.size.width)x\(framebuffer.size.height)") // Create your view to display the framebuffer } ``` -------------------------------- ### Create VNCConnection Instance Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Instantiate VNCConnection using the previously created settings. It is crucial to maintain a strong reference to the connection object. ```swift let connection = VNCConnection(settings: settings) self.connection = connection // Keep a strong reference ``` -------------------------------- ### Manage VNC Connection Lifecycle Source: https://context7.com/royalapplications/royalvnc/llms.txt The `VNCConnection` class handles VNC session management. Instantiate it with settings, assign a delegate for callbacks, and call `connect()` to initiate the session. Disconnection is asynchronous. ```swift import RoyalVNCKit class VNCClientManager { private var connection: VNCConnection? func startConnection() { let settings = VNCConnection.Settings( isDebugLoggingEnabled: false, hostname: "server.local", port: 5900, isShared: true, isScalingEnabled: true, useDisplayLink: true, inputMode: .forwardKeyboardShortcutsEvenIfInUseLocally, isClipboardRedirectionEnabled: true, colorDepth: .depth24Bit, frameEncodings: .default ) // Create connection and keep strong reference let connection = VNCConnection(settings: settings) self.connection = connection // Assign delegate for callbacks connection.delegate = self // Initiate connection asynchronously connection.connect() } func stopConnection() { // Disconnect is asynchronous - wait for delegate callback connection?.disconnect() } } ``` -------------------------------- ### Handle VNC Connection State Changes Source: https://context7.com/royalapplications/royalvnc/llms.txt Implement this method to react to different connection states like connecting, connected, disconnecting, and disconnected. It includes error handling for disconnections and cleans up resources upon disconnection. ```swift import RoyalVNCKit extension VNCClientManager: VNCConnectionDelegate { // Called when connection state changes (connecting, connected, disconnecting, disconnected) func connection(_ connection: VNCConnection, stateDidChange connectionState: VNCConnection.ConnectionState) { switch connectionState.status { case .connecting: print("Connecting to VNC server...") case .connected: print("Successfully connected!") case .disconnecting: print("Disconnecting...") case .disconnected: if let error = connectionState.error as? VNCError, error.shouldDisplayToUser { print("Disconnected with error: \(error.localizedDescription)") } else { print("Disconnected") } // Clean up - don't reuse the connection self.connection?.delegate = nil self.connection = nil } } ``` -------------------------------- ### Handle VNC Authentication Requests Source: https://context7.com/royalapplications/royalvnc/llms.txt Implement this method to provide credentials when the VNC server requires authentication. It supports different authentication types, including username/password and standard password. ```swift // Called when authentication is required func connection(_ connection: VNCConnection, credentialFor authenticationType: VNCAuthenticationType, completion: @escaping (VNCCredential?) -> Void) { // Determine what credentials are needed if authenticationType.requiresUsername { // Apple Remote Desktop or UltraVNC MS-Logon II let credential = VNCUsernamePasswordCredential( username: "admin", password: "secretPassword" ) completion(credential) } else if authenticationType.requiresPassword { // Standard VNC password authentication let credential = VNCPasswordCredential(password: "vncPassword") completion(credential) } else { // No authentication required completion(nil) } } ``` -------------------------------- ### Handle VNC Errors Source: https://context7.com/royalapplications/royalvnc/llms.txt Demonstrates categorizing and responding to protocol, authentication, and connection errors using VNCError. ```swift import RoyalVNCKit extension VNCClientManager { func handleConnectionError(_ error: Error) { guard let vncError = error as? VNCError else { print("Unknown error: \(error.localizedDescription)") return } // Check if error should be shown to user if vncError.shouldDisplayToUser { displayErrorAlert(vncError) } // Handle specific error types switch vncError { case .protocol(let protocolError): print("Protocol error: \(protocolError)") // Handle protocol-level issues (unsupported features, invalid messages) case .authentication(let authError): print("Authentication failed: \(authError)") // Prompt user to re-enter credentials if vncError.isAuthenticationError { promptForCredentials() } case .connection(let connectionError): print("Connection error: \(connectionError)") // Handle network issues, timeouts, server disconnects } } func displayErrorAlert(_ error: VNCError) { let message = error.localizedDescription ?? "An unknown error occurred" print("Error to display: \(message)") // Show alert dialog to user } func promptForCredentials() { // Show credential input dialog print("Please enter your credentials again") } } ``` -------------------------------- ### Handle VNC Authentication Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Determines the required credential type based on the authentication configuration and provides the necessary credentials. ```swift if authenticationType.requiresUsername { // TODO: Ask user to provide credential data credential = VNCUsernamePasswordCredential(username: "MyUser", password: "MyPass") } else if authenticationType.requiresPassword { // TODO: Ask user to provide credential data credential = VNCPasswordCredential(password: "MyPass") } else { credential = nil } completion(credential) } ``` -------------------------------- ### Send Keyboard Input with Royal VNC SDK Source: https://context7.com/royalapplications/royalvnc/llms.txt Use `keyDown()` and `keyUp()` with `VNCKeyCode` to send keyboard input. The SDK can convert character strings to key codes. Ensure a connection is established before sending input. ```swift import RoyalVNCKit extension VNCClientManager { // Type a string of characters func typeText(_ text: String) { guard let connection = connection else { return } let keyCodes = VNCKeyCode.keyCodesFrom(characters: text) for keyCode in keyCodes { connection.keyDown(keyCode) connection.keyUp(keyCode) } } // Send special key combinations func sendCtrlAltDelete() { guard let connection = connection else { return } // Press modifier keys connection.keyDown(.control) connection.keyDown(.option) // Alt key connection.keyDown(.forwardDelete) // Release in reverse order connection.keyUp(.forwardDelete) connection.keyUp(.option) connection.keyUp(.control) } // Send individual special keys func sendSpecialKeys() { guard let connection = connection else { return } // Send Enter/Return connection.keyDown(.return) connection.keyUp(.return) // Send Escape connection.keyDown(.escape) connection.keyUp(.escape) // Send Tab connection.keyDown(.tab) connection.keyUp(.tab) // Send Arrow keys connection.keyDown(.leftArrow) connection.keyUp(.leftArrow) connection.keyDown(.upArrow) connection.keyUp(.upArrow) // Send Function keys connection.keyDown(.f1) connection.keyUp(.f1) // Send with modifier (Ctrl+C for copy) connection.keyDown(.control) connection.keyDown(VNCKeyCode(UInt32(Character("c").asciiValue!))) connection.keyUp(VNCKeyCode(UInt32(Character("c").asciiValue!))) connection.keyUp(.control) } } ``` -------------------------------- ### Implement VNCConnectionDelegate Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Assign an implementation of VNCConnectionDelegate to receive notifications for connection state changes and framebuffer updates. A delegate is essential for authentication; without it, connections may fail unless no authentication is required. ```swift connection.delegate = self extension MyConnectionController: VNCConnectionDelegate { func connection(_ connection: VNCConnection, stateDidChange connectionState: VNCConnection.ConnectionState) { // TODO: Update/show/hide progress indicator depending on connectionState.status // TODO: Destroy framebuffer view and disconnect delegate if the connection was closed } func connection(_ connection: VNCConnection, credentialFor authenticationType: VNCAuthenticationType, completion: @escaping (VNCCredential?) -> Void) { // TODO: Provide credential for authenticationType completion(nil) } func connection(_ connection: VNCConnection, didCreateFramebuffer framebuffer: VNCFramebuffer) { // TODO: Create a framebuffer view and add it to the view hierarchy } func connection(_ connection: VNCConnection, didResizeFramebuffer framebuffer: VNCFramebuffer) { // TODO: Resize your previously created framebuffer view } func connection(_ connection: VNCConnection, didUpdateFramebuffer framebuffer: VNCFramebuffer, x: UInt16, y: UInt16, width: UInt16, height: UInt16) { // TODO: Update the image in your framebuffer view } func connection(_ connection: VNCConnection, didUpdateCursor cursor: VNCCursor) { // TODO: Update the local cursor shown in the framebuffer view } } ``` -------------------------------- ### Handle VNC Authentication Credentials Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Implement the connection(_:credentialFor:completion:) delegate method to provide user credentials for the specified VNCAuthenticationType. Pass nil to the completion handler to cancel authentication. Use convenience extensions like requiresUsername and requiresPassword to determine required data. ```swift func connection(_ connection: VNCConnection, credentialFor authenticationType: VNCAuthenticationType, completion: @escaping (VNCCredential?) -> Void) { let credential: VNCCredential? ``` -------------------------------- ### Handle Framebuffer Resizing Source: https://context7.com/royalapplications/royalvnc/llms.txt Called when the remote desktop's framebuffer is resized. Update your display view to match the new dimensions. ```swift // Called when remote desktop is resized func connection(_ connection: VNCConnection, didResizeFramebuffer framebuffer: VNCFramebuffer) { print("Framebuffer resized to: \(framebuffer.size.width)x\(framebuffer.size.height)") // Resize your display view } ``` -------------------------------- ### Handle VNC Authentication Types in Swift Source: https://context7.com/royalapplications/royalvnc/llms.txt Implement the `connection(_:credentialFor:completion:)` delegate method to provide credentials based on the requested `VNCAuthenticationType`. Use `VNCPasswordCredential` for standard VNC passwords and `VNCUsernamePasswordCredential` for types requiring usernames. ```swift import RoyalVNCKit func connection(_ connection: VNCConnection, credentialFor authenticationType: VNCAuthenticationType, completion: @escaping (VNCCredential?) -> Void) { switch authenticationType { case .vnc: // Standard VNC authentication - password only // requiresUsername: false, requiresPassword: true let credential = VNCPasswordCredential(password: getStoredPassword()) completion(credential) case .appleRemoteDesktop: // Apple Remote Desktop - username and password required // requiresUsername: true, requiresPassword: true let credential = VNCUsernamePasswordCredential( username: getStoredUsername(), password: getStoredPassword() ) completion(credential) case .ultraVNCMSLogonII: // UltraVNC MS-Logon II - username and password required // requiresUsername: true, requiresPassword: true let credential = VNCUsernamePasswordCredential( username: getDomainUsername(), // e.g., "DOMAIN\user" password: getStoredPassword() ) completion(credential) } // To cancel authentication, pass nil // completion(nil) } ``` ```swift // Helper to check credential requirements func promptForCredentials(authenticationType: VNCAuthenticationType) { if authenticationType.requiresUsername { print("Username required") } if authenticationType.requiresPassword { print("Password required") } } ``` -------------------------------- ### Send Mouse Input with Royal VNC SDK Source: https://context7.com/royalapplications/royalvnc/llms.txt Control the remote mouse using methods for button clicks, movement, and scrolling. Mouse positions are specified in framebuffer coordinates. Ensure a connection is established before sending input. ```swift import RoyalVNCKit extension VNCClientManager { // Move mouse to position func moveMouse(x: UInt16, y: UInt16) { connection?.mouseMove(x: x, y: y) } // Left click at position func leftClick(x: UInt16, y: UInt16) { guard let connection = connection else { return } connection.mouseButtonDown(.left, x: x, y: y) connection.mouseButtonUp(.left, x: x, y: y) } // Right click at position func rightClick(x: UInt16, y: UInt16) { guard let connection = connection else { return } connection.mouseButtonDown(.right, x: x, y: y) connection.mouseButtonUp(.right, x: x, y: y) } // Middle click func middleClick(x: UInt16, y: UInt16) { guard let connection = connection else { return } connection.mouseButtonDown(.middle, x: x, y: y) connection.mouseButtonUp(.middle, x: x, y: y) } // Double click func doubleClick(x: UInt16, y: UInt16) { leftClick(x: x, y: y) leftClick(x: x, y: y) } // Drag operation (click and hold while moving) func drag(from startX: UInt16, startY: UInt16, to endX: UInt16, endY: UInt16) { guard let connection = connection else { return } connection.mouseButtonDown(.left, x: startX, y: startY) connection.mouseMove(x: endX, y: endY) connection.mouseButtonUp(.left, x: endX, y: endY) } // Scroll wheel func scroll(x: UInt16, y: UInt16, direction: VNCMouseWheel, steps: UInt32 = 3) { guard let connection = connection else { return } connection.mouseWheel(direction, x: x, y: y, steps: steps) } // Scroll up func scrollUp(x: UInt16, y: UInt16) { scroll(x: x, y: y, direction: .up, steps: 3) } // Scroll down func scrollDown(x: UInt16, y: UInt16) { scroll(x: x, y: y, direction: .down, steps: 3) } } ``` -------------------------------- ### Handle Cursor Updates Source: https://context7.com/royalapplications/royalvnc/llms.txt Called when the remote cursor image changes. Use this to update the local cursor display if needed. ```swift // Called when cursor image changes func connection(_ connection: VNCConnection, didUpdateCursor cursor: VNCCursor) { if !cursor.isEmpty, let cgImage = cursor.cgImage { // Update local cursor display print("Cursor updated: \(cursor.size.width)x\(cursor.size.height)") } } } ``` -------------------------------- ### Handle Framebuffer Updates Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Implements the delegate method to update the view layer with the latest framebuffer image. ```swift func connection(_ connection: VNCConnection, didUpdateFramebuffer framebuffer: VNCFramebuffer, x: UInt16, y: UInt16, width: UInt16, height: UInt16) { // TODO: Only invalidate the part of the image that was updated, indicated by the x, y, width and height parameters self.view.layer?.contents = framebuffer.cgImage } ``` -------------------------------- ### Disconnect VNC Connection Source: https://github.com/royalapplications/royalvnc/blob/main/USAGE.md Initiates an asynchronous disconnection and handles the state change delegate method to clean up resources. ```swift // Begin disconnection, wait for response in connection(_:stateDidChange:) self.connection.disconnect() func connection(_ connection: VNCConnection, stateDidChange connectionState: VNCConnection.ConnectionState) { if connectionState.status == .disconnected { self.connection.delegate = nil // TODO: Destroy framebuffer view if let error = connectionState.error as? VNCError, error.shouldDisplayToUser { // TODO: Present error to the user } } } ``` -------------------------------- ### Access VNC Framebuffer Data Source: https://context7.com/royalapplications/royalvnc/llms.txt Provides methods to retrieve framebuffer images, inspect display properties, and process raw pixel data. ```swift import RoyalVNCKit #if os(macOS) import AppKit #endif extension VNCClientManager { // Get framebuffer as CGImage (cross-platform Apple) func getFramebufferImage() -> CGImage? { return connection?.framebuffer?.cgImage } // Get framebuffer properties func printFramebufferInfo() { guard let framebuffer = connection?.framebuffer else { return } print("Size: \(framebuffer.size.width) x \(framebuffer.size.height)") print("Color Depth: \(framebuffer.colorDepth)") print("Byte Count: \(framebuffer.surfaceByteCount)") print("Number of Screens: \(framebuffer.screens.count)") // Screen information for multi-monitor setups for screen in framebuffer.screens { print("Screen \(screen.id): \(screen.frame)") } } #if os(macOS) // Get as NSImage for macOS func getFramebufferNSImage() -> NSImage? { return connection?.framebuffer?.nsImage } // Render to a CALayer func renderToLayer(_ layer: CALayer) { if let cgImage = connection?.framebuffer?.cgImage { layer.contents = cgImage } } #endif // Access raw pixel data (for custom rendering pipelines) func processRawPixelData() { guard let framebuffer = connection?.framebuffer else { return } // Get RGBA32 pixel data var pixelDataSize = 0 let rgbaData = framebuffer.copyPixelDataToRGBA32(pixelDataSize: &pixelDataSize) // Process the pixel data... // Data is in RGBA format, 4 bytes per pixel // Don't forget to free the memory when done framebuffer.destroyRGBA32PixelData(rgbaData) } } ``` -------------------------------- ### Handle Framebuffer Updates Source: https://context7.com/royalapplications/royalvnc/llms.txt This method is called when a portion of the framebuffer is updated. Optimize rendering by only redrawing the changed region, or redraw the entire framebuffer for simpler implementations. ```swift // Called when a region of the framebuffer is updated func connection(_ connection: VNCConnection, didUpdateFramebuffer framebuffer: VNCFramebuffer, x: UInt16, y: UInt16, width: UInt16, height: UInt16) { // Update display - can optimize by only redrawing the updated region // For simple implementations, redraw the entire framebuffer: if let cgImage = framebuffer.cgImage { // Display cgImage in your view DispatchQueue.main.async { self.displayView?.layer?.contents = cgImage } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.