• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fwl/cfwl_notedriver.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fxcrt/fx_extension.h"
13 #include "third_party/base/ptr_util.h"
14 #include "third_party/base/stl_util.h"
15 #include "xfa/fwl/cfwl_app.h"
16 #include "xfa/fwl/cfwl_eventtarget.h"
17 #include "xfa/fwl/cfwl_form.h"
18 #include "xfa/fwl/cfwl_messagekey.h"
19 #include "xfa/fwl/cfwl_messagekillfocus.h"
20 #include "xfa/fwl/cfwl_messagemouse.h"
21 #include "xfa/fwl/cfwl_messagemousewheel.h"
22 #include "xfa/fwl/cfwl_messagesetfocus.h"
23 #include "xfa/fwl/cfwl_noteloop.h"
24 #include "xfa/fwl/cfwl_widgetmgr.h"
25 
CFWL_NoteDriver()26 CFWL_NoteDriver::CFWL_NoteDriver()
27     : m_pHover(nullptr),
28       m_pFocus(nullptr),
29       m_pGrab(nullptr),
30       m_pNoteLoop(pdfium::MakeUnique<CFWL_NoteLoop>()) {
31   PushNoteLoop(m_pNoteLoop.get());
32 }
33 
~CFWL_NoteDriver()34 CFWL_NoteDriver::~CFWL_NoteDriver() {}
35 
SendEvent(CFWL_Event * pNote)36 void CFWL_NoteDriver::SendEvent(CFWL_Event* pNote) {
37   for (const auto& pair : m_eventTargets) {
38     if (pair.second->IsValid())
39       pair.second->ProcessEvent(pNote);
40   }
41 }
42 
RegisterEventTarget(CFWL_Widget * pListener,CFWL_Widget * pEventSource)43 void CFWL_NoteDriver::RegisterEventTarget(CFWL_Widget* pListener,
44                                           CFWL_Widget* pEventSource) {
45   uint32_t key = pListener->GetEventKey();
46   if (key == 0) {
47     do {
48       key = rand();
49     } while (key == 0 || pdfium::ContainsKey(m_eventTargets, key));
50     pListener->SetEventKey(key);
51   }
52   if (!m_eventTargets[key])
53     m_eventTargets[key] = pdfium::MakeUnique<CFWL_EventTarget>(pListener);
54 
55   m_eventTargets[key]->SetEventSource(pEventSource);
56 }
57 
UnregisterEventTarget(CFWL_Widget * pListener)58 void CFWL_NoteDriver::UnregisterEventTarget(CFWL_Widget* pListener) {
59   uint32_t key = pListener->GetEventKey();
60   if (key == 0)
61     return;
62 
63   auto it = m_eventTargets.find(key);
64   if (it != m_eventTargets.end())
65     it->second->FlagInvalid();
66 }
67 
PushNoteLoop(CFWL_NoteLoop * pNoteLoop)68 void CFWL_NoteDriver::PushNoteLoop(CFWL_NoteLoop* pNoteLoop) {
69   m_NoteLoopQueue.push_back(pNoteLoop);
70 }
71 
PopNoteLoop()72 CFWL_NoteLoop* CFWL_NoteDriver::PopNoteLoop() {
73   if (m_NoteLoopQueue.empty())
74     return nullptr;
75 
76   CFWL_NoteLoop* p = m_NoteLoopQueue.back();
77   m_NoteLoopQueue.pop_back();
78   return p;
79 }
80 
SetFocus(CFWL_Widget * pFocus)81 bool CFWL_NoteDriver::SetFocus(CFWL_Widget* pFocus) {
82   if (m_pFocus == pFocus)
83     return true;
84 
85   CFWL_Widget* pPrev = m_pFocus;
86   m_pFocus = pFocus;
87   if (pPrev) {
88     if (IFWL_WidgetDelegate* pDelegate = pPrev->GetDelegate()) {
89       CFWL_MessageKillFocus ms(pPrev, pPrev);
90       pDelegate->OnProcessMessage(&ms);
91     }
92   }
93   if (pFocus) {
94     CFWL_Widget* pWidget =
95         pFocus->GetOwnerApp()->GetWidgetMgr()->GetSystemFormWidget(pFocus);
96     CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
97     if (pForm)
98       pForm->SetSubFocus(pFocus);
99 
100     if (IFWL_WidgetDelegate* pDelegate = pFocus->GetDelegate()) {
101       CFWL_MessageSetFocus ms(nullptr, pFocus);
102       pDelegate->OnProcessMessage(&ms);
103     }
104   }
105   return true;
106 }
107 
Run()108 void CFWL_NoteDriver::Run() {
109 #if _FX_OS_ == _FX_OS_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
110   for (;;) {
111     CFWL_NoteLoop* pTopLoop = GetTopLoop();
112     if (!pTopLoop || !pTopLoop->ContinueModal())
113       break;
114     UnqueueMessageAndProcess(pTopLoop);
115   }
116 #endif  // _FX_OS_ == _FX_OS_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
117 }
118 
NotifyTargetHide(CFWL_Widget * pNoteTarget)119 void CFWL_NoteDriver::NotifyTargetHide(CFWL_Widget* pNoteTarget) {
120   if (m_pFocus == pNoteTarget)
121     m_pFocus = nullptr;
122   if (m_pHover == pNoteTarget)
123     m_pHover = nullptr;
124   if (m_pGrab == pNoteTarget)
125     m_pGrab = nullptr;
126 }
127 
NotifyTargetDestroy(CFWL_Widget * pNoteTarget)128 void CFWL_NoteDriver::NotifyTargetDestroy(CFWL_Widget* pNoteTarget) {
129   if (m_pFocus == pNoteTarget)
130     m_pFocus = nullptr;
131   if (m_pHover == pNoteTarget)
132     m_pHover = nullptr;
133   if (m_pGrab == pNoteTarget)
134     m_pGrab = nullptr;
135 
136   UnregisterEventTarget(pNoteTarget);
137 
138   for (CFWL_Widget* pWidget : m_Forms) {
139     CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
140     if (!pForm)
141       continue;
142 
143     CFWL_Widget* pSubFocus = pForm->GetSubFocus();
144     if (!pSubFocus)
145       return;
146 
147     if (pSubFocus == pNoteTarget)
148       pForm->SetSubFocus(nullptr);
149   }
150 }
151 
RegisterForm(CFWL_Widget * pForm)152 void CFWL_NoteDriver::RegisterForm(CFWL_Widget* pForm) {
153   if (!pForm || pdfium::ContainsValue(m_Forms, pForm))
154     return;
155 
156   m_Forms.push_back(pForm);
157   if (m_Forms.size() == 1 && !m_NoteLoopQueue.empty() && m_NoteLoopQueue[0])
158     m_NoteLoopQueue[0]->SetMainForm(pForm);
159 }
160 
UnRegisterForm(CFWL_Widget * pForm)161 void CFWL_NoteDriver::UnRegisterForm(CFWL_Widget* pForm) {
162   auto iter = std::find(m_Forms.begin(), m_Forms.end(), pForm);
163   if (iter != m_Forms.end())
164     m_Forms.erase(iter);
165 }
166 
QueueMessage(std::unique_ptr<CFWL_Message> pMessage)167 void CFWL_NoteDriver::QueueMessage(std::unique_ptr<CFWL_Message> pMessage) {
168   m_NoteQueue.push_back(std::move(pMessage));
169 }
170 
UnqueueMessageAndProcess(CFWL_NoteLoop * pNoteLoop)171 void CFWL_NoteDriver::UnqueueMessageAndProcess(CFWL_NoteLoop* pNoteLoop) {
172   if (m_NoteQueue.empty())
173     return;
174 
175   std::unique_ptr<CFWL_Message> pMessage = std::move(m_NoteQueue.front());
176   m_NoteQueue.pop_front();
177   if (!IsValidMessage(pMessage.get()))
178     return;
179 
180   ProcessMessage(std::move(pMessage));
181 }
182 
GetTopLoop() const183 CFWL_NoteLoop* CFWL_NoteDriver::GetTopLoop() const {
184   return !m_NoteLoopQueue.empty() ? m_NoteLoopQueue.back() : nullptr;
185 }
186 
ProcessMessage(std::unique_ptr<CFWL_Message> pMessage)187 void CFWL_NoteDriver::ProcessMessage(std::unique_ptr<CFWL_Message> pMessage) {
188   CFWL_WidgetMgr* pWidgetMgr =
189       pMessage->m_pDstTarget->GetOwnerApp()->GetWidgetMgr();
190   CFWL_Widget* pMessageForm = pWidgetMgr->IsFormDisabled()
191                                   ? pMessage->m_pDstTarget
192                                   : GetMessageForm(pMessage->m_pDstTarget);
193   if (!pMessageForm)
194     return;
195 
196   if (!DispatchMessage(pMessage.get(), pMessageForm))
197     return;
198 
199   if (pMessage->GetType() == CFWL_Message::Type::Mouse)
200     MouseSecondary(pMessage.get());
201 }
202 
DispatchMessage(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)203 bool CFWL_NoteDriver::DispatchMessage(CFWL_Message* pMessage,
204                                       CFWL_Widget* pMessageForm) {
205   switch (pMessage->GetType()) {
206     case CFWL_Message::Type::SetFocus: {
207       if (!DoSetFocus(pMessage, pMessageForm))
208         return false;
209       break;
210     }
211     case CFWL_Message::Type::KillFocus: {
212       if (!DoKillFocus(pMessage, pMessageForm))
213         return false;
214       break;
215     }
216     case CFWL_Message::Type::Key: {
217       if (!DoKey(pMessage, pMessageForm))
218         return false;
219       break;
220     }
221     case CFWL_Message::Type::Mouse: {
222       if (!DoMouse(pMessage, pMessageForm))
223         return false;
224       break;
225     }
226     case CFWL_Message::Type::MouseWheel: {
227       if (!DoWheel(pMessage, pMessageForm))
228         return false;
229       break;
230     }
231     default:
232       break;
233   }
234   if (IFWL_WidgetDelegate* pDelegate = pMessage->m_pDstTarget->GetDelegate())
235     pDelegate->OnProcessMessage(pMessage);
236 
237   return true;
238 }
239 
DoSetFocus(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)240 bool CFWL_NoteDriver::DoSetFocus(CFWL_Message* pMessage,
241                                  CFWL_Widget* pMessageForm) {
242   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
243   if (pWidgetMgr->IsFormDisabled()) {
244     m_pFocus = pMessage->m_pDstTarget;
245     return true;
246   }
247 
248   CFWL_Widget* pWidget = pMessage->m_pDstTarget;
249   if (!pWidget)
250     return false;
251 
252   CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
253   CFWL_Widget* pSubFocus = pForm->GetSubFocus();
254   if (pSubFocus && ((pSubFocus->GetStates() & FWL_WGTSTATE_Focused) == 0)) {
255     pMessage->m_pDstTarget = pSubFocus;
256     if (m_pFocus != pMessage->m_pDstTarget) {
257       m_pFocus = pMessage->m_pDstTarget;
258       return true;
259     }
260   }
261   return false;
262 }
263 
DoKillFocus(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)264 bool CFWL_NoteDriver::DoKillFocus(CFWL_Message* pMessage,
265                                   CFWL_Widget* pMessageForm) {
266   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
267   if (pWidgetMgr->IsFormDisabled()) {
268     if (m_pFocus == pMessage->m_pDstTarget)
269       m_pFocus = nullptr;
270     return true;
271   }
272 
273   CFWL_Form* pForm = static_cast<CFWL_Form*>(pMessage->m_pDstTarget);
274   if (!pForm)
275     return false;
276 
277   CFWL_Widget* pSubFocus = pForm->GetSubFocus();
278   if (pSubFocus && (pSubFocus->GetStates() & FWL_WGTSTATE_Focused)) {
279     pMessage->m_pDstTarget = pSubFocus;
280     if (m_pFocus == pMessage->m_pDstTarget) {
281       m_pFocus = nullptr;
282       return true;
283     }
284   }
285   return false;
286 }
287 
DoKey(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)288 bool CFWL_NoteDriver::DoKey(CFWL_Message* pMessage, CFWL_Widget* pMessageForm) {
289   CFWL_MessageKey* pMsg = static_cast<CFWL_MessageKey*>(pMessage);
290 #if (_FX_OS_ != _FX_OS_MACOSX_)
291   if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
292       pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
293     CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
294     CFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
295     CFWL_Widget* pFocus = m_pFocus;
296     if (m_pFocus && pWidgetMgr->GetSystemFormWidget(m_pFocus) != pForm)
297       pFocus = nullptr;
298 
299     bool bFind = false;
300     CFWL_Widget* pNextTabStop = pWidgetMgr->NextTab(pForm, pFocus, bFind);
301     if (!pNextTabStop) {
302       bFind = false;
303       pNextTabStop = pWidgetMgr->NextTab(pForm, nullptr, bFind);
304     }
305     if (pNextTabStop == pFocus)
306       return true;
307     if (pNextTabStop)
308       SetFocus(pNextTabStop);
309     return true;
310   }
311 #endif
312 
313   if (!m_pFocus) {
314     if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
315         pMsg->m_dwKeyCode == FWL_VKEY_Return) {
316       CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
317       CFWL_Widget* defButton = pWidgetMgr->GetDefaultButton(pMessageForm);
318       if (defButton) {
319         pMsg->m_pDstTarget = defButton;
320         return true;
321       }
322     }
323     return false;
324   }
325   pMsg->m_pDstTarget = m_pFocus;
326   return true;
327 }
328 
DoMouse(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)329 bool CFWL_NoteDriver::DoMouse(CFWL_Message* pMessage,
330                               CFWL_Widget* pMessageForm) {
331   CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
332   if (pMsg->m_dwCmd == FWL_MouseCommand::Leave ||
333       pMsg->m_dwCmd == FWL_MouseCommand::Hover ||
334       pMsg->m_dwCmd == FWL_MouseCommand::Enter) {
335     return !!pMsg->m_pDstTarget;
336   }
337   if (pMsg->m_pDstTarget != pMessageForm)
338     pMsg->m_pos = pMsg->m_pDstTarget->TransformTo(pMessageForm, pMsg->m_pos);
339   if (!DoMouseEx(pMsg, pMessageForm))
340     pMsg->m_pDstTarget = pMessageForm;
341   return true;
342 }
343 
DoWheel(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)344 bool CFWL_NoteDriver::DoWheel(CFWL_Message* pMessage,
345                               CFWL_Widget* pMessageForm) {
346   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
347   if (!pWidgetMgr)
348     return false;
349 
350   CFWL_MessageMouseWheel* pMsg = static_cast<CFWL_MessageMouseWheel*>(pMessage);
351   CFWL_Widget* pDst = pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_pos);
352   if (!pDst)
353     return false;
354 
355   pMsg->m_pos = pMessageForm->TransformTo(pDst, pMsg->m_pos);
356   pMsg->m_pDstTarget = pDst;
357   return true;
358 }
359 
DoMouseEx(CFWL_Message * pMessage,CFWL_Widget * pMessageForm)360 bool CFWL_NoteDriver::DoMouseEx(CFWL_Message* pMessage,
361                                 CFWL_Widget* pMessageForm) {
362   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
363   if (!pWidgetMgr)
364     return false;
365   CFWL_Widget* pTarget = nullptr;
366   if (m_pGrab)
367     pTarget = m_pGrab;
368 
369   CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
370   if (!pTarget)
371     pTarget = pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_pos);
372   if (!pTarget)
373     return false;
374   if (pTarget && pMessageForm != pTarget)
375     pMsg->m_pos = pMessageForm->TransformTo(pTarget, pMsg->m_pos);
376 
377   pMsg->m_pDstTarget = pTarget;
378   return true;
379 }
380 
MouseSecondary(CFWL_Message * pMessage)381 void CFWL_NoteDriver::MouseSecondary(CFWL_Message* pMessage) {
382   CFWL_Widget* pTarget = pMessage->m_pDstTarget;
383   if (pTarget == m_pHover)
384     return;
385 
386   CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
387   if (m_pHover) {
388     CFWL_MessageMouse msLeave(nullptr, m_pHover);
389     msLeave.m_pos = pTarget->TransformTo(m_pHover, pMsg->m_pos);
390     msLeave.m_dwFlags = 0;
391     msLeave.m_dwCmd = FWL_MouseCommand::Leave;
392     DispatchMessage(&msLeave, nullptr);
393   }
394   if (pTarget->GetClassID() == FWL_Type::Form) {
395     m_pHover = nullptr;
396     return;
397   }
398   m_pHover = pTarget;
399 
400   CFWL_MessageMouse msHover(nullptr, pTarget);
401   msHover.m_pos = pMsg->m_pos;
402   msHover.m_dwFlags = 0;
403   msHover.m_dwCmd = FWL_MouseCommand::Hover;
404   DispatchMessage(&msHover, nullptr);
405 }
406 
IsValidMessage(CFWL_Message * pMessage)407 bool CFWL_NoteDriver::IsValidMessage(CFWL_Message* pMessage) {
408   for (CFWL_NoteLoop* pNoteLoop : m_NoteLoopQueue) {
409     CFWL_Widget* pForm = pNoteLoop->GetForm();
410     if (pForm && pForm == pMessage->m_pDstTarget)
411       return true;
412   }
413   for (CFWL_Widget* pWidget : m_Forms) {
414     CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
415     if (pForm == pMessage->m_pDstTarget)
416       return true;
417   }
418   return false;
419 }
420 
GetMessageForm(CFWL_Widget * pDstTarget)421 CFWL_Widget* CFWL_NoteDriver::GetMessageForm(CFWL_Widget* pDstTarget) {
422   if (m_NoteLoopQueue.empty())
423     return nullptr;
424 
425   CFWL_Widget* pMessageForm = nullptr;
426   if (m_NoteLoopQueue.size() > 1)
427     pMessageForm = m_NoteLoopQueue.back()->GetForm();
428   else if (!pdfium::ContainsValue(m_Forms, pDstTarget))
429     pMessageForm = pDstTarget;
430 
431   if (!pMessageForm && pDstTarget) {
432     CFWL_WidgetMgr* pWidgetMgr = pDstTarget->GetOwnerApp()->GetWidgetMgr();
433     if (!pWidgetMgr)
434       return nullptr;
435 
436     pMessageForm = pWidgetMgr->GetSystemFormWidget(pDstTarget);
437   }
438   return pMessageForm;
439 }
440 
ClearEventTargets()441 void CFWL_NoteDriver::ClearEventTargets() {
442   auto it = m_eventTargets.begin();
443   while (it != m_eventTargets.end()) {
444     auto old = it++;
445     if (!old->second->IsValid())
446       m_eventTargets.erase(old);
447   }
448 }
449