// 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/include/fx_ext.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/fwl_appimp.h"
#include "xfa/fwl/core/fwl_formimp.h"
#include "xfa/fwl/core/fwl_widgetimp.h"
#include "xfa/fwl/core/fwl_widgetmgrimp.h"
#include "xfa/fwl/core/ifwl_adapterwidgetmgr.h"
#include "xfa/fwl/core/ifwl_app.h"
#include "xfa/fwl/core/ifwl_tooltiptarget.h"

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

FWL_ERR 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_ERR_Indefinite;
    CFWL_NoteDriver* pDriver = pApp->GetNoteDriver();
    if (!pDriver)
      return FWL_ERR_Indefinite;
    pDriver->SendEvent(&ev);
#if (_FX_OS_ == _FX_WIN32_DESKTOP_)
  }
#endif
  return FWL_ERR_Indefinite;
}
CFWL_WidgetImp* CFWL_NoteLoop::GetForm() {
  return m_pForm;
}
FX_BOOL CFWL_NoteLoop::ContinueModal() {
  return m_bContinueModal;
}
FWL_ERR CFWL_NoteLoop::EndModalLoop() {
  m_bContinueModal = FALSE;
#if (_FX_OS_ == _FX_MACOSX_)
  CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  IFWL_AdapterWidgetMgr* adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();
  adapterWidgetMgr->EndLoop();
#endif
  return FWL_ERR_Succeeded;
}

FWL_ERR CFWL_NoteLoop::SetMainForm(CFWL_WidgetImp* pForm) {
  m_pForm = pForm;
  return FWL_ERR_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_sendEventCalled(0),
      m_pHover(nullptr),
      m_pFocus(nullptr),
      m_pGrab(nullptr) {
  m_pNoteLoop = new CFWL_NoteLoop;
  PushNoteLoop(m_pNoteLoop);
}
CFWL_NoteDriver::~CFWL_NoteDriver() {
  delete m_pNoteLoop;
  ClearInvalidEventTargets(TRUE);
}

FX_BOOL CFWL_NoteDriver::SendEvent(CFWL_Event* pNote) {
  int32_t iCount = m_eventTargets.GetCount();
  if (iCount < 1)
    return TRUE;
  if (CFWL_EventType::Mouse == pNote->GetClassID()) {
    CFWL_EvtMouse* pMouse = static_cast<CFWL_EvtMouse*>(pNote);
    if (FWL_MSGMOUSECMD_MouseHover == pMouse->m_dwCmd) {
      if (m_pNoteLoop->GetForm() &&
          CFWL_ToolTipContainer::getInstance()->ProcessEnter(
              pMouse, m_pNoteLoop->GetForm()->GetInterface())) {
      }
    } else if (FWL_MSGMOUSECMD_MouseLeave == pMouse->m_dwCmd) {
      CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse);
    } else if ((FWL_MSGMOUSECMD_LButtonDown <= pMouse->m_dwCmd) &&
               (FWL_MSGMOUSECMD_MButtonDblClk >= pMouse->m_dwCmd)) {
      CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse);
    }
  }
  m_sendEventCalled++;
  FX_POSITION pos = m_eventTargets.GetStartPosition();
  while (pos) {
    void* key = nullptr;
    void* value = nullptr;
    m_eventTargets.GetNextAssoc(pos, key, value);

    CFWL_EventTarget* pEventTarget = static_cast<CFWL_EventTarget*>(value);
    if (pEventTarget && !pEventTarget->IsInvalid())
      pEventTarget->ProcessEvent(pNote);
  }
  m_sendEventCalled--;
  return TRUE;
}

