diff options
author | Vinicius Jarina <viniciusjarina@gmail.com> | 2017-04-14 03:37:44 +0300 |
---|---|---|
committer | Vinicius Jarina <viniciusjarina@gmail.com> | 2017-04-14 03:37:44 +0300 |
commit | 90964353cb46b5be0e4c667bd87edd23d9d8ce56 (patch) | |
tree | 74d58f320295948b89c33cac127096f5f1f59980 | |
parent | ef545e1c206520c3cbfda7ec8cd060caa19b83cd (diff) |
[Mac] Fixed using Popover with `NSView`.viniciusjarina_fix_popover_mac_crash
* Added a overload to `IPopoverBackend.Show` receiving an object.
We can’t wrap and unwrap the NSView to be used with the Popover, because this will change the parent of the window when we unwrap it, invalidating the `NSView.Window`, making NSPopover throw a NSException, due the missing NSWindow inside the NSView.
* This patch pass the NSView all the way down, without wrap it inside a EmbeddedNativeWidget, this way avoiding the NSView to lost the NSWindow.
-rw-r--r-- | Xwt.Gtk/Xwt.GtkBackend/PopoverBackend.cs | 22 | ||||
-rw-r--r-- | Xwt.WPF/Xwt.WPFBackend/PopoverBackend.cs | 14 | ||||
-rw-r--r-- | Xwt.XamMac/Xwt.Mac/PopoverBackend.cs | 35 | ||||
-rw-r--r-- | Xwt/Xwt.Backends/IPopoverBackend.cs | 1 | ||||
-rw-r--r-- | Xwt/Xwt/Popover.cs | 13 |
5 files changed, 73 insertions, 12 deletions
diff --git a/Xwt.Gtk/Xwt.GtkBackend/PopoverBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/PopoverBackend.cs index c7dfe1c2..9f5426ec 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/PopoverBackend.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/PopoverBackend.cs @@ -245,9 +245,23 @@ namespace Xwt.GtkBackend { } + public void Show (Xwt.Popover.Position orientation, object reference, Xwt.Rectangle positionRect, Widget child) + { + var nativeReference = reference as Gtk.Widget; + if (nativeReference == null) + return; + Show (orientation, nativeReference, positionRect, child); + } + public void Show (Xwt.Popover.Position orientation, Xwt.Widget reference, Xwt.Rectangle positionRect, Widget child) { - popover.Content = (Gtk.Widget)((WidgetBackend)Toolkit.GetBackend (child)).NativeWidget; + var nativeReference = (Gtk.Widget)((WidgetBackend)Toolkit.GetBackend (child)).NativeWidget; + Show (orientation, nativeReference, positionRect, child); + } + + public void Show (Xwt.Popover.Position orientation, Gtk.Widget reference, Xwt.Rectangle positionRect, Widget child) + { + popover.Content = reference; popover.ArrowPosition = orientation; popover.BackgroundColor = BackgroundColor.ToCairoColor (); popover.Padding = frontend.Padding; @@ -262,10 +276,10 @@ namespace Xwt.GtkBackend popover.Hidden += (o, args) => sink.OnClosed (); - var screenBounds = reference.ScreenBounds; + var screenBounds = reference.Allocation; if (positionRect == Rectangle.Zero) - positionRect = new Rectangle (Point.Zero, screenBounds.Size); - positionRect = positionRect.Offset (screenBounds.Location); + positionRect = new Rectangle (0, 0, screenBounds.Size.Width, screenBounds.Height); + positionRect = positionRect.Offset (screenBounds.Location.X, screenBounds.Y); popover.Show (); popover.Present (); popover.GrabFocus (); diff --git a/Xwt.WPF/Xwt.WPFBackend/PopoverBackend.cs b/Xwt.WPF/Xwt.WPFBackend/PopoverBackend.cs index 3203682c..516560e1 100644 --- a/Xwt.WPF/Xwt.WPFBackend/PopoverBackend.cs +++ b/Xwt.WPF/Xwt.WPFBackend/PopoverBackend.cs @@ -94,8 +94,20 @@ namespace Xwt.WPFBackend EventSink = sink; } + public void Show (Xwt.Popover.Position orientation, object reference, Xwt.Rectangle positionRect, Widget child) + { + var nativeReference = (System.Windows.FrameworkElement)Context.Toolkit.GetNativeWidget (reference); + Show (orientation, nativeReference, positionRect, child); + } + public void Show (Xwt.Popover.Position orientation, Xwt.Widget reference, Xwt.Rectangle positionRect, Widget child) { + var nativeReference = (System.Windows.FrameworkElement)Context.Toolkit.GetNativeWidget (reference); + Show (orientation, nativeReference, positionRect, child); + } + + void Show (Xwt.Popover.Position orientation, System.Windows.FrameworkElement reference, Xwt.Rectangle positionRect, Widget child) + { ActualPosition = orientation; Border.Child = (System.Windows.FrameworkElement)Context.Toolkit.GetNativeWidget (child); NativeWidget.CustomPopupPlacementCallback = (popupSize, targetSize, offset) => { @@ -111,7 +123,7 @@ namespace Xwt.WPFBackend new System.Windows.Controls.Primitives.CustomPopupPlacement (location, System.Windows.Controls.Primitives.PopupPrimaryAxis.Horizontal) }; }; - NativeWidget.PlacementTarget = (System.Windows.FrameworkElement)Context.Toolkit.GetNativeWidget (reference); + NativeWidget.PlacementTarget = reference; NativeWidget.IsOpen = true; } diff --git a/Xwt.XamMac/Xwt.Mac/PopoverBackend.cs b/Xwt.XamMac/Xwt.Mac/PopoverBackend.cs index 09c1fcb8..860bd12d 100644 --- a/Xwt.XamMac/Xwt.Mac/PopoverBackend.cs +++ b/Xwt.XamMac/Xwt.Mac/PopoverBackend.cs @@ -200,6 +200,22 @@ namespace Xwt.Mac } } + public void Show (Popover.Position orientation, object reference, Rectangle positionRect, Widget child) + { + var refView = reference as NSView; + if (refView == null) + return; + + // If the rect is empty, the coordinates of the rect will be ignored. + // Set the width and height, for the positioning to function correctly. + if (Math.Abs (positionRect.Width) < double.Epsilon) + positionRect.Width = refView.Frame.Size.Width; + if (Math.Abs (positionRect.Height) < double.Epsilon) + positionRect.Height = refView.Frame.Size.Height; + + Show (orientation, refView, positionRect, child); + } + public void Show (Popover.Position orientation, Widget referenceWidget, Rectangle positionRect, Widget child) { var refBackend = Toolkit.GetBackend (referenceWidget) as IWidgetBackend; @@ -214,20 +230,25 @@ namespace Xwt.Mac positionRect.X += referenceWidget.WindowBounds.Location.X - rLocation.X; positionRect.Y += referenceWidget.WindowBounds.Location.Y - rLocation.Y; } + + // If the rect is empty, the coordinates of the rect will be ignored. + // Set the width and height, for the positioning to function correctly. + if (Math.Abs (positionRect.Width) < double.Epsilon) + positionRect.Width = referenceWidget.Size.Width; + if (Math.Abs (positionRect.Height) < double.Epsilon) + positionRect.Height = referenceWidget.Size.Height; + } catch (Exception ex) { throw new ArgumentException ("Widget belongs to an unsupported Toolkit", nameof (referenceWidget), ex); } } else if (referenceWidget.Surface.ToolkitEngine != ApplicationContext.Toolkit) throw new ArgumentException ("Widget belongs to an unsupported Toolkit", nameof (referenceWidget)); } + Show (orientation, refView, positionRect, child); + } - // If the rect is empty, the coordinates of the rect will be ignored. - // Set the width and height, for the positioning to function correctly. - if (Math.Abs (positionRect.Width) < double.Epsilon) - positionRect.Width = referenceWidget.Size.Width; - if (Math.Abs (positionRect.Height) < double.Epsilon) - positionRect.Height = referenceWidget.Size.Height; - + void Show (Popover.Position orientation, NSView refView, Rectangle positionRect, Widget child) + { DestroyPopover (); popover = new NSAppearanceCustomizationPopover { diff --git a/Xwt/Xwt.Backends/IPopoverBackend.cs b/Xwt/Xwt.Backends/IPopoverBackend.cs index 3036b044..26d5bb60 100644 --- a/Xwt/Xwt.Backends/IPopoverBackend.cs +++ b/Xwt/Xwt.Backends/IPopoverBackend.cs @@ -35,6 +35,7 @@ namespace Xwt.Backends Color BackgroundColor { get; set; } void Initialize (IPopoverEventSink sink); void Show (Popover.Position arrowPosition, Widget referenceWidget, Xwt.Rectangle positionRect, Xwt.Widget child); + void Show (Popover.Position arrowPosition, object nativeWidget, Xwt.Rectangle positionRect, Xwt.Widget child); void Hide (); } diff --git a/Xwt/Xwt/Popover.cs b/Xwt/Xwt/Popover.cs index 1f2ada42..ac1ab534 100644 --- a/Xwt/Xwt/Popover.cs +++ b/Xwt/Xwt/Popover.cs @@ -143,11 +143,24 @@ namespace Xwt { } + public void Show (Position arrowPosition, object referenceWidget) + { + Show (arrowPosition, referenceWidget, Xwt.Rectangle.Zero); + } + public void Show (Position arrowPosition, Widget referenceWidget) { Show (arrowPosition, referenceWidget, Xwt.Rectangle.Zero); } + public void Show (Position arrowPosition, object referenceWidget, Xwt.Rectangle positionRect) + { + if (content == null) + throw new InvalidOperationException ("A child widget source must be set before running the Popover"); + Backend.Show (arrowPosition, referenceWidget, positionRect, content); + shown = true; + } + public void Show (Position arrowPosition, Widget referenceWidget, Xwt.Rectangle positionRect) { if (content == null) |