Home | History | Annotate | Download | only in core
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
      9 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_panelimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_formimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     14 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
     15 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
     16 #include "xfa/src/fwl/src/basewidget/include/fwl_tooltipctrlimp.h"
     17 CFWL_NoteLoop::CFWL_NoteLoop(CFWL_WidgetImp* pForm)
     18     : m_pForm(pForm), m_bContinueModal(TRUE) {}
     19 FX_BOOL CFWL_NoteLoop::PreProcessMessage(CFWL_Message* pMessage) {
     20   if (!m_pForm) {
     21     return FALSE;
     22   }
     23   return TranslateAccelerator(pMessage);
     24 }
     25 FWL_ERR CFWL_NoteLoop::Idle(int32_t count) {
     26 #if (_FX_OS_ == _FX_WIN32_DESKTOP_)
     27   if (count <= 0)
     28 #endif
     29   {
     30     CFWL_EvtIdle ev;
     31     IFWL_App* pApp = FWL_GetApp();
     32     if (!pApp)
     33       return FWL_ERR_Indefinite;
     34     IFWL_NoteDriver* pDriver = pApp->GetNoteDriver();
     35     if (!pDriver)
     36       return FWL_ERR_Indefinite;
     37     pDriver->SendNote(&ev);
     38   }
     39   return FWL_ERR_Indefinite;
     40 }
     41 CFWL_WidgetImp* CFWL_NoteLoop::GetForm() {
     42   return m_pForm;
     43 }
     44 FX_BOOL CFWL_NoteLoop::ContinueModal() {
     45   return m_bContinueModal;
     46 }
     47 FWL_ERR CFWL_NoteLoop::EndModalLoop() {
     48   m_bContinueModal = FALSE;
     49 #if (_FX_OS_ == _FX_MACOSX_)
     50   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
     51   IFWL_AdapterWidgetMgr* adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();
     52   adapterWidgetMgr->EndLoop();
     53 #endif
     54   return FWL_ERR_Succeeded;
     55 }
     56 FX_BOOL CFWL_NoteLoop::TranslateAccelerator(CFWL_Message* pMessage) {
     57   if (pMessage->GetClassID() != FWL_MSGHASH_Key) {
     58     return FALSE;
     59   }
     60   CFWL_MsgKey* pMsgKey = static_cast<CFWL_MsgKey*>(pMessage);
     61   if (pMsgKey->m_dwCmd != FWL_MSGKEYCMD_KeyDown) {
     62     return FALSE;
     63   }
     64   CFX_MapAccelerators& accel =
     65       static_cast<CFWL_FormImp*>(m_pForm)->GetAccelerator();
     66   FX_POSITION pos = accel.GetStartPosition();
     67   if (!pos) {
     68     return FALSE;
     69   }
     70   FX_DWORD vrKey, rValue;
     71   while (pos) {
     72     accel.GetNextAssoc(pos, vrKey, rValue);
     73     FX_DWORD dwFlags = (vrKey & 0xFF00) >> 8;
     74     FX_DWORD m_dwKeyCode = vrKey & 0x00FF;
     75     if (pMsgKey->m_dwFlags == dwFlags && pMsgKey->m_dwKeyCode == m_dwKeyCode) {
     76       GenerateCommondEvent(rValue);
     77       return TRUE;
     78     }
     79   }
     80   return FALSE;
     81 }
     82 FWL_ERR CFWL_NoteLoop::SetMainForm(CFWL_WidgetImp* pForm) {
     83   m_pForm = pForm;
     84   return FWL_ERR_Succeeded;
     85 }
     86 void CFWL_NoteLoop::GenerateCommondEvent(FX_DWORD dwCommand) {
     87   CFWL_EvtMenuCommand ev;
     88   ev.m_iCommand = dwCommand;
     89   IFWL_NoteThread* pThread = m_pForm->GetOwnerThread();
     90   if (!pThread)
     91     return;
     92   IFWL_NoteDriver* pDriver = pThread->GetNoteDriver();
     93   if (!pDriver)
     94     return;
     95   pDriver->SendNote(&ev);
     96 }
     97 CFWL_NoteDriver::CFWL_NoteDriver()
     98     : m_sendEventCalled(0),
     99       m_maxSize(500),
    100       m_bFullScreen(FALSE),
    101       m_pHover(nullptr),
    102       m_pFocus(nullptr),
    103       m_pGrab(nullptr),
    104       m_hook(nullptr) {
    105   m_pNoteLoop = new CFWL_NoteLoop;
    106   PushNoteLoop(m_pNoteLoop);
    107 }
    108 CFWL_NoteDriver::~CFWL_NoteDriver() {
    109   delete m_pNoteLoop;
    110   ClearInvalidEventTargets(TRUE);
    111 }
    112 FX_BOOL CFWL_NoteDriver::SendNote(CFWL_Note* pNote) {
    113   if (pNote->IsEvent()) {
    114     int32_t iCount = m_eventTargets.GetCount();
    115     if (iCount < 1) {
    116       return TRUE;
    117     }
    118     if (FWL_EVTHASH_Mouse == static_cast<CFWL_Event*>(pNote)->GetClassID()) {
    119       CFWL_EvtMouse* pMouse = static_cast<CFWL_EvtMouse*>(pNote);
    120       if (FWL_MSGMOUSECMD_MouseHover == pMouse->m_dwCmd) {
    121         if (m_pNoteLoop->GetForm() &&
    122             CFWL_ToolTipContainer::getInstance()->ProcessEnter(
    123                 pMouse, m_pNoteLoop->GetForm()->GetInterface())) {
    124         }
    125       } else if (FWL_MSGMOUSECMD_MouseLeave == pMouse->m_dwCmd) {
    126         if (CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse)) {
    127         }
    128       } else if ((FWL_MSGMOUSECMD_LButtonDown <= pMouse->m_dwCmd) &&
    129                  (FWL_MSGMOUSECMD_MButtonDblClk >= pMouse->m_dwCmd)) {
    130         if (CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse)) {
    131         }
    132       }
    133     }
    134     m_sendEventCalled++;
    135     FX_POSITION pos = m_eventTargets.GetStartPosition();
    136     while (pos) {
    137       void* key = NULL;
    138       CFWL_EventTarget* pEventTarget;
    139       m_eventTargets.GetNextAssoc(pos, key, (void*&)pEventTarget);
    140       if (pEventTarget && !pEventTarget->IsInvalid()) {
    141         pEventTarget->ProcessEvent(static_cast<CFWL_Event*>(pNote));
    142       }
    143     }
    144     m_sendEventCalled--;
    145   } else {
    146     if (!pNote->m_pDstTarget)
    147       return FALSE;
    148     IFWL_WidgetDelegate* pDelegate = pNote->m_pDstTarget->SetDelegate(NULL);
    149     if (pDelegate) {
    150       pDelegate->OnProcessMessage(static_cast<CFWL_Message*>(pNote));
    151     }
    152   }
    153   return TRUE;
    154 }
    155 extern void FWL_PostMessageToMainRoop(CFWL_Message* pMessage);
    156 FX_BOOL CFWL_NoteDriver::PostMessage(CFWL_Message* pMessage) {
    157   FWL_PostMessageToMainRoop(pMessage);
    158   return TRUE;
    159 }
    160 #define FWL_NoteDriver_EventKey 1100
    161 FWL_ERR CFWL_NoteDriver::RegisterEventTarget(IFWL_Widget* pListener,
    162                                              IFWL_Widget* pEventSource,
    163                                              FX_DWORD dwFilter) {
    164   FX_DWORD dwkey = (FX_DWORD)(uintptr_t)pListener->GetPrivateData(
    165       (void*)(uintptr_t)FWL_NoteDriver_EventKey);
    166   if (dwkey == 0) {
    167     void* random = FX_Random_MT_Start(0);
    168     dwkey = rand();
    169     FX_Random_MT_Close(random);
    170     pListener->SetPrivateData((void*)(uintptr_t)FWL_NoteDriver_EventKey,
    171                               (void*)(uintptr_t)dwkey, NULL);
    172   }
    173   CFWL_EventTarget* value = NULL;
    174   if (!m_eventTargets.Lookup((void*)(uintptr_t)dwkey, (void*&)value)) {
    175     value = new CFWL_EventTarget(this, pListener);
    176     m_eventTargets.SetAt((void*)(uintptr_t)dwkey, value);
    177   }
    178   value->SetEventSource(pEventSource, dwFilter);
    179   return FWL_ERR_Succeeded;
    180 }
    181 FWL_ERR CFWL_NoteDriver::UnregisterEventTarget(IFWL_Widget* pListener) {
    182   FX_DWORD dwkey = (FX_DWORD)(uintptr_t)pListener->GetPrivateData(
    183       (void*)(uintptr_t)FWL_NoteDriver_EventKey);
    184   if (dwkey == 0) {
    185     return FWL_ERR_Indefinite;
    186   }
    187   CFWL_EventTarget* value = NULL;
    188   if (m_eventTargets.Lookup((void*)(uintptr_t)dwkey, (void*&)value)) {
    189     value->FlagInvalid();
    190   }
    191   return FWL_ERR_Succeeded;
    192 }
    193 void CFWL_NoteDriver::ClearEventTargets(FX_BOOL bRemoveAll) {
    194   ClearInvalidEventTargets(bRemoveAll);
    195 }
    196 int32_t CFWL_NoteDriver::GetQueueMaxSize() const {
    197   return m_maxSize;
    198 }
    199 FWL_ERR CFWL_NoteDriver::SetQueueMaxSize(const int32_t size) {
    200   m_maxSize = size;
    201   return FWL_ERR_Succeeded;
    202 }
    203 IFWL_NoteThread* CFWL_NoteDriver::GetOwnerThread() const {
    204   return FWL_GetApp();
    205 }
    206 FWL_ERR CFWL_NoteDriver::PushNoteLoop(IFWL_NoteLoop* pNoteLoop) {
    207   m_noteLoopQueue.Add(pNoteLoop);
    208   return FWL_ERR_Succeeded;
    209 }
    210 IFWL_NoteLoop* CFWL_NoteDriver::PopNoteLoop() {
    211   int32_t pos = m_noteLoopQueue.GetSize();
    212   if (pos <= 0)
    213     return NULL;
    214   IFWL_NoteLoop* p =
    215       static_cast<IFWL_NoteLoop*>(m_noteLoopQueue.GetAt(pos - 1));
    216   m_noteLoopQueue.RemoveAt(pos - 1);
    217   return p;
    218 }
    219 FX_BOOL CFWL_NoteDriver::SetFocus(IFWL_Widget* pFocus, FX_BOOL bNotify) {
    220   if (m_pFocus == pFocus) {
    221     return TRUE;
    222   }
    223   IFWL_Widget* pPrev = m_pFocus;
    224   m_pFocus = pFocus;
    225   if (pPrev) {
    226     CFWL_MsgKillFocus ms;
    227     ms.m_pDstTarget = pPrev;
    228     ms.m_pSrcTarget = pPrev;
    229     if (bNotify) {
    230       ms.m_dwExtend = 1;
    231     }
    232     IFWL_WidgetDelegate* pDelegate = pPrev->SetDelegate(NULL);
    233     if (pDelegate) {
    234       pDelegate->OnProcessMessage(&ms);
    235     }
    236   }
    237   if (pFocus) {
    238     IFWL_Widget* pWidget =
    239         FWL_GetWidgetMgr()->GetWidget(pFocus, FWL_WGTRELATION_SystemForm);
    240     CFWL_FormImp* pForm =
    241         pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
    242     if (pForm) {
    243       CFWL_WidgetImp* pNewFocus =
    244           static_cast<CFWL_WidgetImp*>(pFocus->GetImpl());
    245       pForm->SetSubFocus(pNewFocus);
    246     }
    247     CFWL_MsgSetFocus ms;
    248     ms.m_pDstTarget = pFocus;
    249     if (bNotify) {
    250       ms.m_dwExtend = 1;
    251     }
    252     IFWL_WidgetDelegate* pDelegate = pFocus->SetDelegate(NULL);
    253     if (pDelegate) {
    254       pDelegate->OnProcessMessage(&ms);
    255     }
    256   }
    257   return TRUE;
    258 }
    259 FWL_ERR CFWL_NoteDriver::Run() {
    260   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    261   if (!pWidgetMgr)
    262     return FWL_ERR_Indefinite;
    263 #if (_FX_OS_ == _FX_MACOSX_)
    264   IFWL_AdapterWidgetMgr* adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();
    265   CFWL_NoteLoop* pTopLoop = GetTopLoop();
    266   if (pTopLoop) {
    267     CFWL_WidgetImp* formImp = pTopLoop->GetForm();
    268     if (formImp) {
    269       IFWL_Widget* pForm = formImp->GetInterface();
    270       adapterWidgetMgr->RunLoop(pForm);
    271     }
    272   }
    273 #elif(_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_)
    274   FX_BOOL bIdle = TRUE;
    275   int32_t iIdleCount = 0;
    276   CFWL_NoteLoop* pTopLoop = NULL;
    277   for (;;) {
    278     pTopLoop = GetTopLoop();
    279     if (!pTopLoop || !pTopLoop->ContinueModal()) {
    280       break;
    281     }
    282     if (UnqueueMessage(pTopLoop)) {
    283       continue;
    284     }
    285     while (bIdle && !(pWidgetMgr->CheckMessage_Native())) {
    286       if (FWL_ERR_Indefinite == pTopLoop->Idle(iIdleCount++)) {
    287         bIdle = FALSE;
    288       }
    289     }
    290     do {
    291       if (FWL_ERR_Indefinite == pWidgetMgr->DispatchMessage_Native()) {
    292         break;
    293       }
    294       if (pWidgetMgr->IsIdleMessage_Native()) {
    295         bIdle = TRUE;
    296         iIdleCount = 0;
    297       }
    298     } while (pWidgetMgr->CheckMessage_Native());
    299   }
    300 #elif(_FX_OS_ == _FX_LINUX_DESKTOP_)
    301   CFWL_NoteLoop* pTopLoop = NULL;
    302   for (;;) {
    303     pTopLoop = GetTopLoop();
    304     if (!pTopLoop || !pTopLoop->ContinueModal()) {
    305       break;
    306     }
    307     if (UnqueueMessage(pTopLoop)) {
    308       continue;
    309     }
    310     if (pWidgetMgr->CheckMessage_Native()) {
    311       pWidgetMgr->DispatchMessage_Native();
    312     }
    313   }
    314 #endif
    315   return FWL_ERR_Succeeded;
    316 }
    317 IFWL_Widget* CFWL_NoteDriver::GetFocus() {
    318   return m_pFocus;
    319 }
    320 IFWL_Widget* CFWL_NoteDriver::GetHover() {
    321   return m_pHover;
    322 }
    323 void CFWL_NoteDriver::SetHover(IFWL_Widget* pHover) {
    324   m_pHover = pHover;
    325 }
    326 void CFWL_NoteDriver::SetGrab(IFWL_Widget* pGrab, FX_BOOL bSet) {
    327   m_pGrab = bSet ? pGrab : NULL;
    328 }
    329 void CFWL_NoteDriver::NotifyTargetHide(IFWL_Widget* pNoteTarget) {
    330   if (m_pFocus == pNoteTarget) {
    331     m_pFocus = NULL;
    332   }
    333   if (m_pHover == pNoteTarget) {
    334     m_pHover = NULL;
    335   }
    336   if (m_pGrab == pNoteTarget) {
    337     m_pGrab = NULL;
    338   }
    339 }
    340 void CFWL_NoteDriver::NotifyTargetDestroy(IFWL_Widget* pNoteTarget) {
    341   if (m_pFocus == pNoteTarget) {
    342     m_pFocus = NULL;
    343   }
    344   if (m_pHover == pNoteTarget) {
    345     m_pHover = NULL;
    346   }
    347   if (m_pGrab == pNoteTarget) {
    348     m_pGrab = NULL;
    349   }
    350   UnregisterEventTarget(pNoteTarget);
    351   int32_t count = m_forms.GetSize();
    352   for (int32_t nIndex = 0; nIndex < count; nIndex++) {
    353     CFWL_FormImp* pForm = static_cast<CFWL_FormImp*>(m_forms[nIndex]);
    354     if (!pForm) {
    355       continue;
    356     }
    357     CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    358     if (!pSubFocus)
    359       return;
    360     if (pSubFocus && pSubFocus->GetInterface() == pNoteTarget) {
    361       pForm->SetSubFocus(NULL);
    362     }
    363   }
    364 }
    365 void CFWL_NoteDriver::NotifyFullScreenMode(IFWL_Widget* pNoteTarget,
    366                                            FX_BOOL bFullScreen) {
    367   m_bFullScreen = bFullScreen;
    368 }
    369 FWL_ERR CFWL_NoteDriver::RegisterForm(CFWL_WidgetImp* pForm) {
    370   if (!pForm)
    371     return FWL_ERR_Indefinite;
    372   if (m_forms.Find(pForm) >= 0) {
    373     return FWL_ERR_Indefinite;
    374   }
    375   m_forms.Add(pForm);
    376   if (m_forms.GetSize() == 1) {
    377     CFWL_NoteLoop* pLoop =
    378         static_cast<CFWL_NoteLoop*>(m_noteLoopQueue.GetAt(0));
    379     if (!pLoop)
    380       return FWL_ERR_Indefinite;
    381     pLoop->SetMainForm(pForm);
    382   }
    383   return FWL_ERR_Succeeded;
    384 }
    385 FWL_ERR CFWL_NoteDriver::UnRegisterForm(CFWL_WidgetImp* pForm) {
    386   if (!pForm)
    387     return FWL_ERR_Indefinite;
    388   int32_t nIndex = m_forms.Find(pForm);
    389   if (nIndex < 0) {
    390     return FWL_ERR_Indefinite;
    391   }
    392   m_forms.RemoveAt(nIndex);
    393   return FWL_ERR_Succeeded;
    394 }
    395 FX_BOOL CFWL_NoteDriver::QueueMessage(CFWL_Message* pMessage) {
    396   pMessage->Retain();
    397   m_noteQueue.Add(pMessage);
    398   return TRUE;
    399 }
    400 FX_BOOL CFWL_NoteDriver::UnqueueMessage(CFWL_NoteLoop* pNoteLoop) {
    401   if (m_noteQueue.GetSize() < 1) {
    402     return FALSE;
    403   }
    404   CFWL_Message* pMessage = static_cast<CFWL_Message*>(m_noteQueue[0]);
    405   m_noteQueue.RemoveAt(0);
    406   if (!IsValidMessage(pMessage)) {
    407     pMessage->Release();
    408     return TRUE;
    409   }
    410   FX_BOOL bHookMessage = FALSE;
    411   if (m_hook) {
    412     bHookMessage = (*m_hook)(pMessage, m_hookInfo);
    413   }
    414   if (!bHookMessage && !pNoteLoop->PreProcessMessage(pMessage)) {
    415     ProcessMessage(pMessage);
    416   }
    417   pMessage->Release();
    418   return TRUE;
    419 }
    420 CFWL_NoteLoop* CFWL_NoteDriver::GetTopLoop() {
    421   int32_t size = m_noteLoopQueue.GetSize();
    422   if (size <= 0)
    423     return NULL;
    424   return static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[size - 1]);
    425 }
    426 int32_t CFWL_NoteDriver::CountLoop() {
    427   return m_noteLoopQueue.GetSize();
    428 }
    429 void CFWL_NoteDriver::SetHook(FWLMessageHookCallback callback, void* info) {
    430   m_hook = callback;
    431   m_hookInfo = info;
    432 }
    433 FX_BOOL CFWL_NoteDriver::ProcessMessage(CFWL_Message* pMessage) {
    434   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    435   IFWL_Widget* pMessageForm = pWidgetMgr->IsFormDisabled()
    436                                   ? pMessage->m_pDstTarget
    437                                   : GetMessageForm(pMessage->m_pDstTarget);
    438   if (!pMessageForm)
    439     return FALSE;
    440   if (DispatchMessage(pMessage, pMessageForm)) {
    441     if (pMessage->GetClassID() == FWL_MSGHASH_Mouse) {
    442       MouseSecondary(static_cast<CFWL_MsgMouse*>(pMessage));
    443     }
    444     return TRUE;
    445   }
    446   return FALSE;
    447 }
    448 FX_BOOL CFWL_NoteDriver::DispatchMessage(CFWL_Message* pMessage,
    449                                          IFWL_Widget* pMessageForm) {
    450   FX_BOOL bRet = FALSE;
    451   switch (pMessage->GetClassID()) {
    452     case FWL_MSGHASH_Activate: {
    453       bRet = DoActivate(static_cast<CFWL_MsgActivate*>(pMessage), pMessageForm);
    454       break;
    455     }
    456     case FWL_MSGHASH_Deactivate: {
    457       bRet = DoDeactivate(static_cast<CFWL_MsgDeactivate*>(pMessage),
    458                           pMessageForm);
    459       break;
    460     }
    461     case FWL_MSGHASH_SetFocus: {
    462       bRet = DoSetFocus(static_cast<CFWL_MsgSetFocus*>(pMessage), pMessageForm);
    463       break;
    464     }
    465     case FWL_MSGHASH_KillFocus: {
    466       bRet =
    467           DoKillFocus(static_cast<CFWL_MsgKillFocus*>(pMessage), pMessageForm);
    468       break;
    469     }
    470     case FWL_MSGHASH_Key: {
    471       bRet = DoKey(static_cast<CFWL_MsgKey*>(pMessage), pMessageForm);
    472       break;
    473     }
    474     case FWL_MSGHASH_Mouse: {
    475       bRet = DoMouse(static_cast<CFWL_MsgMouse*>(pMessage), pMessageForm);
    476       break;
    477     }
    478     case FWL_MSGHASH_MouseWheel: {
    479       bRet = DoWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage), pMessageForm);
    480       break;
    481     }
    482     case FWL_MSGHASH_Size: {
    483       bRet = DoSize(static_cast<CFWL_MsgSize*>(pMessage));
    484       break;
    485     }
    486     case FWL_MSGHASH_Cursor: {
    487       bRet = TRUE;
    488       break;
    489     }
    490     case FWL_MSGHASH_WindowMove: {
    491       bRet = DoWindowMove(static_cast<CFWL_MsgWindowMove*>(pMessage),
    492                           pMessageForm);
    493       break;
    494     }
    495     case FWL_MSGHASH_DropFiles: {
    496       bRet =
    497           DoDragFiles(static_cast<CFWL_MsgDropFiles*>(pMessage), pMessageForm);
    498       break;
    499     }
    500     default: {
    501       bRet = TRUE;
    502       break;
    503     }
    504   }
    505   if (bRet) {
    506     IFWL_WidgetDelegate* pDelegate = pMessage->m_pDstTarget->SetDelegate(NULL);
    507     if (pDelegate) {
    508       pDelegate->OnProcessMessage(pMessage);
    509     }
    510   }
    511   return bRet;
    512 }
    513 FX_BOOL CFWL_NoteDriver::DoActivate(CFWL_MsgActivate* pMsg,
    514                                     IFWL_Widget* pMessageForm) {
    515   if (m_bFullScreen) {
    516     return FALSE;
    517   }
    518   pMsg->m_pDstTarget = pMessageForm;
    519   return (pMsg->m_pDstTarget)->GetStates() & FWL_WGTSTATE_Deactivated;
    520 }
    521 FX_BOOL CFWL_NoteDriver::DoDeactivate(CFWL_MsgDeactivate* pMsg,
    522                                       IFWL_Widget* pMessageForm) {
    523   if (m_bFullScreen) {
    524     return FALSE;
    525   }
    526   int32_t iTrackLoop = m_noteLoopQueue.GetSize();
    527   if (iTrackLoop <= 0)
    528     return FALSE;
    529   if (iTrackLoop == 1) {
    530     if (pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {
    531       return FALSE;
    532     }
    533     if (pMsg->m_pSrcTarget &&
    534         pMsg->m_pSrcTarget->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {
    535       return FALSE;
    536     }
    537     if (pMsg->m_pSrcTarget && pMsg->m_pSrcTarget->GetClassID() == 1111984755) {
    538       return FALSE;
    539     }
    540     return TRUE;
    541   }
    542   IFWL_Widget* pDst = pMsg->m_pDstTarget;
    543   if (!pDst)
    544     return FALSE;
    545 #if (_FX_OS_ == _FX_MACOSX_)
    546   if (pDst == pMessageForm && pDst->IsInstance(L"FWL_FORMPROXY")) {
    547     return TRUE;
    548   }
    549 #endif
    550   return pDst != pMessageForm &&
    551          !pDst->IsInstance(FX_WSTRC(L"FWL_FORMPROXY")) &&
    552          !pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"));
    553 }
    554 FX_BOOL CFWL_NoteDriver::DoSetFocus(CFWL_MsgSetFocus* pMsg,
    555                                     IFWL_Widget* pMessageForm) {
    556   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    557   if (pWidgetMgr->IsFormDisabled()) {
    558     m_pFocus = pMsg->m_pDstTarget;
    559     return TRUE;
    560   } else {
    561     IFWL_Widget* pWidget = pMsg->m_pDstTarget;
    562     CFWL_FormImp* pForm =
    563         pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
    564     if (pForm) {
    565       CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    566       if (pSubFocus && ((pSubFocus->GetStates() & FWL_WGTSTATE_Focused) == 0)) {
    567         pMsg->m_pDstTarget = pSubFocus->GetInterface();
    568         if (m_pFocus != pMsg->m_pDstTarget) {
    569           m_pFocus = pMsg->m_pDstTarget;
    570           return TRUE;
    571         }
    572       }
    573     }
    574   }
    575   return FALSE;
    576 }
    577 FX_BOOL CFWL_NoteDriver::DoKillFocus(CFWL_MsgKillFocus* pMsg,
    578                                      IFWL_Widget* pMessageForm) {
    579   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    580   if (pWidgetMgr->IsFormDisabled()) {
    581     if (m_pFocus == pMsg->m_pDstTarget) {
    582       m_pFocus = NULL;
    583     }
    584     return TRUE;
    585   }
    586   IFWL_Widget* pWidget = pMsg->m_pDstTarget;
    587   CFWL_FormImp* pForm =
    588       pWidget ? static_cast<CFWL_FormImp*>(pWidget->GetImpl()) : nullptr;
    589   if (pForm) {
    590     CFWL_WidgetImp* pSubFocus = pForm->GetSubFocus();
    591     if (pSubFocus && (pSubFocus->GetStates() & FWL_WGTSTATE_Focused)) {
    592       pMsg->m_pDstTarget = pSubFocus->GetInterface();
    593       if (m_pFocus == pMsg->m_pDstTarget) {
    594         m_pFocus = NULL;
    595         return TRUE;
    596       }
    597     }
    598   }
    599   return FALSE;
    600 }
    601 FX_BOOL CFWL_NoteDriver::DoKey(CFWL_MsgKey* pMsg, IFWL_Widget* pMessageForm) {
    602 #if (_FX_OS_ != _FX_MACOSX_)
    603   if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown &&
    604       pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
    605     CFWL_WidgetMgr* pWidgetMgr =
    606         static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    607     IFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
    608     IFWL_Widget* pFocus = m_pFocus;
    609     if (m_pFocus) {
    610       if (pWidgetMgr->GetWidget(m_pFocus, FWL_WGTRELATION_SystemForm) !=
    611           pForm) {
    612         pFocus = NULL;
    613       }
    614     }
    615     FX_BOOL bFind = FALSE;
    616     IFWL_Widget* pNextTabStop = pWidgetMgr->nextTab(pForm, pFocus, bFind);
    617     if (!pNextTabStop) {
    618       bFind = FALSE;
    619       pNextTabStop = pWidgetMgr->nextTab(pForm, NULL, bFind);
    620     }
    621     if (pNextTabStop == pFocus) {
    622       return TRUE;
    623     }
    624     if (pNextTabStop) {
    625       SetFocus(pNextTabStop);
    626     }
    627     return TRUE;
    628   }
    629 #endif
    630   if (!m_pFocus) {
    631     if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown &&
    632         pMsg->m_dwKeyCode == FWL_VKEY_Return) {
    633       CFWL_WidgetMgr* pWidgetMgr =
    634           static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    635       IFWL_Widget* defButton = pWidgetMgr->GetDefaultButton(pMessageForm);
    636       if (defButton) {
    637         pMsg->m_pDstTarget = defButton;
    638         return TRUE;
    639       }
    640     }
    641     return FALSE;
    642   }
    643   pMsg->m_pDstTarget = m_pFocus;
    644   return TRUE;
    645 }
    646 FX_BOOL CFWL_NoteDriver::DoMouse(CFWL_MsgMouse* pMsg,
    647                                  IFWL_Widget* pMessageForm) {
    648   if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseLeave ||
    649       pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseHover ||
    650       pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseEnter) {
    651     return pMsg->m_pDstTarget != NULL;
    652   }
    653   if (pMsg->m_pDstTarget != pMessageForm) {
    654     pMsg->m_pDstTarget->TransformTo(pMessageForm, pMsg->m_fx, pMsg->m_fy);
    655   }
    656   if (!DoMouseEx(pMsg, pMessageForm)) {
    657     pMsg->m_pDstTarget = pMessageForm;
    658   }
    659   return TRUE;
    660 }
    661 FX_BOOL CFWL_NoteDriver::DoWheel(CFWL_MsgMouseWheel* pMsg,
    662                                  IFWL_Widget* pMessageForm) {
    663   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    664   if (!pWidgetMgr)
    665     return FALSE;
    666   IFWL_Widget* pDst =
    667       pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);
    668   if (!pDst)
    669     return FALSE;
    670   while (pDst && pDst->GetClassID() == FWL_CLASSHASH_Grid) {
    671     pDst = pDst->GetParent();
    672   }
    673   pMessageForm->TransformTo(pDst, pMsg->m_fx, pMsg->m_fy);
    674   pMsg->m_pDstTarget = pDst;
    675   return TRUE;
    676 }
    677 FX_BOOL CFWL_NoteDriver::DoSize(CFWL_MsgSize* pMsg) {
    678   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    679   if (!pWidgetMgr)
    680     return FALSE;
    681   pWidgetMgr->NotifySizeChanged(pMsg->m_pDstTarget, (FX_FLOAT)pMsg->m_iWidth,
    682                                 (FX_FLOAT)pMsg->m_iHeight);
    683   return TRUE;
    684 }
    685 FX_BOOL CFWL_NoteDriver::DoWindowMove(CFWL_MsgWindowMove* pMsg,
    686                                       IFWL_Widget* pMessageForm) {
    687   return pMsg->m_pDstTarget == pMessageForm;
    688 }
    689 FX_BOOL CFWL_NoteDriver::DoDragFiles(CFWL_MsgDropFiles* pMsg,
    690                                      IFWL_Widget* pMessageForm) {
    691   return pMsg->m_pDstTarget == pMessageForm;
    692 }
    693 FX_BOOL CFWL_NoteDriver::DoMouseEx(CFWL_MsgMouse* pMsg,
    694                                    IFWL_Widget* pMessageForm) {
    695   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    696   if (!pWidgetMgr)
    697     return FALSE;
    698   IFWL_Widget* pTarget = NULL;
    699   if (m_pGrab)
    700     pTarget = m_pGrab;
    701   if (!pTarget) {
    702     pTarget =
    703         pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);
    704     while (pTarget && pTarget->GetClassID() == FWL_CLASSHASH_Grid) {
    705       pTarget = pTarget->GetParent();
    706     }
    707   }
    708   if (pTarget) {
    709     if (pMessageForm != pTarget) {
    710       pMessageForm->TransformTo(pTarget, pMsg->m_fx, pMsg->m_fy);
    711     }
    712   }
    713   if (!pTarget)
    714     return FALSE;
    715   pMsg->m_pDstTarget = pTarget;
    716   return TRUE;
    717 }
    718 void CFWL_NoteDriver::MouseSecondary(CFWL_MsgMouse* pMsg) {
    719   IFWL_Widget* pTarget = pMsg->m_pDstTarget;
    720   if (pTarget == m_pHover) {
    721     return;
    722   }
    723   if (m_pHover) {
    724     CFWL_MsgMouse msLeave;
    725     msLeave.m_pDstTarget = m_pHover;
    726     msLeave.m_fx = pMsg->m_fx;
    727     msLeave.m_fy = pMsg->m_fy;
    728     pTarget->TransformTo(m_pHover, msLeave.m_fx, msLeave.m_fy);
    729     msLeave.m_dwFlags = 0;
    730     msLeave.m_dwCmd = FWL_MSGMOUSECMD_MouseLeave;
    731     DispatchMessage(&msLeave, NULL);
    732   }
    733   if (pTarget->GetClassID() == FWL_CLASSHASH_Form) {
    734     m_pHover = NULL;
    735     return;
    736   }
    737   m_pHover = pTarget;
    738   CFWL_MsgMouse msHover;
    739   msHover.m_pDstTarget = pTarget;
    740   msHover.m_fx = pMsg->m_fx;
    741   msHover.m_fy = pMsg->m_fy;
    742   msHover.m_dwFlags = 0;
    743   msHover.m_dwCmd = FWL_MSGMOUSECMD_MouseHover;
    744   DispatchMessage(&msHover, NULL);
    745 }
    746 FX_BOOL CFWL_NoteDriver::IsValidMessage(CFWL_Message* pMessage) {
    747   if (pMessage->GetClassID() == FWL_MSGHASH_Post) {
    748     return TRUE;
    749   }
    750   int32_t iCount = m_noteLoopQueue.GetSize();
    751   for (int32_t i = 0; i < iCount; i++) {
    752     CFWL_NoteLoop* pNoteLoop = static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[i]);
    753     CFWL_WidgetImp* pForm = pNoteLoop->GetForm();
    754     if (pForm && (pForm->GetInterface() == pMessage->m_pDstTarget)) {
    755       return TRUE;
    756     }
    757   }
    758   iCount = m_forms.GetSize();
    759   for (int32_t j = 0; j < iCount; j++) {
    760     CFWL_FormImp* pForm = static_cast<CFWL_FormImp*>(m_forms[j]);
    761     if (pForm->GetInterface() == pMessage->m_pDstTarget) {
    762       return TRUE;
    763     }
    764   }
    765   return FALSE;
    766 }
    767 IFWL_Widget* CFWL_NoteDriver::GetMessageForm(IFWL_Widget* pDstTarget) {
    768   int32_t iTrackLoop = m_noteLoopQueue.GetSize();
    769   if (iTrackLoop <= 0)
    770     return NULL;
    771   IFWL_Widget* pMessageForm = NULL;
    772   if (iTrackLoop > 1) {
    773     CFWL_NoteLoop* pNootLoop =
    774         static_cast<CFWL_NoteLoop*>(m_noteLoopQueue[iTrackLoop - 1]);
    775     pMessageForm = pNootLoop->GetForm()->GetInterface();
    776   } else {
    777     pMessageForm = (m_forms.Find(pDstTarget) < 0) ? NULL : pDstTarget;
    778   }
    779   if (!pMessageForm && pDstTarget) {
    780     CFWL_WidgetMgr* pWidgetMgr =
    781         static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    782     if (!pWidgetMgr)
    783       return NULL;
    784     pMessageForm =
    785         pWidgetMgr->GetWidget(pDstTarget, FWL_WGTRELATION_SystemForm);
    786   }
    787   return pMessageForm;
    788 }
    789 void CFWL_NoteDriver::ClearInvalidEventTargets(FX_BOOL bRemoveAll) {
    790   FX_POSITION pos = m_eventTargets.GetStartPosition();
    791   while (pos) {
    792     void* key = NULL;
    793     CFWL_EventTarget* pEventTarget = NULL;
    794     m_eventTargets.GetNextAssoc(pos, key, (void*&)pEventTarget);
    795     if (pEventTarget && (bRemoveAll || pEventTarget->IsInvalid())) {
    796       m_eventTargets.RemoveKey(key);
    797       delete pEventTarget;
    798     }
    799   }
    800 }
    801 class CFWL_CoreToopTipDP : public IFWL_ToolTipDP {
    802  public:
    803   FWL_ERR GetCaption(IFWL_Widget* pWidget, CFX_WideString& wsCaption);
    804   int32_t GetInitialDelay(IFWL_Widget* pWidget);
    805   int32_t GetAutoPopDelay(IFWL_Widget* pWidget);
    806   CFX_DIBitmap* GetToolTipIcon(IFWL_Widget* pWidget);
    807   CFX_SizeF GetToolTipIconSize(IFWL_Widget* pWidget);
    808   CFX_RectF GetAnchor();
    809   CFWL_CoreToopTipDP();
    810 
    811   CFX_WideString m_wsCaption;
    812   int32_t m_nInitDelayTime;
    813   int32_t m_nAutoPopDelayTime;
    814   CFX_RectF m_fAnchor;
    815 };
    816 CFWL_CoreToopTipDP::CFWL_CoreToopTipDP() {
    817   m_nInitDelayTime = 500;
    818   m_nAutoPopDelayTime = 50000;
    819   m_fAnchor.Set(0.0, 0.0, 0.0, 0.0);
    820 }
    821 FWL_ERR CFWL_CoreToopTipDP::GetCaption(IFWL_Widget* pWidget,
    822                                        CFX_WideString& wsCaption) {
    823   wsCaption = m_wsCaption;
    824   return FWL_ERR_Succeeded;
    825 }
    826 int32_t CFWL_CoreToopTipDP::GetInitialDelay(IFWL_Widget* pWidget) {
    827   return m_nInitDelayTime;
    828 }
    829 int32_t CFWL_CoreToopTipDP::GetAutoPopDelay(IFWL_Widget* pWidget) {
    830   return m_nAutoPopDelayTime;
    831 }
    832 CFX_DIBitmap* CFWL_CoreToopTipDP::GetToolTipIcon(IFWL_Widget* pWidget) {
    833   return NULL;
    834 }
    835 CFX_SizeF CFWL_CoreToopTipDP::GetToolTipIconSize(IFWL_Widget* pWidget) {
    836   CFX_SizeF sz;
    837   sz.Set(0, 0);
    838   return sz;
    839 }
    840 CFX_RectF CFWL_CoreToopTipDP::GetAnchor() {
    841   return m_fAnchor;
    842 }
    843 CFWL_EventTarget::~CFWL_EventTarget() {
    844   m_eventSources.RemoveAll();
    845 }
    846 int32_t CFWL_EventTarget::SetEventSource(IFWL_Widget* pSource,
    847                                          FX_DWORD dwFilter) {
    848   if (pSource) {
    849     m_eventSources.SetAt(pSource, dwFilter);
    850     return m_eventSources.GetCount();
    851   }
    852   return 1;
    853 }
    854 FX_BOOL CFWL_EventTarget::ProcessEvent(CFWL_Event* pEvent) {
    855   IFWL_WidgetDelegate* pDelegate = m_pListener->SetDelegate(NULL);
    856   if (!pDelegate)
    857     return FALSE;
    858   if (m_eventSources.GetCount() == 0) {
    859     pDelegate->OnProcessEvent(pEvent);
    860     return TRUE;
    861   }
    862   FX_POSITION pos = m_eventSources.GetStartPosition();
    863   while (pos) {
    864     IFWL_Widget* pSource = NULL;
    865     FX_DWORD dwFilter = 0;
    866     m_eventSources.GetNextAssoc(pos, (void*&)pSource, dwFilter);
    867     if (pSource == pEvent->m_pSrcTarget ||
    868         pEvent->GetClassID() == FWL_EVTHASH_Idle) {
    869       if (IsFilterEvent(pEvent, dwFilter)) {
    870         pDelegate->OnProcessEvent(pEvent);
    871         return TRUE;
    872       }
    873     }
    874   }
    875   return FALSE;
    876 }
    877 FX_BOOL CFWL_EventTarget::IsFilterEvent(CFWL_Event* pEvent, FX_DWORD dwFilter) {
    878   if (dwFilter == FWL_EVENT_ALL_MASK) {
    879     return TRUE;
    880   }
    881   FX_BOOL bRet = FALSE;
    882   switch (pEvent->GetClassID()) {
    883     case FWL_EVTHASH_Mouse: {
    884       bRet = dwFilter & FWL_EVENT_MOUSE_MASK;
    885       break;
    886     }
    887     case FWL_EVTHASH_MouseWheel: {
    888       bRet = dwFilter & FWL_EVENT_MOUSEWHEEL_MASK;
    889       break;
    890     }
    891     case FWL_EVTHASH_Key: {
    892       bRet = dwFilter & FWL_EVENT_KEY_MASK;
    893       break;
    894     }
    895     case FWL_EVTHASH_SetFocus:
    896     case FWL_EVTHASH_KillFocus: {
    897       bRet = dwFilter & FWL_EVENT_FOCUSCHANGED_MASK;
    898       break;
    899     }
    900     case FWL_EVTHASH_Draw: {
    901       bRet = dwFilter & FWL_EVENT_DRAW_MASK;
    902       break;
    903     }
    904     case FWL_EVTHASH_Close: {
    905       bRet = dwFilter & FWL_EVENT_CLOSE_MASK;
    906       break;
    907     }
    908     case FWL_EVTHASH_SizeChanged: {
    909       bRet = dwFilter & FWL_EVENT_SIZECHANGED_MASK;
    910       break;
    911     }
    912     case FWL_EVTHASH_Idle: {
    913       bRet = dwFilter & FWL_EVENT_IDLE_MASK;
    914       break;
    915     }
    916     default: {
    917       bRet = dwFilter & FWL_EVENT_CONTROL_MASK;
    918       break;
    919     }
    920   }
    921   return bRet;
    922 }
    923 
    924 CFWL_ToolTipContainer* CFWL_ToolTipContainer::s_pInstance = NULL;
    925 
    926 CFWL_ToolTipContainer::CFWL_ToolTipContainer()
    927     : pCurTarget(NULL), m_pToolTipImp(NULL) {
    928   m_ToolTipDp = new CFWL_CoreToopTipDP;
    929   m_ToolTipDp->m_nInitDelayTime = 0;
    930   m_ToolTipDp->m_nAutoPopDelayTime = 2000;
    931 }
    932 CFWL_ToolTipContainer::~CFWL_ToolTipContainer() {
    933   if (m_pToolTipImp) {
    934     IFWL_ToolTip* pToolTip =
    935         static_cast<IFWL_ToolTip*>(m_pToolTipImp->GetInterface());
    936     pToolTip->Finalize();
    937     delete pToolTip;
    938   }
    939   delete m_ToolTipDp;
    940 }
    941 // static
    942 CFWL_ToolTipContainer* CFWL_ToolTipContainer::getInstance() {
    943   if (!s_pInstance) {
    944     s_pInstance = new CFWL_ToolTipContainer;
    945   }
    946   return s_pInstance;
    947 }
    948 // static
    949 void CFWL_ToolTipContainer::DeleteInstance() {
    950   if (s_pInstance) {
    951     delete s_pInstance;
    952     s_pInstance = NULL;
    953   }
    954 }
    955 FX_ERR CFWL_ToolTipContainer::AddToolTipTarget(IFWL_ToolTipTarget* pTarget) {
    956   if (m_arrWidget.Find((void*)pTarget) < 0) {
    957     m_arrWidget.Add((void*)pTarget);
    958     return FWL_ERR_Succeeded;
    959   }
    960   return FWL_ERR_Indefinite;
    961 }
    962 FX_ERR CFWL_ToolTipContainer::RemoveToolTipTarget(IFWL_ToolTipTarget* pTarget) {
    963   int index = m_arrWidget.Find((void*)pTarget);
    964   if (index >= 0) {
    965     m_arrWidget.RemoveAt(index);
    966     return FWL_ERR_Succeeded;
    967   }
    968   return FWL_ERR_Indefinite;
    969 }
    970 FX_BOOL CFWL_ToolTipContainer::HasToolTip(IFWL_Widget* pWedget) {
    971   int32_t iCount = m_arrWidget.GetSize();
    972   for (int32_t i = 0; i < iCount; i++) {
    973     IFWL_ToolTipTarget* p = static_cast<IFWL_ToolTipTarget*>(m_arrWidget[i]);
    974     if (p->GetWidget() == pWedget) {
    975       pCurTarget = p;
    976       return TRUE;
    977     }
    978   }
    979   return FALSE;
    980 }
    981 FX_BOOL CFWL_ToolTipContainer::ProcessEnter(CFWL_EvtMouse* pEvt,
    982                                             IFWL_Widget* pOwner) {
    983   if (HasToolTip(pEvt->m_pDstTarget)) {
    984     if (NULL == m_pToolTipImp) {
    985       CFWL_WidgetImpProperties prop;
    986       prop.m_pDataProvider = m_ToolTipDp;
    987       prop.m_pOwner = pOwner;
    988       CFX_RectF rtTooltip;
    989       rtTooltip.Set(150, 150, 100, 50);
    990       prop.m_rtWidget = rtTooltip;
    991       IFWL_ToolTip* pToolTip = IFWL_ToolTip::Create(prop, nullptr);
    992       pToolTip->Initialize();
    993       m_pToolTipImp = static_cast<CFWL_ToolTipImp*>(pToolTip->GetImpl());
    994       m_pToolTipImp->ModifyStylesEx(FWL_STYLEEXT_TTP_Multiline, 0);
    995       m_pToolTipImp->SetStates(FWL_WGTSTATE_Invisible, TRUE);
    996     }
    997     if (pCurTarget->IsShowed()) {
    998       CFX_WideString wsCaption;
    999       pCurTarget->GetCaption(wsCaption);
   1000       if (!wsCaption.IsEmpty()) {
   1001         m_ToolTipDp->m_wsCaption = wsCaption;
   1002       }
   1003       CFX_RectF rt;
   1004       rt.Reset();
   1005       CFX_SizeF sz;
   1006       sz.Reset();
   1007       pCurTarget->GetToolTipSize(sz);
   1008       if (sz.x > 0 && sz.y > 0) {
   1009         rt.width = sz.x;
   1010         rt.height = sz.y;
   1011       } else {
   1012         CFX_RectF r;
   1013         m_pToolTipImp->GetWidgetRect(r, TRUE);
   1014         rt.width = r.width;
   1015         rt.height = r.height;
   1016       }
   1017       CFX_PointF pt;
   1018       pt.Set(pEvt->m_fx, pEvt->m_fy);
   1019       if (pCurTarget->GetToolTipPos(pt) == FWL_ERR_Succeeded) {
   1020         rt.left = pt.x;
   1021         rt.top = pt.y;
   1022         m_pToolTipImp->ModifyStylesEx(FWL_STYLEEXT_TTP_NoAnchor, 0);
   1023       } else {
   1024         CFX_RectF rtAnchor;
   1025         pCurTarget->GetWidget()->GetClientRect(rtAnchor);
   1026         pCurTarget->GetWidget()->TransformTo(NULL, rtAnchor.left, rtAnchor.top);
   1027         m_pToolTipImp->SetAnchor(rtAnchor);
   1028         m_pToolTipImp->ModifyStylesEx(0, FWL_STYLEEXT_TTP_NoAnchor);
   1029       }
   1030       m_pToolTipImp->SetWidgetRect(rt);
   1031       m_pToolTipImp->Update();
   1032       m_pToolTipImp->Show();
   1033     }
   1034     return TRUE;
   1035   }
   1036   return FALSE;
   1037 }
   1038 FX_BOOL CFWL_ToolTipContainer::ProcessLeave(CFWL_EvtMouse* pEvt) {
   1039   if (HasToolTip(pEvt->m_pDstTarget) && NULL != m_pToolTipImp) {
   1040     m_pToolTipImp->Hide();
   1041     pCurTarget = NULL;
   1042     return TRUE;
   1043   }
   1044   return FALSE;
   1045 }
   1046 IFWL_ToolTipTarget* CFWL_ToolTipContainer::GetCurrentToolTipTarget() {
   1047   return pCurTarget;
   1048 }
   1049 FX_ERR CFWL_ToolTipContainer::SetToolTipInitialDelay(int32_t nDelayTime) {
   1050   m_ToolTipDp->m_nInitDelayTime = nDelayTime;
   1051   return FWL_ERR_Succeeded;
   1052 }
   1053 FX_ERR CFWL_ToolTipContainer::SetToolTipAutoPopDelay(int32_t nDelayTime) {
   1054   m_ToolTipDp->m_nAutoPopDelayTime = nDelayTime;
   1055   return FWL_ERR_Succeeded;
   1056 }
   1057 FWL_ERR FWL_AddToolTipTarget(IFWL_ToolTipTarget* pTarget) {
   1058   return CFWL_ToolTipContainer::getInstance()->AddToolTipTarget(pTarget);
   1059 }
   1060 FWL_ERR FWL_RemoveToolTipTarget(IFWL_ToolTipTarget* pTarget) {
   1061   return CFWL_ToolTipContainer::getInstance()->RemoveToolTipTarget(pTarget);
   1062 }
   1063 FWL_ERR FWL_SetToolTipInitialDelay(int32_t nDelayTime) {
   1064   return CFWL_ToolTipContainer::getInstance()->SetToolTipInitialDelay(
   1065       nDelayTime);
   1066 }
   1067 FWL_ERR FWL_SetToolTipAutoPopDelay(int32_t nDelayTime) {
   1068   return CFWL_ToolTipContainer::getInstance()->SetToolTipAutoPopDelay(
   1069       nDelayTime);
   1070 }
   1071 IFWL_Widget* FWL_GetCurrentThreadModalWidget(IFWL_NoteThread* pNoteThread) {
   1072   if (!pNoteThread)
   1073     return NULL;
   1074   CFWL_NoteDriver* noteDriver =
   1075       static_cast<CFWL_NoteDriver*>(pNoteThread->GetNoteDriver());
   1076   if (!noteDriver)
   1077     return NULL;
   1078   if (noteDriver->CountLoop() == 1) {
   1079     return NULL;
   1080   }
   1081   CFWL_NoteLoop* topLoop = noteDriver->GetTopLoop();
   1082   if (!topLoop)
   1083     return NULL;
   1084   CFWL_WidgetImp* widget = topLoop->GetForm();
   1085   if (!widget)
   1086     return NULL;
   1087   return widget->GetInterface();
   1088 }
   1089 FWL_ERR FWL_SetHook(IFWL_NoteDriver* driver,
   1090                     FWLMessageHookCallback callback,
   1091                     void* info) {
   1092   CFWL_NoteDriver* noteDriver = static_cast<CFWL_NoteDriver*>(driver);
   1093   noteDriver->SetHook(callback, info);
   1094   return FWL_ERR_Succeeded;
   1095 }
   1096