b51cf3c5fee895a40238383a53407f88ef09e416
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Common / BackKeyManager.cs
1 /*
2  * Copyright(c) 2020 Samsung Electronics Co., Ltd.
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.ComponentModel;
19 using System.Collections.Generic;
20 using Tizen.NUI.BaseComponents;
21
22 namespace Tizen.NUI
23 {
24     /// <summary>
25     /// BackKeyManager is a class to manager back key event.
26     /// </summary>
27     [EditorBrowsable(EditorBrowsableState.Never)]
28     public sealed class BackKeyManager
29     {
30         private static readonly BackKeyManager instance = new BackKeyManager();
31
32         /// <summary>
33         /// BackKeyManager construct.
34         /// </summary>
35         private BackKeyManager()
36         {
37             NUIApplication.GetDefaultWindow().KeyEvent += OnWindowKeyEvent;
38         }
39
40         /// <summary>
41         /// Subscriber.
42         /// </summary>
43         [EditorBrowsable(EditorBrowsableState.Never)]
44         public List<View> Subscriber { get; } = new List<View>();
45
46         /// <summary>
47         /// BackKeyManager static instance.
48         /// </summary>
49         [EditorBrowsable(EditorBrowsableState.Never)]
50         public static BackKeyManager Instance { get { return instance; } }
51
52         private Container FindParent(Container child, int step)
53         {
54             Container result = child;
55
56             for (int i = 0; i < step; i++)
57             {
58                 result = result?.GetParent();
59             }
60
61             return result;
62         }
63
64         // If false, comparison1 is on top and if true, comparison2 is on top.
65         private bool CompareElevation(Container comparison1, Container comparison2)
66         {
67             bool result = false;
68
69             Container parent1 = comparison1?.GetParent();
70             Container parent2 = comparison2?.GetParent();
71
72             if ((parent1 == null && parent2 != null) || (parent2 == null && parent1 != null))
73             {
74                 // One is in DefaultLayer but the other is not
75                 if (parent2 == null)
76                 {
77                     // parent1 is in DefaultLayer.
78                     Layer comparison2AsLayer = comparison2 as Layer;
79                     if (comparison2AsLayer != null)
80                     {
81                         result = comparison2AsLayer.Depth > NUIApplication.GetDefaultWindow().GetDefaultLayer().Depth;
82                     }
83                 }
84                 else
85                 {
86                     // parent2 is in DefaultLayer.
87                     Layer comparison1AsLayer = comparison1 as Layer;
88                     if (comparison1AsLayer != null)
89                     {
90                         result = NUIApplication.GetDefaultWindow().GetDefaultLayer().Depth < comparison1AsLayer.Depth;
91                     }
92                 }
93             }
94             else
95             {
96                 // If they have same parent, ready to compare!
97                 if (parent1 == parent2)
98                 {
99
100                     if (comparison1.GetType().FullName.Contains("Layer"))
101                     {
102                         // If comparison1 is Layer, comparison2 is also Layer because only window can have Layer as child in NUI.
103                         // Compare Depth
104                         Layer comparison1AsLayer = comparison1 as Layer;
105                         Layer comparison2AsLayer = comparison2 as Layer;
106                         if (comparison1AsLayer != null && comparison2AsLayer != null)
107                         {
108                             result = comparison1AsLayer.Depth < comparison2AsLayer.Depth;
109                         }
110                     }
111                     else
112                     {
113                         // If comparison1 is View, comparison2 is also View because only window can have Layer as child in NUI.
114                         // Compare SiblingOrder
115                         View comparison1AsView = comparison1 as View;
116                         View comparison2AsView = comparison2 as View;
117                         if (comparison1AsView != null && comparison2AsView != null)
118                         {
119                             result = comparison1AsView.SiblingOrder < comparison2AsView.SiblingOrder;
120                         }
121                     }
122                 }
123                 else
124                 {
125                     // Check ancestor
126                     result = CompareElevation(parent1, parent2);
127                 }
128             }
129
130             return result;
131         }
132
133         private void OnWindowKeyEvent(object source, Window.KeyEventArgs args)
134         {
135             if (args.Key.State == Key.StateType.Up && (args.Key.KeyPressedName == "Back" || args.Key.KeyPressedName == "XF86Back"))
136             {
137                 View top = null;
138
139                 for (int i = 0; i < Subscriber.Count; i++)
140                 {
141                     // Check visibility
142                     if (Subscriber[i].Visibility && Subscriber[i].IsOnWindow)
143                     {
144                         // Initialize first top
145                         if (top == null)
146                         {
147                             top = Subscriber[i];
148                             continue;
149                         }
150                         else
151                         {
152                             if (top.HierarchyDepth != Subscriber[i].HierarchyDepth)
153                             {
154                                 Container compare1 = top;
155                                 Container compare2 = Subscriber[i];
156
157                                 // If their depth is different, sync.
158                                 if (top.HierarchyDepth > Subscriber[i].HierarchyDepth)
159                                 {
160                                     compare1 = FindParent(compare1, top.HierarchyDepth - Subscriber[i].HierarchyDepth);
161                                 }
162                                 else
163                                 {
164                                     compare2 = FindParent(compare2, Subscriber[i].HierarchyDepth - top.HierarchyDepth);
165                                 }
166
167                                 if (compare1 == compare2)
168                                 {
169                                     // One is descendant of the other. Descendant is above ancestor.
170                                     top = top.HierarchyDepth > Subscriber[i].HierarchyDepth ? top : Subscriber[i];
171                                 }
172                                 else
173                                 {
174                                     // Need to compare.
175                                     top = CompareElevation(compare1, compare2) ? Subscriber[i] : top;
176                                 }
177                             }
178                             else
179                             {
180                                 top = CompareElevation(top, Subscriber[i]) ? Subscriber[i] : top;
181                             }
182                         }
183                     }
184                 }
185
186                 top?.EmitBackKeyPressed();
187             }
188         }
189     }
190 }