// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fwl/core/fwl_noteimp.h"

#include "core/fxcrt/fx_ext.h"
#include "third_party/base/stl_util.h"
#include "xfa/fwl/basewidget/fwl_tooltipctrlimp.h"
#include "xfa/fwl/basewidget/ifwl_tooltip.h"
#include "xfa/fwl/core/cfwl_message.h"
#include "xfa/fwl/core/cfwl_widgetmgr.h"
#include "xfa/fwl/core/fwl_appimp.h"
#include "xfa/fwl/core/fwl_formimp.h"
#include "xfa/fwl/core/fwl_widgetimp.h"
#include "xfa/fwl/core/ifwl_app.h"

CFWL_NoteLoop::CFWL_NoteLoop(CFWL_WidgetImp* pForm)
    : m_pForm(pForm), m_bContinueModal(TRUE) {}

FWL_Error CFWL_NoteLoop::Idle(int32_t count) {
#if (_FX_OS_ == _FX_WIN32_DESKTOP_)
  if (count <= 0) {
#endif
    CFWL_EvtIdle ev;
    IFWL_App* pApp = FWL_GetApp();
    if (!pApp)
      return FWL_Error::Indefinite;
    CFWL_NoteDriver* pDriver = pApp->GetNoteDriver();
    if (!pDriver)
      return FWL_Error::Indefinite;
    pDriver->SendEvent(&ev);
#if (_FX_OS_ == _FX_WIN32_DESKTOP_)
  }
#endif
  return FWL_Error::Indefinite;
}
CFWL_WidgetImp* CFWL_NoteLoop::GetForm() {
  return m_pForm;
}
FX_BOOL CFWL_NoteLoop::ContinueModal() {
  return m_bContinueModal;
}
FWL_Error CFWL_NoteLoop::EndModalLoop() {
  m_bContinueModal = FALSE;
  return FWL_Error::Succeeded;
}

FWL_Error CFWL_NoteLoop::SetMainForm(CFWL_WidgetImp* pForm) {
  m_pForm = pForm;
  return FWL_Error::Succeeded;
}
void CFWL_NoteLoop::GenerateCommondEvent(uint32_t dwCommand) {
  CFWL_EvtMenuCommand ev;
  ev.m_iCommand = dwCommand;
  IFWL_App* pApp = m_pForm->GetOwnerApp();
  if (!pApp)
    return;

  CFWL_NoteDriver* pDriver = pApp->GetNoteDriver();
  if (!pDriver)
    return;

  pDriver->SendEvent(&ev);
}
CFWL_NoteDriver::CFWL_NoteDriver()
    : m_pHover(nullptr),
      m_pFocus(nullptr),
      m_pGrab(nullptr),
      m_pNoteLoop(new CFWL_NoteLoop) {
  PushNoteLoop(m_pNoteLoop.get());
}
CFWL_NoteDriver::~CFWL_NoteDriver() {
  ClearInvalidEventTargets(TRUE);
}

void CFWL_NoteDriver::SendEvent(CFWL_Event* pNote) {
  if (m_eventTargets.empty())
    return;

  for (const auto& pair : m_eventTargets) {
    CFWL_EventTarget* pEventTarget = pair.second;
    if (pEventTarget && !pEventTarget->IsInvalid())
      pEventTarget->ProcessEvent(pNote);
  }
}

FWL_Error CFWL_NoteDriver::RegisterEventTarget(IFWL_Widget* pListener,
                                               IFWL_Widget* pEventSource,
                                               uint32_t dwFilter) {
  uint32_t key = pListener->GetEventKey();
  if (key == 0) {
    do {
      key = rand();
    } while (key == 0 || pdfium::ContainsKey(m_eventTargets, key));
    pListener->SetEventKey(key);
  }
  if (!m_eventTargets[key])
    m_eventTargets[key] = new CFWL_EventTarget(this, pListener);

  m_eventTargets[key]->SetEventSource(pEventSource, dwFilter);
  return FWL_Error::Succeeded;
}

