| 969 | } |
| 970 | |
| 971 | bool ManagerService::SendKeyEvent(const std::string& vm_id, uint32_t key_code, bool pressed) { |
| 972 | // try_lock: these are called from WndProc which can be re-entered while |
| 973 | // the UI thread holds vms_mutex_ (e.g. WM_ACTIVATEAPP during WaitForSingleObject). |
| 974 | std::unique_lock<std::mutex> lock(vms_mutex_, std::try_to_lock); |
| 975 | if (!lock.owns_lock()) return false; |
| 976 | VmRecord* vm = FindVm(vm_id); |
| 977 | if (!vm) return false; |
| 978 | |
| 979 | ipc::Message msg; |
| 980 | msg.channel = ipc::Channel::kInput; |
| 981 | msg.kind = ipc::Kind::kRequest; |
| 982 | msg.type = "input.key_event"; |
| 983 | msg.vm_id = vm_id; |
| 984 | msg.request_id = GetTickCount64(); |
| 985 | msg.fields["key_code"] = std::to_string(key_code); |
| 986 | msg.fields["pressed"] = pressed ? "1" : "0"; |
| 987 | return SendRuntimeMessage(*vm, msg); |
| 988 | } |
| 989 | |
| 990 | bool ManagerService::SendPointerEvent(const std::string& vm_id, |
| 991 | int32_t x, int32_t y, uint32_t buttons) { |