Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
11 KiB

  1. #include "stdafx.h"
  2. #include "Ctrl.h"
  3. #include "Animation.h"
  4. #if ENABLE_MSGTABLE_API
  5. /***************************************************************************\
  6. *****************************************************************************
  7. *
  8. * Global Functions
  9. *
  10. *****************************************************************************
  11. \***************************************************************************/
  12. //------------------------------------------------------------------------------
  13. DUSER_API void WINAPI
  14. DUserStopAnimation(Visual * pgvSubject, PRID pridAni)
  15. {
  16. if (pgvSubject == NULL) {
  17. PromptInvalid("Invalid pgvSubject");
  18. return;
  19. }
  20. if (pridAni <= 0) {
  21. PromptInvalid("Invalid Animation pridAni");
  22. return;
  23. }
  24. DuExtension * pext = DuExtension::GetExtension(pgvSubject, pridAni);
  25. if (pext != NULL) {
  26. pext->GetStub()->OnRemoveExisting();
  27. }
  28. }
  29. /***************************************************************************\
  30. *****************************************************************************
  31. *
  32. * class DuAnimation
  33. *
  34. *****************************************************************************
  35. \***************************************************************************/
  36. MSGID DuAnimation::s_msgidComplete = 0;
  37. //------------------------------------------------------------------------------
  38. DuAnimation::~DuAnimation()
  39. {
  40. Destroy(TRUE);
  41. SafeRelease(m_pipol);
  42. SafeRelease(m_pgflow);
  43. #if DEBUG_TRACECREATION
  44. Trace("STOP Animation 0x%p @ %d (%d frames)\n", this, GetTickCount(), m_DEBUG_cUpdates);
  45. #endif // DEBUG_TRACECREATION
  46. //
  47. // Ensure proper destruction
  48. //
  49. AssertMsg(m_hact == NULL, "Action should already be destroyed");
  50. }
  51. /***************************************************************************\
  52. *
  53. * DuAnimation::InitClass
  54. *
  55. * InitClass() is called during startup and provides an opportunity to
  56. * initialize common data.
  57. *
  58. \***************************************************************************/
  59. HRESULT
  60. DuAnimation::InitClass()
  61. {
  62. s_msgidComplete = RegisterGadgetMessage(&_uuidof(Animation::evComplete));
  63. if (s_msgidComplete == 0) {
  64. return (HRESULT) GetLastError();
  65. }
  66. return S_OK;
  67. }
  68. //------------------------------------------------------------------------------
  69. HRESULT
  70. DuAnimation::PreBuild(DUser::Gadget::ConstructInfo * pci)
  71. {
  72. //
  73. // Validate parameters
  74. //
  75. Animation::AniCI * pDesc = reinterpret_cast<Animation::AniCI *>(pci);
  76. if ((pDesc->pipol == NULL) || (pDesc->pgflow == NULL)) {
  77. PromptInvalid("Must provide valid Interpolation and Flow objects");
  78. return E_INVALIDARG;
  79. }
  80. PRID pridExtension = 0;
  81. VerifyHR(pDesc->pgflow->GetPRID(&pridExtension));
  82. if (pridExtension == 0) {
  83. PromptInvalid("Flow must register PRID");
  84. return E_INVALIDARG;
  85. }
  86. return S_OK;
  87. }
  88. //------------------------------------------------------------------------------
  89. HRESULT
  90. DuAnimation::PostBuild(DUser::Gadget::ConstructInfo * pci)
  91. {
  92. //
  93. // Check parameters. This should be validated in PreBuild().
  94. //
  95. Animation::AniCI * pDesc = reinterpret_cast<Animation::AniCI *>(pci);
  96. Assert(pDesc->pipol != NULL);
  97. Assert(pDesc->pgflow != NULL);
  98. //
  99. // Setup the Action
  100. //
  101. GMA_ACTION gma;
  102. ZeroMemory(&gma, sizeof(gma));
  103. gma.cbSize = sizeof(gma);
  104. gma.flDelay = pDesc->act.flDelay;
  105. gma.flDuration = pDesc->act.flDuration;
  106. gma.flPeriod = pDesc->act.flPeriod;
  107. gma.cRepeat = pDesc->act.cRepeat;
  108. gma.dwPause = pDesc->act.dwPause;
  109. gma.pfnProc = RawActionProc;
  110. gma.pvData = this;
  111. m_hact = CreateAction(&gma);
  112. if (m_hact == NULL) {
  113. return (HRESULT) GetLastError();
  114. }
  115. PRID pridExtension;
  116. VerifyHR(pDesc->pgflow->GetPRID(&pridExtension));
  117. HRESULT hr = DuExtension::Create(pDesc->pgvSubject, pridExtension, DuExtension::oAsyncDestroy);
  118. if (FAILED(hr)) {
  119. return hr;
  120. }
  121. //
  122. // Store the related objects
  123. //
  124. pDesc->pipol->AddRef();
  125. pDesc->pgflow->AddRef();
  126. m_pipol = pDesc->pipol;
  127. m_pgflow = pDesc->pgflow;
  128. //
  129. // Animations need to be AddRef()'d again (have a reference count of 2)
  130. // because they need to outlive the initial call to Release() after the
  131. // called has setup the animation returned from BuildAnimation().
  132. //
  133. // This is because the Animation continues to life until it has fully
  134. // executed (or has been aborted).
  135. //
  136. AddRef();
  137. return S_OK;
  138. }
  139. //------------------------------------------------------------------------------
  140. void
  141. DuAnimation::Destroy(BOOL fFinal)
  142. {
  143. //
  144. // Mark that we have already started the destruction process and don't need
  145. // to start again. We only want to post the destruction message once.
  146. //
  147. if (m_fStartDestroy) {
  148. return;
  149. }
  150. m_fStartDestroy = TRUE;
  151. if (m_pgvSubject != NULL) {
  152. #if DBG
  153. DuAnimation * paniExist = static_cast<DuAnimation *> (GetExtension(m_pgvSubject, m_pridListen));
  154. if (paniExist != NULL) {
  155. AssertMsg(paniExist == this, "Animations must match");
  156. }
  157. #endif // DBG
  158. CleanupChangeGadget();
  159. }
  160. //
  161. // Destroy the Animation
  162. //
  163. AssertMsg(!fFinal, "Object is already being destructed");
  164. if (fFinal) {
  165. GetStub()->OnAsyncDestroy();
  166. } else {
  167. PostAsyncDestroy();
  168. }
  169. }
  170. //------------------------------------------------------------------------------
  171. HRESULT
  172. DuAnimation::ApiOnAsyncDestroy(Animation::OnAsyncDestroyMsg *)
  173. {
  174. AssertMsg(m_fStartDestroy, "Must call Destroy() to start the destruction process.");
  175. AssertMsg(!m_fProcessing, "Should not be processing when start destruction");
  176. AssertMsg(m_pgvSubject == NULL, "Animation should already have detached from Gadget");
  177. HACTION hact = m_hact;
  178. //
  179. // Set everything to NULL now.
  180. //
  181. m_hact = NULL;
  182. if (hact != NULL) {
  183. ::DeleteHandle(hact);
  184. hact = NULL;
  185. }
  186. Release();
  187. return S_OK;
  188. }
  189. //------------------------------------------------------------------------------
  190. HRESULT
  191. DuAnimation::ApiSetTime(Animation::SetTimeMsg * pmsg)
  192. {
  193. GMA_ACTIONINFO mai;
  194. //
  195. // TODO: Need to save these values from the last time so that they are
  196. // valid.
  197. //
  198. mai.hact = m_hact;
  199. mai.pvData = this;
  200. mai.flDuration = 0.0f;
  201. m_time = (Animation::ETime) pmsg->time;
  202. switch (pmsg->time)
  203. {
  204. case Animation::tComplete:
  205. // Don't do anything
  206. return S_OK;
  207. default:
  208. case Animation::tAbort:
  209. case Animation::tDestroy:
  210. goto Done;
  211. case Animation::tEnd:
  212. mai.flProgress = 1.0f;
  213. break;
  214. case Animation::tReset:
  215. mai.flProgress = 0.0f;
  216. break;
  217. }
  218. mai.cEvent = 0;
  219. mai.cPeriods = 0;
  220. mai.fFinished = FALSE;
  221. m_fProcessing = TRUE;
  222. m_pgflow->OnAction(m_pgvSubject, m_pipol, mai.flProgress);
  223. Assert(m_fProcessing);
  224. m_fProcessing = FALSE;
  225. Done:
  226. ::DeleteHandle(m_hact);
  227. return S_OK;
  228. }
  229. //------------------------------------------------------------------------------
  230. void
  231. DuAnimation::CleanupChangeGadget()
  232. {
  233. //
  234. // Give the derived Animation a chance to cleanup
  235. //
  236. // Check that we are still the Animation attached to this Gadget. We need
  237. // to remove this property immediately. We can not wait for a posted
  238. // message to be processed because we may need to set it right now if we are
  239. // creating a new Animation.
  240. //
  241. BOOL fStarted = FALSE;
  242. Animation::CompleteEvent msg;
  243. msg.cbSize = sizeof(msg);
  244. msg.nMsg = s_msgidComplete;
  245. msg.hgadMsg = GetHandle();
  246. msg.fNormal = IsStartDelete(m_pgvSubject->GetHandle(), &fStarted) && (!fStarted);
  247. DUserSendEvent(&msg, 0);
  248. Assert(m_pgvSubject != NULL);
  249. Assert(m_pridListen != 0);
  250. Verify(SUCCEEDED(m_pgvSubject->RemoveProperty(m_pridListen)));
  251. m_pgvSubject = NULL;
  252. }
  253. //------------------------------------------------------------------------------
  254. void CALLBACK
  255. DuAnimation::RawActionProc(
  256. IN GMA_ACTIONINFO * pmai)
  257. {
  258. //
  259. // Need to AddRef while processing the Animation to ensure that it does not
  260. // get destroyed from under us, for example, during one of the callbacks.
  261. //
  262. DuAnimation * pani = (DuAnimation *) pmai->pvData;
  263. pani->AddRef();
  264. Assert(!pani->m_fProcessing);
  265. #if DEBUG_TRACECREATION
  266. Trace("START RawActionP 0x%p @ %d\n", pani, GetTickCount());
  267. #endif // DEBUG_TRACECREATION
  268. pani->ActionProc(pmai);
  269. #if DEBUG_TRACECREATION
  270. Trace("STOP RawActionP 0x%p @ %d\n", pani, GetTickCount());
  271. #endif // DEBUG_TRACECREATION
  272. Assert(!pani->m_fProcessing);
  273. pani->Release();
  274. }
  275. //------------------------------------------------------------------------------
  276. void
  277. DuAnimation::ActionProc(
  278. IN GMA_ACTIONINFO * pmai)
  279. {
  280. #if DBG
  281. m_DEBUG_cUpdates++;
  282. #endif // DBG
  283. if ((!m_fStartDestroy) && (m_pgvSubject != NULL)) {
  284. //
  285. // This ActionProc will be called when the Action is being destroyed, so
  286. // we only want to invoke the Action under certain circumstances.
  287. //
  288. switch (m_time)
  289. {
  290. case Animation::tComplete:
  291. case Animation::tEnd:
  292. case Animation::tReset:
  293. //
  294. // All of these are valid to complete. If it isn't in this list, we
  295. // don't want to execute it during a shutdown.
  296. //
  297. m_fProcessing = TRUE;
  298. m_pgflow->OnAction(m_pgvSubject, m_pipol, pmai->flProgress);
  299. Assert(m_fProcessing);
  300. m_fProcessing = FALSE;
  301. break;
  302. }
  303. }
  304. if (pmai->fFinished) {
  305. m_hact = NULL;
  306. Destroy(FALSE);
  307. }
  308. }
  309. //------------------------------------------------------------------------------
  310. HRESULT
  311. DuAnimation::ApiOnRemoveExisting(Animation::OnRemoveExistingMsg *)
  312. {
  313. GetStub()->SetTime(Animation::tDestroy);
  314. return S_OK;
  315. }
  316. //------------------------------------------------------------------------------
  317. HRESULT
  318. DuAnimation::ApiOnDestroySubject(Animation::OnDestroySubjectMsg *)
  319. {
  320. AddRef();
  321. if (m_pgvSubject != NULL) {
  322. CleanupChangeGadget();
  323. //
  324. // The Gadget that we are modifying is being destroyed, so we need
  325. // to stop animating it.
  326. //
  327. m_time = Animation::tDestroy;
  328. Destroy(FALSE);
  329. }
  330. Release();
  331. return S_OK;
  332. }
  333. #else
  334. //------------------------------------------------------------------------------
  335. DUSER_API void WINAPI
  336. DUserStopAnimation(Visual * pgvSubject, PRID pridAni)
  337. {
  338. UNREFERENCED_PARAMETER(pgvSubject);
  339. UNREFERENCED_PARAMETER(pridAni);
  340. PromptInvalid("Not implemented without MsgTable support");
  341. }
  342. #endif // ENABLE_MSGTABLE_API