* 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 <condition_variable>
#include <mutex>
#include <input_manager.h>
#include "selection_service.h"
#include "selection_common.h"
#include "selection_log.h"
#include "common_event_manager.h"
#include "selection_config.h"
#include "selection_input_monitor.h"
#include "selection_errors.h"
#include "hisysevent_adapter.h"
#include "selection_timer.h"
#ifdef SCENE_BOARD_ENABLE
#include "window_manager_lite.h"
#else
#include "window_manager.h"
#endif
using namespace OHOS;
using namespace OHOS::SelectionFwk;
using namespace OHOS::AppExecFwk;
using namespace OHOS::MMI;
using namespace OHOS::EventFwk;
std::atomic<uint32_t> selSeqId = 0;
const std::unordered_set<std::string> appBlocklist = {};
static int64_t GetCurrentTimeMillis()
{
auto now = std::chrono::system_clock::now();
auto duration = now.time_since_epoch();
return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
}
uint32_t GenerateSequenceId()
{
return selSeqId.fetch_add(1, std::memory_order_seq_cst);
}
bool BaseSelectionInputMonitor::IsSelectionTriggered() const
{
return IsSelectionDone();
}
const SelectionInfo& BaseSelectionInputMonitor::GetSelectionInfo() const
{
return selectionInfo_;
}
void BaseSelectionInputMonitor::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
{
SELECTION_HILOGD("Before keyEvent, curSelectState: %{public}d, subSelectState: %{public}d; "
"keyAction: %{public}d",
curSelectState, subSelectState, keyEvent->GetKeyAction());
ProcessInputEvent(keyEvent);
SELECTION_HILOGD("After keyEvent, curSelectState: %{public}d, subSelectState: %{public}d",
curSelectState, subSelectState);
}
void BaseSelectionInputMonitor::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
{
SELECTION_HILOGD("Before pointerEvent, curSelectState: %{public}d, subSelectState: %{public}d; "
"buttonId: %{public}d, pointerAction: %{public}d",
curSelectState, subSelectState, pointerEvent->GetButtonId(), pointerEvent->GetPointerAction());
ProcessInputEvent(pointerEvent);
SELECTION_HILOGD("After pointerEvent, curSelectState: %{public}d, subSelectState: %{public}d",
curSelectState, subSelectState);
}
void BaseSelectionInputMonitor::ProcessInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
{
if (curSelectState == SelectInputState::SELECT_INPUT_DONE) {
if (subSelectState != SelectInputSubState::SUB_INITIAL) {
curSelectState = SelectInputState::SELECT_INPUT_WORD_END;
return;
}
ResetState();
return;
}
if (subSelectState != SelectInputSubState::SUB_WAIT_KEY_CTRL_DOWN &&
subSelectState != SelectInputSubState::SUB_WAIT_KEY_CTRL_UP &&
subSelectState != SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN) {
return;
}
int32_t keyCode = keyEvent->GetKeyCode();
int32_t action = keyEvent->GetKeyAction();
if (keyCode != KeyEvent::KEYCODE_CTRL_LEFT && keyCode != KeyEvent::KEYCODE_CTRL_RIGHT) {
ResetState();
return;
}
if (action == KeyEvent::KEY_ACTION_DOWN && keyEvent->IsRepeatKey()) {
SELECTION_HILOGD("current ctrl down is repeat, ignore");
return;
}
SELECTION_HILOGI("[SelectionService] Processed ctrl key with action: %{public}d.", action);
if ((subSelectState == SelectInputSubState::SUB_WAIT_KEY_CTRL_DOWN ||
subSelectState == SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN) &&
action == KeyEvent::KEY_ACTION_DOWN) {
subSelectState = SelectInputSubState::SUB_WAIT_KEY_CTRL_UP;
return;
}
if (subSelectState == SelectInputSubState::SUB_WAIT_KEY_CTRL_UP && action == KeyEvent::KEY_ACTION_UP) {
if (curSelectState == SelectInputState::SELECT_INPUT_WORD_END) {
curSelectState = SelectInputState::SELECT_INPUT_DONE;
SELECTION_HILOGI("[SelectionService] Set curSelectState SELECT_INPUT_DONE.");
}
subSelectState = SelectInputSubState::SUB_INITIAL;
} else {
if (action == KeyEvent::KEY_ACTION_UP && keyEvent->IsRepeatKey()) {
SELECTION_HILOGD("current ctrl up is repeat, ignore");
return;
}
curSelectState = SelectInputState::SELECT_INPUT_INITIAL;
subSelectState = SelectInputSubState::SUB_INITIAL;
SELECTION_HILOGI("[SelectionService] Set curSelectState SELECT_INPUT_INITIAL.");
}
FinishedWordSelection();
return;
}
void BaseSelectionInputMonitor::ProcessInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t buttonId = pointerEvent->GetButtonId();
int32_t action = pointerEvent->GetPointerAction();
if (action == PointerEvent::POINTER_ACTION_ENTER_WINDOW ||
action == PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
return;
}
if (buttonId == PointerEvent::BUTTON_NONE && action == PointerEvent::POINTER_ACTION_MOVE) {
if (ProcessMovement(pointerEvent)) {
return;
}
}
if (buttonId != PointerEvent::MOUSE_BUTTON_LEFT) {
ResetState();
return;
}
SELECTION_HILOGD("[SelectionService] into PointerEvent, curSelectState = %{public}d.", curSelectState);
switch (curSelectState) {
case SelectInputState::SELECT_INPUT_INITIAL:
InputInitialProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_WORD_BEGIN:
InputWordBeginProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_WAIT_LEFT_MOVE:
InputWordLeftMoveProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_WAIT_DOUBLE_CLICK:
InputWordDoubleClickProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_WORD_END:
InputWordEndProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_DONE:
InputDoneProcess(pointerEvent);
break;
case SelectInputState::SELECT_INPUT_WAIT_TRIPLE_CLICK:
InputWordTripleClickProcess(pointerEvent);
break;
default:
break;
}
FinishedWordSelection();
return;
}
bool BaseSelectionInputMonitor::ProcessMovement(std::shared_ptr<PointerEvent> pointerEvent) const
{
if (subSelectState == SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_DOWN) {
if (IsTinyMovement(pointerEvent)) {
if (curSelectState == SelectInputState::SELECT_INPUT_DONE) {
curSelectState = SelectInputState::SELECT_INPUT_WAIT_TRIPLE_CLICK;
}
return true;
}
}
if (subSelectState == SelectInputSubState::SUB_WAIT_KEY_CTRL_DOWN ||
subSelectState == SelectInputSubState::SUB_WAIT_KEY_CTRL_UP) {
return true;
}
if (subSelectState == SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN) {
subSelectState = SelectInputSubState::SUB_WAIT_KEY_CTRL_DOWN;
return true;
}
return false;
}
bool BaseSelectionInputMonitor::IsTinyMovement(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t pointerId = pointerEvent->GetPointerId();
PointerEvent::PointerItem pointerItem;
pointerEvent->GetPointerItem(pointerId, pointerItem);
if (abs(selectionInfo_.startDisplayX - pointerItem.GetGlobalX()) > MAX_POSITION_CHANGE_OFFSET ||
abs(selectionInfo_.startDisplayY - pointerItem.GetGlobalY()) > MAX_POSITION_CHANGE_OFFSET) {
return false;
}
return true;
}
bool BaseSelectionInputMonitor::IsClickTimeout(uint32_t time) const
{
auto curTime = GetCurrentTimeMillis();
auto duration = curTime - lastClickTime;
lastClickTime = curTime;
return (duration > time);
}
void BaseSelectionInputMonitor::OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const
{
SELECTION_HILOGI("[SelectionService] into axisEvent");
};
void BaseSelectionInputMonitor::ResetProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
SELECTION_HILOGI("ResetProcess with action: %{public}d.", pointerEvent->GetPointerAction());
curSelectState = SelectInputState::SELECT_INPUT_INITIAL;
subSelectState = SelectInputSubState::SUB_INITIAL;
OnInputEvent(pointerEvent);
}
void BaseSelectionInputMonitor::SaveSelectionStartInfo(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t pointerId = pointerEvent->GetPointerId();
PointerEvent::PointerItem pointerItem;
pointerEvent->GetPointerItem(pointerId, pointerItem);
selectionInfo_.startDisplayX = pointerItem.GetGlobalX();
selectionInfo_.startDisplayY = pointerItem.GetGlobalY();
selectionInfo_.endDisplayX = pointerItem.GetGlobalX();
selectionInfo_.endDisplayY = pointerItem.GetGlobalY();
selectionInfo_.startWindowX = pointerItem.GetWindowX();
selectionInfo_.startWindowY = pointerItem.GetWindowY();
selectionInfo_.endWindowX = pointerItem.GetWindowX();
selectionInfo_.endWindowY = pointerItem.GetWindowY();
int32_t displayId = pointerEvent->GetTargetDisplayId();
int32_t windowId = pointerEvent->GetTargetWindowId();
if (displayId < 0 || windowId < 0) {
SELECTION_HILOGE("Get invalid displayId or windowId from pointerEvent! displayId:%{public}d,"
"windowId: %{public}d", displayId, windowId);
return;
}
selectionInfo_.displayId = static_cast<std::uint32_t>(displayId);
selectionInfo_.windowId = static_cast<std::uint32_t>(windowId);
OHOS::Rosen::WindowInfoOption windowInfoOption;
windowInfoOption.windowId = static_cast<std::int32_t>(selectionInfo_.windowId);
SELECTION_HILOGI("Begin to call ListWindowInfo");
std::vector<sptr<Rosen::WindowInfo>> infos;
#ifdef SCENE_BOARD_ENABLE
Rosen::WMError ret = Rosen::WindowManagerLite::GetInstance().ListWindowInfo(windowInfoOption, infos);
#else
Rosen::WMError ret = Rosen::WindowManager::GetInstance().ListWindowInfo(windowInfoOption, infos);
#endif
SELECTION_HILOGI("ListWindowInfo(windowId: %{public}d), ret: %{public}d, infos size: %{public}zu",
windowInfoOption.windowId, ret, infos.size());
for (auto& info : infos) {
SELECTION_HILOGI("WindowInfo bundleName:%{public}s, windowtype:%{public}d, width:%{public}d, height:%{public}d",
info->windowMetaInfo.bundleName.c_str(), info->windowMetaInfo.windowType,
info->windowLayoutInfo.rect.width_, info->windowLayoutInfo.rect.height_);
}
if (ret == Rosen::WMError::WM_OK && !infos.empty()) {
selectionInfo_.bundleName = infos[0]->windowMetaInfo.bundleName;
}
}
void BaseSelectionInputMonitor::SaveSelectionEndInfo(std::shared_ptr<PointerEvent> pointerEvent) const
{
SaveSelectionType();
int32_t pointerId = pointerEvent->GetPointerId();
PointerEvent::PointerItem pointerItem;
pointerEvent->GetPointerItem(pointerId, pointerItem);
selectionInfo_.endDisplayX = pointerItem.GetGlobalX();
selectionInfo_.endDisplayY = pointerItem.GetGlobalY();
selectionInfo_.endWindowX = pointerItem.GetWindowX();
selectionInfo_.endWindowY = pointerItem.GetWindowY();
}
void BaseSelectionInputMonitor::SaveSelectionType() const
{
switch (curSelectState) {
case SelectInputState::SELECT_INPUT_WAIT_LEFT_MOVE:
selectionInfo_.selectionType = MOVE_SELECTION;
break;
case SelectInputState::SELECT_INPUT_WAIT_DOUBLE_CLICK:
selectionInfo_.selectionType = DOUBLE_CLICKED_SELECTION;
break;
case SelectInputState::SELECT_INPUT_WAIT_TRIPLE_CLICK:
selectionInfo_.selectionType = TRIPLE_CLICKED_SELECTION;
break;
default:
break;
}
}
bool BaseSelectionInputMonitor::IsSelectionDone() const
{
return curSelectState == SelectInputState::SELECT_INPUT_DONE;
}
bool BaseSelectionInputMonitor::IsInputWordEnd() const
{
return curSelectState == SelectInputState::SELECT_INPUT_WORD_END;
}
bool BaseSelectionInputMonitor::GetCtrlSelectFlag() const
{
return MemSelectionConfig::GetInstance().GetTriggered();
}
void BaseSelectionInputMonitor::InputInitialProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
int32_t buttonId = pointerEvent->GetButtonId();
if (action == PointerEvent::POINTER_ACTION_BUTTON_DOWN && buttonId == PointerEvent::MOUSE_BUTTON_LEFT) {
curSelectState = SelectInputState::SELECT_INPUT_WORD_BEGIN;
subSelectState = SelectInputSubState::SUB_INITIAL;
lastClickTime = GetCurrentTimeMillis();
SaveSelectionStartInfo(pointerEvent);
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WORD_BEGIN.");
}
return;
}
void BaseSelectionInputMonitor::InputWordBeginProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (action == PointerEvent::POINTER_ACTION_MOVE) {
curSelectState = SelectInputState::SELECT_INPUT_WAIT_LEFT_MOVE;
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_UP;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WAIT_LEFT_MOVE.");
} else if (action == PointerEvent::POINTER_ACTION_BUTTON_UP) {
curSelectState = SelectInputState::SELECT_INPUT_WAIT_DOUBLE_CLICK;
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_DOWN;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WAIT_DOUBLE_CLICK.");
}
return;
}
void BaseSelectionInputMonitor::ProcessWordSelection(std::shared_ptr<PointerEvent> pointerEvent) const
{
SaveSelectionEndInfo(pointerEvent);
if (GetCtrlSelectFlag()) {
if (curSelectState == SelectInputState::SELECT_INPUT_WAIT_DOUBLE_CLICK) {
subSelectState = SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN;
} else {
subSelectState = SelectInputSubState::SUB_WAIT_KEY_CTRL_DOWN;
}
curSelectState = SelectInputState::SELECT_INPUT_WORD_END;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WORD_END");
} else {
if (curSelectState == SelectInputState::SELECT_INPUT_WAIT_DOUBLE_CLICK) {
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_DOWN;
} else {
subSelectState = SelectInputSubState::SUB_INITIAL;
}
curSelectState = SelectInputState::SELECT_INPUT_DONE;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_DONE.");
}
}
void BaseSelectionInputMonitor::InputWordLeftMoveProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (action == PointerEvent::POINTER_ACTION_BUTTON_UP) {
ProcessWordSelection(pointerEvent);
} else if (action != PointerEvent::POINTER_ACTION_MOVE) {
SELECTION_HILOGI("Action reset. subSelectState is %{public}d, action is %{public}d.", subSelectState, action);
ResetProcess(pointerEvent);
}
return;
}
void BaseSelectionInputMonitor::JudgeTripleClick(std::shared_ptr<PointerEvent> pointerEvent) const
{
if (IsClickTimeout(TRIPLE_CLICK_TIME)) {
ResetProcess(pointerEvent);
return;
}
curSelectState = SelectInputState::SELECT_INPUT_WAIT_TRIPLE_CLICK;
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_UP;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WAIT_TRIPLE_CLICK.");
}
void BaseSelectionInputMonitor::InputWordDoubleClickProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (subSelectState == SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_DOWN &&
action == PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
if (IsClickTimeout(DOUBLE_CLICK_TIME)) {
ResetProcess(pointerEvent);
return;
}
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_UP;
SELECTION_HILOGI("set subSelectState to SUB_WAIT_POINTER_ACTION_BUTTON_UP.");
return;
}
if (subSelectState == SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_UP) {
if (action == PointerEvent::POINTER_ACTION_BUTTON_UP) {
ProcessWordSelection(pointerEvent);
} else if (action == PointerEvent::POINTER_ACTION_MOVE) {
curSelectState = SelectInputState::SELECT_INPUT_WAIT_LEFT_MOVE;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WAIT_LEFT_MOVE.");
}
return;
}
if (subSelectState == SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN &&
action == PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
JudgeTripleClick(pointerEvent);
}
return;
}
void BaseSelectionInputMonitor::InputWordEndProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (action != PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
ResetState();
return;
}
if (subSelectState != SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_DOWN &&
subSelectState != SelectInputSubState::SUB_WAIT_BUTTON_OR_CTRL_DOWN) {
ResetProcess(pointerEvent);
return;
}
SELECTION_HILOGI("Begin JudgeTripleClick.");
JudgeTripleClick(pointerEvent);
}
void BaseSelectionInputMonitor::InputDoneProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
InputWordEndProcess(pointerEvent);
}
void BaseSelectionInputMonitor::InputWordTripleClickProcess(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (action == PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
SELECTION_HILOGI("[Deprecated] this branch may not be entered.");
if (IsClickTimeout(TRIPLE_CLICK_TIME)) {
ResetProcess(pointerEvent);
return;
}
subSelectState = SelectInputSubState::SUB_WAIT_POINTER_ACTION_BUTTON_UP;
} else if (action == PointerEvent::POINTER_ACTION_BUTTON_UP) {
ProcessWordSelection(pointerEvent);
} else if (action == PointerEvent::POINTER_ACTION_MOVE) {
curSelectState = SelectInputState::SELECT_INPUT_WAIT_LEFT_MOVE;
SELECTION_HILOGI("set curSelectState to SELECT_INPUT_WAIT_LEFT_MOVE.");
} else {
SELECTION_HILOGI("Action reset. subSelectState is %{public}d, action is %{public}d.", subSelectState, action);
ResetProcess(pointerEvent);
}
return;
}
void BaseSelectionInputMonitor::FinishedWordSelection() const
{
if (!IsSelectionDone()) {
return;
}
GenerateSequenceId();
SELECTION_HILOGW("[selectevent] curSelectState:%{public}d. Selection event id is %{public}u.", curSelectState,
selSeqId.load());
}
void BaseSelectionInputMonitor::ResetState() const
{
curSelectState = SelectInputState::SELECT_INPUT_INITIAL;
subSelectState = SelectInputSubState::SUB_INITIAL;
SELECTION_HILOGD("ResetState.");
}
SelectionInputMonitor::SelectionInputMonitor()
{
baseInputMonitor_ = std::make_shared<BaseSelectionInputMonitor>();
}
SelectionInputMonitor::~SelectionInputMonitor()
{
SELECTION_HILOGI("~SelectionInputMonitor called");
}
void SelectionInputMonitor::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
{
baseInputMonitor_->OnInputEvent(keyEvent);
FinishedWordSelection();
}
void SelectionInputMonitor::HandleWordSelected() const
{
if (!SelectionService::GetInstance()->HasExtAbilityConnection()) {
int32_t ret = SelectionService::GetInstance()->ConnectExtAbilityFromConfig();
if (ret != 0) {
SELECTION_HILOGE("start selection extension ability failed");
}
}
SelectionService::GetInstance()->ResetPluginUnloadTimer();
}
void SelectionInputMonitor::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
{
HandleWindowFocused(pointerEvent);
if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
SELECTION_HILOGD("Detect multimode event: POINTER_ACTION_BUTTON_DOWN");
}
baseInputMonitor_->OnInputEvent(pointerEvent);
FinishedWordSelection();
}
void SelectionInputMonitor::OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const
{
baseInputMonitor_->OnInputEvent(axisEvent);
}
bool SelectionInputMonitor::GetCanGetSelectionContentFlag() const
{
return SelectionService::GetInstance()->CanGetPasteboardContent();
}
void SelectionInputMonitor::SetCanGetSelectionContentFlag(bool flag) const
{
SelectionService::GetInstance()->SetPasteboardFlag(flag);
}
void SelectionInputMonitor::HandleWindowFocused(std::shared_ptr<PointerEvent> pointerEvent) const
{
int32_t action = pointerEvent->GetPointerAction();
if (action != PointerEvent::POINTER_ACTION_BUTTON_DOWN && action != PointerEvent::POINTER_ACTION_DOWN) {
return;
}
auto windowId = pointerEvent->GetTargetWindowId();
Rosen::FocusChangeInfo focusInfo;
#ifdef SCENE_BOARD_ENABLE
Rosen::WindowManagerLite::GetInstance().GetFocusWindowInfo(focusInfo);
#else
Rosen::WindowManager::GetInstance().GetFocusWindowInfo(focusInfo);
#endif
auto windowType = static_cast<uint32_t>(focusInfo.windowType_);
if (windowId != focusInfo.windowId_) {
SELECTION_HILOGI("Clicked window is not focused, focus-changed event will dispose selection panel later");
return;
}
SelectionFocusChangeInfo focusChangeInfo(focusInfo.windowId_, focusInfo.displayId_, focusInfo.pid_,
focusInfo.uid_, windowType, true, FocusChangeSource::InputManager);
sptr<ISelectionListener> listener = SelectionService::GetInstance()->GetListener();
if (listener == nullptr) {
SELECTION_HILOGD("Selection listener is nullptr");
return;
}
ErrCode errCode = listener->FocusChange(focusChangeInfo);
if (errCode != NO_ERROR) {
SELECTION_HILOGE("Failed to call ISelectionListener::FocusChange, error code: %{public}d.", errCode);
}
}
bool SelectionInputMonitor::IsAppInBlocklist(const std::string& bundleName) const
{
return std::find(appBlocklist.begin(), appBlocklist.end(), bundleName) != appBlocklist.end();
}
void SelectionInputMonitor::FinishedWordSelection() const
{
if (!baseInputMonitor_->IsSelectionTriggered()) {
return;
}
HandleWordSelected();
if (SelectionService::GetInstance()->GetScreenLockedFlag()) {
SELECTION_HILOGW("The screen is locked, skip notifying selection info.");
return;
}
auto selectionInfo = baseInputMonitor_->GetSelectionInfo();
if (selectionInfo.bundleName.empty()) {
SELECTION_HILOGE("Failed to get Selected bundleName, skip notifying selection info.");
}
if (IsAppInBlocklist(selectionInfo.bundleName)) {
SELECTION_HILOGW("The app [%{public}s] is in the blocklist, skip notifying selection info.",
selectionInfo.bundleName.c_str());
return;
}
if (!MemSelectionConfig::GetInstance().GetEnable()) {
SELECTION_HILOGI("Selection switch is off, skip notifying selection info.");
return;
}
SelectionInfoData infoData;
infoData.data = selectionInfo;
sptr<ISelectionListener> listener = SelectionService::GetInstance()->GetListener();
if (listener == nullptr) {
SELECTION_HILOGE("Selection listener is nullptr");
return;
}
SetCanGetSelectionContentFlag(true);
listener->OnSelectionChange(infoData);
}
int32_t SelectionInputMonitor::GetSelectionContent(std::string& selectionContent)
{
SELECTION_HILOGI("SelectionInputMonitor::GetSelectionContent start");
if (!baseInputMonitor_) {
SELECTION_HILOGE("baseInputMonitor_ is nullptr");
return SelectionServiceError::INVALID_DATA;
}
HisyseventAdapter::GetInstance()->AddSelectionCount();
SetCanGetSelectionContentFlag(false);
auto selectionInfo = baseInputMonitor_->GetSelectionInfo();
return SelectionService::GetInstance()->GetPasteboardContent(selectionContent, selectionInfo.windowId,
selectionInfo.bundleName);
}
int32_t SelectionInputMonitor::SetPanelShowingStatus(bool status) const
{
SELECTION_HILOGI("set panel showing status: %{public}d", status);
isPanelShowing_ = status;
return 0;
}
bool SelectionInputMonitor::GetPanelShowingStatus() const
{
return isPanelShowing_;
}