FWL_Error CFWL_NoteDriver::UnregisterEventTarget(IFWL_Widget* pListener) {
  uint32_t key = pListener->GetEventKey();
  if (key == 0)
    return FWL_Error::Indefinite;

  auto it = m_eventTargets.find(key);
  if (it != m_eventTargets.end())
    it->second->FlagInvalid();

  return FWL_Error::Succeeded;
}

void CFWL_NoteDriver::ClearEventTargets(FX_BOOL bRemoveAll) {
  ClearInvalidEventTargets(bRemoveAll);
}
IFWL_App* CFWL_NoteDriver::GetOwnerApp() const {
  return FWL_GetApp();
}
FWL_Error CFWL_NoteDriver::PushNoteLoop(CFWL_NoteLoop* pNoteLoop) {
  m_noteLoopQueue.Add(pNoteLoop);
  return FWL_Error::Succeeded;
}
CFWL_NoteLoop* CFWL_NoteDriver::PopNoteLoop() {
  int32_t pos = m_noteLoopQueue.GetSize();
  if (pos <= 0)
    return nullptr;

  CFWL_NoteLoop* p = m_noteLoopQueue.GetAt(pos - 1);
  m_noteLoopQueue.RemoveAt(pos - 1);
  return p;
}
FX_BOOL CFWL_NoteDriver::SetFocus(IFWL_Widget* pFocus, FX_BOOL bNotify) {
  if (m_pFocus == pFocus) {
    return TRUE;
  }
  IFWL_Widget* pPrev = m_pFocus;
  m_pFocus = pFocus;
  if (pPrev) {
    CFWL_MsgKillFocus ms;
    ms.m_pDstTarget = pPrev;
    ms.m_pSrcTarget = pPrev;
    if (bNotify) {
      ms.m_dwExtend = 1;
    }
    IFWL_WidgetDelegate* pDelegate = pPrev->SetDelegate(nullptr);
    if (pDelegate) {
      pDelegate->OnProcessMessage(&ms);
    }
  }
  if (pFocus) {
    IFWL_Widget* pWidget =
        CFWL_WidgetMgr::GetInstance()->GetSystemFormWidget(pFocus);
    CFWL_FormImp* pForm =
        pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
    if (pForm) {
      CFWL_WidgetImp* pNewFocus =
          static_cast<CFWL_WidgetImp*>(pFocus->GetImpl());
      pForm->SetSubFocus(pNewFocus);
    }
    CFWL_MsgSetFocus ms;
    ms.m_pDstTarget = pFocus;
    if (bNotify) {
      ms.m_dwExtend = 1;
    }
    IFWL_WidgetDelegate* pDelegate = pFocus->SetDelegate(nullptr);
    if (pDelegate) {
      pDelegate->OnProcessMessage(&ms);
    }
  }
  return TRUE;
}
FWL_Error CFWL_NoteDriver::Run() {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (!pWidgetMgr)
    return FWL_Error::Indefinite;

#if (_FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_WIN32_DESKTOP_ || \
     _FX_OS_ == _FX_WIN64_)
  CFWL_NoteLoop* pTopLoop = nullptr;
  for (;;) {
    pTopLoop = GetTopLoop();
    if (!pTopLoop || !pTopLoop->ContinueModal())
      break;
    if (UnqueueMessage(pTopLoop))
      continue;
  }
#endif

  return FWL_Error::Succeeded;
}

