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_noteimp.h"
10 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
11 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
12 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
13 
FWL_UseOffscreen(IFWL_Widget * pWidget)14 FX_BOOL FWL_UseOffscreen(IFWL_Widget* pWidget) {
15 #if (_FX_OS_ == _FX_MACOSX_)
16   return FALSE;
17 #else
18   return pWidget->GetStyles() & FWL_WGTSTYLE_Offscreen;
19 #endif
20 }
FWL_GetWidgetMgr()21 IFWL_WidgetMgr* FWL_GetWidgetMgr() {
22   IFWL_App* pApp = FWL_GetApp();
23   if (!pApp)
24     return NULL;
25   return pApp->GetWidgetMgr();
26 }
CFWL_WidgetMgr(IFWL_AdapterNative * pAdapterNative)27 CFWL_WidgetMgr::CFWL_WidgetMgr(IFWL_AdapterNative* pAdapterNative)
28     : m_dwCapability(0) {
29   m_pDelegate = new CFWL_WidgetMgrDelegate(this);
30   m_pAdapter = pAdapterNative->GetWidgetMgr(m_pDelegate);
31   FXSYS_assert(m_pAdapter);
32   CFWL_WidgetMgrItem* pRoot = new CFWL_WidgetMgrItem;
33   m_mapWidgetItem.SetAt(NULL, pRoot);
34 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
35   m_rtScreen.Reset();
36   IFWL_AdapterMonitorMgr* pMonitorMgr = pAdapterNative->GetMonitorMgr();
37   if (pMonitorMgr) {
38     FWL_HMONITOR monitor = pMonitorMgr->GetCurrentMonitor();
39     if (monitor) {
40       pMonitorMgr->GetMonitorSize(monitor, m_rtScreen.width, m_rtScreen.height);
41     }
42   }
43 #endif
44 }
~CFWL_WidgetMgr()45 CFWL_WidgetMgr::~CFWL_WidgetMgr() {
46   FX_POSITION ps = m_mapWidgetItem.GetStartPosition();
47   while (ps) {
48     void* pWidget;
49     CFWL_WidgetMgrItem* pItem;
50     m_mapWidgetItem.GetNextAssoc(ps, pWidget, (void*&)pItem);
51     delete pItem;
52   }
53   m_mapWidgetItem.RemoveAll();
54   if (m_pDelegate) {
55     delete m_pDelegate;
56     m_pDelegate = NULL;
57   }
58 }
CountWidgets(IFWL_Widget * pParent)59 int32_t CFWL_WidgetMgr::CountWidgets(IFWL_Widget* pParent) {
60   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent);
61   return TravelWidgetMgr(pParentItem, NULL, NULL);
62 }
GetWidget(int32_t nIndex,IFWL_Widget * pParent)63 IFWL_Widget* CFWL_WidgetMgr::GetWidget(int32_t nIndex, IFWL_Widget* pParent) {
64   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent);
65   IFWL_Widget* pWidget = NULL;
66   TravelWidgetMgr(pParentItem, &nIndex, NULL, &pWidget);
67   return pWidget;
68 }
GetWidget(IFWL_Widget * pWidget,FWL_WGTRELATION eRelation)69 IFWL_Widget* CFWL_WidgetMgr::GetWidget(IFWL_Widget* pWidget,
70                                        FWL_WGTRELATION eRelation) {
71   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
72   if (!pItem) {
73     return NULL;
74   }
75   IFWL_Widget* pRet = NULL;
76   switch (eRelation) {
77     case FWL_WGTRELATION_Parent: {
78       pRet = pItem->pParent ? pItem->pParent->pWidget : NULL;
79       break;
80     }
81     case FWL_WGTRELATION_Owner: {
82       pRet = pItem->pOwner ? pItem->pOwner->pWidget : NULL;
83       break;
84     }
85     case FWL_WGTRELATION_FirstSibling: {
86       pItem = pItem->pPrevious;
87       while (pItem && pItem->pPrevious) {
88         pItem = pItem->pPrevious;
89       }
90       pRet = pItem ? pItem->pWidget : NULL;
91       break;
92     }
93     case FWL_WGTRELATION_PriorSibling: {
94       pRet = pItem->pPrevious ? pItem->pPrevious->pWidget : NULL;
95       break;
96     }
97     case FWL_WGTRELATION_NextSibling: {
98       pRet = pItem->pNext ? pItem->pNext->pWidget : NULL;
99       break;
100     }
101     case FWL_WGTRELATION_LastSibling: {
102       pItem = pItem->pNext;
103       while (pItem && pItem->pNext) {
104         pItem = pItem->pNext;
105       }
106       pRet = pItem ? pItem->pWidget : NULL;
107       break;
108     }
109     case FWL_WGTRELATION_FirstChild: {
110       pRet = pItem->pChild ? pItem->pChild->pWidget : NULL;
111       break;
112     }
113     case FWL_WGTRELATION_LastChild: {
114       pItem = pItem->pChild;
115       while (pItem && pItem->pNext) {
116         pItem = pItem->pNext;
117       }
118       pRet = pItem ? pItem->pWidget : NULL;
119       break;
120     }
121     case FWL_WGTRELATION_SystemForm: {
122       while (pItem) {
123         if (IsAbleNative(pItem->pWidget)) {
124           pRet = pItem->pWidget;
125           break;
126         }
127         pItem = pItem->pParent;
128       }
129       break;
130     }
131     default: {}
132   }
133   return pRet;
134 }
GetWidgetIndex(IFWL_Widget * pWidget)135 int32_t CFWL_WidgetMgr::GetWidgetIndex(IFWL_Widget* pWidget) {
136   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
137   if (!pItem)
138     return -1;
139   return TravelWidgetMgr(pItem->pParent, NULL, pItem);
140 }
SetWidgetIndex(IFWL_Widget * pWidget,int32_t nIndex)141 FX_BOOL CFWL_WidgetMgr::SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex) {
142   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
143   if (!pItem)
144     return FALSE;
145   if (!pItem->pParent)
146     return FALSE;
147   CFWL_WidgetMgrItem* pChild = pItem->pParent->pChild;
148   int32_t i = 0;
149   while (pChild) {
150     if (pChild == pItem) {
151       if (i == nIndex) {
152         return TRUE;
153       }
154       if (pChild->pPrevious) {
155         pChild->pPrevious->pNext = pChild->pNext;
156       }
157       if (pChild->pNext) {
158         pChild->pNext->pPrevious = pChild->pPrevious;
159       }
160       if (pItem->pParent->pChild == pItem) {
161         pItem->pParent->pChild = pItem->pNext;
162       }
163       pItem->pNext = NULL;
164       pItem->pPrevious = NULL;
165       break;
166     }
167     if (!pChild->pNext) {
168       break;
169     }
170     pChild = pChild->pNext;
171     ++i;
172   }
173   pChild = pItem->pParent->pChild;
174   if (pChild) {
175     if (nIndex < 0) {
176       while (pChild->pNext) {
177         pChild = pChild->pNext;
178       }
179       pChild->pNext = pItem;
180       pItem->pPrevious = pChild;
181       pItem->pNext = NULL;
182       return TRUE;
183     }
184     i = 0;
185     while (i < nIndex && pChild->pNext) {
186       pChild = pChild->pNext;
187       ++i;
188     }
189     if (!pChild->pNext) {
190       pChild->pNext = pItem;
191       pItem->pPrevious = pChild;
192       pItem->pNext = NULL;
193       return TRUE;
194     }
195     if (pChild->pPrevious) {
196       pItem->pPrevious = pChild->pPrevious;
197       pChild->pPrevious->pNext = pItem;
198     }
199     pChild->pPrevious = pItem;
200     pItem->pNext = pChild;
201     if (pItem->pParent->pChild == pChild) {
202       pItem->pParent->pChild = pItem;
203     }
204   } else {
205     pItem->pParent->pChild = pItem;
206     pItem->pPrevious = NULL;
207     pItem->pNext = NULL;
208   }
209   return TRUE;
210 }
RepaintWidget(IFWL_Widget * pWidget,const CFX_RectF * pRect)211 FWL_ERR CFWL_WidgetMgr::RepaintWidget(IFWL_Widget* pWidget,
212                                       const CFX_RectF* pRect) {
213   if (!m_pAdapter)
214     return FWL_ERR_Indefinite;
215   IFWL_Widget* pNative = pWidget;
216   CFX_RectF rect(*pRect);
217   if (IsFormDisabled()) {
218     IFWL_Widget* pOuter = pWidget->GetOuter();
219     while (pOuter) {
220       CFX_RectF rtTemp;
221       pNative->GetWidgetRect(rtTemp);
222       rect.left += rtTemp.left;
223       rect.top += rtTemp.top;
224       pNative = pOuter;
225       pOuter = pOuter->GetOuter();
226     }
227   } else if (!IsAbleNative(pWidget)) {
228     pNative = GetWidget(pWidget, FWL_WGTRELATION_SystemForm);
229     if (!pNative)
230       return FWL_ERR_Indefinite;
231     pWidget->TransformTo(pNative, rect.left, rect.top);
232   }
233   AddRedrawCounts(pNative);
234   return m_pAdapter->RepaintWidget(pNative, &rect);
235 }
AddWidget(IFWL_Widget * pWidget)236 void CFWL_WidgetMgr::AddWidget(IFWL_Widget* pWidget) {
237   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(NULL);
238   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
239   if (!pItem) {
240     pItem = new CFWL_WidgetMgrItem;
241     pItem->pWidget = pWidget;
242     m_mapWidgetItem.SetAt(pWidget, pItem);
243   }
244   if (pItem->pParent && pItem->pParent != pParentItem) {
245     if (pItem->pPrevious) {
246       pItem->pPrevious->pNext = pItem->pNext;
247     }
248     if (pItem->pNext) {
249       pItem->pNext->pPrevious = pItem->pPrevious;
250     }
251     if (pItem->pParent->pChild == pItem) {
252       pItem->pParent->pChild = pItem->pNext;
253     }
254   }
255   pItem->pParent = pParentItem;
256   SetWidgetIndex(pWidget, -1);
257 }
InsertWidget(IFWL_Widget * pParent,IFWL_Widget * pChild,int32_t nIndex)258 void CFWL_WidgetMgr::InsertWidget(IFWL_Widget* pParent,
259                                   IFWL_Widget* pChild,
260                                   int32_t nIndex) {
261   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent);
262   if (!pParentItem) {
263     pParentItem = new CFWL_WidgetMgrItem;
264     pParentItem->pWidget = pParent;
265     m_mapWidgetItem.SetAt(pParent, pParentItem);
266     CFWL_WidgetMgrItem* pRoot = GetWidgetMgrItem(NULL);
267     pParentItem->pParent = pRoot;
268     SetWidgetIndex(pParent, -1);
269   }
270   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pChild);
271   if (!pItem) {
272     pItem = new CFWL_WidgetMgrItem;
273     pItem->pWidget = pChild;
274     m_mapWidgetItem.SetAt(pChild, pItem);
275   }
276   if (pItem->pParent && pItem->pParent != pParentItem) {
277     if (pItem->pPrevious) {
278       pItem->pPrevious->pNext = pItem->pNext;
279     }
280     if (pItem->pNext) {
281       pItem->pNext->pPrevious = pItem->pPrevious;
282     }
283     if (pItem->pParent->pChild == pItem) {
284       pItem->pParent->pChild = pItem->pNext;
285     }
286   }
287   pItem->pParent = pParentItem;
288   SetWidgetIndex(pChild, nIndex);
289 }
RemoveWidget(IFWL_Widget * pWidget)290 void CFWL_WidgetMgr::RemoveWidget(IFWL_Widget* pWidget) {
291   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
292   if (!pItem) {
293     return;
294   }
295   if (pItem->pPrevious) {
296     pItem->pPrevious->pNext = pItem->pNext;
297   }
298   if (pItem->pNext) {
299     pItem->pNext->pPrevious = pItem->pPrevious;
300   }
301   if (pItem->pParent && pItem->pParent->pChild == pItem) {
302     pItem->pParent->pChild = pItem->pNext;
303   }
304   CFWL_WidgetMgrItem* pChild = pItem->pChild;
305   while (pChild) {
306     CFWL_WidgetMgrItem* pNext = pChild->pNext;
307     RemoveWidget(pChild->pWidget);
308     pChild = pNext;
309   }
310   m_mapWidgetItem.RemoveKey(pWidget);
311   delete pItem;
312 }
SetOwner(IFWL_Widget * pOwner,IFWL_Widget * pOwned)313 void CFWL_WidgetMgr::SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned) {
314   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pOwner);
315   if (!pParentItem) {
316     pParentItem = new CFWL_WidgetMgrItem;
317     pParentItem->pWidget = pOwner;
318     m_mapWidgetItem.SetAt(pOwner, pParentItem);
319     CFWL_WidgetMgrItem* pRoot = GetWidgetMgrItem(NULL);
320     pParentItem->pParent = pRoot;
321     SetWidgetIndex(pOwner, -1);
322   }
323   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pOwned);
324   if (!pItem) {
325     pItem = new CFWL_WidgetMgrItem;
326     pItem->pWidget = pOwned;
327     m_mapWidgetItem.SetAt(pOwned, pItem);
328   }
329   pItem->pOwner = pParentItem;
330 }
SetParent(IFWL_Widget * pParent,IFWL_Widget * pChild)331 void CFWL_WidgetMgr::SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild) {
332   CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent);
333   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pChild);
334   if (!pItem)
335     return;
336   if (pItem->pParent && pItem->pParent != pParentItem) {
337     if (pItem->pPrevious) {
338       pItem->pPrevious->pNext = pItem->pNext;
339     }
340     if (pItem->pNext) {
341       pItem->pNext->pPrevious = pItem->pPrevious;
342     }
343     if (pItem->pParent->pChild == pItem) {
344       pItem->pParent->pChild = pItem->pNext;
345     }
346     pItem->pNext = NULL;
347     pItem->pPrevious = NULL;
348   }
349   pItem->pParent = pParentItem;
350   SetWidgetIndex(pChild, -1);
351   if (!m_pAdapter)
352     return;
353   m_pAdapter->SetParentWidget(pChild, pParent);
354 }
IsChild(IFWL_Widget * pChild,IFWL_Widget * pParent)355 FX_BOOL CFWL_WidgetMgr::IsChild(IFWL_Widget* pChild, IFWL_Widget* pParent) {
356   IFWL_Widget* pTemp = pChild;
357   do {
358     if (pTemp == pParent) {
359       return TRUE;
360     }
361     pTemp = GetWidget(pTemp, FWL_WGTRELATION_Parent);
362   } while (pTemp);
363   return FALSE;
364 }
CreateWidget_Native(IFWL_Widget * pWidget)365 FWL_ERR CFWL_WidgetMgr::CreateWidget_Native(IFWL_Widget* pWidget) {
366   if (!IsAbleNative(pWidget)) {
367     return FWL_ERR_Succeeded;
368   }
369   return m_pAdapter->CreateWidget(pWidget, pWidget->GetOwner());
370 }
DestroyWidget_Native(IFWL_Widget * pWidget)371 FWL_ERR CFWL_WidgetMgr::DestroyWidget_Native(IFWL_Widget* pWidget) {
372   if (!IsAbleNative(pWidget)) {
373     return FWL_ERR_Succeeded;
374   }
375   return m_pAdapter->DestroyWidget(pWidget);
376 }
GetWidgetRect_Native(IFWL_Widget * pWidget,CFX_RectF & rect)377 FWL_ERR CFWL_WidgetMgr::GetWidgetRect_Native(IFWL_Widget* pWidget,
378                                              CFX_RectF& rect) {
379   if (!IsAbleNative(pWidget)) {
380     return FWL_ERR_Succeeded;
381   }
382   return m_pAdapter->GetWidgetRect(pWidget, rect);
383 }
SetWidgetRect_Native(IFWL_Widget * pWidget,const CFX_RectF & rect)384 FWL_ERR CFWL_WidgetMgr::SetWidgetRect_Native(IFWL_Widget* pWidget,
385                                              const CFX_RectF& rect) {
386   if (FWL_UseOffscreen(pWidget)) {
387     CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
388     pItem->iRedrawCounter++;
389     if (pItem->pOffscreen) {
390       CFX_RenderDevice* pDevice = pItem->pOffscreen->GetRenderDevice();
391       if (pDevice && pDevice->GetBitmap()) {
392         CFX_DIBitmap* pBitmap = pDevice->GetBitmap();
393         if (pBitmap->GetWidth() - rect.width > 1 ||
394             pBitmap->GetHeight() - rect.height > 1) {
395           delete pItem->pOffscreen;
396           pItem->pOffscreen = NULL;
397         }
398       }
399     }
400 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
401     pItem->bOutsideChanged = !m_rtScreen.Contains(rect);
402 #endif
403   }
404   return m_pAdapter->SetWidgetRect(pWidget, rect);
405 }
SetWidgetPosition_Native(IFWL_Widget * pWidget,FX_FLOAT fx,FX_FLOAT fy)406 FWL_ERR CFWL_WidgetMgr::SetWidgetPosition_Native(IFWL_Widget* pWidget,
407                                                  FX_FLOAT fx,
408                                                  FX_FLOAT fy) {
409   return m_pAdapter->SetWidgetPosition(pWidget, fx, fy);
410 }
SetWidgetIcon_Native(IFWL_Widget * pWidget,const CFX_DIBitmap * pIcon,FX_BOOL bBig)411 FWL_ERR CFWL_WidgetMgr::SetWidgetIcon_Native(IFWL_Widget* pWidget,
412                                              const CFX_DIBitmap* pIcon,
413                                              FX_BOOL bBig) {
414   return m_pAdapter->SetWidgetIcon(pWidget, pIcon, bBig);
415 }
SetWidgetCaption_Native(IFWL_Widget * pWidget,const CFX_WideStringC & wsCaption)416 FWL_ERR CFWL_WidgetMgr::SetWidgetCaption_Native(
417     IFWL_Widget* pWidget,
418     const CFX_WideStringC& wsCaption) {
419   return m_pAdapter->SetWidgetCaption(pWidget, wsCaption);
420 }
SetBorderRegion_Native(IFWL_Widget * pWidget,CFX_Path * pPath)421 FWL_ERR CFWL_WidgetMgr::SetBorderRegion_Native(IFWL_Widget* pWidget,
422                                                CFX_Path* pPath) {
423   return m_pAdapter->SetBorderRegion(pWidget, pPath);
424 }
ShowWidget_Native(IFWL_Widget * pWidget)425 FWL_ERR CFWL_WidgetMgr::ShowWidget_Native(IFWL_Widget* pWidget) {
426   return m_pAdapter->ShowWidget(pWidget);
427 }
HideWidget_Native(IFWL_Widget * pWidget)428 FWL_ERR CFWL_WidgetMgr::HideWidget_Native(IFWL_Widget* pWidget) {
429   return m_pAdapter->HideWidget(pWidget);
430 }
SetNormal_Native(IFWL_Widget * pWidget)431 FWL_ERR CFWL_WidgetMgr::SetNormal_Native(IFWL_Widget* pWidget) {
432   return m_pAdapter->SetNormal(pWidget);
433 }
SetMaximize_Native(IFWL_Widget * pWidget)434 FWL_ERR CFWL_WidgetMgr::SetMaximize_Native(IFWL_Widget* pWidget) {
435   return m_pAdapter->SetMaximize(pWidget);
436 }
SetMinimize_Native(IFWL_Widget * pWidget)437 FWL_ERR CFWL_WidgetMgr::SetMinimize_Native(IFWL_Widget* pWidget) {
438   return m_pAdapter->SetMinimize(pWidget);
439 }
CheckMessage_Native()440 FX_BOOL CFWL_WidgetMgr::CheckMessage_Native() {
441   return m_pAdapter->CheckMessage();
442 }
DispatchMessage_Native()443 FWL_ERR CFWL_WidgetMgr::DispatchMessage_Native() {
444   return m_pAdapter->DispatchMessage();
445 }
IsIdleMessage_Native()446 FX_BOOL CFWL_WidgetMgr::IsIdleMessage_Native() {
447   return m_pAdapter->IsIdleMessage();
448 }
Exit_Native(int32_t iExitCode)449 FWL_ERR CFWL_WidgetMgr::Exit_Native(int32_t iExitCode) {
450   return m_pAdapter->Exit(iExitCode);
451 }
CreateWidgetWithNativeId_Native(IFWL_Widget * pWidget,void * vp)452 FWL_ERR CFWL_WidgetMgr::CreateWidgetWithNativeId_Native(IFWL_Widget* pWidget,
453                                                         void* vp) {
454   return m_pAdapter->CreateWidgetWithNativeId(pWidget, vp);
455 }
GetWidgetAtPoint(IFWL_Widget * parent,FX_FLOAT x,FX_FLOAT y)456 IFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(IFWL_Widget* parent,
457                                               FX_FLOAT x,
458                                               FX_FLOAT y) {
459   if (!parent)
460     return NULL;
461   FX_FLOAT x1;
462   FX_FLOAT y1;
463   IFWL_Widget* child = GetWidget(parent, FWL_WGTRELATION_LastChild);
464   while (child) {
465     if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) {
466       x1 = x;
467       y1 = y;
468       CFX_Matrix matrixOnParent;
469       child->GetMatrix(matrixOnParent);
470       CFX_Matrix m;
471       m.SetIdentity();
472       m.SetReverse(matrixOnParent);
473       m.TransformPoint(x1, y1);
474       CFX_RectF bounds;
475       child->GetWidgetRect(bounds);
476       if (bounds.Contains(x1, y1)) {
477         x1 -= bounds.left;
478         y1 -= bounds.top;
479         return GetWidgetAtPoint(child, x1, y1);
480       }
481     }
482     child = GetWidget(child, FWL_WGTRELATION_PriorSibling);
483   }
484   return parent;
485 }
NotifySizeChanged(IFWL_Widget * pForm,FX_FLOAT fx,FX_FLOAT fy)486 void CFWL_WidgetMgr::NotifySizeChanged(IFWL_Widget* pForm,
487                                        FX_FLOAT fx,
488                                        FX_FLOAT fy) {
489   if (!FWL_UseOffscreen(pForm)) {
490     return;
491   }
492   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pForm);
493   if (pItem->pOffscreen) {
494     delete pItem->pOffscreen;
495     pItem->pOffscreen = NULL;
496   }
497 }
nextTab(IFWL_Widget * parent,IFWL_Widget * focus,FX_BOOL & bFind)498 IFWL_Widget* CFWL_WidgetMgr::nextTab(IFWL_Widget* parent,
499                                      IFWL_Widget* focus,
500                                      FX_BOOL& bFind) {
501   IFWL_Widget* child =
502       FWL_GetWidgetMgr()->GetWidget(parent, FWL_WGTRELATION_FirstChild);
503   while (child) {
504     if (focus == child) {
505       bFind = TRUE;
506     }
507     if ((child->GetStyles() & FWL_WGTSTYLE_TabStop) &&
508         (!focus || (focus != child && bFind))) {
509       return child;
510     }
511     IFWL_Widget* bRet = nextTab(child, focus, bFind);
512     if (bRet) {
513       return bRet;
514     }
515     child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling);
516   }
517   return NULL;
518 }
CountRadioButtonGroup(IFWL_Widget * pFirst)519 int32_t CFWL_WidgetMgr::CountRadioButtonGroup(IFWL_Widget* pFirst) {
520   int32_t iRet = 0;
521   IFWL_Widget* pChild = pFirst;
522   while (pChild) {
523     if ((pChild->GetStyles() & FWL_WGTSTYLE_Group) &&
524         pChild->GetClassID() == 3811304691) {
525       iRet++;
526     }
527     pChild = GetWidget(pChild, FWL_WGTRELATION_NextSibling);
528   }
529   return iRet;
530 }
GetSiblingRadioButton(IFWL_Widget * pWidget,FX_BOOL bNext)531 IFWL_Widget* CFWL_WidgetMgr::GetSiblingRadioButton(IFWL_Widget* pWidget,
532                                                    FX_BOOL bNext) {
533   while ((pWidget = GetWidget(pWidget, bNext ? FWL_WGTRELATION_NextSibling
534                                              : FWL_WGTRELATION_PriorSibling)) !=
535          NULL) {
536     if (pWidget->GetClassID() == 3811304691) {
537       return pWidget;
538     }
539   }
540   return NULL;
541 }
GetRadioButtonGroupHeader(IFWL_Widget * pRadioButton)542 IFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader(
543     IFWL_Widget* pRadioButton) {
544   if (pRadioButton->GetStyles() & FWL_WGTSTYLE_Group) {
545     return pRadioButton;
546   }
547   IFWL_Widget* pNext = pRadioButton;
548   while ((pNext = GetSiblingRadioButton(pNext, FALSE)) != NULL) {
549     if (pNext->GetStyles() & FWL_WGTSTYLE_Group) {
550       return pNext;
551     }
552   }
553   pNext = GetWidget(pRadioButton, FWL_WGTRELATION_LastSibling);
554   if ((pNext->GetStyles() & FWL_WGTSTYLE_Group) &&
555       pNext->GetClassID() == 3811304691) {
556     return pNext;
557   }
558   while ((pNext = GetSiblingRadioButton(pNext, FALSE)) && pNext &&
559          pNext != pRadioButton) {
560     if (pNext->GetStyles() & FWL_WGTSTYLE_Group) {
561       return pNext;
562     }
563   }
564   pNext = GetWidget(pRadioButton, FWL_WGTRELATION_FirstSibling);
565   if (pNext && (pNext->GetStyles() == FWL_WGTSTYLE_Group) &&
566       pNext->GetClassID() == 3811304691) {
567     return pNext;
568   }
569   return GetSiblingRadioButton(pNext, TRUE);
570 }
GetSameGroupRadioButton(IFWL_Widget * pRadioButton,CFX_PtrArray & group)571 void CFWL_WidgetMgr::GetSameGroupRadioButton(IFWL_Widget* pRadioButton,
572                                              CFX_PtrArray& group) {
573   IFWL_Widget* pFirst = GetWidget(pRadioButton, FWL_WGTRELATION_FirstSibling);
574   if (!pFirst) {
575     pFirst = pRadioButton;
576   }
577   int32_t iGroup = CountRadioButtonGroup(pFirst);
578   if (iGroup < 2) {
579     if (pFirst->GetClassID() == 3811304691) {
580       group.Add(pFirst);
581     }
582     IFWL_Widget* pNext = pFirst;
583     while ((pNext = GetSiblingRadioButton(pNext, TRUE)) != NULL) {
584       group.Add(pNext);
585     }
586     return;
587   }
588   IFWL_Widget* pNext = GetRadioButtonGroupHeader(pRadioButton);
589   do {
590     group.Add(pNext);
591     pNext = GetSiblingRadioButton(pNext, TRUE);
592     if (!pNext) {
593       if (pFirst->GetClassID() == 3811304691) {
594         pNext = pFirst;
595       } else {
596         pNext = GetSiblingRadioButton(pFirst, TRUE);
597       }
598     }
599   } while (pNext && ((pNext->GetStyles() & FWL_WGTSTYLE_Group) == 0));
600 }
GetDefaultButton(IFWL_Widget * pParent)601 IFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(IFWL_Widget* pParent) {
602   if ((pParent->GetClassID() == 3521614244) &&
603       (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
604     return pParent;
605   }
606   IFWL_Widget* child =
607       FWL_GetWidgetMgr()->GetWidget(pParent, FWL_WGTRELATION_FirstChild);
608   while (child) {
609     if ((child->GetClassID() == 3521614244) &&
610         (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
611       return child;
612     }
613     IFWL_Widget* find = GetDefaultButton(child);
614     if (find) {
615       return find;
616     }
617     child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling);
618   }
619   return NULL;
620 }
AddRedrawCounts(IFWL_Widget * pWidget)621 void CFWL_WidgetMgr::AddRedrawCounts(IFWL_Widget* pWidget) {
622   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
623   (pItem->iRedrawCounter)++;
624 }
ResetRedrawCounts(IFWL_Widget * pWidget)625 void CFWL_WidgetMgr::ResetRedrawCounts(IFWL_Widget* pWidget) {
626   CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
627   pItem->iRedrawCounter = 0;
628 }
GetWidgetMgrItem(IFWL_Widget * pWidget)629 CFWL_WidgetMgrItem* CFWL_WidgetMgr::GetWidgetMgrItem(IFWL_Widget* pWidget) {
630   return static_cast<CFWL_WidgetMgrItem*>(m_mapWidgetItem.GetValueAt(pWidget));
631 }
TravelWidgetMgr(CFWL_WidgetMgrItem * pParent,int32_t * pIndex,CFWL_WidgetMgrItem * pItem,IFWL_Widget ** pWidget)632 int32_t CFWL_WidgetMgr::TravelWidgetMgr(CFWL_WidgetMgrItem* pParent,
633                                         int32_t* pIndex,
634                                         CFWL_WidgetMgrItem* pItem,
635                                         IFWL_Widget** pWidget) {
636   if (!pParent) {
637     return 0;
638   }
639   int32_t iCount = 0;
640   CFWL_WidgetMgrItem* pChild = pParent->pChild;
641   while (pChild) {
642     iCount++;
643     if (pIndex) {
644       if (*pIndex == 0) {
645         *pWidget = pChild->pWidget;
646         return iCount;
647       }
648       pIndex--;
649     }
650     if (pItem && pItem == pChild) {
651       return iCount - 1;
652     }
653     pChild = pChild->pNext;
654   }
655   if (pIndex) {
656     return 0;
657   } else if (pItem) {
658     return -1;
659   }
660   return iCount - 1;
661 }
IsAbleNative(IFWL_Widget * pWidget)662 FX_BOOL CFWL_WidgetMgr::IsAbleNative(IFWL_Widget* pWidget) {
663   if (!pWidget)
664     return FALSE;
665   if (!pWidget->IsInstance(FX_WSTRC(FWL_CLASS_Form))) {
666     return FALSE;
667   }
668   FX_DWORD dwStyles = pWidget->GetStyles();
669   return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
670           FWL_WGTSTYLE_OverLapper) ||
671          (dwStyles & FWL_WGTSTYLE_Popup);
672 }
IsThreadEnabled()673 FX_BOOL CFWL_WidgetMgr::IsThreadEnabled() {
674   return !(m_dwCapability & FWL_WGTMGR_DisableThread);
675 }
IsFormDisabled()676 FX_BOOL CFWL_WidgetMgr::IsFormDisabled() {
677   return m_dwCapability & FWL_WGTMGR_DisableForm;
678 }
GetAdapterPopupPos(IFWL_Widget * pWidget,FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)679 FX_BOOL CFWL_WidgetMgr::GetAdapterPopupPos(IFWL_Widget* pWidget,
680                                            FX_FLOAT fMinHeight,
681                                            FX_FLOAT fMaxHeight,
682                                            const CFX_RectF& rtAnchor,
683                                            CFX_RectF& rtPopup) {
684   IFWL_AdapterWidgetMgr* pSDApapter = GetAdapterWidgetMgr();
685   return pSDApapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor,
686                                  rtPopup);
687 }
CFWL_WidgetMgrDelegate(CFWL_WidgetMgr * pWidgetMgr)688 CFWL_WidgetMgrDelegate::CFWL_WidgetMgrDelegate(CFWL_WidgetMgr* pWidgetMgr)
689     : m_pWidgetMgr(pWidgetMgr) {}
OnSetCapability(FX_DWORD dwCapability)690 FWL_ERR CFWL_WidgetMgrDelegate::OnSetCapability(FX_DWORD dwCapability) {
691   m_pWidgetMgr->m_dwCapability = dwCapability;
692   return FWL_ERR_Succeeded;
693 }
OnProcessMessageToForm(CFWL_Message * pMessage)694 int32_t CFWL_WidgetMgrDelegate::OnProcessMessageToForm(CFWL_Message* pMessage) {
695   if (!pMessage)
696     return 0;
697   if (!pMessage->m_pDstTarget)
698     return 0;
699   IFWL_Widget* pDstWidget = pMessage->m_pDstTarget;
700   IFWL_NoteThread* pNoteThread = pDstWidget->GetOwnerThread();
701   if (!pNoteThread)
702     return 0;
703   CFWL_NoteDriver* pNoteDriver =
704       static_cast<CFWL_NoteDriver*>(pNoteThread->GetNoteDriver());
705   if (!pNoteDriver)
706     return 0;
707   if (m_pWidgetMgr->IsThreadEnabled()) {
708     pMessage = static_cast<CFWL_Message*>(pMessage->Clone());
709   }
710   if (m_pWidgetMgr->IsFormDisabled()) {
711     pNoteDriver->ProcessMessage(pMessage);
712   } else {
713     pNoteDriver->QueueMessage(pMessage);
714   }
715 #if (_FX_OS_ == _FX_MACOSX_)
716   CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop();
717   if (pTopLoop) {
718     pNoteDriver->UnqueueMessage(pTopLoop);
719   }
720 #endif
721   if (m_pWidgetMgr->IsThreadEnabled()) {
722     pMessage->Release();
723   }
724   return FWL_ERR_Succeeded;
725 }
OnDrawWidget(IFWL_Widget * pWidget,CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)726 FWL_ERR CFWL_WidgetMgrDelegate::OnDrawWidget(IFWL_Widget* pWidget,
727                                              CFX_Graphics* pGraphics,
728                                              const CFX_Matrix* pMatrix) {
729   if (!pWidget)
730     return FWL_ERR_Indefinite;
731   if (!pGraphics)
732     return FWL_ERR_Indefinite;
733   CFX_Graphics* pTemp = DrawWidgetBefore(pWidget, pGraphics, pMatrix);
734   CFX_RectF clipCopy;
735   pWidget->GetWidgetRect(clipCopy);
736   clipCopy.left = clipCopy.top = 0;
737   if (bUseOffscreenDirect(pWidget)) {
738     DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix);
739     return FWL_ERR_Succeeded;
740   }
741   CFX_RectF clipBounds;
742 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) || \
743     (_FX_OS_ == _FX_LINUX_DESKTOP_) || (_FX_OS_ == _FX_ANDROID_)
744   IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL);
745   pDelegate->OnDrawWidget(pTemp, pMatrix);
746   pGraphics->GetClipRect(clipBounds);
747   clipCopy = clipBounds;
748 #elif(_FX_OS_ == _FX_MACOSX_)
749   if (m_pWidgetMgr->IsFormDisabled()) {
750     IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL);
751     pDelegate->OnDrawWidget(pTemp, pMatrix);
752     pGraphics->GetClipRect(clipBounds);
753     clipCopy = clipBounds;
754   } else {
755     clipBounds.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d);
756     const_cast<CFX_Matrix*>(pMatrix)->SetIdentity();  // FIXME: const cast.
757 #ifdef FWL_UseMacSystemBorder
758 #else
759 #endif
760     {
761       IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL);
762       pDelegate->OnDrawWidget(pTemp, pMatrix);
763     }
764   }
765 #endif
766   if (!m_pWidgetMgr->IsFormDisabled()) {
767     CFX_RectF rtClient;
768     pWidget->GetClientRect(rtClient);
769     clipBounds.Intersect(rtClient);
770   }
771   if (!clipBounds.IsEmpty()) {
772     DrawChild(pWidget, clipBounds, pTemp, pMatrix);
773   }
774   DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix);
775   m_pWidgetMgr->ResetRedrawCounts(pWidget);
776   return FWL_ERR_Succeeded;
777 }
DrawChild(IFWL_Widget * parent,const CFX_RectF & rtClip,CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)778 void CFWL_WidgetMgrDelegate::DrawChild(IFWL_Widget* parent,
779                                        const CFX_RectF& rtClip,
780                                        CFX_Graphics* pGraphics,
781                                        const CFX_Matrix* pMatrix) {
782   if (!parent)
783     return;
784   FX_BOOL bFormDisable = m_pWidgetMgr->IsFormDisabled();
785   IFWL_Widget* pNextChild =
786       m_pWidgetMgr->GetWidget(parent, FWL_WGTRELATION_FirstChild);
787   while (pNextChild) {
788     IFWL_Widget* child = pNextChild;
789     pNextChild = m_pWidgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling);
790     if (child->GetStates() & FWL_WGTSTATE_Invisible) {
791       continue;
792     }
793     CFX_RectF rtWidget;
794     child->GetWidgetRect(rtWidget);
795     if (rtWidget.IsEmpty()) {
796       continue;
797     }
798     CFX_Matrix widgetMatrix;
799     CFX_RectF clipBounds(rtWidget);
800     if (!bFormDisable) {
801       child->GetMatrix(widgetMatrix, TRUE);
802     }
803     if (pMatrix) {
804       widgetMatrix.Concat(*pMatrix);
805     }
806     if (!bFormDisable) {
807       widgetMatrix.TransformPoint(clipBounds.left, clipBounds.top);
808       clipBounds.Intersect(rtClip);
809       if (clipBounds.IsEmpty()) {
810         continue;
811       }
812       pGraphics->SaveGraphState();
813       pGraphics->SetClipRect(clipBounds);
814     }
815     widgetMatrix.Translate(rtWidget.left, rtWidget.top, TRUE);
816     IFWL_WidgetDelegate* pDelegate = child->SetDelegate(NULL);
817     if (pDelegate) {
818       if (m_pWidgetMgr->IsFormDisabled() ||
819           IsNeedRepaint(child, &widgetMatrix, rtClip)) {
820         pDelegate->OnDrawWidget(pGraphics, &widgetMatrix);
821       }
822     }
823     if (!bFormDisable) {
824       pGraphics->RestoreGraphState();
825     }
826     DrawChild(child, clipBounds, pGraphics,
827               bFormDisable ? &widgetMatrix : pMatrix);
828     child = m_pWidgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling);
829   }
830 }
DrawWidgetBefore(IFWL_Widget * pWidget,CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)831 CFX_Graphics* CFWL_WidgetMgrDelegate::DrawWidgetBefore(
832     IFWL_Widget* pWidget,
833     CFX_Graphics* pGraphics,
834     const CFX_Matrix* pMatrix) {
835   if (!FWL_UseOffscreen(pWidget)) {
836     return pGraphics;
837   }
838   CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget);
839   if (!pItem->pOffscreen) {
840     pItem->pOffscreen = new CFX_Graphics;
841     CFX_RectF rect;
842     pWidget->GetWidgetRect(rect);
843     pItem->pOffscreen->Create((int32_t)rect.width, (int32_t)rect.height,
844                               FXDIB_Argb);
845   }
846   CFX_RectF rect;
847   pGraphics->GetClipRect(rect);
848   pItem->pOffscreen->SetClipRect(rect);
849   return pItem->pOffscreen;
850 }
DrawWidgetAfter(IFWL_Widget * pWidget,CFX_Graphics * pGraphics,CFX_RectF & rtClip,const CFX_Matrix * pMatrix)851 void CFWL_WidgetMgrDelegate::DrawWidgetAfter(IFWL_Widget* pWidget,
852                                              CFX_Graphics* pGraphics,
853                                              CFX_RectF& rtClip,
854                                              const CFX_Matrix* pMatrix) {
855   if (FWL_UseOffscreen(pWidget)) {
856     CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget);
857     pGraphics->Transfer(pItem->pOffscreen, rtClip.left, rtClip.top, rtClip,
858                         pMatrix);
859 #ifdef _WIN32
860     pItem->pOffscreen->ClearClip();
861 #endif
862   }
863   CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget);
864   pItem->iRedrawCounter = 0;
865 }
866 #define FWL_NEEDREPAINTHIT_Point 12
867 #define FWL_NEEDREPAINTHIT_Piece 3
868 typedef struct _FWL_NeedRepaintHitData {
869   CFX_PointF hitPoint;
870   FX_BOOL bNotNeedRepaint;
871   FX_BOOL bNotContainByDirty;
872 } FWL_NeedRepaintHitData;
IsNeedRepaint(IFWL_Widget * pWidget,CFX_Matrix * pMatrix,const CFX_RectF & rtDirty)873 FX_BOOL CFWL_WidgetMgrDelegate::IsNeedRepaint(IFWL_Widget* pWidget,
874                                               CFX_Matrix* pMatrix,
875                                               const CFX_RectF& rtDirty) {
876   CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget);
877   if (pItem && pItem->iRedrawCounter > 0) {
878     pItem->iRedrawCounter = 0;
879     return TRUE;
880   }
881   CFX_RectF rtWidget;
882   pWidget->GetWidgetRect(rtWidget);
883   rtWidget.left = rtWidget.top = 0;
884   pMatrix->TransformRect(rtWidget);
885   if (!rtWidget.IntersectWith(rtDirty)) {
886     return FALSE;
887   }
888   IFWL_Widget* pChild =
889       FWL_GetWidgetMgr()->GetWidget(pWidget, FWL_WGTRELATION_FirstChild);
890   if (!pChild) {
891     return TRUE;
892   }
893   if (pChild->GetClassID() == 3150298670) {
894     CFX_RectF rtTemp;
895     pChild->GetWidgetRect(rtTemp);
896     if (rtTemp.width >= rtWidget.width && rtTemp.height >= rtWidget.height) {
897       pChild =
898           FWL_GetWidgetMgr()->GetWidget(pChild, FWL_WGTRELATION_FirstChild);
899       if (!pChild) {
900         return TRUE;
901       }
902     }
903   }
904   CFX_RectF rtChilds;
905   rtChilds.Empty();
906   FX_BOOL bChildIntersectWithDirty = FALSE;
907   FX_BOOL bOrginPtIntersectWidthChild = FALSE;
908   FX_BOOL bOrginPtIntersectWidthDirty =
909       rtDirty.Contains(rtWidget.left, rtWidget.top);
910   static FWL_NeedRepaintHitData hitPoint[FWL_NEEDREPAINTHIT_Point];
911   static int32_t iSize = sizeof(FWL_NeedRepaintHitData);
912   FXSYS_memset(hitPoint, 0, iSize);
913   FX_FLOAT fxPiece = rtWidget.width / FWL_NEEDREPAINTHIT_Piece;
914   FX_FLOAT fyPiece = rtWidget.height / FWL_NEEDREPAINTHIT_Piece;
915   hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left;
916   hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x =
917       hitPoint[10].hitPoint.x = fxPiece + rtWidget.left;
918   hitPoint[1].hitPoint.x = hitPoint[4].hitPoint.x = hitPoint[8].hitPoint.x =
919       hitPoint[11].hitPoint.x = fxPiece * 2 + rtWidget.left;
920   hitPoint[5].hitPoint.x = hitPoint[9].hitPoint.x =
921       rtWidget.width + rtWidget.left;
922   hitPoint[0].hitPoint.y = hitPoint[1].hitPoint.y = rtWidget.top;
923   hitPoint[2].hitPoint.y = hitPoint[3].hitPoint.y = hitPoint[4].hitPoint.y =
924       hitPoint[5].hitPoint.y = fyPiece + rtWidget.top;
925   hitPoint[6].hitPoint.y = hitPoint[7].hitPoint.y = hitPoint[8].hitPoint.y =
926       hitPoint[9].hitPoint.y = fyPiece * 2 + rtWidget.top;
927   hitPoint[10].hitPoint.y = hitPoint[11].hitPoint.y =
928       rtWidget.height + rtWidget.top;
929   do {
930     CFX_RectF rect;
931     pChild->GetWidgetRect(rect);
932     CFX_RectF r = rect;
933     r.left += rtWidget.left;
934     r.top += rtWidget.top;
935     if (r.IsEmpty()) {
936       continue;
937     }
938     if (r.Contains(rtDirty)) {
939       return FALSE;
940     }
941     if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty)) {
942       bChildIntersectWithDirty = TRUE;
943     }
944     if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) {
945       bOrginPtIntersectWidthChild = rect.Contains(0, 0);
946     }
947     if (rtChilds.IsEmpty()) {
948       rtChilds = rect;
949     } else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible)) {
950       rtChilds.Union(rect);
951     }
952     for (int32_t i = 0; i < FWL_NEEDREPAINTHIT_Point; i++) {
953       if (hitPoint[i].bNotContainByDirty || hitPoint[i].bNotNeedRepaint) {
954         continue;
955       }
956       if (!rtDirty.Contains(hitPoint[i].hitPoint)) {
957         hitPoint[i].bNotContainByDirty = TRUE;
958         continue;
959       }
960       if (r.Contains(hitPoint[i].hitPoint)) {
961         hitPoint[i].bNotNeedRepaint = TRUE;
962       }
963     }
964   } while ((pChild = FWL_GetWidgetMgr()->GetWidget(
965                 pChild, FWL_WGTRELATION_NextSibling)) != NULL);
966   if (!bChildIntersectWithDirty) {
967     return TRUE;
968   }
969   if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) {
970     return TRUE;
971   }
972   if (rtChilds.IsEmpty()) {
973     return TRUE;
974   }
975   int32_t repaintPoint = FWL_NEEDREPAINTHIT_Point;
976   for (int32_t i = 0; i < FWL_NEEDREPAINTHIT_Point; i++) {
977     if (hitPoint[i].bNotNeedRepaint) {
978       repaintPoint--;
979     }
980   }
981   if (repaintPoint > 0) {
982     return TRUE;
983   }
984   pMatrix->TransformRect(rtChilds);
985   if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget)) {
986     return FALSE;
987   }
988   return TRUE;
989 }
bUseOffscreenDirect(IFWL_Widget * pWidget)990 FX_BOOL CFWL_WidgetMgrDelegate::bUseOffscreenDirect(IFWL_Widget* pWidget) {
991   CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget);
992   if (!FWL_UseOffscreen(pWidget) || !(pItem->pOffscreen)) {
993     return FALSE;
994   }
995 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
996   if (pItem->bOutsideChanged) {
997     CFX_RectF r;
998     pWidget->GetWidgetRect(r);
999     CFX_RectF temp(m_pWidgetMgr->m_rtScreen);
1000     temp.Deflate(50, 50);
1001     if (!temp.Contains(r)) {
1002       return FALSE;
1003     }
1004     pItem->bOutsideChanged = FALSE;
1005   }
1006 #endif
1007   return pItem->iRedrawCounter == 0;
1008 }
FWL_WriteBMP(CFX_DIBitmap * pBitmap,const FX_CHAR * filename)1009 static void FWL_WriteBMP(CFX_DIBitmap* pBitmap, const FX_CHAR* filename) {
1010   FILE* file = fopen(filename, "wb");
1011   if (file == NULL) {
1012     return;
1013   }
1014   int size = 14 + 40 + pBitmap->GetPitch() * pBitmap->GetHeight();
1015   unsigned char buffer[40];
1016   buffer[0] = 'B';
1017   buffer[1] = 'M';
1018   buffer[2] = (unsigned char)size;
1019   buffer[3] = (unsigned char)(size >> 8);
1020   buffer[4] = (unsigned char)(size >> 16);
1021   buffer[5] = (unsigned char)(size >> 24);
1022   buffer[6] = buffer[7] = buffer[8] = buffer[9] = 0;
1023   buffer[10] = 54;
1024   buffer[11] = buffer[12] = buffer[13] = 0;
1025   fwrite(buffer, 14, 1, file);
1026   memset(buffer, 0, 40);
1027   buffer[0] = 40;
1028   buffer[4] = (unsigned char)pBitmap->GetWidth();
1029   buffer[5] = (unsigned char)(pBitmap->GetWidth() >> 8);
1030   buffer[6] = (unsigned char)(pBitmap->GetWidth() >> 16);
1031   buffer[7] = (unsigned char)(pBitmap->GetWidth() >> 24);
1032   buffer[8] = (unsigned char)(-pBitmap->GetHeight());
1033   buffer[9] = (unsigned char)((-pBitmap->GetHeight()) >> 8);
1034   buffer[10] = (unsigned char)((-pBitmap->GetHeight()) >> 16);
1035   buffer[11] = (unsigned char)((-pBitmap->GetHeight()) >> 24);
1036   buffer[12] = 1;
1037   buffer[14] = pBitmap->GetBPP();
1038   fwrite(buffer, 40, 1, file);
1039   for (int row = 0; row < pBitmap->GetHeight(); row++) {
1040     uint8_t* scan_line = pBitmap->GetBuffer() + row * pBitmap->GetPitch();
1041     fwrite(scan_line, pBitmap->GetPitch(), 1, file);
1042   }
1043   fclose(file);
1044 }
FWL_WidgetMgrSnapshot(IFWL_Widget * pWidget,const CFX_WideString * saveFile,const CFX_Matrix * pMatrix)1045 FWL_ERR FWL_WidgetMgrSnapshot(IFWL_Widget* pWidget,
1046                               const CFX_WideString* saveFile,
1047                               const CFX_Matrix* pMatrix) {
1048   CFX_RectF r;
1049   pWidget->GetWidgetRect(r);
1050   CFX_Graphics gs;
1051   gs.Create((int32_t)r.width, (int32_t)r.height, FXDIB_Argb);
1052   CFWL_WidgetMgr* widgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
1053   CFWL_WidgetMgrDelegate* delegate = widgetMgr->GetDelegate();
1054   delegate->OnDrawWidget(pWidget, &gs, pMatrix);
1055   CFX_DIBitmap* dib = gs.GetRenderDevice()->GetBitmap();
1056   FWL_WriteBMP(dib, saveFile->UTF8Encode());
1057   return FWL_ERR_Succeeded;
1058 }
FWL_WidgetIsChild(IFWL_Widget * parent,IFWL_Widget * find)1059 FX_BOOL FWL_WidgetIsChild(IFWL_Widget* parent, IFWL_Widget* find) {
1060   if (!find) {
1061     return FALSE;
1062   }
1063   IFWL_Widget* child =
1064       FWL_GetWidgetMgr()->GetWidget(parent, FWL_WGTRELATION_FirstChild);
1065   while (child) {
1066     if (child == find) {
1067       return TRUE;
1068     }
1069     if (FWL_WidgetIsChild(child, find)) {
1070       return TRUE;
1071     }
1072     child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling);
1073   }
1074   return FALSE;
1075 }
1076