I have hacked up the following implementation for WS_EX_TRANSPARENT
for the X11 backend. It will try to get a RGBA Visual, create a RGBA
Colormap and set that as the colormap to be used for CreateWindow.

The issue is that even with the RGBA colormap and
BackColor.Transparent set for the control it isn't transparent. I have
tried filling the client area in OnPaintBackground with
Brushes.Transparent but that also just results a black client
rectangle. Could it be that Color.Transparent doesn't match what is
expected by X?

May be someone can take a look and help me to figure out what is
wrong? Patch and test case attached.

Regards.
--
Ivan N. Zlatev

Web: http://www.i-nZ.net
"It's all some kind of whacked out conspiracy."
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs	(revision 82534)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs	(working copy)
@@ -1659,4 +1659,19 @@
 		public int nimage;     /* number of images */
 		public IntPtr images;   /* array of XcursorImage pointers */
 	}
+
+	[StructLayout(LayoutKind.Sequential)]
+	internal struct XVisualInfo
+	{
+		internal IntPtr visual;
+		internal int visualid;
+		internal int screen;
+		internal uint depth;
+		internal int klass;
+		internal uint red_mask;
+		internal uint green_mask;
+		internal uint blue_mask;
+		internal int colormap_size;
+		internal int bits_per_rgb;		
+	}
 }
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/Xlib.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/Xlib.cs	(revision 82534)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/Xlib.cs	(working copy)
@@ -346,5 +346,11 @@
 
 		[DllImport (libX11)]
 		public extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
+
+		[DllImport (libX11)]
+		internal extern static IntPtr XGetVisualInfo (IntPtr display, int vinfo_mask, ref XVisualInfo vinfo_template, ref int nitems);
+
+		[DllImport (libX11)]
+		internal extern static IntPtr XCreateColormap (IntPtr display, IntPtr window, IntPtr visual, int alloc);
 	}
 }
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs	(revision 82534)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs	(working copy)
@@ -1214,8 +1214,32 @@
 						((X11Hwnd)ModalWindows.Peek()).Activate ();
 				}
 			}
-                }
+		}
 
+		public IntPtr GetRGBAColormap ()
+		{
+			IntPtr rgbaColormap = IntPtr.Zero;
+
+			// try to find the rgba visual
+			XVisualInfo visual = new XVisualInfo ();
+			visual.screen = (int) display;
+			visual.depth = 32;
+			visual.red_mask = 0xff0000;
+			visual.green_mask = 0x00ff00;
+			visual.blue_mask = 0x0000ff;
+			int mask = 0x2  /* VisualIDMask */ | 0x04  /* VisualDepthMask */ | 0x10 /* VisualRedMaskMask */ | 
+				0x20 /* VisualGreenMaskMask */ | 0x40 /* VisualBlueMaskMask */;
+
+			int nitems = 0;
+			IntPtr vPtr = Xlib.XGetVisualInfo (display, mask, ref visual, ref nitems);
+			if (vPtr != IntPtr.Zero && nitems > 0) {
+				rgbaColormap = Xlib.XCreateColormap (display, this.RootWindow.Handle, vPtr, 0x0 /* AllocNone */);
+				Xlib.XFree (vPtr);
+			}
+
+			return rgbaColormap;
+		}
+
 		public void GetDisplaySize (out Size size)
 		{
 			XWindowAttributes attributes = new XWindowAttributes();
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Hwnd.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Hwnd.cs	(revision 82534)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Hwnd.cs	(working copy)
@@ -130,7 +130,7 @@
 			    && !StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
 				if (x<0) x = 50;
 				if (y<0) y = 50;
-			}
+			}			
 			// minimum width/height
 			if (width<1) width=1;
 			if (height<1) height=1;
@@ -154,7 +154,13 @@
 
 			ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
 
-			if (display.CustomVisual != IntPtr.Zero && display.CustomColormap != IntPtr.Zero) {
+			if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TRANSPARENT)) {
+				IntPtr colormap = Display.GetRGBAColormap ();
+				if (colormap != IntPtr.Zero) {
+					ValueMask |= SetWindowValuemask.ColorMap;
+					Attributes.colormap = colormap;
+				}
+			} else if (display.CustomVisual != IntPtr.Zero && display.CustomColormap != IntPtr.Zero) {
 				ValueMask |= SetWindowValuemask.ColorMap;
 				Attributes.colormap = display.CustomColormap;
 			}
using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;

namespace mwfbugs
{
	public class TransparentControlTest
	{
		public static void Main (string[] args)
		{
			Form f = new Form ();
			LogPanel p = new LogPanel ("ContainerPanel");
			p.BackColor = Color.Blue;
			LogControl above = new LogControl ("AboveControl");
			above.BackColor = Color.Red;
			above.Width = 20;
			above.Height = 20;
			TransparentControl t = new TransparentControl ("TransparentControl");
			t.Width = 200;
			t.Height = 200;
			LogControl below = new LogControl ("BelowControl");
			below.BackColor = Color.Green;
			below.Width = 50;
			below.Height = 50;

			p.Controls.Add (below);
			p.Controls.Add (t);
			p.Controls.Add (above);
			f.Controls.Add (p);
			f.ShowDialog ();
		}
	}


	public class TransparentControl : LogControl
	{

		public TransparentControl (string name) : base (name)
		{   
			// this.SetStyle (ControlStyles.SupportsTransparentBackColor, true);
			this.BackColor = Color.Transparent;
		}

		protected override void OnPaintBackground (PaintEventArgs pevent)
		{
			//pevent.Graphics.FillRectangle (new SolidBrush (Color.Transparent), new Rectangle (0, 0, this.Width, this.Height));
		}


		protected override CreateParams CreateParams {
			get {
				CreateParams cp = base.CreateParams;
				cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
				return cp;
			}
		}

		protected override void OnClick (EventArgs e)
		{
			this.Parent.Refresh ();
			base.OnClick (e);

		}

		protected override void OnPaint (PaintEventArgs e)
		{
			base.OnPaint (e);
			e.Graphics.DrawLine (new Pen (Color.Orange), new Point (0, 0), new Point (200, 200));
		}


	}

	public class LogPanel : Panel
	{
		private string _name;

		public LogPanel (string name)
		{
			_name = name;
		}

		public string Name {
			get { return _name; }
		}

		public override string Text {
			get { return _name; }
			set {  base.Text = value;}
		}

		protected override void OnPaint (PaintEventArgs e)
		{
			Console.WriteLine (this.Name + ": " + "OnPaint");
			base.OnPaint (e);
		}

		protected override void WndProc (ref Message m)
		{
			if (m.Msg == 15) {
				Console.WriteLine (this.Name + ": " + "WM_PAINT");
			}
			base.WndProc (ref m);
		}
	}

	public class LogControl : UserControl
	{

		private string _name;

		public LogControl (string name)
		{
			_name = name;
		}

		public string Name {
			get { return _name; }
		}

		public override string Text {
			get { return _name; }
			set {  base.Text = value;}
		}


		protected override void OnPaint (PaintEventArgs e)
		{
			Console.WriteLine (this.Name + ": " + "OnPaint");
			base.OnPaint (e);
		}

		protected override void WndProc (ref Message m)
		{
			if (m.Msg == 15) {
				Console.WriteLine (this.Name + ": " + "WM_PAINT");
			}
			base.WndProc (ref m);
		}


	}
}

_______________________________________________
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Reply via email to