IFWL_Widget* CFWL_NoteDriver::GetFocus() {
  return m_pFocus;
}
IFWL_Widget* CFWL_NoteDriver::GetHover() {
  return m_pHover;
}
void CFWL_NoteDriver::SetHover(IFWL_Widget* pHover) {
  m_pHover = pHover;
}
void CFWL_NoteDriver::SetGrab(IFWL_Widget* pGrab, FX_BOOL bSet) {
  m_pGrab = bSet ? pGrab : nullptr;
}
void CFWL_NoteDriver::NotifyTargetHide(IFWL_Widget* pNoteTarget) {
  if (m_pFocus == pNoteTarget) {
    m_pFocus = nullptr;
  }
  if (m_pHover == pNoteTarget) {
    m_pHover = nullptr;
  }
  if (m_pGrab == pNoteTarget) {
    m_pGrab = nullptr;
  }
}
void CFWL_NoteDriver::NotifyTargetDestroy(IFWL_Widget* pNoteTarget) {
  if (m_pFocus == pNoteTarget) {
    m_pFocus = nullptr;
  }
  if (m_pHover == pNoteTarget) {
    m_pHover = nullptr;
  }
  if (m_pGrab == pNoteTarget) {
    m_pGrab = nullptr;
  }
  UnregisterEventTarget(pNoteTarget);
  int32_t count = m_forms.GetSize();
  for (int32_t nIndex = 0; nIndex < count; nIndex++) {
    CFWL_FormImp* pForm = static_cast<CFWL_FormImp*>(m_forms[nIndex]);
    if (!pForm) {
      continue;
    }
    CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    if (!pSubFocus)
      return;
    if (pSubFocus && pSubFocus->GetInterface() == pNoteTarget) {
      pForm->SetSubFocus(nullptr);
    }
  }
}

FWL_Error CFWL_NoteDriver::RegisterForm(CFWL_WidgetImp* pForm) {
  if (!pForm)
    return FWL_Error::Indefinite;
  if (m_forms.Find(pForm) >= 0) {
    return FWL_Error::Indefinite;
  }
  m_forms.Add(pForm);
  if (m_forms.GetSize() == 1) {
    CFWL_NoteLoop* pLoop =
        static_cast<CFWL_NoteLoop*>(m_noteLoopQueue.GetAt(0));
    if (!pLoop)
      return FWL_Error::Indefinite;
    pLoop->SetMainForm(pForm);
  }
  return FWL_Error::Succeeded;
}
FWL_Error CFWL_NoteDriver::UnRegisterForm(CFWL_WidgetImp* pForm) {
  if (!pForm)
    return FWL_Error::Indefinite;
  int32_t nIndex = m_forms.Find(pForm);
  if (nIndex < 0) {
    return FWL_Error::Indefinite;
  }
  m_forms.RemoveAt(nIndex);
  return FWL_Error::Succeeded;
}
FX_BOOL CFWL_NoteDriver::QueueMessage(CFWL_Message* pMessage) {
  pMessage->Retain();
  m_noteQueue.Add(pMessage);
  return TRUE;
}
FX_BOOL CFWL_NoteDriver::UnqueueMessage(CFWL_NoteLoop* pNoteLoop) {
  if (m_noteQueue.GetSize() < 1) {
    return FALSE;
  }
  CFWL_Message* pMessage = m_noteQueue[0];
  m_noteQueue.RemoveAt(0);
  if (!IsValidMessage(pMessage)) {
    pMessage->Release();
    return TRUE;
  }
  ProcessMessage(pMessage);

  pMessage->Release();
  return TRUE;
}
CFWL_NoteLoop* CFWL_NoteDriver::GetTopLoop() {
  int32_t size = m_noteLoopQueue.GetSize();
  if (size <= 0)
    return nullptr;
  return static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[size - 1]);
}
int32_t CFWL_NoteDriver::CountLoop() {
  return m_noteLoopQueue.GetSize();
}

FX_BOOL CFWL_NoteDriver::ProcessMessage(CFWL_Message* pMessage) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  IFWL_Widget* pMessageForm = pWidgetMgr->IsFormDisabled()
                                  ? pMessage->m_pDstTarget
                                  : GetMessageForm(pMessage->m_pDstTarget);
  if (!pMessageForm)
    return FALSE;
  if (DispatchMessage(pMessage, pMessageForm)) {
    if (pMessage->GetClassID() == CFWL_MessageType::Mouse)
      MouseSecondary(static_cast<CFWL_MsgMouse*>(pMessage));
    return TRUE;
  }
  return FALSE;
}

