Gdk.Rectangle GetScreenCoordinates(Gdk.Rectangle caret) { if (parent != null) { return(GtkUtil.ToScreenCoordinates(parent, parent.GdkWindow, caret)); } if (xwtParent != null) { return(GtkUtil.ToScreenCoordinates(xwtParent, caret.ToXwtRectangle())); } return(Gdk.Rectangle.Zero); }
protected Rectangle GetScreenCoordinates(Rectangle targetRect) { // TODO: Fix cross toolkit coords var gtkTarget = target as Gtk.Widget; if (gtkTarget != null) { return(GtkUtil.ToScreenCoordinates(gtkTarget, gtkTarget.GdkWindow, targetRect.ToGdkRectangle()).ToXwtRectangle()); } #if MAC var nsTarget = target as AppKit.NSView; if (nsTarget != null) { var lo = nsTarget.ConvertPointToView(new CoreGraphics.CGPoint((nfloat)targetRect.X, (nfloat)targetRect.Y), null); lo = nsTarget.Window.ConvertRectToScreen(new CoreGraphics.CGRect(lo, CoreGraphics.CGSize.Empty)).Location; var r = new CoreGraphics.CGRect(lo.X, lo.Y, 0, nsTarget.IsFlipped ? 0 : nsTarget.Frame.Height); var desktopBounds = new Rectangle(); foreach (var s in AppKit.NSScreen.Screens) { var sr = s.Frame; desktopBounds = desktopBounds.Union(new Rectangle(sr.X, sr.Y, sr.Width, sr.Height)); } r.Y = (nfloat)desktopBounds.Height - r.Y - r.Height; if (desktopBounds.Y < 0) { r.Y += (nfloat)desktopBounds.Y; } return(new Rectangle(r.X, r.Y, r.Width, r.Height)); } #endif var xwtTarget = target as Widget; if (xwtTarget != null) { return(GtkUtil.ToScreenCoordinates(xwtTarget, targetRect).ToXwtRectangle()); } return(Rectangle.Zero); }
public virtual void RepositionWindow(Gdk.Rectangle?newCaret = null) { if (parent == null) { return; } int x, y; if (newCaret.HasValue) //Update caret if parameter is given { currentCaret = newCaret.Value; } Gdk.Rectangle caret = currentCaret; Gdk.Window window = targetWindow; if (targetWindow == null) { return; } PopupPosition position = Theme.TargetPosition; this.position = Theme.TargetPosition; UpdatePadding(); window.GetOrigin(out x, out y); var alloc = parent.Allocation; if (eventProvided) { caret.X = x; caret.Y = y; caret.Width = caret.Height = 1; } else { if (caret.Equals(Gdk.Rectangle.Zero)) { caret = new Gdk.Rectangle(0, 0, alloc.Width, alloc.Height); } caret = GtkUtil.ToScreenCoordinates(parent, parent.GdkWindow, caret); } Gtk.Requisition request = SizeRequest(); var screen = parent.Screen; Gdk.Rectangle geometry = GtkWorkarounds.GetUsableMonitorGeometry(screen, screen.GetMonitorAtPoint(caret.X, caret.Y)); // Add some spacing between the screen border and the popover window geometry.Inflate(-5, -5); // Flip the orientation if the window doesn't fit the screen. int intPos = (int)position; switch ((PopupPosition)(intPos & 0x0f)) { case PopupPosition.Top: if (caret.Bottom + request.Height > geometry.Bottom) { intPos = (intPos & 0xf0) | (int)PopupPosition.Bottom; } break; case PopupPosition.Bottom: if (caret.Top - request.Height < geometry.X) { intPos = (intPos & 0xf0) | (int)PopupPosition.Top; } break; case PopupPosition.Right: if (caret.X - request.Width < geometry.X) { intPos = (intPos & 0xf0) | (int)PopupPosition.Left; } break; case PopupPosition.Left: if (caret.Right + request.Width > geometry.Right) { intPos = (intPos & 0xf0) | (int)PopupPosition.Right; } break; } position = (PopupPosition)intPos; UpdatePadding(); // Calculate base coordinate switch ((PopupPosition)((int)position & 0x0f)) { case PopupPosition.Top: y = caret.Bottom; break; case PopupPosition.Bottom: y = caret.Y - request.Height; break; case PopupPosition.Right: x = caret.X - request.Width; break; case PopupPosition.Left: x = caret.Right; break; } int offset; if ((position & PopupPosition.Top) != 0 || (position & PopupPosition.Bottom) != 0) { if (((int)position & 0x10) != 0) { x = caret.X - MinArrowSpacing - Theme.ArrowWidth / 2; } else if (((int)position & 0x20) != 0) { x = caret.Right - request.Width + MinArrowSpacing + Theme.ArrowWidth / 2; } else { x = caret.X + (caret.Width - request.Width) / 2; } if (x < geometry.Left) { x = geometry.Left; } else if (x + request.Width > geometry.Right) { x = geometry.Right - request.Width; } offset = caret.X + caret.Width / 2 - x; if (offset - Theme.ArrowWidth / 2 < MinArrowSpacing) { offset = MinArrowSpacing + Theme.ArrowWidth / 2; } if (offset > request.Width - MinArrowSpacing - Theme.ArrowWidth / 2) { offset = request.Width - MinArrowSpacing - Theme.ArrowWidth / 2; } } else { if (((int)position & 0x10) != 0) { y = caret.Y - MinArrowSpacing - Theme.ArrowWidth / 2; } else if (((int)position & 0x20) != 0) { y = caret.Bottom - request.Height + MinArrowSpacing + Theme.ArrowWidth / 2; } else { y = caret.Y + (caret.Height - request.Height) / 2; } if (y < geometry.Top) { y = geometry.Top; } else if (y + request.Height > geometry.Bottom) { y = geometry.Bottom - request.Height; } if (MaximumYTopBound > 0) { y = Math.Max(MaximumYTopBound, y); } offset = caret.Y + caret.Height / 2 - y; if (offset - Theme.ArrowWidth / 2 < MinArrowSpacing) { offset = MinArrowSpacing + Theme.ArrowWidth / 2; } if (offset > request.Height - MinArrowSpacing - Theme.ArrowWidth / 2) { offset = request.Height - MinArrowSpacing - Theme.ArrowWidth / 2; } } Theme.ArrowOffset = offset; this.position = position; UpdatePadding(); Move(x, y); Show(); if (!ShowWindowShadow) { DesktopService.RemoveWindowShadow(this); } }