1 // -------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All Rights Reserved.
3 // -------------------------------------------------------------------
4 //From \\authoring\Sparkle\Source\1.0.1083.0\Common\Source\Framework\Controls
5 namespace System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.Controls
9 using System.Windows.Input;
10 using System.Windows.Controls.Primitives;
11 using System.Windows.Media;
12 using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.UserInterface;
15 // This class contains specific behavior for the Popup associated with PropertyContainer.
16 // Basically, it is a workaround for Windows OS bug #1745919. The "StaysOpen = false" setting
17 // on a Popup does not function as we expect when the Popup is created within another
18 // "StaysOpen = false" popup (or if anything has capture). What happens is the Popup first
19 // checks if anything has capture, and only takes capture if nothing else has taken it. But the
20 // StaysOpen behavior is implemented using the capture, so we lose that. Also, related to that
21 // the Closed event will not be called, so to workaround both of those issues we essentially
22 // re-implement the popup capture grabbing code, except we take capture no matter what.
24 internal class WorkaroundPopup : Popup
26 private bool releasingCapture = false;
28 protected override void OnOpened(EventArgs e)
30 this.releasingCapture = false;
32 if (this.Child != null)
34 this.Child.Focusable = true;
36 Mouse.Capture(this.Child, CaptureMode.SubTree);
38 this.SetValue(FocusScopeManager.FocusScopePriorityProperty, 1);
42 protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
44 base.OnGotKeyboardFocus(e);
47 protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
49 base.OnLostKeyboardFocus(e);
52 protected override void OnGotFocus(RoutedEventArgs e)
57 protected override void OnLostFocus(RoutedEventArgs e)
62 protected override void OnLostMouseCapture(System.Windows.Input.MouseEventArgs e)
65 // This code is a stripped down implementation of Popup.OnMouseLostCapture
66 if (!this.releasingCapture && Mouse.Captured != this.Child)
68 if (e.OriginalSource == this.Child)
70 if (Mouse.Captured == null)
75 else if (this.IsDescendentOfPopup(sender as DependencyObject))
77 if (this.IsOpen && Mouse.Captured == null)
79 Mouse.Capture(this.Child, CaptureMode.SubTree);
87 base.OnLostMouseCapture(e);
90 protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
92 // Check if the mouse down occured within the popup, if it did, leave the popup open. If it didn't, then close
93 // the popup and release capture.
94 if (e.OriginalSource == this.Child && this.Child.InputHitTest(e.GetPosition(this.Child)) == null)
97 this.ReleaseChildMouseCapture();
102 private bool IsDescendentOfPopup(DependencyObject currentObject)
104 while (currentObject != null)
106 if (currentObject == this || currentObject == this.Child)
110 currentObject = VisualTreeHelper.GetParent(currentObject);
116 private void ReleaseChildMouseCapture()
118 if (Mouse.Captured == this.Child)
120 this.releasingCapture = true;
122 this.releasingCapture = false;
126 protected override void OnKeyDown(KeyEventArgs e)
128 if (e.Key == Key.Escape)
131 this.ReleaseChildMouseCapture();
136 protected override void OnClosed(EventArgs e)
138 this.ReleaseChildMouseCapture();