FX_BOOL CFWL_NoteDriver::DispatchMessage(CFWL_Message* pMessage,
                                         IFWL_Widget* pMessageForm) {
  FX_BOOL bRet = FALSE;
  switch (pMessage->GetClassID()) {
    case CFWL_MessageType::Activate: {
      bRet = DoActivate(static_cast<CFWL_MsgActivate*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::Deactivate: {
      bRet = DoDeactivate(static_cast<CFWL_MsgDeactivate*>(pMessage),
                          pMessageForm);
      break;
    }
    case CFWL_MessageType::SetFocus: {
      bRet = DoSetFocus(static_cast<CFWL_MsgSetFocus*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::KillFocus: {
      bRet =
          DoKillFocus(static_cast<CFWL_MsgKillFocus*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::Key: {
      bRet = DoKey(static_cast<CFWL_MsgKey*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::Mouse: {
      bRet = DoMouse(static_cast<CFWL_MsgMouse*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::MouseWheel: {
      bRet = DoWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage), pMessageForm);
      break;
    }
    case CFWL_MessageType::Size: {
      bRet = DoSize(static_cast<CFWL_MsgSize*>(pMessage));
      break;
    }
    case CFWL_MessageType::Cursor: {
      bRet = TRUE;
      break;
    }
    case CFWL_MessageType::WindowMove: {
      bRet = DoWindowMove(static_cast<CFWL_MsgWindowMove*>(pMessage),
                          pMessageForm);
      break;
    }
    case CFWL_MessageType::DropFiles: {
      bRet =
          DoDragFiles(static_cast<CFWL_MsgDropFiles*>(pMessage), pMessageForm);
      break;
    }
    default: {
      bRet = TRUE;
      break;
    }
  }
  if (bRet) {
    IFWL_WidgetDelegate* pDelegate =
        pMessage->m_pDstTarget->SetDelegate(nullptr);
    if (pDelegate)
      pDelegate->OnProcessMessage(pMessage);
  }
  return bRet;
}

FX_BOOL CFWL_NoteDriver::DoActivate(CFWL_MsgActivate* pMsg,
                                    IFWL_Widget* pMessageForm) {
  pMsg->m_pDstTarget = pMessageForm;
  return (pMsg->m_pDstTarget)->GetStates() & FWL_WGTSTATE_Deactivated;
}
FX_BOOL CFWL_NoteDriver::DoDeactivate(CFWL_MsgDeactivate* pMsg,
                                      IFWL_Widget* pMessageForm) {
  int32_t iTrackLoop = m_noteLoopQueue.GetSize();
  if (iTrackLoop <= 0)
    return FALSE;
  if (iTrackLoop == 1) {
    if (pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {
      return FALSE;
    }
    if (pMsg->m_pSrcTarget &&
        pMsg->m_pSrcTarget->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {
      return FALSE;
    }
    if (pMsg->m_pSrcTarget &&
        pMsg->m_pSrcTarget->GetClassID() == FWL_Type::ToolTip) {
      return FALSE;
    }
    return TRUE;
  }
  IFWL_Widget* pDst = pMsg->m_pDstTarget;
  if (!pDst)
    return FALSE;
#if (_FX_OS_ == _FX_MACOSX_)
  if (pDst == pMessageForm && pDst->IsInstance(L"FWL_FORMPROXY")) {
    return TRUE;
  }
#endif
  return pDst != pMessageForm &&
         !pDst->IsInstance(FX_WSTRC(L"FWL_FORMPROXY")) &&
         !pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"));
}
FX_BOOL CFWL_NoteDriver::DoSetFocus(CFWL_MsgSetFocus* pMsg,
                                    IFWL_Widget* pMessageForm) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (pWidgetMgr->IsFormDisabled()) {
    m_pFocus = pMsg->m_pDstTarget;
    return TRUE;
  }
  IFWL_Widget* pWidget = pMsg->m_pDstTarget;
  CFWL_FormImp* pForm =
      pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
  if (pForm) {
    CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    if (pSubFocus && ((pSubFocus->GetStates() & FWL_WGTSTATE_Focused) == 0)) {
      pMsg->m_pDstTarget = pSubFocus->GetInterface();
      if (m_pFocus != pMsg->m_pDstTarget) {
        m_pFocus = pMsg->m_pDstTarget;
        return TRUE;
      }
    }
  }
  return FALSE;
}
FX_BOOL CFWL_NoteDriver::DoKillFocus(CFWL_MsgKillFocus* pMsg,
                                     IFWL_Widget* pMessageForm) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (pWidgetMgr->IsFormDisabled()) {
    if (m_pFocus == pMsg->m_pDstTarget) {
      m_pFocus = nullptr;
    }
    return TRUE;
  }
  IFWL_Widget* pWidget = pMsg->m_pDstTarget;
  CFWL_FormImp* pForm =
      pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
  if (pForm) {
    CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    if (pSubFocus && (pSubFocus->GetStates() & FWL_WGTSTATE_Focused)) {
      pMsg->m_pDstTarget = pSubFocus->GetInterface();
      if (m_pFocus == pMsg->m_pDstTarget) {
        m_pFocus = nullptr;
        return TRUE;
      }
    }
  }
  return FALSE;
}
FX_BOOL CFWL_NoteDriver::DoKey(CFWL_MsgKey* pMsg, IFWL_Widget* pMessageForm) {
#if (_FX_OS_ != _FX_MACOSX_)
  if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
      pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
    CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
    IFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
    IFWL_Widget* pFocus = m_pFocus;
    if (m_pFocus) {
      if (pWidgetMgr->GetSystemFormWidget(m_pFocus) != pForm)
        pFocus = nullptr;
    }
    FX_BOOL bFind = FALSE;
    IFWL_Widget* pNextTabStop = pWidgetMgr->nextTab(pForm, pFocus, bFind);
    if (!pNextTabStop) {
      bFind = FALSE;
      pNextTabStop = pWidgetMgr->nextTab(pForm, nullptr, bFind);
    }
    if (pNextTabStop == pFocus) {
      return TRUE;
    }
    if (pNextTabStop) {
      SetFocus(pNextTabStop);
    }
    return TRUE;
  }
#endif
  if (!m_pFocus) {
    if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
        pMsg->m_dwKeyCode == FWL_VKEY_Return) {
      CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
      IFWL_Widget* defButton = pWidgetMgr->GetDefaultButton(pMessageForm);
      if (defButton) {
        pMsg->m_pDstTarget = defButton;
        return TRUE;
      }
    }
    return FALSE;
  }
  pMsg->m_pDstTarget = m_pFocus;
  return TRUE;
}
FX_BOOL CFWL_NoteDriver::DoMouse(CFWL_MsgMouse* pMsg,
                                 IFWL_Widget* pMessageForm) {
  if (pMsg->m_dwCmd == FWL_MouseCommand::Leave ||
      pMsg->m_dwCmd == FWL_MouseCommand::Hover ||
      pMsg->m_dwCmd == FWL_MouseCommand::Enter) {
    return !!pMsg->m_pDstTarget;
  }
  if (pMsg->m_pDstTarget != pMessageForm) {
    pMsg->m_pDstTarget->TransformTo(pMessageForm, pMsg->m_fx, pMsg->m_fy);
  }
  if (!DoMouseEx(pMsg, pMessageForm)) {
    pMsg->m_pDstTarget = pMessageForm;
  }
  return TRUE;
}
FX_BOOL CFWL_NoteDriver::DoWheel(CFWL_MsgMouseWheel* pMsg,
                                 IFWL_Widget* pMessageForm) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (!pWidgetMgr)
    return FALSE;

  IFWL_Widget* pDst =
      pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);
  if (!pDst)
    return FALSE;

  pMessageForm->TransformTo(pDst, pMsg->m_fx, pMsg->m_fy);
  pMsg->m_pDstTarget = pDst;
  return TRUE;
}
FX_BOOL CFWL_NoteDriver::DoSize(CFWL_MsgSize* pMsg) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (!pWidgetMgr)
    return FALSE;
  pWidgetMgr->NotifySizeChanged(pMsg->m_pDstTarget, (FX_FLOAT)pMsg->m_iWidth,
                                (FX_FLOAT)pMsg->m_iHeight);
  return TRUE;
}
FX_BOOL CFWL_NoteDriver::DoWindowMove(CFWL_MsgWindowMove* pMsg,
                                      IFWL_Widget* pMessageForm) {
  return pMsg->m_pDstTarget == pMessageForm;
}
FX_BOOL CFWL_NoteDriver::DoDragFiles(CFWL_MsgDropFiles* pMsg,
                                     IFWL_Widget* pMessageForm) {
  return pMsg->m_pDstTarget == pMessageForm;
}
FX_BOOL CFWL_NoteDriver::DoMouseEx(CFWL_MsgMouse* pMsg,
                                   IFWL_Widget* pMessageForm) {
  CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
  if (!pWidgetMgr)
    return FALSE;
  IFWL_Widget* pTarget = nullptr;
  if (m_pGrab)
    pTarget = m_pGrab;
  if (!pTarget) {
    pTarget =
        pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);
  }
  if (pTarget) {
    if (pMessageForm != pTarget) {
      pMessageForm->TransformTo(pTarget, pMsg->m_fx, pMsg->m_fy);
    }
  }
  if (!pTarget)
    return FALSE;
  pMsg->m_pDstTarget = pTarget;
  return TRUE;
}
void CFWL_NoteDriver::MouseSecondary(CFWL_MsgMouse* pMsg) {
  IFWL_Widget* pTarget = pMsg->m_pDstTarget;
  if (pTarget == m_pHover) {
    return;
  }
  if (m_pHover) {
    CFWL_MsgMouse msLeave;
    msLeave.m_pDstTarget = m_pHover;
    msLeave.m_fx = pMsg->m_fx;
    msLeave.m_fy = pMsg->m_fy;
    pTarget->TransformTo(m_pHover, msLeave.m_fx, msLeave.m_fy);
    msLeave.m_dwFlags = 0;
    msLeave.m_dwCmd = FWL_MouseCommand::Leave;
    DispatchMessage(&msLeave, nullptr);
  }
  if (pTarget->GetClassID() == FWL_Type::Form) {
    m_pHover = nullptr;
    return;
  }
  m_pHover = pTarget;
  CFWL_MsgMouse msHover;
  msHover.m_pDstTarget = pTarget;
  msHover.m_fx = pMsg->m_fx;
  msHover.m_fy = pMsg->m_fy;
  msHover.m_dwFlags = 0;
  msHover.m_dwCmd = FWL_MouseCommand::Hover;
  DispatchMessage(&msHover, nullptr);
}
FX_BOOL CFWL_NoteDriver::IsValidMessage(CFWL_Message* pMessage) {
  if (pMessage->GetClassID() == CFWL_MessageType::Post)
    return TRUE;

  int32_t iCount = m_noteLoopQueue.GetSize();
  for (int32_t i = 0; i < iCount; i++) {
    CFWL_NoteLoop* pNoteLoop = static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[i]);
    CFWL_WidgetImp* pForm = pNoteLoop->GetForm();
    if (pForm && (pForm->GetInterface() == pMessage->m_pDstTarget))
      return TRUE;
  }
  iCount = m_forms.GetSize();
  for (int32_t j = 0; j < iCount; j++) {
    CFWL_FormImp* pForm = static_cast<CFWL_FormImp*>(m_forms[j]);
    if (pForm->GetInterface() == pMessage->m_pDstTarget)
      return TRUE;
  }
  return FALSE;
}

IFWL_Widget* CFWL_NoteDriver::GetMessageForm(IFWL_Widget* pDstTarget) {
  int32_t iTrackLoop = m_noteLoopQueue.GetSize();
  if (iTrackLoop <= 0)
    return nullptr;
  IFWL_Widget* pMessageForm = nullptr;
  if (iTrackLoop > 1) {
    CFWL_NoteLoop* pNootLoop =
        static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[iTrackLoop - 1]);
    pMessageForm = pNootLoop->GetForm()->GetInterface();
  } else if (m_forms.Find(pDstTarget->GetImpl()) < 0) {
    pMessageForm = pDstTarget;
  }
  if (!pMessageForm && pDstTarget) {
    CFWL_WidgetMgr* pWidgetMgr = CFWL_WidgetMgr::GetInstance();
    if (!pWidgetMgr)
      return nullptr;
    pMessageForm = pWidgetMgr->GetSystemFormWidget(pDstTarget);
  }
  return pMessageForm;
}

