[WidgetControl]Fix callback memory freed bug
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.WidgetControl / Tizen.Applications / WidgetControl.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using Tizen.Applications;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.Applications
23 {
24     /// <summary>
25     /// The class for receiving widget events and sending data to the widget.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class WidgetControl : IDisposable
29     {
30         private const string LogTag = "Tizen.Applications.WidgetControl";
31         private static Interop.WidgetService.LifecycleCallback _onLifecycleCallback;
32         /// <summary>
33         /// Class for the widget instance.
34         /// </summary>
35         /// <since_tizen> 3 </since_tizen>
36         public class Instance
37         {
38             private string _widgetId;
39
40             internal Instance(string widgetId)
41             {
42                 _widgetId = widgetId;
43             }
44
45             /// <summary>
46             /// The widget ID.
47             /// </summary>
48             /// <since_tizen> 3 </since_tizen>
49             public string Id { get; internal set; }
50
51             /// <summary>
52             /// Gets the widget content.
53             /// </summary>
54             /// <since_tizen> 3 </since_tizen>
55             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
56             public Bundle GetContent()
57             {
58                 IntPtr h;
59
60                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetContent(_widgetId, Id, out h);
61
62                 switch (err)
63                 {
64                     case Interop.WidgetService.ErrorCode.InvalidParameter:
65                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
66
67                     case Interop.WidgetService.ErrorCode.IoError:
68                         throw new InvalidOperationException("Failed to access DB");
69                 }
70
71                 return new Bundle(new SafeBundleHandle(h, true));
72             }
73
74             /// <summary>
75             /// Changes the content for the widget instance.
76             /// </summary>
77             /// <since_tizen> 3 </since_tizen>
78             /// <param name="content">Content to be changed.</param>
79             /// <param name="force"> True if you want to update your widget even if the provider is paused, otherwise false.</param>
80             /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
81             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
82             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
83             public void ChangeContent(Bundle content, bool force)
84             {
85                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UpdateContent(_widgetId, Id, content.SafeBundleHandle, force ? 1 : 0);
86
87                 switch (err)
88                 {
89                     case Interop.WidgetService.ErrorCode.InvalidParameter:
90                         throw new ArgumentException("Invalid parameter");
91
92                     case Interop.WidgetService.ErrorCode.Canceled:
93                         throw new InvalidOperationException("Provider is paused, so this update request is canceld");
94
95                     case Interop.WidgetService.ErrorCode.OutOfMemory:
96                         throw new InvalidOperationException("Out-of-memory at unmanaged code");
97
98                     case Interop.WidgetService.ErrorCode.Fault:
99                         throw new InvalidOperationException("Failed to create a request packet");
100
101                     case Interop.WidgetService.ErrorCode.PermissionDenied:
102                         throw new UnauthorizedAccessException();
103                 }
104             }
105
106             /// <summary>
107             /// Changes the update period for the widget instance.
108             /// </summary>
109             /// <since_tizen> 3 </since_tizen>
110             /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
111             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
112             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
113             public void ChangePeriod(double period)
114             {
115                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.ChangePeriod(_widgetId, Id, period);
116
117                 switch (err)
118                 {
119                     case Interop.WidgetService.ErrorCode.InvalidParameter:
120                         throw new ArgumentException("Invalid parameter");
121
122                     case Interop.WidgetService.ErrorCode.OutOfMemory:
123                         throw new InvalidOperationException("Out-of-memory at unmanaged code");
124
125                     case Interop.WidgetService.ErrorCode.Fault:
126                         throw new InvalidOperationException("Failed to create a request packet");
127
128                     case Interop.WidgetService.ErrorCode.PermissionDenied:
129                         throw new UnauthorizedAccessException();
130                 }
131             }
132         }
133
134         /// <summary>
135         /// The class for the widget size information.
136         /// </summary>
137         /// <since_tizen> 3 </since_tizen>
138         public class Scale
139         {
140
141             internal Scale()
142             {
143             }
144
145             /// <summary>
146             /// Enumeration for the types of widget size.
147             /// </summary>
148             /// <since_tizen> 3 </since_tizen>
149             public enum SizeType : int
150             {
151                 /// <summary>
152                 /// 175x175 based on 720x1280 resolution.
153                 /// </summary>
154                 Basic1x1 = 0x0001,
155
156                 /// <summary>
157                 /// 354x175 based on 720x1280 resolution.
158                 /// </summary>
159                 Basic2x1 = 0x0002,
160
161                 /// <summary>
162                 /// 354x354 based on 720x1280 resolution.
163                 /// </summary>
164                 Basic2x2 = 0x0004,
165
166                 /// <summary>
167                 /// 712x175 based on 720x1280 resolution.
168                 /// </summary>
169                 Basic4x1 = 0x0008,
170
171                 /// <summary>
172                 /// 712x354 based on 720x1280 resolution.
173                 /// </summary>
174                 Basic4x2 = 0x0010,
175
176                 /// <summary>
177                 /// 712x533 based on 720x1280 resolution.
178                 /// </summary>
179                 Basic4x3 = 0x0020,
180
181                 /// <summary>
182                 /// 712x712 based on 720x1280 resolution.
183                 /// </summary>
184                 Basic4x4 = 0x0040,
185
186                 /// <summary>
187                 /// 712x891 based on 720x1280 resolution.
188                 /// </summary>
189                 Basic4x5 = 0x0080,
190
191                 /// <summary>
192                 /// 712x1070 based on 720x1280 resolution.
193                 /// </summary>
194                 Basic4x6 = 0x0100,
195
196
197                 /// <summary>
198                 /// 224x215 based on 720x1280 resolution.
199                 /// </summary>
200                 Easy1x1 = 0x1000,
201
202                 /// <summary>
203                 /// 680x215 based on 720x1280 resolution.
204                 /// </summary>
205                 Easy1x2 = 0x2000,
206
207                 /// <summary>
208                 /// 680x653 based on 720x1280 resolution.
209                 /// </summary>
210                 Easy1x3 = 0x4000,
211
212                 /// <summary>
213                 /// 720x1280 based on 720x1280 resolution.
214                 /// </summary>
215                 Full = 0x0800,
216             }
217
218             /// <summary>
219             /// Widget width.
220             /// </summary>
221             /// <since_tizen> 3 </since_tizen>
222             public int Width { get; internal set; }
223
224             /// <summary>
225             ///Widget height.
226             /// </summary>
227             /// <since_tizen> 3 </since_tizen>
228             public int Height { get; internal set; }
229
230             /// <summary>
231             /// The path for the widget preview image file.
232             /// </summary>
233             /// <since_tizen> 3 </since_tizen>
234             public string PreviewImagePath { get; internal set; }
235
236             /// <summary>
237             /// The size type of the widget.
238             /// </summary>
239             /// <since_tizen> 3 </since_tizen>
240             public SizeType Type { get; internal set; }
241         }
242
243         private event EventHandler<WidgetLifecycleEventArgs> _created;
244         private event EventHandler<WidgetLifecycleEventArgs> _resumed;
245         private event EventHandler<WidgetLifecycleEventArgs> _paused;
246         private event EventHandler<WidgetLifecycleEventArgs> _destroyed;
247         private bool _disposedValue = false;
248         private static IDictionary<string, int> s_lifecycleEventRefCnt = new Dictionary<string, int>();
249         private static IList<WidgetControl> s_eventObjects = new List<WidgetControl>();
250
251         /// <summary>
252         /// Factory method for the WidgetControl.
253         /// It will create all the objects of WidgetControl based on the package ID.
254         /// </summary>
255         /// <since_tizen> 3 </since_tizen>
256         /// <param name="pkgId">Package ID.</param>
257         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
258         /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
259         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
260         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
261         public static WidgetControl[] CreateAll(string pkgId)
262         {
263             List<WidgetControl> list = new List<WidgetControl>();
264
265             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
266             {
267                 list.Add(new WidgetControl(widgetId));
268             }, IntPtr.Zero);
269
270             switch (err)
271             {
272                 case Interop.WidgetService.ErrorCode.InvalidParameter:
273                     throw new ArgumentException("Invalid parameter");
274
275                 case Interop.WidgetService.ErrorCode.IoError:
276                     throw new InvalidOperationException("Failed to access DB");
277
278                 case Interop.WidgetService.ErrorCode.PermissionDenied:
279                     throw new UnauthorizedAccessException();
280             }
281
282             return list.ToArray();
283         }
284
285         /// <summary>
286         /// Gets all the widget IDs by the package ID.
287         /// </summary>
288         /// <since_tizen> 3 </since_tizen>
289         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
290         /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
291         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
292         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
293         public static string[] GetWidgetIds(string pkgId)
294         {
295             List<string> list = new List<string>();
296
297             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
298             {
299                 list.Add(widgetId);
300             }, IntPtr.Zero);
301
302             switch (err)
303             {
304                 case Interop.WidgetService.ErrorCode.InvalidParameter:
305                     throw new ArgumentException("Invalid parameter");
306
307                 case Interop.WidgetService.ErrorCode.IoError:
308                     throw new InvalidOperationException("Failed to access DB");
309
310                 case Interop.WidgetService.ErrorCode.PermissionDenied:
311                     throw new UnauthorizedAccessException();
312             }
313
314             return list.ToArray();
315         }
316
317         /// <summary>
318         /// The widget ID.
319         /// </summary>
320         /// <since_tizen> 3 </since_tizen>
321         public string Id { get; internal set; }
322
323         /// <summary>
324         /// The flag value for "nodisplay".
325         /// </summary>
326         /// <since_tizen> 3 </since_tizen>
327         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
328         public bool IsNoDisplay
329         {
330             get
331             {
332                 if (Interop.WidgetService.GetNoDisplay(Id) != 0)
333                     return true;
334
335                 return false;
336             }
337         }
338
339         /// <summary>
340         ///  The event handler for a created widget instance.
341         /// </summary>
342         /// <since_tizen> 3 </since_tizen>
343         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
344         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
345         public event EventHandler<WidgetLifecycleEventArgs> Created
346         {
347             add
348             {
349                 RegisterLifecycleEvent();
350                 _created += value;
351             }
352             remove
353             {
354                 _created -= value;
355                 UnregisterLifecycleEvent();
356             }
357         }
358
359         /// <summary>
360         /// The event handler for a resumed widget instance.
361         /// </summary>
362         /// <since_tizen> 3 </since_tizen>
363         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
364         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
365         public event EventHandler<WidgetLifecycleEventArgs> Resumed
366         {
367             add
368             {
369                 RegisterLifecycleEvent();
370                 _resumed += value;
371             }
372             remove
373             {
374                 _resumed -= value;
375                 UnregisterLifecycleEvent();
376             }
377         }
378
379         /// <summary>
380         /// The event handler for a paused widget instance.
381         /// </summary>
382         /// <since_tizen> 3 </since_tizen>
383         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
384         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
385         public event EventHandler<WidgetLifecycleEventArgs> Paused
386         {
387             add
388             {
389                 RegisterLifecycleEvent();
390                 _paused += value;
391             }
392             remove
393             {
394                 _paused -= value;
395                 UnregisterLifecycleEvent();
396             }
397         }
398
399         /// <summary>
400         /// The event handler for a destroyed widget instance.
401         /// </summary>
402         /// <since_tizen> 3 </since_tizen>
403         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
404         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
405         public event EventHandler<WidgetLifecycleEventArgs> Destroyed
406         {
407             add
408             {
409                 RegisterLifecycleEvent();
410                 _destroyed += value;
411             }
412             remove
413             {
414                 _destroyed -= value;
415                 UnregisterLifecycleEvent();
416             }
417         }
418
419         /// <summary>
420         /// The constructor of the WidgetControl object.
421         /// </summary>
422         /// <since_tizen> 3 </since_tizen>
423         /// <param name="widgetId">Widget ID.</param>
424         public WidgetControl(string widgetId)
425         {
426             Id = widgetId;
427         }
428
429         /// <summary>
430         /// Finalizer of the WidgetControl class.
431         /// </summary>
432         ~WidgetControl()
433         {
434             Dispose(false);
435         }
436
437         /// <summary>
438         /// Gets the objects for widget instance information.
439         /// </summary>
440         /// <since_tizen> 3 </since_tizen>
441         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
442         /// <exception cref="NotSupportedException">Thrown when the API is not supported in this device.</exception>
443         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
444         public IEnumerable<Instance> GetInstances()
445         {
446             IList<Instance> instances = new List<Instance>();
447             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetInstances(Id, (widgetId, instanceId, userData) =>
448             {
449                 instances.Add(new Instance(widgetId) { Id = instanceId });
450             }, IntPtr.Zero);
451
452             switch (err)
453             {
454                 case Interop.WidgetService.ErrorCode.InvalidParameter:
455                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
456
457                 case Interop.WidgetService.ErrorCode.NotSupported:
458                     throw new NotSupportedException();
459
460                 case Interop.WidgetService.ErrorCode.PermissionDenied:
461                     throw new UnauthorizedAccessException();
462             }
463
464             return instances;
465         }
466
467         /// <summary>
468         /// Gets the objects for widget scale information.
469         /// </summary>
470         /// <since_tizen> 3 </since_tizen>
471         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
472         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
473         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
474         public IEnumerable<Scale> GetScales()
475         {
476             IntPtr wPtr;
477             IntPtr hPtr;
478             IntPtr typesPtr;
479             int[] w;
480             int[] h;
481             int[] types;
482             int cnt1 = 100;
483             int cnt2 = 100;
484             IList<Scale> scales = new List<Scale>();
485             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetSupportedSizes(Id, ref cnt1, out wPtr, out hPtr);
486
487             if (cnt1 == 0)
488             {
489                 Log.Error(LogTag, "No supported size :" + Id);
490                 return null;
491             }
492
493             switch (err)
494             {
495                 case Interop.WidgetService.ErrorCode.InvalidParameter:
496                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
497
498                 case Interop.WidgetService.ErrorCode.IoError:
499                     throw new InvalidOperationException("Failed to access DB");
500
501                 case Interop.WidgetService.ErrorCode.PermissionDenied:
502                     throw new UnauthorizedAccessException();
503             }
504             w = new int[cnt1];
505             Marshal.Copy(wPtr, w, 0, cnt1);
506             Interop.Libc.Free(wPtr);
507
508             h = new int[cnt1];
509             Marshal.Copy(hPtr, h, 0, cnt1);
510             Interop.Libc.Free(hPtr);
511
512             err = Interop.WidgetService.GetSupportedSizeTypes(Id, ref cnt2, out typesPtr);
513             switch (err)
514             {
515                 case Interop.WidgetService.ErrorCode.InvalidParameter:
516                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
517
518                 case Interop.WidgetService.ErrorCode.IoError:
519                     throw new InvalidOperationException("Failed to access DB");
520
521                 case Interop.WidgetService.ErrorCode.PermissionDenied:
522                     throw new UnauthorizedAccessException();
523             }
524
525             if (cnt1 != cnt2)
526             {
527                 Log.Error(LogTag, "Count not match cnt1 :" + cnt1 + ", cnt2 :" + cnt2);
528                 return null;
529             }
530
531             types = new int[cnt2];
532             Marshal.Copy(typesPtr, types, 0, cnt2);
533             Interop.Libc.Free(typesPtr);
534
535             for (int i = 0; i < cnt1; i++)
536             {
537                 string prev = Interop.WidgetService.GetPreviewImagePath(Id, types[i]);
538
539                 scales.Add(new Scale()
540                 {
541                     Width = w[i],
542                     Height = h[i],
543                     PreviewImagePath = prev,
544                     Type = (Scale.SizeType)types[i]
545                 });
546             }
547             return scales;
548         }
549
550         /// <summary>
551         /// Gets the widget name.
552         /// </summary>
553         /// <since_tizen> 3 </since_tizen>
554         /// <param name="lang">Language.</param>
555         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
556         /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
557         public string GetName(string lang)
558         {
559             if (lang == null)
560                 throw new ArgumentNullException();
561
562             return Interop.WidgetService.GetName(Id, lang);
563         }
564
565         /// <summary>
566         /// Gets the widget icon path.
567         /// </summary>
568         /// <since_tizen> 3 </since_tizen>
569         /// <param name="lang">Language.</param>
570         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
571         /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
572         public string GetIconPath(string lang)
573         {
574             if (lang == null)
575                 throw new ArgumentNullException();
576
577             string pkgId = Interop.WidgetService.GetPkgId(Id);
578
579             return Interop.WidgetService.GetIcon(pkgId, lang);
580         }
581
582         /// <summary>
583         /// Releases all the resources used by the WidgetControl class.
584         /// </summary>
585         /// <since_tizen> 3 </since_tizen>
586         public void Dispose()
587         {
588             Dispose(true);
589             GC.SuppressFinalize(this);
590         }
591
592         private void Dispose(bool disposing)
593         {
594             if (!_disposedValue)
595             {
596                 if (disposing)
597                 {
598                 }
599
600                 _created = null;
601                 _resumed = null;
602                 _paused = null;
603                 _destroyed = null;
604                 UnregisterLifecycleEvent();
605
606                 _disposedValue = true;
607             }
608         }
609
610         private void RegisterLifecycleEvent()
611         {
612             if (!s_lifecycleEventRefCnt.ContainsKey(Id))
613                 s_lifecycleEventRefCnt[Id] = 0;
614
615             if (_created != null || _paused != null || _resumed != null || _destroyed != null)
616                 return;
617
618             if (s_lifecycleEventRefCnt[Id] == 0)
619             {
620                 if (_onLifecycleCallback == null)
621                     _onLifecycleCallback = new Interop.WidgetService.LifecycleCallback(OnLifecycleEvent);
622
623                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.SetLifecycleEvent(Id, _onLifecycleCallback, IntPtr.Zero);
624                 switch (err)
625                 {
626                     case Interop.WidgetService.ErrorCode.InvalidParameter:
627                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
628
629                     case Interop.WidgetService.ErrorCode.PermissionDenied:
630                         throw new UnauthorizedAccessException();
631                 }
632             }
633
634             s_lifecycleEventRefCnt[Id]++;
635             s_eventObjects.Add(this);
636             Log.Debug(LogTag, "register lifecycle cb " + Id + " [" + s_lifecycleEventRefCnt[Id] + "]");
637         }
638
639         private void UnregisterLifecycleEvent()
640         {
641             if (!s_lifecycleEventRefCnt.ContainsKey(Id))
642                 return;
643
644             if (s_lifecycleEventRefCnt[Id] <= 0)
645                 return;
646
647             if (_created != null || _paused != null || _resumed != null || _destroyed != null)
648                 return;
649
650             if (s_lifecycleEventRefCnt[Id] == 1)
651             {
652                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UnsetLifecycleEvent(Id, IntPtr.Zero);
653
654                 switch (err)
655                 {
656                     case Interop.WidgetService.ErrorCode.InvalidParameter:
657                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
658
659                     case Interop.WidgetService.ErrorCode.PermissionDenied:
660                         throw new UnauthorizedAccessException();
661
662                     case Interop.WidgetService.ErrorCode.NotExist:
663                         throw new InvalidOperationException("Event handler is not exist");
664                 }
665                 _onLifecycleCallback = null;
666             }
667
668             s_eventObjects.Remove(this);
669             s_lifecycleEventRefCnt[Id]--;
670             Log.Debug(LogTag, "unregister lifecycle cb " + Id + " [" + s_lifecycleEventRefCnt[Id] + "]");
671         }
672
673         private static int OnLifecycleEvent(string widgetId, Interop.WidgetService.LifecycleEvent e, string instanceId, IntPtr userData)
674         {
675             Log.Debug(LogTag, "Lifecycle event : " + instanceId + " [" + e + "]");
676             switch (e)
677             {
678                 case Interop.WidgetService.LifecycleEvent.Created:
679                     foreach (WidgetControl c in s_eventObjects)
680                     {
681                         if (c.Id.CompareTo(widgetId) == 0)
682                         {
683                             c._created?.Invoke(null, new WidgetLifecycleEventArgs()
684                             {
685                                 WidgetId = widgetId,
686                                 InstanceId = instanceId,
687                                 Type = WidgetLifecycleEventArgs.EventType.Created
688                             });
689                         }
690                     }
691                     break;
692
693                 case Interop.WidgetService.LifecycleEvent.Resumed:
694                     foreach (WidgetControl c in s_eventObjects)
695                     {
696                         if (c.Id.CompareTo(widgetId) == 0)
697                         {
698                             c._resumed?.Invoke(null, new WidgetLifecycleEventArgs()
699                             {
700                                 WidgetId = widgetId,
701                                 InstanceId = instanceId,
702                                 Type = WidgetLifecycleEventArgs.EventType.Resumed
703                             });
704                        }
705                     }
706                     break;
707
708                 case Interop.WidgetService.LifecycleEvent.Paused:
709                     foreach (WidgetControl c in s_eventObjects)
710                     {
711                         if (c.Id.CompareTo(widgetId) == 0)
712                         {
713                             c._paused?.Invoke(null, new WidgetLifecycleEventArgs()
714                             {
715                                 WidgetId = widgetId,
716                                 InstanceId = instanceId,
717                                 Type = WidgetLifecycleEventArgs.EventType.Paused
718                             });
719                         }
720                     }
721                     break;
722
723                 case Interop.WidgetService.LifecycleEvent.Destroyed:
724                     foreach (WidgetControl c in s_eventObjects)
725                     {
726                         if (c.Id.CompareTo(widgetId) == 0)
727                         {
728                             c._destroyed?.Invoke(null, new WidgetLifecycleEventArgs()
729                             {
730                                 WidgetId = widgetId,
731                                 InstanceId = instanceId,
732                                 Type = WidgetLifecycleEventArgs.EventType.Destroyed
733                             });
734                         }
735                     }
736                     break;
737             }
738             return 0;
739
740         }
741     }
742 }