#define FWL_NoteDriver_EventKey 1100
FWL_ERR CFWL_NoteDriver::RegisterEventTarget(IFWL_Widget* pListener,
                                             IFWL_Widget* pEventSource,
                                             uint32_t dwFilter) {
  uint32_t dwkey = (uint32_t)(uintptr_t)pListener->GetPrivateData(
      (void*)(uintptr_t)FWL_NoteDriver_EventKey);
  if (dwkey == 0) {
    void* random = FX_Random_MT_Start(0);
    dwkey = rand();
    FX_Random_MT_Close(random);
    pListener->SetPrivateData((void*)(uintptr_t)FWL_NoteDriver_EventKey,
                              (void*)(uintptr_t)dwkey, NULL);
  }
  CFWL_EventTarget* value = NULL;
  if (!m_eventTargets.Lookup((void*)(uintptr_t)dwkey, (void*&)value)) {
    value = new CFWL_EventTarget(this, pListener);
    m_eventTargets.SetAt((void*)(uintptr_t)dwkey, value);
  }
  value->SetEventSource(pEventSource, dwFilter);
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_NoteDriver::UnregisterEventTarget(IFWL_Widget* pListener) {
  uint32_t dwkey = (uint32_t)(uintptr_t)pListener->GetPrivateData(
      (void*)(uintptr_t)FWL_NoteDriver_EventKey);
  if (dwkey == 0) {
    return FWL_ERR_Indefinite;
  }
  CFWL_EventTarget* value = NULL;
  if (m_eventTargets.Lookup((void*)(uintptr_t)dwkey, (void*&)value)) {
    value->FlagInvalid();
  }
  return FWL_ERR_Succeeded;
}
void CFWL_NoteDriver::ClearEventTargets(FX_BOOL bRemoveAll) {
  ClearInvalidEventTargets(bRemoveAll);
}
IFWL_App* CFWL_NoteDriver::GetOwnerApp() const {
  return FWL_GetApp();
}
FWL_ERR CFWL_NoteDriver::PushNoteLoop(CFWL_NoteLoop* pNoteLoop) {
  m_noteLoopQueue.Add(pNoteLoop);
  return FWL_ERR_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(NULL);
    if (pDelegate) {
      pDelegate->OnProcessMessage(&ms);
    }
  }
  if (pFocus) {
    IFWL_Widget* pWidget =
        FWL_GetWidgetMgr()->GetWidget(pFocus, FWL_WGTRELATION_SystemForm);
    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(NULL);
    if (pDelegate) {
      pDelegate->OnProcessMessage(&ms);
    }
  }
  return TRUE;
}
FWL_ERR CFWL_NoteDriver::Run() {
  CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  if (!pWidgetMgr)
    return FWL_ERR_Indefinite;
#if (_FX_OS_ == _FX_MACOSX_)
  IFWL_AdapterWidgetMgr* adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();
  CFWL_NoteLoop* pTopLoop = GetTopLoop();
  if (pTopLoop) {
    CFWL_WidgetImp* formImp = pTopLoop->GetForm();
    if (formImp) {
      IFWL_Widget* pForm = formImp->GetInterface();
      adapterWidgetMgr->RunLoop(pForm);
    }
  }
#elif(_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_)
    FX_BOOL bIdle = TRUE;
    int32_t iIdleCount = 0;
    CFWL_NoteLoop* pTopLoop = NULL;
    for (;;) {
      pTopLoop = GetTopLoop();
      if (!pTopLoop || !pTopLoop->ContinueModal()) {
        break;
      }
      if (UnqueueMessage(pTopLoop)) {
        continue;
      }
      while (bIdle && !(pWidgetMgr->CheckMessage_Native())) {
        if (FWL_ERR_Indefinite == pTopLoop->Idle(iIdleCount++)) {
          bIdle = FALSE;
        }
      }
      do {
        if (FWL_ERR_Indefinite == pWidgetMgr->DispatchMessage_Native()) {
          break;
        }
        if (pWidgetMgr->IsIdleMessage_Native()) {
          bIdle = TRUE;
          iIdleCount = 0;
        }
      } while (pWidgetMgr->CheckMessage_Native());
    }
#elif(_FX_OS_ == _FX_LINUX_DESKTOP_)
    CFWL_NoteLoop* pTopLoop = NULL;
    for (;;) {
      pTopLoop = GetTopLoop();
      if (!pTopLoop || !pTopLoop->ContinueModal()) {
        break;
      }
      if (UnqueueMessage(pTopLoop)) {
        continue;
      }
      if (pWidgetMgr->CheckMessage_Native()) {
        pWidgetMgr->DispatchMessage_Native();
      }
    }
#endif
  return FWL_ERR_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 : NULL;
}
void CFWL_NoteDriver::NotifyTargetHide(IFWL_Widget* pNoteTarget) {
  if (m_pFocus == pNoteTarget) {
    m_pFocus = NULL;
  }
  if (m_pHover == pNoteTarget) {
    m_pHover = NULL;
  }
  if (m_pGrab == pNoteTarget) {
    m_pGrab = NULL;
  }
}
void CFWL_NoteDriver::NotifyTargetDestroy(IFWL_Widget* pNoteTarget) {
  if (m_pFocus == pNoteTarget) {
    m_pFocus = NULL;
  }
  if (m_pHover == pNoteTarget) {
    m_pHover = NULL;
  }
  if (m_pGrab == pNoteTarget) {
    m_pGrab = NULL;
  }
  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(NULL);
    }
  }
}