void CFWL_NoteDriver::ClearInvalidEventTargets(FX_BOOL bRemoveAll) {
  auto it = m_eventTargets.begin();
  while (it != m_eventTargets.end()) {
    auto old = it++;
    if (old->second && (bRemoveAll || old->second->IsInvalid())) {
      delete old->second;
      m_eventTargets.erase(old);
    }
  }
}

class CFWL_CoreToolTipDP : public IFWL_ToolTipDP {
 public:
  CFWL_CoreToolTipDP(int32_t iInitDelayTime, int32_t iAutoDelayTime);

  // IFWL_ToolTipDP
  FWL_Error GetCaption(IFWL_Widget* pWidget,
                       CFX_WideString& wsCaption) override;
  int32_t GetInitialDelay(IFWL_Widget* pWidget) override;
  int32_t GetAutoPopDelay(IFWL_Widget* pWidget) override;
  CFX_DIBitmap* GetToolTipIcon(IFWL_Widget* pWidget) override;
  CFX_SizeF GetToolTipIconSize(IFWL_Widget* pWidget) override;

  CFX_RectF GetAnchor();

  CFX_WideString m_wsCaption;
  int32_t m_nInitDelayTime;
  int32_t m_nAutoPopDelayTime;
  CFX_RectF m_fAnchor;
};

