[NUI] Fix svace issue for BorderWindow
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Window / BorderWindow.cs
1 /*
2  * Copyright(c) 2022 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 extern alias TizenSystemInformation;
18 using TizenSystemInformation.Tizen.System;
19
20 using System;
21 using System.Collections.Generic;
22 using System.ComponentModel;
23 using System.Linq;
24 using System.Threading;
25 using Tizen.NUI.BaseComponents;
26
27 namespace Tizen.NUI
28 {
29     public partial class Window
30     {
31         #region Constant Fields
32         #endregion //Constant Fields
33
34         #region Fields
35         private IBorderInterface borderInterface = null;
36         private Layer borderWindowRootLayer = null;
37         private Layer borderWindowBottomLayer = null;
38         private WindowOrientation currentOrientation;
39
40         // for border area
41         private View rootView = null;
42         private BorderView borderView = null;
43         private View topView = null;
44         private View contentsView = null;
45         private View bottomView = null;
46         private float borderHeight = 0;
47         private int screenWidth = 0;
48         private int screenHeight = 0;
49
50         private bool isBorderWindow = false;
51         private bool hasTopView = false;
52         private bool hasBottomView = false;
53         private bool isEnabledOverlayMode = false;
54         private bool isMaximized = false;
55
56
57         // for config
58         private Size2D minSize = null;
59         private Size2D maxSize = null;
60         private uint borderLineThickness = 0;
61         private BorderResizePolicyType borderResizePolicy = BorderResizePolicyType.Free;
62         #endregion //Fields
63
64         #region Constructors
65         #endregion //Constructors
66
67         #region Distructors
68         #endregion //Distructors
69
70         #region Delegates
71         internal delegate void BorderCloseDelegate();
72         private BorderCloseDelegate borderCloseDelegate = null;
73
74         #endregion //Delegates
75
76         #region Events
77         #endregion //Events
78
79         #region Enums
80         /// <summary>
81         /// This is an enum for the resize direction or move value when the border area is touched.
82         /// </summary>
83         [EditorBrowsable(EditorBrowsableState.Never)]
84         public enum BorderDirection
85         {
86             None        = ResizeDirection.None,
87             TopLeft     = ResizeDirection.TopLeft,
88             Top         = ResizeDirection.Top,
89             TopRight    = ResizeDirection.TopRight,
90             Left        = ResizeDirection.Left,
91             Right       = ResizeDirection.Right,
92             BottomLeft  = ResizeDirection.BottomLeft,
93             Bottom      = ResizeDirection.Bottom,
94             BottomRight = ResizeDirection.BottomRight,
95             Move,
96         }
97
98         /// <summary>
99         /// This enum is the policy when resizing the border window.
100         /// </summary>
101         [EditorBrowsable(EditorBrowsableState.Never)]
102         public enum BorderResizePolicyType
103         {
104           /// <summary>
105           /// The window can be resized freely.
106           /// </summary>
107           Free = 0,
108           /// <summary>
109           /// The window is resized according to the ratio.
110           /// </summary>
111           KeepRatio = 1,
112           /// <summary>
113           /// The window is not resized and is fixed.
114           /// </summary>
115           Fixed = 2,
116         }
117         #endregion //Enums
118
119         #region Interfaces
120         #endregion //Interfaces
121
122         #region Properties
123         /// <summary>
124         /// Whether the border is enabled.
125         /// </summary>
126         [EditorBrowsable(EditorBrowsableState.Never)]
127         public bool IsBorderEnabled => isBorderWindow;
128         #endregion //Properties
129
130         #region Indexers
131         #endregion //Indexers
132
133         #region Methods
134
135         /// <summary>
136         /// Update BorderProperty
137         /// </summary>
138         internal void UpdateProperty()
139         {
140             if (borderInterface != null)
141             {
142                 bool isNeedResizeByLine = false;
143                 bool isNeedResizeByBorder = false;
144                 using var val = new Uint16Pair(Interop.Window.GetSize(SwigCPtr), true);
145                 if (borderLineThickness != borderInterface.BorderLineThickness)
146                 {
147                     isNeedResizeByLine = true;
148                     int diffBorderLine = (int)borderInterface.BorderLineThickness - (int)borderLineThickness;
149                     borderLineThickness = borderInterface.BorderLineThickness;
150
151                     if (borderView != null)
152                     {
153                         Extents extents = borderView.Padding;
154                         ushort start = (extents.Start + diffBorderLine) > 0 ? (ushort)(extents.Start + diffBorderLine) : (ushort)0;
155                         ushort end = (extents.End + diffBorderLine) > 0 ? (ushort)(extents.End + diffBorderLine) : (ushort)0;
156                         ushort top = (extents.Top + diffBorderLine) > 0 ? (ushort)(extents.Top + diffBorderLine) : (ushort)0;
157                         ushort bottom = (extents.Bottom + diffBorderLine) > 0 ? (ushort)(extents.Bottom + diffBorderLine) : (ushort)0;
158                         borderView.Padding = new Extents(start, end, top, bottom);
159                         if (IsMaximized() == true)
160                         {
161                             borderView.OnMaximize(true);
162                         }
163                     }
164
165                     val.SetWidth((ushort)(val.GetWidth() + diffBorderLine * 2));
166                     val.SetHeight((ushort)(val.GetHeight() + diffBorderLine * 2));
167                 }
168
169                 float height = 0;
170                 if (hasTopView) height += topView.SizeHeight;
171                 if (hasBottomView) height += bottomView.SizeHeight;
172                 if (height != borderHeight)
173                 {
174                     isNeedResizeByBorder = true;
175                     float diff = height - borderHeight;
176                     borderHeight = height;
177                     val.SetHeight((ushort)(val.GetHeight() + diff));
178                 }
179
180                 if (isNeedResizeByLine == true || isNeedResizeByBorder == true)
181                 {
182                     Interop.Window.SetSize(SwigCPtr, Uint16Pair.getCPtr(val));
183                 }
184
185                 if (minSize != borderInterface.MinSize || (borderInterface.MinSize != null && isNeedResizeByLine == true))
186                 {
187                     using Size2D mimimumSize = new Size2D((borderInterface.MinSize?.Width + (int)borderLineThickness * 2 ?? 0), (borderInterface.MinSize?.Height ?? 0) + (int)(borderHeight + borderLineThickness * 2));
188                     SetMimimumSize(mimimumSize);
189                     minSize = borderInterface.MinSize;
190                 }
191
192                 if (maxSize != borderInterface.MaxSize || (borderInterface.MaxSize != null && isNeedResizeByLine == true))
193                 {
194                     using Size2D maximumSize = new Size2D((borderInterface.MaxSize?.Width + (int)borderLineThickness * 2 ?? 0), (borderInterface.MaxSize?.Height ?? 0) + (int)(borderHeight + borderLineThickness * 2));
195                     SetMaximumSize(maximumSize);
196                     maxSize = borderInterface.MaxSize;
197                 }
198
199                 if (borderResizePolicy != borderInterface.ResizePolicy)
200                 {
201                     AddAuxiliaryHint("wm.policy.win.resize_aspect_ratio", "0");
202                     borderResizePolicy = borderInterface.ResizePolicy;
203                     if (borderResizePolicy == BorderResizePolicyType.KeepRatio)
204                     {
205                         AddAuxiliaryHint("wm.policy.win.resize_aspect_ratio", "1");
206                     }
207                 }
208
209             }
210         }
211         /// <summary>
212         /// Called when the border is closed.
213         /// If the delegate is declared, the delegate is called, otherwise window is destroyed.
214         /// </summary>
215         internal void BorderDestroy()
216         {
217             if (borderCloseDelegate != null)
218             {
219                 borderCloseDelegate();
220             }
221             else
222             {
223                 Destroy();
224             }
225         }
226         /// <summary>
227         /// Enable the border window with IBorderInterface.
228         /// This adds a border area to the Window.
229         /// The border's UI is configured using IBorderInterface.
230         /// Users can reisze and move by touching the border area.
231         /// </summary>
232         /// <param name="borderInterface">The IBorderInterface.</param>
233         /// <param name="borderCloseDelegate">The BorderCloseDelegate. When close, this delegate is called.</param>
234         /// <returns>Whether the border window is enabled</returns>
235         internal bool EnableBorder(IBorderInterface borderInterface, BorderCloseDelegate borderCloseDelegate = null)
236         {
237             if (isBorderWindow == true)
238             {
239                 Tizen.Log.Error("NUI", $"Already EnableBorderWindow\n");
240                 return false;
241             }
242
243             try
244             {
245                 Information.TryGetValue<int>("http://tizen.org/feature/screen.width", out screenWidth);
246                 Information.TryGetValue<int>("http://tizen.org/feature/screen.height", out screenHeight);
247             }
248             catch (DllNotFoundException e)
249             {
250                 Tizen.Log.Fatal("NUI", $"{e}\n");
251             }
252
253             if (borderInterface == null)
254             {
255                 borderInterface = new DefaultBorder();
256             }
257             this.borderInterface = borderInterface;
258             this.borderCloseDelegate = borderCloseDelegate;
259
260             GetDefaultLayer().Name = "OriginalRootLayer";
261
262             borderInterface.BorderWindow = this;
263
264             if (CreateBorder() == true)
265             {
266                 Tizen.Log.Info("NUI", $"currentOrientation {currentOrientation}\n");
267                 currentOrientation = GetCurrentOrientation();
268                 currentOrientation = (currentOrientation == WindowOrientation.Portrait || currentOrientation == WindowOrientation.PortraitInverse) ? WindowOrientation.Portrait : WindowOrientation.Landscape;
269
270                 using var realWindowSize = new Size2D(WindowSize.Width, WindowSize.Height);
271
272                 isBorderWindow = true;
273
274                 Resized += OnBorderWindowResized;
275
276                 Moved += OnBorderWindowMoved;
277
278                 MoveCompleted += OnBorderWindowMoveCompleted;
279
280                 ResizeCompleted += OnBorderWindowResizeCompleted;
281
282                 OrientationChanged += OnBorderWindowOrientationChanged;
283
284                 borderInterface.OnCreated(borderView);
285
286                 // Increase the window size as much as the border area.
287                 borderHeight = 0;
288                 if (hasTopView) borderHeight += topView.SizeHeight;
289                 if (hasBottomView) borderHeight += bottomView.SizeHeight;
290
291                 // Sets the minimum / maximum size to be resized by RequestResizeToServer.
292                 var minSize = borderInterface.MinSize;
293                 if (null != minSize)
294                 {
295                     using Size2D mimimumSize = new Size2D(minSize.Width + (int)borderInterface.BorderLineThickness * 2, minSize.Height + (int)(borderHeight + borderInterface.BorderLineThickness * 2));
296                     SetMimimumSize(mimimumSize);
297                 }
298                 var maxSize = borderInterface.MaxSize;
299                 if (null != maxSize)
300                 {
301                     using Size2D maximumSize = new Size2D(maxSize.Width + (int)borderInterface.BorderLineThickness * 2, maxSize.Height + (int)(borderHeight + borderInterface.BorderLineThickness * 2));
302                     SetMaximumSize(maximumSize);
303                 }
304
305                 // When running the app for the first time, if it runs in full size, do Maximize(true).
306                 if (screenWidth != 0 && screenHeight != 0 &&
307                     realWindowSize.Width >= screenWidth && realWindowSize.Height >= screenHeight &&
308                     IsMaximized() == false)
309                 {
310                     Maximize(true);
311                     borderInterface.OnMaximize(true);
312                     ResizedEventArgs e = new ResizedEventArgs();
313                     e.WindowSize = WindowSize;
314                     windowResizeEventHandler?.Invoke(this, e);
315                 }
316                 else
317                 {
318                     borderInterface.OnMaximize(IsMaximized());
319                     if (borderHeight > 0)
320                     {
321                         borderLineThickness = borderInterface.BorderLineThickness;
322                         WindowSize += new Size2D((int)borderLineThickness * 2, (int)(borderHeight + borderLineThickness * 2));
323                     }
324                 }
325
326                 // If it is BorderResizePolicyType.KeepRatio type, it will be resized according to the ratio.
327                 if (borderInterface.ResizePolicy == BorderResizePolicyType.KeepRatio)
328                 {
329                     AddAuxiliaryHint("wm.policy.win.resize_aspect_ratio", "1");
330                 }
331
332                 // Add a view to the border layer.
333                 GetBorderWindowBottomLayer().Add(rootView);
334
335                 FocusChanged += OnWindowFocusChanged;
336
337                 return true;
338             }
339             else
340             {
341                 this.borderInterface.Dispose();
342                 return false;
343             }
344         }
345
346         private void OnWindowFocusChanged(object sender, Window.FocusChangedEventArgs e)
347         {
348             if (e.FocusGained == true && IsMaximized() == false)
349             {
350                 // Raises the window when the window is focused.
351                 Raise();
352             }
353         }
354
355         /// Create the border UI.
356         private bool CreateBorder()
357         {
358             rootView = new View()
359             {
360                 WidthResizePolicy = ResizePolicyType.FillToParent,
361                 HeightResizePolicy = ResizePolicyType.FillToParent,
362                 BackgroundColor = Color.Transparent,
363             };
364
365             ushort padding = (ushort) borderLineThickness;
366             borderView = new BorderView()
367             {
368                 GrabTouchAfterLeave = true,
369                 WidthResizePolicy = ResizePolicyType.FillToParent,
370                 HeightResizePolicy = ResizePolicyType.FillToParent,
371                 BackgroundColor = Color.Transparent,
372                 Layout = new LinearLayout() {
373                     LinearOrientation = LinearLayout.Orientation.Vertical,
374                     LinearAlignment = LinearLayout.Alignment.Top
375                 },
376                 Padding = new Extents(padding, padding, padding, padding),
377             };
378             borderInterface.CreateBorderView(borderView);
379
380             topView = new View()
381             {
382                 WidthSpecification = LayoutParamPolicies.MatchParent,
383                 SizeHeight = borderInterface.BorderHeight,
384                 BackgroundColor = Color.Transparent,
385             };
386
387             contentsView = new View()
388             {
389                 BackgroundColor = Color.Transparent,
390                 WidthSpecification = LayoutParamPolicies.MatchParent,
391             };
392
393             bottomView = new View()
394             {
395                 WidthSpecification = LayoutParamPolicies.MatchParent,
396                 SizeHeight = borderInterface.BorderHeight,
397                 BackgroundColor = Color.Transparent,
398             };
399
400             // // Gets the Border's UI.
401             if (borderInterface.CreateTopBorderView(topView) == true && topView != null)
402             {
403                 borderView.Add(topView);
404                 hasTopView = true;
405             }
406             borderView.Add(contentsView);
407             if (borderInterface.CreateBottomBorderView(bottomView) == true && bottomView != null)
408             {
409                 borderView.Add(bottomView);
410                 hasBottomView = true;
411             }
412             rootView.Add(borderView);
413
414             return hasTopView || hasBottomView;
415         }
416
417         /// <summary>
418         /// Calculates which direction to resize or to move.
419         /// </summary>
420         /// <param name="xPosition">The X position.</param>
421         /// <param name="yPosition">The Y position.</param>
422         /// <returns>The BorderDirection</returns>
423         [EditorBrowsable(EditorBrowsableState.Never)]
424         public BorderDirection GetDirection(float xPosition, float yPosition)
425         {
426             BorderDirection direction = BorderDirection.None;
427
428             // check bottom left corner
429             if (xPosition < borderInterface.TouchThickness && yPosition > WindowSize.Height + borderHeight - borderInterface.TouchThickness)
430             {
431                 direction = BorderDirection.BottomLeft;
432             }
433             // check bottom right corner
434             else if (xPosition > WindowSize.Width + (float)(borderLineThickness * 2) - borderInterface.TouchThickness && yPosition > WindowSize.Height + borderHeight - borderInterface.TouchThickness)
435             {
436                 direction = BorderDirection.BottomRight;
437             }
438             // check top left corner
439             else if (xPosition < borderInterface.TouchThickness && yPosition <  borderInterface.TouchThickness)
440             {
441                 direction = BorderDirection.TopLeft;
442             }
443             // check top right corner
444             else if (xPosition > WindowSize.Width + (float)(borderLineThickness * 2) - borderInterface.TouchThickness && yPosition < borderInterface.TouchThickness)
445             {
446                 direction = BorderDirection.TopRight;
447             }
448             // check left side
449             else if (xPosition < borderInterface.TouchThickness)
450             {
451                 direction = BorderDirection.Left;
452             }
453             // check right side
454             else if (xPosition > WindowSize.Width + (float)(borderLineThickness * 2) - borderInterface.TouchThickness)
455             {
456                 direction = BorderDirection.Right;
457             }
458             // check bottom side
459             else if (yPosition > WindowSize.Height + borderHeight + borderLineThickness - borderInterface.TouchThickness)
460             {
461                 direction = BorderDirection.Bottom;
462             }
463             // check top side
464             else if (yPosition < borderInterface.TouchThickness)
465             {
466                 direction = BorderDirection.Top;
467             }
468             // check move
469             else if ((yPosition > WindowSize.Height) || (hasTopView == true && yPosition < topView.SizeHeight))
470             {
471                 direction = BorderDirection.Move;
472             }
473
474             return direction;
475         }
476
477         /// <summary>
478         /// Gets position and size of the border window
479         /// </summary>
480         /// <returns>The total window size including the border area in the default window.</returns>
481         [EditorBrowsable(EditorBrowsableState.Never)]
482         public Rectangle WindowPositionSizeWithBorder
483         {
484             get
485             {
486                 using var position = GetPosition();
487                 using var size = GetWindowSizeWithBorder();
488                 Rectangle ret = new Rectangle(position?.X ?? 0, position?.Y ?? 0, size?.Width ?? 0, size?.Height ?? 0);
489                 return ret;
490             }
491         }
492
493         /// <summary>
494         /// Gets size of the border window
495         /// </summary>
496         /// <returns>The total window size including the border area in the default window.</returns>
497         [EditorBrowsable(EditorBrowsableState.Never)]
498         public Size2D WindowSizeWithBorder
499         {
500             get
501             {
502                 return GetWindowSizeWithBorder();
503             }
504         }
505
506         private Size2D GetWindowSizeWithBorder()
507         {
508             var val = new Uint16Pair(Interop.Window.GetSize(SwigCPtr), true);
509             Size2D size = new Size2D(val.GetWidth(), val.GetHeight());
510             val.Dispose();
511             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
512             return size;
513         }
514
515         private void DoOverlayMode(bool enable)
516         {
517             if (borderInterface.OverlayMode == true)
518             {
519                 if (isEnabledOverlayMode != enable)
520                 {
521                     borderView?.OverlayMode(enable);
522                     borderInterface.OnOverlayMode(enable);
523                     if (enable == true)
524                     {
525                         GetBorderWindowBottomLayer().RaiseToTop();
526                     }
527                     else
528                     {
529                         GetBorderWindowBottomLayer().LowerToBottom();
530                     }
531                     isEnabledOverlayMode = enable;
532                 }
533             }
534         }
535
536         private void DoMaximize(bool isMaximized)
537         {
538             if (this.isMaximized != isMaximized)
539             {
540                 borderView?.OnMaximize(isMaximized);
541                 borderInterface.OnMaximize(isMaximized);
542             }
543             this.isMaximized = isMaximized;
544         }
545
546         // Called when the window position has changed.
547         private void OnBorderWindowMoved(object sender, WindowMovedEventArgs e)
548         {
549             Tizen.Log.Info("NUI", $"OnBorderWindowMoved {e.WindowPosition.X}, {e.WindowPosition.Y}\n");
550             borderInterface.OnMoved(e.WindowPosition.X, e.WindowPosition.Y);
551         }
552
553         private void OnBorderWindowMoveCompleted(object sender, WindowMoveCompletedEventArgs e)
554         {
555             Tizen.Log.Info("NUI", $"OnBorderWindowMoveCompleted {e.WindowCompletedPosition.X}, {e.WindowCompletedPosition.Y}\n");
556             borderInterface.OnMoveCompleted(e.WindowCompletedPosition.X, e.WindowCompletedPosition.Y);
557         }
558
559         private void OnBorderWindowResizeCompleted(object sender, WindowResizeCompletedEventArgs e)
560         {
561             Tizen.Log.Info("NUI", $"OnBorderWindowResizeCompleted {e.WindowCompletedSize.Width}, {e.WindowCompletedSize.Height}\n");
562             borderInterface.OnResizeCompleted(e.WindowCompletedSize.Width, e.WindowCompletedSize.Height);
563         }
564
565         private void OnBorderWindowOrientationChanged(object sender, WindowOrientationChangedEventArgs e)
566         {
567             WindowOrientation orientation = e.WindowOrientation;
568             orientation = (orientation == WindowOrientation.Portrait || orientation == WindowOrientation.PortraitInverse) ? WindowOrientation.Portrait : WindowOrientation.Landscape;
569             if (currentOrientation != orientation)
570             {
571                 if (isEnabledOverlayMode == false && IsFloatingModeEnabled() == false)
572                 {
573                     using var val = new Uint16Pair(Interop.Window.GetSize(SwigCPtr), true);
574                     Tizen.Log.Info("NUI", $"OnBorderWindowOrientationChanged {e.WindowOrientation} {val.GetWidth()},{val.GetHeight()}\n");
575                     uint borderLine = borderLineThickness * 2;
576                     WindowSize = new Size2D((int)(val.GetWidth() - borderHeight - borderLine), (int)(val.GetHeight() - borderLine));
577                 }
578             }
579             currentOrientation = orientation;
580         }
581
582         // Called when the window size has changed.
583         private void OnBorderWindowResized(object sender, Window.ResizedEventArgs e)
584         {
585             Tizen.Log.Info("NUI", $"OnBorderWindowResized {e.WindowSize.Width},{e.WindowSize.Height}\n");
586             int resizeWidth = e.WindowSize.Width;
587             int resizeHeight = e.WindowSize.Height;
588
589             borderInterface.OnResized(resizeWidth, resizeHeight);
590
591              // reset borderHeight
592             borderHeight = 0;
593             if (hasTopView) borderHeight += topView.SizeHeight;
594             if (hasBottomView) borderHeight += bottomView.SizeHeight;
595
596             bool isMaximized = IsMaximized();
597             bool isEnabledOverlay = (borderInterface.OverlayMode == true && isMaximized == true);
598
599             float width = 0;
600             float height = isEnabledOverlay ? 0 : borderHeight;
601             float y = isEnabledOverlay ? 0 : ((hasTopView == true) ? topView.SizeHeight : 0);
602
603             if (isMaximized == false)
604             {
605                 width = (float)(borderLineThickness * 2);
606                 height += (float)(borderLineThickness * 2);
607                 y += borderLineThickness;
608             }
609
610             Interop.ActorInternal.SetSize(GetBorderWindowRootLayer().SwigCPtr, resizeWidth, resizeHeight);
611             Interop.ActorInternal.SetSize(GetBorderWindowBottomLayer().SwigCPtr, resizeWidth + width, resizeHeight + height);
612             Interop.ActorInternal.SetPosition(GetBorderWindowRootLayer().SwigCPtr, 0, y);
613
614             if (contentsView != null)
615             {
616                 contentsView.SizeHeight = resizeHeight - (isEnabledOverlay ? borderHeight : 0);
617             }
618             DoMaximize(isMaximized);
619
620             DoOverlayMode(isEnabledOverlay);
621
622             if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
623         }
624
625         internal Layer GetBorderWindowBottomLayer()
626         {
627             if (borderWindowBottomLayer == null)
628             {
629                 borderWindowBottomLayer = new Layer();
630                 borderWindowBottomLayer.Name = "BorderWindowBottomLayer";
631                 using Vector3 topCentor = new Vector3(0.5f, 0.0f, 0.5f);
632                 Interop.ActorInternal.SetParentOrigin(borderWindowBottomLayer.SwigCPtr, topCentor.SwigCPtr);
633                 Interop.Actor.SetAnchorPoint(borderWindowBottomLayer.SwigCPtr, topCentor.SwigCPtr);
634                 Interop.Actor.Add(rootLayer.SwigCPtr, borderWindowBottomLayer.SwigCPtr);
635                 Interop.ActorInternal.SetSize(borderWindowBottomLayer.SwigCPtr, WindowSize.Width + (float)(borderLineThickness * 2), WindowSize.Height + (float)(borderLineThickness * 2));
636                 borderWindowBottomLayer.SetWindow(this);
637                 borderWindowBottomLayer.LowerToBottom();
638
639                 if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
640             }
641             return borderWindowBottomLayer;
642         }
643
644         internal Layer GetBorderWindowRootLayer()
645         {
646             if (borderWindowRootLayer == null)
647             {
648                 borderWindowRootLayer = new Layer();
649                 borderWindowRootLayer.Name = "RootLayer";
650                 using Vector3 topCentor = new Vector3(0.5f, 0.0f, 0.5f);
651                 Interop.ActorInternal.SetParentOrigin(borderWindowRootLayer.SwigCPtr, topCentor.SwigCPtr);
652                 Interop.Actor.SetAnchorPoint(borderWindowRootLayer.SwigCPtr, topCentor.SwigCPtr);
653                 Interop.Actor.Add(rootLayer.SwigCPtr, borderWindowRootLayer.SwigCPtr);
654                 Interop.ActorInternal.SetSize(borderWindowRootLayer.SwigCPtr, WindowSize.Width, WindowSize.Height - borderHeight - borderLineThickness * 2);
655                 float height = (hasTopView == true) ? topView.SizeHeight : 0;
656                 Interop.ActorInternal.SetPosition(borderWindowRootLayer.SwigCPtr, 0, height + borderLineThickness);
657                 using PropertyValue propertyValue = new Tizen.NUI.PropertyValue((int)Tizen.NUI.ClippingModeType.ClipToBoundingBox);
658                 Tizen.NUI.Object.SetProperty(borderWindowRootLayer.SwigCPtr, Tizen.NUI.BaseComponents.View.Property.ClippingMode, propertyValue);
659
660                 if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
661             }
662
663             return borderWindowRootLayer;
664         }
665
666         internal void DisposeBorder()
667         {
668             Resized -= OnBorderWindowResized;
669             FocusChanged -= OnWindowFocusChanged;
670             Moved -= OnBorderWindowMoved;
671             MoveCompleted -= OnBorderWindowMoveCompleted;
672             ResizeCompleted -= OnBorderWindowResizeCompleted;
673             OrientationChanged -= OnBorderWindowOrientationChanged;
674             borderInterface.Dispose();
675             GetBorderWindowBottomLayer().Dispose();
676         }
677
678         private void convertBorderWindowSizeToRealWindowSize(Uint16Pair size)
679         {
680             if (isBorderWindow == true)
681             {
682                 var height = (ushort)(size.GetHeight() + borderHeight + borderLineThickness * 2);
683                 var width = (ushort)(size.GetWidth() + borderLineThickness * 2);
684                 size.SetHeight(height);
685                 size.SetWidth(width);
686             }
687         }
688
689         private void convertRealWindowSizeToBorderWindowSize(Uint16Pair size)
690         {
691             if (isBorderWindow == true && !(borderInterface.OverlayMode == true && IsMaximized() == true))
692             {
693                 var borderLine = IsMaximized() == true ? 0 : borderLineThickness * 2;
694                 var height = (ushort)(size.GetHeight() - borderHeight - borderLine);
695                 var width = (ushort)(size.GetWidth() - borderLine);
696                 size.SetHeight(height);
697                 size.SetWidth(width);
698             }
699         }
700         #endregion //Methods
701
702         #region Structs
703         #endregion //Structs
704
705         #region Classes
706         // View class for border view.
707         private class BorderView : View
708         {
709             private bool isEnabledOverlay = false;
710             private Extents prePadding = new Extents(0, 0, 0, 0);
711
712             internal BorderView() : base()
713             {
714                 // BorderView will use custom HitTest function.
715                 RegisterHitTestCallback();
716             }
717
718             /// <summary>
719             /// Set whether or not it is in overlay mode.
720             /// The borderView's OverlayMode means that it is displayed at the top of the screen.
721             /// In this case, the borderView should pass the event so that lower layers can receive the event.
722             /// </summary>
723             /// <param name="enabled">The true if borderView is Overlay mode. false otherwise.</param>
724             [EditorBrowsable(EditorBrowsableState.Never)]
725             public void OverlayMode(bool enabled)
726             {
727                 isEnabledOverlay = enabled;
728             }
729
730             /// <summary>
731             /// Called when the window is maximized.
732             /// </summary>
733             /// <param name="isMaximized">If window is maximized or unmaximized.</param>
734             [EditorBrowsable(EditorBrowsableState.Never)]
735             public void OnMaximize(bool isMaximized)
736             {
737                 // When maximized, it is displayed in full without border lines.
738                 if (isMaximized == true)
739                 {
740                     prePadding = Padding;
741                     Padding = new Extents(0, 0, 0, 0);
742                 }
743                 else
744                 {
745                     Padding = prePadding;
746                 }
747
748             }
749
750             protected override bool HitTest(Touch touch)
751             {
752                 // If borderView is in overlay mode, pass the hittest.
753                 return (isEnabledOverlay == false);
754             }
755         }
756         #endregion //Classes
757     }
758 }