FWL_ERR CFWL_NoteDriver::RegisterForm(CFWL_WidgetImp* pForm) {
  if (!pForm)
    return FWL_ERR_Indefinite;
  if (m_forms.Find(pForm) >= 0) {
    return FWL_ERR_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_ERR_Indefinite;
    pLoop->SetMainForm(pForm);
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_NoteDriver::UnRegisterForm(CFWL_WidgetImp* pForm) {
  if (!pForm)
    return FWL_ERR_Indefinite;
  int32_t nIndex = m_forms.Find(pForm);
  if (nIndex < 0) {
    return FWL_ERR_Indefinite;
  }
  m_forms.RemoveAt(nIndex);
  return FWL_ERR_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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  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(NULL);
    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() == 1111984755) {
      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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  if (pWidgetMgr->IsFormDisabled()) {
    m_pFocus = pMsg->m_pDstTarget;
    return TRUE;
  } else {
    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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  if (pWidgetMgr->IsFormDisabled()) {
    if (m_pFocus == pMsg->m_pDstTarget) {
      m_pFocus = NULL;
    }
    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 = NULL;
        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_MSGKEYCMD_KeyDown &&
      pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
    CFWL_WidgetMgr* pWidgetMgr =
        static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    IFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
    IFWL_Widget* pFocus = m_pFocus;
    if (m_pFocus) {
      if (pWidgetMgr->GetWidget(m_pFocus, FWL_WGTRELATION_SystemForm) !=
          pForm) {
        pFocus = NULL;
      }
    }
    FX_BOOL bFind = FALSE;
    IFWL_Widget* pNextTabStop = pWidgetMgr->nextTab(pForm, pFocus, bFind);
    if (!pNextTabStop) {
      bFind = FALSE;
      pNextTabStop = pWidgetMgr->nextTab(pForm, NULL, bFind);
    }
    if (pNextTabStop == pFocus) {
      return TRUE;
    }
    if (pNextTabStop) {
      SetFocus(pNextTabStop);
    }
    return TRUE;
  }
#endif
  if (!m_pFocus) {
    if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown &&
        pMsg->m_dwKeyCode == FWL_VKEY_Return) {
      CFWL_WidgetMgr* pWidgetMgr =
          static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
      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_MSGMOUSECMD_MouseLeave ||
      pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseHover ||
      pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseEnter) {
    return pMsg->m_pDstTarget != NULL;
  }
  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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  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 = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
  if (!pWidgetMgr)
    return FALSE;
  IFWL_Widget* pTarget = NULL;
  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_MSGMOUSECMD_MouseLeave;
    DispatchMessage(&msLeave, NULL);
  }
  if (pTarget->GetClassID() == FWL_CLASSHASH_Form) {
    m_pHover = NULL;
    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_MSGMOUSECMD_MouseHover;
  DispatchMessage(&msHover, NULL);
}
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 =
        static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    if (!pWidgetMgr)
      return nullptr;
    pMessageForm =
        pWidgetMgr->GetWidget(pDstTarget, FWL_WGTRELATION_SystemForm);
  }
  return pMessageForm;
}

void CFWL_NoteDriver::ClearInvalidEventTargets(FX_BOOL bRemoveAll) {
  FX_POSITION pos = m_eventTargets.GetStartPosition();
  while (pos) {
    void* key = NULL;
    CFWL_EventTarget* pEventTarget = NULL;
    m_eventTargets.GetNextAssoc(pos, key, (void*&)pEventTarget);
    if (pEventTarget && (bRemoveAll || pEventTarget->IsInvalid())) {
      m_eventTargets.RemoveKey(key);
      delete pEventTarget;
    }
  }
}
class CFWL_CoreToolTipDP : public IFWL_ToolTipDP {
 public:
  FWL_ERR GetCaption(IFWL_Widget* pWidget, CFX_WideString& wsCaption);
  int32_t GetInitialDelay(IFWL_Widget* pWidget);
  int32_t GetAutoPopDelay(IFWL_Widget* pWidget);
  CFX_DIBitmap* GetToolTipIcon(IFWL_Widget* pWidget);
  CFX_SizeF GetToolTipIconSize(IFWL_Widget* pWidget);
  CFX_RectF GetAnchor();
  CFWL_CoreToolTipDP();

  CFX_WideString m_wsCaption;
  int32_t m_nInitDelayTime;
  int32_t m_nAutoPopDelayTime;
  CFX_RectF m_fAnchor;
};
CFWL_CoreToolTipDP::CFWL_CoreToolTipDP() {
  m_nInitDelayTime = 500;
  m_nAutoPopDelayTime = 50000;
  m_fAnchor.Set(0.0, 0.0, 0.0, 0.0);
}
FWL_ERR CFWL_CoreToolTipDP::GetCaption(IFWL_Widget* pWidget,
                                       CFX_WideString& wsCaption) {
  wsCaption = m_wsCaption;
  return FWL_ERR_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 NULL;
}
CFX_SizeF CFWL_CoreToolTipDP::GetToolTipIconSize(IFWL_Widget* pWidget) {
  return CFX_SizeF();
}
CFX_RectF CFWL_CoreToolTipDP::GetAnchor() {
  return m_fAnchor;
}
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(NULL);
  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 = NULL;
    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;

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

CFWL_ToolTipContainer* CFWL_ToolTipContainer::s_pInstance = NULL;

CFWL_ToolTipContainer::CFWL_ToolTipContainer()
    : pCurTarget(NULL), m_pToolTipImp(NULL) {
  m_ToolTipDp = new CFWL_CoreToolTipDP;
  m_ToolTipDp->m_nInitDelayTime = 0;
  m_ToolTipDp->m_nAutoPopDelayTime = 2000;
}
CFWL_ToolTipContainer::~CFWL_ToolTipContainer() {
  if (m_pToolTipImp) {
    IFWL_ToolTip* pToolTip =
        static_cast<IFWL_ToolTip*>(m_pToolTipImp->GetInterface());
    pToolTip->Finalize();
    delete pToolTip;
  }
  delete m_ToolTipDp;
}

// 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 = NULL;
}

