Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/class
diff options
context:
space:
mode:
authorKarl <5079870+PreferLinux@users.noreply.github.com>2020-01-13 19:10:57 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2020-01-13 19:10:57 +0300
commitd7e84ac6d18d84d8072ad45b87932b0353f05192 (patch)
tree82f93fb923dee5c3804223a737dc9d93c6b1663f /mcs/class
parent87cfaf15ae8687524b1f18e21c85a2680d7fe5e0 (diff)
[Winforms] Implement correct Control.Region / ClipRegion support on X11 (#18421)
Fixes https://xamarin.github.io/bugzilla-archives/20/20233/bug.html Previously, on Linux, setting Control.Region just set the clipping for painting, but didn't influence the visibility of other controls behind the one it was set on. This implements this correctly via X11 Shape extension.
Diffstat (limited to 'mcs/class')
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/X11Structs.cs31
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs76
2 files changed, 105 insertions, 2 deletions
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/X11Structs.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/X11Structs.cs
index cfac29e9bed..42eb4f89fd4 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/X11Structs.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/X11Structs.cs
@@ -1698,6 +1698,16 @@ namespace System.Windows.Forms {
[StructLayout (LayoutKind.Sequential)]
[Serializable]
+ internal struct XRectangle
+ {
+ public short X;
+ public short Y;
+ public ushort Width;
+ public ushort Height;
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ [Serializable]
internal class XIMCallback
{
public IntPtr client_data;
@@ -1818,4 +1828,25 @@ namespace System.Windows.Forms {
public short width;
public short height;
}
+
+ internal enum XShapeOperation {
+ ShapeSet,
+ ShapeUnion,
+ ShapeIntersect,
+ ShapeSubtract,
+ ShapeInvert
+ }
+
+ internal enum XShapeKind {
+ ShapeBounding,
+ ShapeClip,
+ //ShapeInput // Not usable without more imports
+ }
+
+ internal enum XOrdering {
+ Unsorted,
+ YSorted,
+ YXSorted,
+ YXBanded
+ }
}
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
index cde5f7ae773..63021f5f87b 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
@@ -135,6 +135,9 @@ namespace System.Windows.Forms {
// Last window containing the pointer
static IntPtr LastPointerWindow; // The last window containing the pointer
+ // Shape extension
+ bool? hasShapeExtension;
+
// Our atoms
static IntPtr WM_PROTOCOLS;
static IntPtr WM_DELETE_WINDOW;
@@ -1482,7 +1485,7 @@ namespace System.Windows.Forms {
}
int NextTimeout (ArrayList timers, DateTime now) {
- int timeout = 0;
+ int timeout = int.MaxValue;
foreach (Timer timer in timers) {
int next = (int) (timer.Expires - now).TotalMilliseconds;
@@ -5562,6 +5565,26 @@ namespace System.Windows.Forms {
}
}
+ internal bool HasShapeExtension {
+ get {
+ if (!hasShapeExtension.HasValue) {
+ try {
+ hasShapeExtension = XShapeQueryExtension(DisplayHandle, out _, out _);
+ } catch {
+ hasShapeExtension = false;
+ }
+ }
+
+ return hasShapeExtension.Value;
+ }
+ }
+
+ internal override bool UserClipWontExposeParent {
+ get {
+ return !HasShapeExtension;
+ }
+ }
+
internal override void SetClipRegion(IntPtr handle, Region region)
{
Hwnd hwnd;
@@ -5571,7 +5594,33 @@ namespace System.Windows.Forms {
return;
}
- hwnd.UserClip = region;
+ if (hwnd.UserClip != region) {
+ hwnd.UserClip = region;
+
+ if (!HasShapeExtension)
+ return;
+
+ XRectangle[] rects = null;;
+ if (region == null) {
+ rects = new XRectangle[1];
+ rects[0].X = 0;
+ rects[0].Y = 0;
+ rects[0].Width = (ushort)hwnd.Width;
+ rects[0].Height = (ushort)hwnd.Height;
+ } else {
+ RectangleF[] scans;
+ using (var m = new Matrix())
+ scans = region.GetRegionScans(m);
+ rects = new XRectangle[scans.Length];
+ for (int i = 0; i < scans.Length; i++) {
+ rects[i].X = (short) Math.Clamp(scans[i].X, short.MinValue, short.MaxValue);
+ rects[i].Y = (short) Math.Clamp(scans[i].Y, short.MinValue, short.MaxValue);
+ rects[i].Width = (ushort) Math.Clamp(scans[i].Width, ushort.MinValue, ushort.MaxValue);
+ rects[i].Height = (ushort) Math.Clamp(scans[i].Height, ushort.MinValue, ushort.MaxValue);
+ }
+ }
+ XShapeCombineRectangles(DisplayHandle, hwnd.WholeWindow, XShapeKind.ShapeBounding, 0, 0, rects, rects.Length, XShapeOperation.ShapeSet, XOrdering.Unsorted);
+ }
}
internal override void SetCursor(IntPtr handle, IntPtr cursor)
@@ -7242,6 +7291,22 @@ namespace System.Windows.Forms {
}
#endregion
+#region Shape extension imports
+ [DllImport("libXext", EntryPoint="XShapeQueryExtension")]
+ internal extern static bool _XShapeQueryExtension(IntPtr display, out int event_base, out int error_base);
+ internal static bool XShapeQueryExtension(IntPtr display, out int event_base, out int error_base) {
+ DebugHelper.TraceWriteLine (nameof(XShapeQueryExtension));
+ return _XShapeQueryExtension(display, out event_base, out error_base);
+ }
+
+ [DllImport("libXext", EntryPoint="XShapeCombineRectangles")]
+ internal extern static void _XShapeCombineRectangles(IntPtr display, IntPtr window, XShapeKind dest_kind, int x_off, int y_off, XRectangle[] rectangles, int n_rects, XShapeOperation op, XOrdering ordering);
+ internal static void XShapeCombineRectangles(IntPtr display, IntPtr window, int dest_kind, int x_off, int y_off, XRectangle[] rectangles, int n_rects, int op, int ordering) {
+ DebugHelper.TraceWriteLine (nameof(XShapeCombineRectangles));
+ _XShapeCombineRectangles(display, window, dest_kind, x_off, y_off, rectangles, n_rects, op, ordering);
+ }
+#endregion
+
#region Xinerama imports
[DllImport ("libXinerama", EntryPoint="XineramaQueryScreens")]
extern static IntPtr _XineramaQueryScreens (IntPtr display, out int number);
@@ -7640,6 +7705,13 @@ namespace System.Windows.Forms {
internal extern static void gtk_clipboard_set_text (IntPtr clipboard, string text, int len);
#endregion
+#region Shape extension imports
+ [DllImport("libXext")]
+ internal extern static bool XShapeQueryExtension(IntPtr display, out int event_base, out int error_base);
+
+ [DllImport("libXext")]
+ internal extern static void XShapeCombineRectangles(IntPtr display, IntPtr window, XShapeKind dest_kind, int x_off, int y_off, XRectangle[] rectangles, int n_rects, XShapeOperation op, XOrdering ordering);
+#endregion
#region Xinerama imports
[DllImport ("libXinerama")]