private void DispatcherTimerOnTick(object sender, EventArgs eventArgs)
        {
            int secsSinceLastInput = NativeMethods.GetLastInputTime();
            if (secsSinceLastInput > 5 * 60)
            {
                return;
            }

            MouseUtilities.Win32Point win32Point = new MouseUtilities.Win32Point();
            NativeMethods.GetCursorPos(ref win32Point);

            foreach (NotificationWindow notificationWindow in AppLogic.NotificationWindows)
            {
                if (VisualTreeHelper.GetDescendantBounds(notificationWindow).Contains(
                    notificationWindow.PointFromScreen(new System.Windows.Point(win32Point.X, win32Point.Y))))
                {
                    return;
                }
            }

            //            this.RemoveNotifications();
            this.Close();
        }
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!endAnimationEnded)
            {
                e.Cancel = true;
            }

            if (!endAnimationStarted)
            {
                endAnimationStarted = true;
                //                Storyboard sb = this.FindResource("WindowStoryboard2") as Storyboard;

                Storyboard sb = new Storyboard();

                var opacityAnimation = new DoubleAnimation();
                sb.Children.Add(opacityAnimation);
                Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(System.Windows.UIElement.OpacityProperty));
                opacityAnimation.To = 0;
                opacityAnimation.FillBehavior = FillBehavior.HoldEnd;
                opacityAnimation.BeginTime = TimeSpan.FromSeconds(0);
                //                opacityAnimation.Duration = TimeSpan.FromSeconds(0.8);
                opacityAnimation.Duration = TimeSpan.FromSeconds(0.6);

                DoubleAnimation myDoubleAnimation = new DoubleAnimation();
                myDoubleAnimation.To = this.Top + this.Height / 4;

                myDoubleAnimation.BeginTime = TimeSpan.FromSeconds(0);
                //                myDoubleAnimation.Duration = TimeSpan.FromSeconds(0.8);
                myDoubleAnimation.Duration = TimeSpan.FromSeconds(0.6);

                sb.Children.Add(myDoubleAnimation);
                //                Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(System.Windows.Window.LeftProperty));
                Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(System.Windows.Window.TopProperty));

                Timeline.SetDesiredFrameRate(opacityAnimation, 30);
                Timeline.SetDesiredFrameRate(myDoubleAnimation, 30);
                sb.SlipBehavior = SlipBehavior.Slip;

                sb.Completed += (o, args) =>
                {
                    endAnimationEnded = true;

                    MouseUtilities.Win32Point win32Point = new MouseUtilities.Win32Point();
                    NativeMethods.GetCursorPos(ref win32Point);
                    bool mouseOverAny = false;
                    foreach (NotificationWindow notificationWindow in AppLogic.NotificationWindows.Where(window => !window.endAnimationStarted && !window.animationRunning))
                    {
                        if (VisualTreeHelper.GetDescendantBounds(notificationWindow).Contains(
                            notificationWindow.PointFromScreen(new System.Windows.Point(win32Point.X, win32Point.Y))))
                        {
                            mouseOverAny = true;
                            break;
                        }
                    }
                    if (mouseOverAny)
                    {
                        this.removeLater = true;
                    }
                    RemoveNotifications();
                };
                var hwnd = new WindowInteropHelper(this).Handle;
                NativeMethodsTransparency.SetWindowExTransparent(hwnd);
                sb.Begin(this, true);

                //                RemoveNotifications();
            }
        }
        private void Window_MouseLeave(object sender, MouseEventArgs e)
        {
            if (animationRunning)
            {
                return;
            }

            MouseUtilities.Win32Point win32Point = new MouseUtilities.Win32Point();
            NativeMethods.GetCursorPos(ref win32Point);

            bool mouseOverAny = false;
            foreach (NotificationWindow notificationWindow in AppLogic.NotificationWindows.Where(window => window != this))
            {
                if (notificationWindow.animationRunning || notificationWindow.endAnimationStarted)
                {
                    continue;
                }

                if (VisualTreeHelper.GetDescendantBounds(notificationWindow).Contains(
                        notificationWindow.PointFromScreen(new System.Windows.Point(win32Point.X, win32Point.Y))))
                {
                    mouseOverAny = true;
                    notificationWindow.removeLater = true;
                }
            }

            this.removeLater = true;

            if (!mouseOverAny)
            {
                this.RemoveNotifications();
            }
        }
        private void RemoveNotifications()
        {
            var index = AppLogic.NotificationWindows.IndexOf(this);
            if (index < 0)
            {
                return;
            }

            this.Close();

            bool allAnimationsDone = AppLogic.NotificationWindows.Where(window => window.endAnimationStarted).All(window => window.endAnimationEnded);

            index = AppLogic.NotificationWindows.IndexOf(this);
            if (index >= 0 && endAnimationEnded)
            {
                AppLogic.NotificationWindows.RemoveAt(index);
            }

            MouseUtilities.Win32Point win32Point = new MouseUtilities.Win32Point();
            NativeMethods.GetCursorPos(ref win32Point);

            // if mouse over any notification don't restack them
            if (AppLogic.NotificationWindows.Where(window => !window.endAnimationStarted && !window.animationRunning).Any(notificationWindow => VisualTreeHelper.GetDescendantBounds(notificationWindow).Contains(
                notificationWindow.PointFromScreen(new System.Windows.Point(win32Point.X, win32Point.Y)))))
            {
                return;
            }

            // remove notifications scheduled for removal
            foreach (NotificationWindow notificationWindow in AppLogic.NotificationWindows.Where(window => window.removeLater))
            {
                if (notificationWindow == this)
                {
                    continue;
                }
                notificationWindow.Close();
            }

            // don't restack if any closing animations running
            if (!allAnimationsDone)
            {
                return;
            }

            // restack all notifications
            foreach (NotificationWindow notificationWindow in AppLogic.NotificationWindows)
            {
                var point = notificationWindow.CalculateTopAndLeft();
                var newTop = point.Y - AppLogic.NotificationWindows.IndexOf(notificationWindow) * notificationWindow.Height;
                notificationWindow.calculatedTop = newTop;

                notificationWindow.BeginAnimation(TopProperty, null);

                notificationWindow.Left = point.X;
                notificationWindow.Top = newTop;
            }
        }