# Remote control The remote control feature allows someone to take control of another user's screen in a session when given permission. A user can either request remote control of another user's screen or the other user can give it to them. Once given permission, a user can control the other user's mouse and keyboard, and even copy text from their screen. > **Note:** Since this enables remote control of a user's screen, it is your responsibility as the developer to inform the user of the permission they're giving to the person who can remote control their screen. This includes all notices, consents, and a well-defined user experience. ## Prerequisites - Set up [screen sharing](/docs/video-sdk/macos/share/). You must configure screen sharing in order for remote control to work. - Turn on remote control on the web portal. Go to **Account Settings**, **In Session (Basic)**, and toggle the **Remote control** option on. Optionally select the **Allow remote controlling user to share clipboard** option. - Before starting, check whether controllers can request (`canRequestControl`) and users can start remote control. ## Remote Control Flow 1. On the requester side, identify the remote user (`ZMVideoSDKUser`) to have remote control over, check for request access, and request for access. ```swift let user: ZMVideoSDKUser; // Get the user you want to remote control of let shareActionList = user.getShareActionList() // The shareActionList can contain 0 to multiple shares coming from the selected user if let shareActionList = shareActionList, shareActionList.count > 0 { // Get the share you want - Example the first share let shareAction = shareActionList[0] if shareAction.getRemoteControlHelper().canRequestControl() { shareAction.getRemoteControlHelper().requestRemoteControl() } } ``` ```objectivec ZMVideoSDKUser* user; // Get the user you want to remote control of NSArray* shareActionList = [user getShareActionList]; // The shareActionList can contain 0 to multiple share coming from the selected user if (shareActionList.count > 0) { // Get the share you want - Example the first share ZMVideoSDKShareAction* shareAction = [shareActionList objectAtIndex:0]; if ([[shareAction getRemoteControlHelper] canRequestControl]) { [[shareAction getRemoteControlHelper] requestRemoteControl]; } } ``` 2. The requester will then get the `onRemoteControlRequestReceived` callback within the `ZMVideoSDKDelegate` class. From this callback, the approver will get the user requesting for remote control access and also the `ZMVideoSDKRemoteControlRequestHandler`, which the SDK will use to either approve or deny the request. If the approver denied the request, the requester can request again. > **Note**: For macOS, the approver must give their application access in the **Accessibility** tab in the **Privacy and Security** preferences of their Mac. ```swift func onRemoteControlRequestReceived(user: ZMVideoSDKUser, handler: ZMVideoSDKRemoteControlRequestHandler) { handler.approve() // OR handler.deny() } ``` ```objectivec - (void)onRemoteControlRequestReceived:(ZMVideoSDKUser *)user shareAction:(ZMVideoSDKShareAction *)shareAction handler:(ZMVideoSDKRemoteControlRequestHandler *)handler { [handler approve]; // OR [handler deny]; } ``` 3. Both the requestor and approver will receive an `onRemoteControlStatus` callback under the `ZMVideoSDKDelegate` class on the request status. With a `CanRequestControl` callback status on the requestor side, check if `canRemoteControl` is `true` and `isRemoteControlling` is `false` before starting remote control. ```swift let remoteControlHelper = shareAction.getRemoteControlHelper() if remoteControlHelper.canRemoteControl() && !remoteControlHelper.isRemoteControlling() { remoteControlHelper.enterRemoteControl() } ``` ```objectivec ZMVideoSDKRemoteControlHelper* remoteControlHelper = [shareAction getRemoteControlHelper]; if ([remoteControlHelper canRemoteControl] && ![remoteControlHelper isRemoteControlling]) { [remoteControlHelper enterRemoteControl]; } ``` 4. After entering remote control status, the requestor can choose to temporarily pause remote control using `leaveRemoteControl` and enter again later on with `enterRemoteControl`, or to end it with `endRemoteControl`. Whereas the approver can also choose to get the list of approved users using `getRemoteControlApprovedUserList` or to revoke all the approved user using `revokeRemoteControl`. ```swift // Requestor remoteControlHelper.leaveRemoteControl() remoteControlHelper.endRemoteControl() // Approver - These methods are only available for the local user themselves. shareAction.getRemoteControlApprovedUserList() shareAction.revokeRemoteControl() ``` ```objectivec // Requestor [remoteControlHelper leaveRemoteControl]; [remoteControlHelper endRemoteControl]; // Approver - These methods are only available for the local user themselves. [shareAction getRemoteControlApprovedUserList] [shareAction revokeRemoteControl]; ``` ## Callbacks There are 2 callbacks related to remote control access under the `ZMVideoSDKDelegate` class. 1. `onRemoteControlRequestReceived`: Triggered when a remote user requests to remote control the local user. ```swift func onRemoteControlRequestReceived(user: ZMVideoSDKUser, shareAction: ZMVideoSDKShareAction, handler: ZMVideoSDKRemoteControlRequestHandler) { handler.approve() // OR handler.deny() } ``` ```objectivec - (void)onRemoteControlRequestReceived:(ZMVideoSDKUser *)user handler:(ZMVideoSDKRemoteControlRequestHandler *)handler { [handler approve]; // OR [handler deny]; } ``` 2. `onRemoteControlStatus`: Triggered when the remote control status changes. This applies to the local user either requesting remote control, controlling the remote user, or is being controlled by a remote user. **`ZMVideoSDKRemoteControlStatus Enum`** ```objectivec None // For initialization CanRequestControl // Local user can enable the remote control RequestDenied // Local user have received a refused of remote control GotControl // Local user got control when remote control begins LostControl // Local user lost control when remote control ends ControlStart // Local user start controlling remotely another user ControlStop // Local user stop controlling remotely another user GiveControlTo // Local user gave remote control access to an user ControlRevoked // Local user revoked remote control access to an user ControlledBy // Local user is being remotely controlled by an user NotControlled // Local user is not remotely controlled by an user ``` ```swift func onRemoteControlStatus(status: ZMVideoSDKRemoteControlStatus, user: ZMVideoSDKUser, shareAction: ZMVideoSDKShareAction) {} ``` ```objectivec - (void)onRemoteControlStatus:(ZMVideoSDKRemoteControlStatus)status user:(ZMVideoSDKUser *)user shareAction:(ZMVideoSDKShareAction *)shareAction ```