* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "inputEventClient.h"
#include <map>
#include <memory>
#include <thread>
#include <chrono>
#include <sstream>
#include <iostream>
#include <mutex>
#include "define_multimodal.h"
#include "input_manager.h"
#include "input_event.h"
#include "ipc_skeleton.h"
#include "key_event.h"
#include "mmi_api_metrics_histograms.h"
#include "mmi_log.h"
#include "oh_input_manager.h"
#include "ohos.multimodalInput.inputEventClient.proj.hpp"
#include "ohos.multimodalInput.inputEventClient.impl.hpp"
#include "pointer_event.h"
#include "stdexcept"
#include "taihe/runtime.hpp"
#include "accesstoken_kit.h"
#include "tokenid_kit.h"
#include "ani_common.h"
#include "mouse_controller_impl.h"
#include "keyboard_controller_impl.h"
#include "touch_controller_impl.h"
#include "ohos.multimodalInput.mouseEvent.impl.h"
#include "ohos.multimodalInput.keyCode.impl.h"
#undef MMI_LOG_TAG
#define MMI_LOG_TAG "aniInputEventClient"
using namespace taihe;
using namespace ohos::multimodalInput::inputEventClient;
using namespace OHOS::MMI;
using TaiheError_t = OHOS::MMI::TaiheError;
namespace {
const std::string INJECT_INPUT_PERMISSION_NAME = "ohos.permission.INJECT_INPUT_EVENT";
const std::string MODULE_NAME = "inputEventClient";
enum class MouseControllerOperation {
CREATE,
MOVE_TO,
PRESS_BUTTON,
RELEASE_BUTTON,
BEGIN_AXIS,
UPDATE_AXIS,
END_AXIS,
};
enum class KeyboardControllerOperation {
CREATE,
PRESS_KEY,
RELEASE_KEY,
};
enum class TouchControllerOperation {
CREATE,
DOWN,
MOVE,
UP,
};
void SetMouseControllerBusinessError(int32_t errorCode, MouseControllerOperation operation);
void SetKeyboardControllerBusinessError(int32_t errorCode, KeyboardControllerOperation operation);
void SetTouchControllerBusinessError(int32_t errorCode, TouchControllerOperation operation);
std::string MakePermissionCheckErrMsg(const std::string &moduleName,
const std::string &permissionName)
{
std::stringstream ss;
ss << "Permission denied. An attempt was made to " <<
moduleName << " forbidden by permission:" <<
permissionName << ".";
return ss.str();
}
bool IsSystemApp()
{
static bool isSystemApp = []() {
uint64_t tokenId = OHOS::IPCSkeleton::GetSelfTokenID();
return OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
}();
return isSystemApp;
}
bool CheckPermission(const std::string &permissionCode)
{
uint64_t tokenId = OHOS::IPCSkeleton::GetSelfTokenID();
using OHOS::Security::AccessToken::AccessTokenID;
auto tokenType = OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(static_cast<AccessTokenID>(tokenId));
if ((tokenType == OHOS::Security::AccessToken::TOKEN_HAP) ||
(tokenType == OHOS::Security::AccessToken::TOKEN_NATIVE)) {
int32_t ret = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, permissionCode);
if (ret != OHOS::Security::AccessToken::PERMISSION_GRANTED) {
MMI_HILOGE("Check permission failed ret:%{public}d permission:%{public}s", ret, permissionCode.c_str());
return false;
}
MMI_HILOGD("Check interceptor permission success permission:%{public}s", permissionCode.c_str());
return true;
} else if (tokenType == OHOS::Security::AccessToken::TOKEN_SHELL) {
MMI_HILOGI("Token type is shell");
return true;
} else {
MMI_HILOGE("Unsupported token type:%{public}d", tokenType);
return false;
}
}
bool CheckInputEventClentPermission(std::function<void(int32_t)> histogramError)
{
if (!IsSystemApp()) {
taihe::set_business_error(COMMON_USE_SYSAPI_ERROR, "Non system applications use system API");
histogramError(COMMON_USE_SYSAPI_ERROR);
return false;
}
if (!CheckPermission(INJECT_INPUT_PERMISSION_NAME)) {
std::string errMsg = MakePermissionCheckErrMsg(MODULE_NAME, INJECT_INPUT_PERMISSION_NAME);
taihe::set_business_error(COMMON_PERMISSION_CHECK_ERROR, errMsg);
histogramError(COMMON_PERMISSION_CHECK_ERROR);
return false;
}
return true;
}
int32_t ConvertTaiheAxisToNative(::ohos::multimodalInput::mouseEvent::Axis axis) {
static const std::map<int32_t, int32_t> AXIS_MAP = {
{ static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Axis::key_t::SCROLL_VERTICAL),
static_cast<int32_t>(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL) },
{ static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Axis::key_t::SCROLL_HORIZONTAL),
static_cast<int32_t>(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL) },
{ static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Axis::key_t::PINCH),
static_cast<int32_t>(PointerEvent::AXIS_TYPE_PINCH) }
};
int32_t axisValue = static_cast<int32_t>(axis);
auto it = AXIS_MAP.find(axisValue);
if (it != AXIS_MAP.end()) {
return it->second;
}
MMI_HILOGW("Unknown Taihe axis: %{public}d, using as-is", axisValue);
return axisValue;
}
bool IsValidEtsButton(::ohos::multimodalInput::mouseEvent::Button button)
{
int32_t buttonValue = static_cast<int32_t>(button);
return (buttonValue >= static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Button::key_t::LEFT) &&
buttonValue <= static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Button::key_t::TASK));
}
bool IsValidEtsAxis(::ohos::multimodalInput::mouseEvent::Axis axis)
{
int32_t axisValue = static_cast<int32_t>(axis);
return (axisValue >= static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Axis::key_t::SCROLL_VERTICAL) &&
axisValue <= static_cast<int32_t>(::ohos::multimodalInput::mouseEvent::Axis::key_t::PINCH));
}
static std::unordered_map<int32_t, int32_t> THMouseButton2Native = {
{ JS_MOUSE_BUTTON_LEFT, PointerEvent::MOUSE_BUTTON_LEFT },
{ JS_MOUSE_BUTTON_RIGHT, PointerEvent::MOUSE_BUTTON_RIGHT },
{ JS_MOUSE_BUTTON_MIDDLE, PointerEvent::MOUSE_BUTTON_MIDDLE },
{ JS_MOUSE_BUTTON_SIDE, PointerEvent::MOUSE_BUTTON_SIDE },
{ JS_MOUSE_BUTTON_EXTRA, PointerEvent::MOUSE_BUTTON_EXTRA },
{ JS_MOUSE_BUTTON_FORWARD, PointerEvent::MOUSE_BUTTON_FORWARD },
{ JS_MOUSE_BUTTON_BACK, PointerEvent::MOUSE_BUTTON_BACK },
{ JS_MOUSE_BUTTON_TASK, PointerEvent::MOUSE_BUTTON_TASK }
};
#ifdef OHOS_BUILD_ENABLE_VKEYBOARD
void GetInjectionEventDataNative(Input_KeyEvent* keyEventNative,
::ohos::multimodalInput::inputEventClient::KeyEvent const& thKeyEvent,
std::function<void(int32_t)> histogramError)
{
if (thKeyEvent.keyCode < 0) {
set_business_error(INPUT_PARAMETER_ERROR, "keyCode must be greater than or equal to 0");
histogramError(INPUT_PARAMETER_ERROR);
return;
}
if (thKeyEvent.keyDownDuration < 0) {
MMI_HILOGE("keyDownDuration:%{public}d is less 0, can not process", thKeyEvent.keyDownDuration);
set_business_error(INPUT_PARAMETER_ERROR, "keyDownDuration must be greater than or equal to 0");
histogramError(INPUT_PARAMETER_ERROR);
return;
}
auto keyAction = thKeyEvent.isPressed ? Input_KeyEventAction::KEY_ACTION_DOWN : Input_KeyEventAction::KEY_ACTION_UP;
OH_Input_SetKeyEventAction(keyEventNative, keyAction);
OH_Input_SetKeyEventKeyCode(keyEventNative, thKeyEvent.keyCode);
OH_Input_SetKeyEventActionTime(keyEventNative, static_cast<int64_t>(thKeyEvent.keyDownDuration));
Input_Result result = static_cast<Input_Result>(OH_Input_InjectKeyEvent(keyEventNative));
if (result != INPUT_SUCCESS) {
MMI_HILOGE("OH_Input_InjectKeyEvent error");
}
}
#else
void GetInjectionEventData(std::shared_ptr<OHOS::MMI::KeyEvent> keyEventNative,
::ohos::multimodalInput::inputEventClient::KeyEvent const& thKeyEvent,
std::function<void(int32_t)> histogramError)
{
if (keyEventNative == nullptr) {
MMI_HILOGE("keyEventNative is null");
return;
}
if (thKeyEvent.keyDownDuration < 0) {
MMI_HILOGE("keyDownDuration value is invalid.value:%{public}d", thKeyEvent.keyDownDuration);
set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.");
histogramError(INPUT_PARAMETER_ERROR);
return;
}
if (thKeyEvent.keyCode < 0) {
MMI_HILOGE("keyCode value is invalid, can not process");
set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.");
histogramError(INPUT_PARAMETER_ERROR);
return;
}
keyEventNative->SetRepeat(true);
keyEventNative->AddFlag(OHOS::MMI::InputEvent::EVENT_FLAG_NO_INTERCEPT);
keyEventNative->SetKeyCode(thKeyEvent.keyCode);
auto keyAction = thKeyEvent.isPressed ? OHOS::MMI::KeyEvent::KEY_ACTION_DOWN : OHOS::MMI::KeyEvent::KEY_ACTION_UP;
keyEventNative->SetKeyAction(keyAction);
OHOS::MMI::KeyEvent::KeyItem item;
item.SetKeyCode(thKeyEvent.keyCode);
item.SetPressed(thKeyEvent.isPressed);
item.SetDownTime(static_cast<int64_t>(thKeyEvent.keyDownDuration));
keyEventNative->AddKeyItem(item);
InputManager::GetInstance()->SimulateInputEvent(keyEventNative);
std::this_thread::sleep_for(std::chrono::milliseconds(thKeyEvent.keyDownDuration));
}
#endif
void InjectKeyEventSync(::ohos::multimodalInput::inputEventClient::KeyEventData const& keyEvent)
{
MMI_HISTOGRAM_BOOLEAN("InputKit.inputEventClient.injectKeyEvent.Call", true);
auto histogramError = [](int32_t errorCode) {
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectKeyEvent.Error", errorCode);
};
if (!CheckInputEventClentPermission(histogramError)) {
return;
}
#ifdef OHOS_BUILD_ENABLE_VKEYBOARD
Input_KeyEvent* keyEventNative = OH_Input_CreateKeyEvent();
GetInjectionEventDataNative(keyEventNative, keyEvent.keyEvent, histogramError);
OH_Input_DestroyKeyEvent(&keyEventNative);
#else
auto newKeyEvent = OHOS::MMI::KeyEvent::Create();
GetInjectionEventData(newKeyEvent, keyEvent.keyEvent, histogramError);
#endif
}
void InjectEventSync(::ohos::multimodalInput::inputEventClient::KeyEventInfo const& keyEvent)
{
MMI_HISTOGRAM_BOOLEAN("InputKit.inputEventClient.injectEvent.Call", true);
auto histogramError = [](int32_t errorCode) {
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectEvent.Error", errorCode);
};
if (!CheckInputEventClentPermission(histogramError)) {
return;
}
#ifdef OHOS_BUILD_ENABLE_VKEYBOARD
Input_KeyEvent* keyEventNative = OH_Input_CreateKeyEvent();
GetInjectionEventDataNative(keyEventNative, keyEvent.KeyEvent, histogramError);
OH_Input_DestroyKeyEvent(&keyEventNative);
#else
auto lkeyEvent = OHOS::MMI::KeyEvent::Create();
GetInjectionEventData(lkeyEvent, keyEvent.KeyEvent, histogramError);
#endif
}
void HandleMouseButton(::ohos::multimodalInput::mouseEvent::MouseEvent mouseEvent,
std::shared_ptr<PointerEvent> pointerEvent, int32_t action)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
int32_t button = static_cast<int32_t>(mouseEvent.button.get_value());
if (button < 0) {
MMI_HILOGE("button:%{public}d is less 0, can not process", button);
set_business_error(INPUT_PARAMETER_ERROR, "button must be greater than or equal to 0");
}
if (THMouseButton2Native.find(button) != THMouseButton2Native.end()) {
button = THMouseButton2Native[button];
} else {
MMI_HILOGE("button is unknown!");
}
pointerEvent->SetButtonId(button);
if (action == TH_MOUSE_CALLBACK_EVENT::JS_CALLBACK_MOUSE_ACTION_BUTTON_DOWN) {
pointerEvent->SetButtonPressed(button);
} else if (action == TH_MOUSE_CALLBACK_EVENT::JS_CALLBACK_MOUSE_ACTION_BUTTON_UP) {
pointerEvent->DeleteReleaseButton(button);
}
}
void HandleMouseAction(::ohos::multimodalInput::mouseEvent::MouseEvent mouseEvent,
std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
int32_t action = static_cast<int32_t>(mouseEvent.action.get_value());
switch (action) {
case TAHE_MOVE:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
break;
case TAHE_BUTTON_DOWN:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_BUTTON_DOWN);
item.SetPressed(true);
break;
case TAHE_BUTTON_UP:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_BUTTON_UP);
item.SetPressed(false);
break;
case TAHE_ACTION_DOWN:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
item.SetPressed(true);
break;
case TAHE_ACTION_UP:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
item.SetPressed(false);
break;
default:
MMI_HILOGE("action is unknown");
break;
}
if (action == TAHE_BUTTON_DOWN || action == TAHE_BUTTON_UP|| action == TAHE_MOVE) {
HandleMouseButton(mouseEvent, pointerEvent, action);
}
}
void HandleMousePropertyInt32(::ohos::multimodalInput::mouseEvent::MouseEvent mouseEvent,
std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
int32_t screenX = mouseEvent.screenX;
int32_t screenY = mouseEvent.screenY;
int32_t toolType = mouseEvent.toolType.get_value();
if (toolType < 0) {
MMI_HILOGE("toolType:%{public}d is less 0, can not process", toolType);
::taihe::set_business_error(INPUT_PARAMETER_ERROR, "toolType must be greater than or equal to 0");
}
double globalX = INT32_MAX;
if (mouseEvent.globalX.has_value()) {
globalX = mouseEvent.globalX.value();
}
double globalY = INT32_MAX;
if (mouseEvent.globalY.has_value()) {
globalY = mouseEvent.globalY.value();
}
pointerEvent->SetSourceType(toolType);
item.SetPointerId(0);
item.SetDisplayX(screenX);
item.SetDisplayY(screenY);
item.SetDisplayXPos(screenX);
item.SetDisplayYPos(screenY);
if (globalX != INT32_MAX && globalY != INT32_MAX) {
item.SetGlobalX(globalX);
item.SetGlobalY(globalY);
}
pointerEvent->SetPointerId(0);
pointerEvent->AddPointerItem(item);
}
void HandleMousePressedButtons(::ohos::multimodalInput::mouseEvent::MouseEvent mouseEvent,
std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
std::vector<int32_t> jsPressedButtons {};
for (auto it = mouseEvent.pressedButtons.begin(); it != mouseEvent.pressedButtons.end(); ++it) {
jsPressedButtons.push_back(static_cast<int32_t>(*it));
}
std::vector<int32_t> nativePressedButtons { };
for (const auto jsButton : jsPressedButtons) {
if (THMouseButton2Native.find(jsButton) == THMouseButton2Native.end()) {
MMI_HILOGE("Unknown jsButton:%{public}d", jsButton);
continue;
}
nativePressedButtons.push_back(THMouseButton2Native[jsButton]);
}
auto buttonId = pointerEvent->GetButtonId();
auto iter = std::find_if(nativePressedButtons.begin(), nativePressedButtons.end(),
[buttonId] (int32_t elem) { return elem == buttonId; }
);
if (iter != nativePressedButtons.end()) {
item.SetPressed(true);
}
for (const auto button : nativePressedButtons) {
pointerEvent->SetButtonPressed(button);
}
}
void InjectMouseEventSync(::ohos::multimodalInput::inputEventClient::MouseEventData const& mouseEvent)
{
MMI_HISTOGRAM_BOOLEAN("InputKit.inputEventClient.injectMouseEvent.Call", true);
auto histogramError = [](int32_t errorCode) {
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectMouseEvent.Error", errorCode);
};
if (!CheckInputEventClentPermission(histogramError)) {
return;
}
auto pointerEvent = PointerEvent::Create();
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
PointerEvent::PointerItem item;
HandleMouseAction(mouseEvent.mouseEvent, pointerEvent, item);
HandleMousePropertyInt32(mouseEvent.mouseEvent, pointerEvent, item);
HandleMousePressedButtons(mouseEvent.mouseEvent, pointerEvent, item);
bool useGlobalCoordinate = mouseEvent.useGlobalCoordinate.value_or(false);
int32_t useCoordinate = PointerEvent::DISPLAY_COORDINATE;
if (useGlobalCoordinate) {
MMI_HILOGD("useGlobalCoordinate");
if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
if (!item.IsValidGlobalXY()) {
MMI_HILOGE("globalX globalY is invalid");
::taihe::set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.globalX globalY is invalid");
return;
}
}
useCoordinate = PointerEvent::GLOBAL_COORDINATE;
}
InputManager::GetInstance()->SimulateInputEvent(pointerEvent, true, useCoordinate);
}
int32_t HandleTouchAction(::ohos::multimodalInput::touchEvent::TouchEvent touchEvent,
std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return RET_ERR;
}
int32_t action = static_cast<int32_t>(touchEvent.action.get_value());
switch (action) {
case TH_TOUCH_CALLBACK_EVENT::JS_CALLBACK_TOUCH_ACTION_DOWN:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
item.SetPressed(true);
break;
case TH_TOUCH_CALLBACK_EVENT::JS_CALLBACK_TOUCH_ACTION_MOVE:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
break;
case TH_TOUCH_CALLBACK_EVENT::JS_CALLBACK_TOUCH_ACTION_UP:
pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
item.SetPressed(false);
break;
default:
action = RET_ERR;
MMI_HILOGE("action is unknown");
break;
}
return action;
}
void HandleTouchAttribute(std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item,
::ohos::multimodalInput::touchEvent::Touch& touch, int32_t isTouch)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
int32_t pointerId = touch.id;
int32_t screenX = touch.screenX;
int32_t screenY = touch.screenY;
int64_t pressedTime = touch.pressedTime;
int32_t toolType = static_cast<int32_t>(touch.toolType.get_value());
double pressure = touch.pressure;
int32_t globalX = touch.globalX.has_value()? touch.globalX.value() : INT_MAX;
int32_t globalY = touch.globalY.has_value()? touch.globalY.value() : INT_MAX;
item.SetDisplayX(screenX);
item.SetDisplayY(screenY);
item.SetDisplayXPos(screenX);
item.SetDisplayYPos(screenY);
item.SetRawDisplayX(screenX);
item.SetRawDisplayY(screenY);
item.SetPointerId(pointerId);
item.SetToolType(toolType);
item.SetPressure(pressure);
if (globalX != INT_MAX && globalY != INT_MAX) {
item.SetGlobalX(globalX);
item.SetGlobalY(globalY);
}
if (isTouch) {
pointerEvent->SetPointerId(pointerId);
pointerEvent->SetActionTime(pressedTime);
}
}
void HandleTouchesProperty(std::shared_ptr<PointerEvent> pointerEvent,
::taihe::array_view<::ohos::multimodalInput::touchEvent::Touch>& touches,
std::vector<PointerEvent::PointerItem>& pointerItems)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
for (auto it = touches.begin(); it != touches.end(); ++it) {
PointerEvent::PointerItem pointerItem;
HandleTouchAttribute(pointerEvent, pointerItem, *it, false);
pointerItems.push_back(pointerItem);
}
}
bool HandleTouchPropertyInt32(::ohos::multimodalInput::touchEvent::TouchEvent touchEvent,
std::shared_ptr<PointerEvent> pointerEvent, PointerEvent::PointerItem &item, int32_t action)
{
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return false;
}
int32_t sourceType = touchEvent.sourceType.get_value();
if (sourceType < 0) {
MMI_HILOGE("sourceType must be greater than or equal to 0");
return false;
}
if (sourceType == TH_TOUCH_CALLBACK_SOURCETYPE::TOUCH_SCREEN || sourceType == TH_TOUCH_CALLBACK_SOURCETYPE::PEN) {
sourceType = PointerEvent::SOURCE_TYPE_TOUCHSCREEN;
}
int32_t screenId = touchEvent.base.screenId;
HandleTouchAttribute(pointerEvent, item, touchEvent.touch, true);
bool autoToVirtualScreen = true;
int32_t fixedMode = 1;
if (touchEvent.fixedMode.has_value()) {
fixedMode = static_cast<int32_t>(touchEvent.fixedMode.value());
if (fixedMode < static_cast<int32_t>(PointerEvent::FixedMode::NORMAL) ||
fixedMode >= static_cast<int32_t>(PointerEvent::FixedMode::SCREEN_MODE_MAX)) {
MMI_HILOGE("fixedMode is not defined");
return false;
}
if (fixedMode != static_cast<int32_t>(PointerEvent::FixedMode::AUTO)) {
autoToVirtualScreen = false;
}
}
pointerEvent->AddPointerItem(item);
pointerEvent->SetSourceType(sourceType);
pointerEvent->SetTargetDisplayId(screenId);
pointerEvent->SetAutoToVirtualScreen(autoToVirtualScreen);
std::vector<PointerEvent::PointerItem> pointerItems;
HandleTouchesProperty(pointerEvent, touchEvent.touches, pointerItems);
for (auto &pointeritem : pointerItems) {
pointerEvent->AddPointerItem(pointeritem);
}
if ((action == TH_TOUCH_CALLBACK_EVENT::JS_CALLBACK_TOUCH_ACTION_MOVE) ||
(action == TH_TOUCH_CALLBACK_EVENT::JS_CALLBACK_TOUCH_ACTION_UP)) {
pointerEvent->UpdatePointerItem(item.GetPointerId(), item);
}
return true;
}
void InjectTouchEventSync(::ohos::multimodalInput::inputEventClient::TouchEventData const& touchEvent)
{
MMI_HISTOGRAM_BOOLEAN("InputKit.inputEventClient.injectTouchEvent.Call", true);
auto histogramError = [](int32_t errorCode) {
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectTouchEvent.Error", errorCode);
};
if (!CheckInputEventClentPermission(histogramError)) {
return;
}
auto pointerEvent = PointerEvent::Create();
if (pointerEvent == nullptr) {
MMI_HILOGE("pointerEvent is null");
return;
}
PointerEvent::PointerItem item;
int32_t action = HandleTouchAction(touchEvent.touchEvent, pointerEvent, item);
if (action == RET_ERR) {
MMI_HILOGE("touch action type invaild");
set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.");
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectTouchEvent.Error", INPUT_PARAMETER_ERROR);
return;
}
if (!HandleTouchPropertyInt32(touchEvent.touchEvent, pointerEvent, item, action)) {
MMI_HILOGE("touch property invaild");
set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.");
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectTouchEvent.Error", INPUT_PARAMETER_ERROR);
return;
}
bool useGlobalCoordinate = touchEvent.useGlobalCoordinate.value_or(false);
int32_t useCoordinate = PointerEvent::DISPLAY_COORDINATE;
if (useGlobalCoordinate) {
MMI_HILOGD("useGlobalCoordinate");
if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
if (!item.IsValidGlobalXY()) {
MMI_HILOGE("globalX globalY is invalid");
::taihe::set_business_error(INPUT_PARAMETER_ERROR, "Parameter error.globalX globalY is invalid");
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.injectTouchEvent.Error", INPUT_PARAMETER_ERROR);
return;
}
}
useCoordinate = PointerEvent::GLOBAL_COORDINATE;
}
InputManager::GetInstance()->SimulateInputEvent(pointerEvent,
pointerEvent->GetAutoToVirtualScreen(), useCoordinate);
}
void PermitInjectionSync(bool result)
{
MMI_HISTOGRAM_BOOLEAN("InputKit.inputEventClient.permitInjection.Call", true);
auto histogramError = [](int32_t errorCode) {
MMI_HISTOGRAM_ERROR("InputKit.inputEventClient.permitInjection.Error", errorCode);
};
if (!CheckInputEventClentPermission(histogramError)) {
return;
}
InputManager::GetInstance()->Authorize(result);
}
class MouseControllerImpl {
public:
explicit MouseControllerImpl(std::shared_ptr<OHOS::MMI::MouseControllerImpl> impl)
: nativeImpl_(impl) {
MMI_HILOGD("MouseControllerImpl created with native impl");
}
MouseControllerImpl() : nativeImpl_(nullptr) {
MMI_HILOGW("MouseControllerImpl created without native impl (error case)");
}
~MouseControllerImpl() = default;
void MoveToSync(int32_t displayId, int32_t displayX, int32_t displayY)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::MOVE_TO);
return;
}
int32_t ret = nativeImpl_->MoveTo(displayId, displayX, displayY);
if (ret != RET_OK) {
MMI_HILOGE("MoveTo failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::MOVE_TO);
}
}
void PressButtonSync(::ohos::multimodalInput::mouseEvent::Button button)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::PRESS_BUTTON);
return;
}
if (!IsValidEtsButton(button)) {
int32_t buttonValue = static_cast<int32_t>(button);
MMI_HILOGE("Invalid button value: %{public}d", buttonValue);
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::COMMON_PARAMETER_ERROR,
"Parameter error. Invalid button value");
return;
}
int32_t nativeButton = TaiheMouseButonConverter::ConvertEts2Native(button);
int32_t ret = nativeImpl_->PressButton(nativeButton);
if (ret != RET_OK) {
MMI_HILOGE("PressButton failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::PRESS_BUTTON);
}
}
void ReleaseButtonSync(::ohos::multimodalInput::mouseEvent::Button button)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::RELEASE_BUTTON);
return;
}
if (!IsValidEtsButton(button)) {
int32_t buttonValue = static_cast<int32_t>(button);
MMI_HILOGE("Invalid button value: %{public}d", buttonValue);
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::COMMON_PARAMETER_ERROR,
"Parameter error. Invalid button value");
return;
}
int32_t nativeButton = TaiheMouseButonConverter::ConvertEts2Native(button);
int32_t ret = nativeImpl_->ReleaseButton(nativeButton);
if (ret != RET_OK) {
MMI_HILOGE("ReleaseButton failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::RELEASE_BUTTON);
}
}
void BeginAxisSync(::ohos::multimodalInput::mouseEvent::Axis axis, int32_t value)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::BEGIN_AXIS);
return;
}
if (!IsValidEtsAxis(axis)) {
int32_t axisValue = static_cast<int32_t>(axis);
MMI_HILOGE("Invalid axis value: %{public}d", axisValue);
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::COMMON_PARAMETER_ERROR,
"Parameter error. Invalid axis value");
return;
}
int32_t nativeAxis = ConvertTaiheAxisToNative(axis);
int32_t ret = nativeImpl_->BeginAxis(nativeAxis, value);
if (ret != RET_OK) {
MMI_HILOGE("BeginAxis failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::BEGIN_AXIS);
}
}
void UpdateAxisSync(::ohos::multimodalInput::mouseEvent::Axis axis, int32_t value)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::UPDATE_AXIS);
return;
}
if (!IsValidEtsAxis(axis)) {
int32_t axisValue = static_cast<int32_t>(axis);
MMI_HILOGE("Invalid axis value: %{public}d", axisValue);
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::COMMON_PARAMETER_ERROR,
"Parameter error. Invalid axis value");
return;
}
int32_t nativeAxis = ConvertTaiheAxisToNative(axis);
int32_t ret = nativeImpl_->UpdateAxis(nativeAxis, value);
if (ret != RET_OK) {
MMI_HILOGE("UpdateAxis failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::UPDATE_AXIS);
}
}
void EndAxisSync(::ohos::multimodalInput::mouseEvent::Axis axis)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetMouseControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
MouseControllerOperation::END_AXIS);
return;
}
if (!IsValidEtsAxis(axis)) {
int32_t axisValue = static_cast<int32_t>(axis);
MMI_HILOGE("Invalid axis value: %{public}d", axisValue);
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::COMMON_PARAMETER_ERROR,
"Parameter error. Invalid axis value");
return;
}
int32_t nativeAxis = ConvertTaiheAxisToNative(axis);
int32_t ret = nativeImpl_->EndAxis(nativeAxis);
if (ret != RET_OK) {
MMI_HILOGE("EndAxis failed, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::END_AXIS);
}
}
private:
std::shared_ptr<OHOS::MMI::MouseControllerImpl> nativeImpl_;
};
::ohos::multimodalInput::inputEventClient::MouseController CreateMouseControllerSync()
{
CALL_DEBUG_ENTER;
std::shared_ptr<OHOS::MMI::MouseControllerImpl> nativeImpl = nullptr;
int32_t ret = InputManager::GetInstance()->CreateMouseController(nativeImpl);
if (ret != RET_OK || nativeImpl == nullptr) {
MMI_HILOGE("Failed to create native MouseControllerImpl, ret=%{public}d", ret);
SetMouseControllerBusinessError(ret, MouseControllerOperation::CREATE);
return make_holder<MouseControllerImpl,
::ohos::multimodalInput::inputEventClient::MouseController>();
}
MMI_HILOGD("MouseController created successfully");
return make_holder<MouseControllerImpl,
::ohos::multimodalInput::inputEventClient::MouseController>(nativeImpl);
}
constexpr const char* CONTROL_DEVICE_PERMISSION = "ohos.permission.CONTROL_DEVICE";
std::string GetTouchControllerActionName(TouchControllerOperation operation)
{
switch (operation) {
case TouchControllerOperation::DOWN:
return "touch down";
case TouchControllerOperation::MOVE:
return "touch move";
case TouchControllerOperation::UP:
return "touch up";
case TouchControllerOperation::CREATE:
default:
return "create TouchController";
}
}
std::string GetMouseControllerActionName(MouseControllerOperation operation)
{
switch (operation) {
case MouseControllerOperation::MOVE_TO:
return "move mouse";
case MouseControllerOperation::PRESS_BUTTON:
return "press button";
case MouseControllerOperation::RELEASE_BUTTON:
return "release button";
case MouseControllerOperation::BEGIN_AXIS:
return "begin axis";
case MouseControllerOperation::UPDATE_AXIS:
return "update axis";
case MouseControllerOperation::END_AXIS:
return "end axis";
case MouseControllerOperation::CREATE:
default:
return "create MouseController";
}
}
std::string GetKeyboardControllerActionName(KeyboardControllerOperation operation)
{
switch (operation) {
case KeyboardControllerOperation::PRESS_KEY:
return "press key";
case KeyboardControllerOperation::RELEASE_KEY:
return "release key";
case KeyboardControllerOperation::CREATE:
default:
return "create KeyboardController";
}
}
int32_t NormalizeControllerErrorCode(int32_t errorCode)
{
if (errorCode == ERROR_NO_PERMISSION) {
return OHOS::MMI::TaiheErrorCode::COMMON_PERMISSION_CHECK_ERROR;
}
if (errorCode == CAPABILITY_NOT_SUPPORTED) {
return OHOS::MMI::TaiheErrorCode::INPUT_DEVICE_NOT_SUPPORTED;
}
return errorCode;
}
void SetTouchControllerBusinessError(int32_t errorCode, TouchControllerOperation operation)
{
errorCode = NormalizeControllerErrorCode(errorCode);
if (errorCode == OHOS::MMI::TaiheErrorCode::COMMON_PERMISSION_CHECK_ERROR) {
std::string msg = MakePermissionCheckErrMsg(GetTouchControllerActionName(operation), CONTROL_DEVICE_PERMISSION);
taihe::set_business_error(errorCode, msg);
return;
}
TaiheError_t codeMsg;
if (TaiheConverter::GetApiError(errorCode, codeMsg)) {
taihe::set_business_error(errorCode, codeMsg.msg);
return;
}
if (TaiheConverter::GetApiError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION, codeMsg)) {
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION, codeMsg.msg);
return;
}
taihe::set_business_error(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION, "Input service exception.");
}
void SetMouseControllerBusinessError(int32_t errorCode, MouseControllerOperation operation)
{
errorCode = NormalizeControllerErrorCode(errorCode);
if (errorCode == OHOS::MMI::TaiheErrorCode::COMMON_PERMISSION_CHECK_ERROR) {
std::string msg = MakePermissionCheckErrMsg(GetMouseControllerActionName(operation), CONTROL_DEVICE_PERMISSION);
taihe::set_business_error(errorCode, msg);
return;
}
TaiheError_t codeMsg;
TaiheConverter::GetErrorCodeOrDefault(errorCode, codeMsg);
taihe::set_business_error(codeMsg.errorCode, codeMsg.msg);
}
void SetKeyboardControllerBusinessError(int32_t errorCode, KeyboardControllerOperation operation)
{
errorCode = NormalizeControllerErrorCode(errorCode);
if (errorCode == OHOS::MMI::TaiheErrorCode::COMMON_PERMISSION_CHECK_ERROR) {
std::string msg = MakePermissionCheckErrMsg(GetKeyboardControllerActionName(operation),
CONTROL_DEVICE_PERMISSION);
taihe::set_business_error(errorCode, msg);
return;
}
TaiheError_t codeMsg;
TaiheConverter::GetErrorCodeOrDefault(errorCode, codeMsg);
taihe::set_business_error(codeMsg.errorCode, codeMsg.msg);
}
class TaiheTouchControllerImpl {
public:
explicit TaiheTouchControllerImpl(std::shared_ptr<OHOS::MMI::TouchControllerImpl> impl) : nativeImpl_(impl)
{
MMI_HILOGD("TaiheTouchControllerImpl created with native impl");
}
TaiheTouchControllerImpl() : nativeImpl_(nullptr)
{
MMI_HILOGW("TaiheTouchControllerImpl created without native impl");
}
~TaiheTouchControllerImpl() = default;
void TouchDownSync(::ohos::multimodalInput::inputEventClient::TouchPoint touch)
{
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetTouchControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
TouchControllerOperation::DOWN);
return;
}
int32_t ret = nativeImpl_->TouchDown(touch.id, touch.displayId, touch.displayX, touch.displayY);
if (ret != RET_OK) {
MMI_HILOGE("TouchDown failed, ret=%{public}d", ret);
SetTouchControllerBusinessError(ret, TouchControllerOperation::DOWN);
}
}
void TouchMoveSync(::ohos::multimodalInput::inputEventClient::TouchPoint touch)
{
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetTouchControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
TouchControllerOperation::MOVE);
return;
}
int32_t ret = nativeImpl_->TouchMove(touch.id, touch.displayId, touch.displayX, touch.displayY);
if (ret != RET_OK) {
MMI_HILOGE("TouchMove failed, ret=%{public}d", ret);
SetTouchControllerBusinessError(ret, TouchControllerOperation::MOVE);
}
}
void TouchUpSync(::ohos::multimodalInput::inputEventClient::TouchPoint touch)
{
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetTouchControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
TouchControllerOperation::UP);
return;
}
int32_t ret = nativeImpl_->TouchUp(touch.id, touch.displayId, touch.displayX, touch.displayY);
if (ret != RET_OK) {
MMI_HILOGE("TouchUp failed, ret=%{public}d", ret);
SetTouchControllerBusinessError(ret, TouchControllerOperation::UP);
}
}
private:
std::shared_ptr<OHOS::MMI::TouchControllerImpl> nativeImpl_;
};
::ohos::multimodalInput::inputEventClient::TouchController CreateTouchControllerSync()
{
CALL_DEBUG_ENTER;
std::shared_ptr<OHOS::MMI::TouchControllerImpl> nativeImpl = nullptr;
int32_t ret = InputManager::GetInstance()->CreateTouchController(nativeImpl);
if (ret != RET_OK || nativeImpl == nullptr) {
MMI_HILOGE("Failed to create native TouchControllerImpl, ret=%{public}d", ret);
SetTouchControllerBusinessError(ret, TouchControllerOperation::CREATE);
return make_holder<TaiheTouchControllerImpl,
::ohos::multimodalInput::inputEventClient::TouchController>();
}
MMI_HILOGD("TouchController created successfully");
return make_holder<TaiheTouchControllerImpl,
::ohos::multimodalInput::inputEventClient::TouchController>(nativeImpl);
}
class KeyboardControllerImpl {
public:
explicit KeyboardControllerImpl(std::shared_ptr<OHOS::MMI::KeyboardControllerImpl> impl)
: nativeImpl_(impl) {
MMI_HILOGD("KeyboardControllerImpl created with native impl");
}
KeyboardControllerImpl() : nativeImpl_(nullptr) {
MMI_HILOGW("KeyboardControllerImpl created without native impl (error case)");
}
~KeyboardControllerImpl() = default;
void PressKeySync(::ohos::multimodalInput::keyCode::KeyCode keyCode)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetKeyboardControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
KeyboardControllerOperation::PRESS_KEY);
return;
}
int32_t nativeKeyCode = TaiheKeyCodeConverter::GetKeyCodeByValue(keyCode);
int32_t ret = nativeImpl_->PressKey(nativeKeyCode);
if (ret != RET_OK) {
MMI_HILOGE("PressKey failed, ret=%{public}d", ret);
SetKeyboardControllerBusinessError(ret, KeyboardControllerOperation::PRESS_KEY);
}
}
void ReleaseKeySync(::ohos::multimodalInput::keyCode::KeyCode keyCode)
{
CALL_DEBUG_ENTER;
if (nativeImpl_ == nullptr) {
MMI_HILOGE("Native implementation is null");
SetKeyboardControllerBusinessError(OHOS::MMI::TaiheErrorCode::INPUT_SERVICE_EXCEPTION,
KeyboardControllerOperation::RELEASE_KEY);
return;
}
int32_t nativeKeyCode = TaiheKeyCodeConverter::GetKeyCodeByValue(keyCode);
int32_t ret = nativeImpl_->ReleaseKey(nativeKeyCode);
if (ret != RET_OK) {
MMI_HILOGE("ReleaseKey failed, ret=%{public}d", ret);
SetKeyboardControllerBusinessError(ret, KeyboardControllerOperation::RELEASE_KEY);
}
}
private:
std::shared_ptr<OHOS::MMI::KeyboardControllerImpl> nativeImpl_;
};
::ohos::multimodalInput::inputEventClient::KeyboardController CreateKeyboardControllerSync()
{
CALL_DEBUG_ENTER;
std::shared_ptr<OHOS::MMI::KeyboardControllerImpl> nativeImpl = nullptr;
int32_t ret = InputManager::GetInstance()->CreateKeyboardController(nativeImpl);
if (ret != RET_OK || nativeImpl == nullptr) {
MMI_HILOGE("Failed to create native KeyboardControllerImpl, ret=%{public}d", ret);
SetKeyboardControllerBusinessError(ret, KeyboardControllerOperation::CREATE);
return make_holder<KeyboardControllerImpl,
::ohos::multimodalInput::inputEventClient::KeyboardController>();
}
MMI_HILOGD("KeyboardController created successfully");
return make_holder<KeyboardControllerImpl,
::ohos::multimodalInput::inputEventClient::KeyboardController>(nativeImpl);
}
}
TH_EXPORT_CPP_API_InjectKeyEventSync(InjectKeyEventSync);
TH_EXPORT_CPP_API_InjectEventSync(InjectEventSync);
TH_EXPORT_CPP_API_InjectMouseEventSync(InjectMouseEventSync);
TH_EXPORT_CPP_API_InjectTouchEventSync(InjectTouchEventSync);
TH_EXPORT_CPP_API_PermitInjectionSync(PermitInjectionSync);
TH_EXPORT_CPP_API_CreateMouseControllerSync(CreateMouseControllerSync);
TH_EXPORT_CPP_API_CreateTouchControllerSync(CreateTouchControllerSync);
TH_EXPORT_CPP_API_CreateKeyboardControllerSync(CreateKeyboardControllerSync);