CFWL_CoreToolTipDP::CFWL_CoreToolTipDP(int32_t iInitDelayTime,
                                       int32_t iAutoDelayTime)
    : m_nInitDelayTime(iInitDelayTime), m_nAutoPopDelayTime(iAutoDelayTime) {
  m_fAnchor.Set(0.0, 0.0, 0.0, 0.0);
}

FWL_Error CFWL_CoreToolTipDP::GetCaption(IFWL_Widget* pWidget,
                                         CFX_WideString& wsCaption) {
  wsCaption = m_wsCaption;
  return FWL_Error::Succeeded;
}

int32_t CFWL_CoreToolTipDP::GetInitialDelay(IFWL_Widget* pWidget) {
  return m_nInitDelayTime;
}

int32_t CFWL_CoreToolTipDP::GetAutoPopDelay(IFWL_Widget* pWidget) {
  return m_nAutoPopDelayTime;
}

CFX_DIBitmap* CFWL_CoreToolTipDP::GetToolTipIcon(IFWL_Widget* pWidget) {
  return nullptr;
}

CFX_SizeF CFWL_CoreToolTipDP::GetToolTipIconSize(IFWL_Widget* pWidget) {
  return CFX_SizeF();
}

CFX_RectF CFWL_CoreToolTipDP::GetAnchor() {
  return m_fAnchor;
}