FX_ERR CFWL_ToolTipContainer::AddToolTipTarget(IFWL_ToolTipTarget* pTarget) {
  if (m_arrWidget.Find(pTarget) < 0) {
    m_arrWidget.Add(pTarget);
    return FWL_ERR_Succeeded;
  }
  return FWL_ERR_Indefinite;
}
FX_ERR CFWL_ToolTipContainer::RemoveToolTipTarget(IFWL_ToolTipTarget* pTarget) {
  int index = m_arrWidget.Find(pTarget);
  if (index >= 0) {
    m_arrWidget.RemoveAt(index);
    return FWL_ERR_Succeeded;
  }
  return FWL_ERR_Indefinite;
}
FX_BOOL CFWL_ToolTipContainer::HasToolTip(IFWL_Widget* pWedget) {
  int32_t iCount = m_arrWidget.GetSize();
  for (int32_t i = 0; i < iCount; i++) {
    IFWL_ToolTipTarget* p = m_arrWidget[i];
    if (p->GetWidget() == pWedget) {
      pCurTarget = p;
      return TRUE;
    }
  }
  return FALSE;
}
FX_BOOL CFWL_ToolTipContainer::ProcessEnter(CFWL_EvtMouse* pEvt,
                                            IFWL_Widget* pOwner) {
  if (HasToolTip(pEvt->m_pDstTarget)) {
    if (NULL == m_pToolTipImp) {
      CFWL_WidgetImpProperties prop;
      prop.m_pDataProvider = m_ToolTipDp;
      prop.m_pOwner = pOwner;
      CFX_RectF rtTooltip;
      rtTooltip.Set(150, 150, 100, 50);
      prop.m_rtWidget = rtTooltip;
      IFWL_ToolTip* pToolTip = IFWL_ToolTip::Create(prop, nullptr);
      pToolTip->Initialize();
      m_pToolTipImp = static_cast<CFWL_ToolTipImp*>(pToolTip->GetImpl());
      m_pToolTipImp->ModifyStylesEx(FWL_STYLEEXT_TTP_Multiline, 0);
      m_pToolTipImp->SetStates(FWL_WGTSTATE_Invisible, TRUE);
    }
    if (pCurTarget->IsShowed()) {
      CFX_WideString wsCaption;
      pCurTarget->GetCaption(wsCaption);
      if (!wsCaption.IsEmpty()) {
        m_ToolTipDp->m_wsCaption = wsCaption;
      }
      CFX_RectF rt;
      CFX_SizeF sz;
      pCurTarget->GetToolTipSize(sz);
      if (sz.x > 0 && sz.y > 0) {
        rt.width = sz.x;
        rt.height = sz.y;
      } else {
        CFX_RectF r;
        m_pToolTipImp->GetWidgetRect(r, TRUE);
        rt.width = r.width;
        rt.height = r.height;
      }
      CFX_PointF pt(pEvt->m_fx, pEvt->m_fy);
      if (pCurTarget->GetToolTipPos(pt) == FWL_ERR_Succeeded) {
        rt.left = pt.x;
        rt.top = pt.y;
        m_pToolTipImp->ModifyStylesEx(FWL_STYLEEXT_TTP_NoAnchor, 0);
      } else {
        CFX_RectF rtAnchor;
        pCurTarget->GetWidget()->GetClientRect(rtAnchor);
        pCurTarget->GetWidget()->TransformTo(NULL, rtAnchor.left, rtAnchor.top);
        m_pToolTipImp->SetAnchor(rtAnchor);
        m_pToolTipImp->ModifyStylesEx(0, FWL_STYLEEXT_TTP_NoAnchor);
      }
      m_pToolTipImp->SetWidgetRect(rt);
      m_pToolTipImp->Update();
      m_pToolTipImp->Show();
    }
    return TRUE;
  }
  return FALSE;
}
FX_BOOL CFWL_ToolTipContainer::ProcessLeave(CFWL_EvtMouse* pEvt) {
  if (HasToolTip(pEvt->m_pDstTarget) && NULL != m_pToolTipImp) {
    m_pToolTipImp->Hide();
    pCurTarget = NULL;
    return TRUE;
  }
  return FALSE;
}
IFWL_ToolTipTarget* CFWL_ToolTipContainer::GetCurrentToolTipTarget() {
  return pCurTarget;
}