CFWL_EventTarget::CFWL_EventTarget(CFWL_NoteDriver* pNoteDriver,
                                   IFWL_Widget* pListener)
    : m_pListener(pListener), m_pNoteDriver(pNoteDriver), m_bInvalid(FALSE) {}
CFWL_EventTarget::~CFWL_EventTarget() {
  m_eventSources.RemoveAll();
}

int32_t CFWL_EventTarget::SetEventSource(IFWL_Widget* pSource,
                                         uint32_t dwFilter) {
  if (pSource) {
    m_eventSources.SetAt(pSource, dwFilter);
    return m_eventSources.GetCount();
  }
  return 1;
}

FX_BOOL CFWL_EventTarget::ProcessEvent(CFWL_Event* pEvent) {
  IFWL_WidgetDelegate* pDelegate = m_pListener->SetDelegate(nullptr);
  if (!pDelegate)
    return FALSE;
  if (m_eventSources.GetCount() == 0) {
    pDelegate->OnProcessEvent(pEvent);
    return TRUE;
  }
  FX_POSITION pos = m_eventSources.GetStartPosition();
  while (pos) {
    IFWL_Widget* pSource = nullptr;
    uint32_t dwFilter = 0;
    m_eventSources.GetNextAssoc(pos, (void*&)pSource, dwFilter);
    if (pSource == pEvent->m_pSrcTarget ||
        pEvent->GetClassID() == CFWL_EventType::Idle) {
      if (IsFilterEvent(pEvent, dwFilter)) {
        pDelegate->OnProcessEvent(pEvent);
        return TRUE;
      }
    }
  }
  return FALSE;
}

FX_BOOL CFWL_EventTarget::IsFilterEvent(CFWL_Event* pEvent, uint32_t dwFilter) {
  if (dwFilter == FWL_EVENT_ALL_MASK)
    return TRUE;

  switch (pEvent->GetClassID()) {
    case CFWL_EventType::Mouse:
      return !!(dwFilter & FWL_EVENT_MOUSE_MASK);
    case CFWL_EventType::MouseWheel:
      return !!(dwFilter & FWL_EVENT_MOUSEWHEEL_MASK);
    case CFWL_EventType::Key:
      return !!(dwFilter & FWL_EVENT_KEY_MASK);
    case CFWL_EventType::SetFocus:
    case CFWL_EventType::KillFocus:
      return !!(dwFilter & FWL_EVENT_FOCUSCHANGED_MASK);
    case CFWL_EventType::Draw:
      return !!(dwFilter & FWL_EVENT_DRAW_MASK);
    case CFWL_EventType::Close:
      return !!(dwFilter & FWL_EVENT_CLOSE_MASK);
    case CFWL_EventType::SizeChanged:
      return !!(dwFilter & FWL_EVENT_SIZECHANGED_MASK);
    case CFWL_EventType::Idle:
      return !!(dwFilter & FWL_EVENT_IDLE_MASK);
    default:
      return !!(dwFilter & FWL_EVENT_CONTROL_MASK);
  }
}

CFWL_ToolTipContainer* CFWL_ToolTipContainer::s_pInstance = nullptr;

CFWL_ToolTipContainer::CFWL_ToolTipContainer()
    : m_pToolTipImp(nullptr), m_pToolTipDp(new CFWL_CoreToolTipDP(0, 2000)) {}

CFWL_ToolTipContainer::~CFWL_ToolTipContainer() {
  if (m_pToolTipImp) {
    IFWL_ToolTip* pToolTip =
        static_cast<IFWL_ToolTip*>(m_pToolTipImp->GetInterface());
    pToolTip->Finalize();
    delete pToolTip;
  }
}

// static
CFWL_ToolTipContainer* CFWL_ToolTipContainer::getInstance() {
  if (!s_pInstance)
    s_pInstance = new CFWL_ToolTipContainer;
  return s_pInstance;
}

// static
void CFWL_ToolTipContainer::DeleteInstance() {
  delete s_pInstance;
  s_pInstance = nullptr;
}
