In System.Windows.Forms:
authorChris Toshok <toshok@novell.com>
Thu, 30 Nov 2006 01:53:42 +0000 (01:53 -0000)
committerChris Toshok <toshok@novell.com>
Thu, 30 Nov 2006 01:53:42 +0000 (01:53 -0000)
[ totally cosmetic eye-candy feature, fixes bug #80089 ]

* Form.cs: only call the XplatUI transparency method (get/set) if
SupportsTransparency says it's supported. Otherwise fallback to
doing nothing (in the set case) or returning the instance field we
cache (in the get case).

* XplatUIStructs.cs: add TransparencySupport flag enum.

* XplatUIDriver.cs: add abstract GetWindowTransparency, and track
change to SupportsTransparency.

* XplatUIOSX.cs: stub out GetWindowTransparency, and return
TransparencySupport.None from SupportsTransparency.

* XplatUIX11.cs: Stub out GetWindowTransparency, and return
TransparencySupport.Set from SupportsTransparency.

* XplatUIWin32.cs: implement GetWindowTransparency calling
GetLayeredWindowAttributes, and implement SupportsTransparency by
checking whether or not both
GetWindowTransparency/SetWindowTransparency are available
entrypoints.  We need to do this since SetWindowTransparency is
available as of win2k, but GetWindowTransparency requires winxp.
yay win32 api.

* XplatUI.cs: Add GetWindowTransparency, and change
SupportsTransparency to allow for either/both Get/Set.

2006-11-29  Chris Toshok  <toshok@ximian.com>

In System.Windows.Forms.X11Internal:
* X11Hwnd.cs: implement GetWindowTransparency, and also add
caching for WINDOW_TYPE and _NET_WM_WINDOW_OPACITY.  We invalidate
the cache when we get a PropertyNotify on that atom.

* X11Display.cs: return GetSet from SupportsTransparency if we
have a compositor running.  otherwise return None.

* XplatUIX11-new.cs: pass SupportsTransparency off onto the
X11Display, and pass GetWindowTransparency off onto the X11Hwnd.

2006-11-29  Chris Toshok  <toshok@ximian.com>

svn path=/trunk/mcs/; revision=68722

12 files changed:
mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Hwnd.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/XplatUIX11-new.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIOSX.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIStructs.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

index 44c26d4790b7857f7b9de79be36cb66e05da28d8..d0d1cf2318d8b87e7ba4ae5c84a6c6e1bf84253e 100644 (file)
@@ -1,3 +1,15 @@
+2006-11-29  Chris Toshok  <toshok@ximian.com>
+
+       * X11Hwnd.cs: implement GetWindowTransparency, and also add
+       caching for WINDOW_TYPE and _NET_WM_WINDOW_OPACITY.  We invalidate
+       the cache when we get a PropertyNotify on that atom.
+
+       * X11Display.cs: return GetSet from SupportsTransparency if we
+       have a compositor running.  otherwise return None.
+
+       * XplatUIX11-new.cs: pass SupportsTransparency off onto the
+       X11Display, and pass GetWindowTransparency off onto the X11Hwnd.
+
 2006-11-29  Chris Toshok  <toshok@ximian.com>
 
        * X11ThreadQueue.cs (EnqueueUnlocked): add the switch motionnotify
index 9b9bbdf9f66c67ab12f38d16546d932180774807..7bd8f350f37d5f31fbfa3ad99fb34d7c527cf1e5 100644 (file)
@@ -502,10 +502,10 @@ namespace System.Windows.Forms.X11Internal {
                        }
                }
 
-               public bool SupportsTransparency ()
+               public TransparencySupport SupportsTransparency ()
                {
                        // compiz adds _NET_WM_WINDOW_OPACITY to _NET_SUPPORTED on the root window, check for that
-                       return ((IList)root_hwnd._NET_SUPPORTED).Contains (Atoms._NET_WM_WINDOW_OPACITY);
+                       return ((IList)root_hwnd._NET_SUPPORTED).Contains (Atoms._NET_WM_WINDOW_OPACITY) ? TransparencySupport.GetSet : TransparencySupport.None;
                }
 
                public void SendAsyncMethod (AsyncMethodData method)
index 7490ccec20ca32db1f3b5fb7be97bc5e1c1439e9..b8faea94c22b3c036e672c37c12bc35e5098069f 100644 (file)
@@ -35,9 +35,12 @@ namespace System.Windows.Forms.X11Internal {
        {
                X11Display display;
 
-               bool refetch_wm_state = true;
+               bool refetch_window_type = true;
+               bool refetch_window_opacity = true;
+
                IntPtr[] wm_state = new IntPtr[0];
                IntPtr[] window_type = new IntPtr[0];
+               double trans = 1.0;
 
                string text;
                X11ThreadQueue queue;
@@ -278,6 +281,8 @@ namespace System.Windows.Forms.X11Internal {
                {
                        if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_WINDOW_TYPE) {
                                // we need to recache our WINDOW_TYPE on the next query
+                               refetch_window_type = true;
+                               window_type = null;
                        }
                        else if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_STATE) {
                                // we need to recache our WM_STATE on the next query
@@ -286,9 +291,11 @@ namespace System.Windows.Forms.X11Internal {
                                // update our Text property
                        }
                        else if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_WINDOW_OPACITY) {
-                               // update the Hwnd's opacity
+                               // we need to recache our _NET_WM_WINDOW_OPACITY on the next query.
+                               refetch_window_opacity = true;
                        }
                        // else we don't care about it
+
                }
 
                public void SetIcon (Icon icon)
@@ -317,6 +324,38 @@ namespace System.Windows.Forms.X11Internal {
                                              PropertyMode.Replace, data, size);
                }
 
+               public double GetWindowTransparency ()
+               {
+                       if (refetch_window_opacity) {
+                               trans = 1.0;
+
+                               IntPtr actual_atom;
+                               int actual_format;
+                               IntPtr nitems;
+                               IntPtr bytes_after;
+                               IntPtr prop = IntPtr.Zero;
+
+                               IntPtr w = WholeWindow;
+                               if (reparented)
+                                       w = display.XGetParent (WholeWindow);
+
+                               Xlib.XGetWindowProperty (display.Handle, w,
+                                                        display.Atoms._NET_WM_WINDOW_OPACITY, IntPtr.Zero, new IntPtr (16), false,
+                                                        display.Atoms.XA_CARDINAL,
+                                                        out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+                               
+                               if (((long)nitems == 1) && (prop != IntPtr.Zero)) {
+                                       int x11_opacity = Marshal.ReadInt32(prop, 0);
+                                       trans = ((double)x11_opacity) / 0xffffffff;
+                               }
+
+                               if (prop != IntPtr.Zero) {
+                                       Xlib.XFree(prop);
+                               }
+                       }
+
+                       return trans;
+               }
 
                public void SetWindowTransparency (double transparency, Color key)
                {
@@ -741,11 +780,11 @@ namespace System.Windows.Forms.X11Internal {
                
                public void FrameExtents (out int left, out int top)
                {
-                       IntPtr                  actual_atom;
-                       int                     actual_format;
-                       IntPtr                  nitems;
-                       IntPtr                  bytes_after;
-                       IntPtr                  prop = IntPtr.Zero;
+                       IntPtr actual_atom;
+                       int actual_format;
+                       IntPtr nitems;
+                       IntPtr bytes_after;
+                       IntPtr prop = IntPtr.Zero;
 
                        Xlib.XGetWindowProperty (display.Handle, WholeWindow,
                                                 display.Atoms._NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false,
@@ -1514,7 +1553,14 @@ namespace System.Windows.Forms.X11Internal {
                }
 
                public IntPtr WINDOW_TYPE {
-                       get { return window_type.Length > 0 ? window_type[0] : IntPtr.Zero; }
+                       get {
+                               if (refetch_window_type) {
+                                       window_type = GetAtomListProperty (display.Atoms._NET_WM_WINDOW_TYPE);
+                                       refetch_window_type = false;
+                               }
+
+                               return window_type.Length > 0 ? window_type[0] : IntPtr.Zero;
+                       }
                        set {
                                Set_WINDOW_TYPE (new IntPtr[] {value}, 1);
                        }
@@ -1522,6 +1568,11 @@ namespace System.Windows.Forms.X11Internal {
 
                public void Set_WINDOW_TYPE (IntPtr[] value, int count)
                {
+                       if (refetch_window_type) {
+                               window_type = GetAtomListProperty (display.Atoms._NET_WM_WINDOW_TYPE);
+                               refetch_window_type = false;
+                       }
+
                        if (ArrayDifferent (window_type, value)) {
                                window_type = value;
                                Xlib.XChangeProperty (display.Handle, WholeWindow,
index b3e6e77bc4a5a31711de2b06a5519e709b7ce0ad..fc0a5f79a24fe5940a31849947a6b1574390a19a 100644 (file)
@@ -921,7 +921,17 @@ namespace System.Windows.Forms.X11Internal {
                        }
                }
 
-               internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key)
+               internal override double GetWindowTransparency (IntPtr handle)
+               {
+                       X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
+
+                       if (hwnd != null)
+                               return hwnd.GetWindowTransparency ();
+                       else
+                               return 0.0;
+               }
+
+               internal override void SetWindowTransparency (IntPtr handle, double transparency, Color key)
                {
                        X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
 
@@ -951,7 +961,7 @@ namespace System.Windows.Forms.X11Internal {
                        return (object) ThreadQueue(thread);
                }
 
-               internal override bool SupportsTransparency()
+               internal override TransparencySupport SupportsTransparency()
                {
                        return display.SupportsTransparency ();
                }
index 33091330053a2c46464dc61f34211d5d33f7939b..1a3db1b4a1501245b349df39a5a13442a921a822 100644 (file)
@@ -1,3 +1,34 @@
+2006-11-29  Chris Toshok  <toshok@ximian.com>
+
+       [ totally cosmetic eye-candy feature, fixes bug #80089 ]
+       
+       * Form.cs: only call the XplatUI transparency method (get/set) if
+       SupportsTransparency says it's supported. Otherwise fallback to
+       doing nothing (in the set case) or returning the instance field we
+       cache (in the get case).
+
+       * XplatUIStructs.cs: add TransparencySupport flag enum.
+       
+       * XplatUIDriver.cs: add abstract GetWindowTransparency, and track
+       change to SupportsTransparency.
+
+       * XplatUIOSX.cs: stub out GetWindowTransparency, and return
+       TransparencySupport.None from SupportsTransparency.
+
+       * XplatUIX11.cs: Stub out GetWindowTransparency, and return
+       TransparencySupport.Set from SupportsTransparency.
+
+       * XplatUIWin32.cs: implement GetWindowTransparency calling
+       GetLayeredWindowAttributes, and implement SupportsTransparency by
+       checking whether or not both
+       GetWindowTransparency/SetWindowTransparency are available
+       entrypoints.  We need to do this since SetWindowTransparency is
+       available as of win2k, but GetWindowTransparency requires winxp.
+       yay win32 api.
+
+       * XplatUI.cs: Add GetWindowTransparency, and change
+       SupportsTransparency to allow for either/both Get/Set.
+
 2006-11-29  Chris Toshok  <toshok@ximian.com>
 
        * DataGrid.cs: keep from going into an infinite loop redrawing a
index b99e06e2cdb3baa76510af31b1844234e3a7b54f..ff9b676d72904e9f0f9160f31b4114697fb1d575 100644 (file)
@@ -237,7 +237,7 @@ namespace System.Windows.Forms {
                                        return;
                                }
 
-                               if (XplatUI.SupportsTransparency()) {
+                               if ((XplatUI.SupportsTransparency() & TransparencySupport.Set) != 0) {
                                        allow_transparency = value;
 
                                        if (value) {
@@ -726,6 +726,11 @@ namespace System.Windows.Forms {
                [MWFCategory("Window Style")]
                public double Opacity {
                        get {
+                               if (IsHandleCreated) {
+                                       if ((XplatUI.SupportsTransparency () & TransparencySupport.Get) != 0)
+                                               return XplatUI.GetWindowTransparency (Handle);
+                               }
+
                                return opacity;
                        }
 
@@ -736,7 +741,8 @@ namespace System.Windows.Forms {
 
                                if (IsHandleCreated) {
                                        UpdateStyles();
-                                       XplatUI.SetWindowTransparency(Handle, opacity, TransparencyKey);
+                                       if ((XplatUI.SupportsTransparency () & TransparencySupport.Set) != 0)
+                                               XplatUI.SetWindowTransparency(Handle, opacity, TransparencyKey);
                                }
                        }
                }
@@ -1400,7 +1406,7 @@ namespace System.Windows.Forms {
 
                        UpdateBounds();
 
-                       if (XplatUI.SupportsTransparency()) {
+                       if ((XplatUI.SupportsTransparency() & TransparencySupport.Set) != 0) {
                                if (allow_transparency) {
                                        XplatUI.SetWindowTransparency(Handle, Opacity, TransparencyKey);
                                }
index 52bdd44e763e5de0771eb765f1845fac75379b23..f4228970f97e5ebf44a2d6c5cca039662fe40e3f 100644 (file)
@@ -869,6 +869,14 @@ namespace System.Windows.Forms {
                        driver.SetWindowStyle(handle, cp);
                }
 
+               internal static double GetWindowTransparency (IntPtr handle)
+               {
+                       #if DriverDebug
+                               Console.WriteLine("SetWindowTransparency({0}): Called", Window(handle));
+                       #endif
+                       return driver.GetWindowTransparency(handle);
+               }
+
                internal static void SetWindowTransparency(IntPtr handle, double transparency, Color key) 
                {
                        #if DriverDebug
@@ -905,7 +913,7 @@ namespace System.Windows.Forms {
                        return driver.StartLoop(thread);
                }
 
-               internal static bool SupportsTransparency() {
+               internal static TransparencySupport SupportsTransparency() {
                        #if DriverDebug
                                Console.WriteLine("SupportsTransparency(): Called, result={0}", driver.SupportsTransparency());
                        #endif
index d067ea300582e8e08d0feaaa7f9ebfb6194c9362..129248b44a68acfa823471ac441d9348634ae3ea 100644 (file)
@@ -159,8 +159,9 @@ namespace System.Windows.Forms {
 
                internal abstract void SetWindowStyle(IntPtr handle, CreateParams cp);
 
+               internal abstract double GetWindowTransparency(IntPtr handle);
                internal abstract void SetWindowTransparency(IntPtr handle, double transparency, Color key);
-               internal abstract bool SupportsTransparency();
+               internal abstract TransparencySupport SupportsTransparency();
 
                internal virtual void SetAllowDrop (IntPtr handle, bool value)
                {
index a45d77f28475755d74413b505304316b578a8586..7b60d5f17ba98d119092b3dfcbce856caff5a054 100644 (file)
@@ -1709,8 +1709,13 @@ namespace System.Windows.Forms {
                internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
                }
 
-               internal override bool SupportsTransparency() {
-                       return false;
+               internal override double GetWindowTransparency(IntPtr handle)
+               {
+                       return 1.0;
+               }
+
+               internal override TransparencySupport SupportsTransparency() {
+                       return TransparencySupport.None;
                }
                
                internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool Top, bool Bottom) {
index c4701a0ab2479727fb98cdc459f6cd277a4bf002..9c456737593cae58a8fadae17e485d2b47762245 100644 (file)
@@ -427,6 +427,14 @@ namespace System.Windows.Forms {
                internal object refobject;
        }
 
+       [Flags]
+       internal enum TransparencySupport {
+               None = 0x00,
+               Get = 0x01,
+               Set = 0x02,
+               GetSet = 0x03
+       }
+
        internal enum WindowActiveFlags {
                WA_INACTIVE             = 0,
                WA_ACTIVE               = 1,
index 1c315c3adfa4511decbae907d918f9a90b3a26d2..6fd134b5259ddcf92e24c83516fd855e8ec4586f 100644 (file)
@@ -1213,7 +1213,17 @@ namespace System.Windows.Forms {
                        Win32SetWindowLong(handle, WindowLong.GWL_EXSTYLE, (uint)cp.ExStyle);
                }
 
-               
+               internal override double GetWindowTransparency(IntPtr handle)
+               {
+                       LayeredWindowAttributes lwa;
+                       COLORREF clrRef;
+                       byte alpha;
+
+                       Win32GetLayeredWindowAttributes (handle, out clrRef, out alpha, out lwa);
+
+                       return ((double)alpha) / 255.0;
+               }
+
                internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
                        LayeredWindowAttributes lwa = LayeredWindowAttributes.LWA_ALPHA;
                        byte opacity = (byte)(transparency*255);
@@ -1230,9 +1240,39 @@ namespace System.Windows.Forms {
                        Win32SetLayeredWindowAttributes(handle, clrRef, opacity, lwa);
                }
 
-               internal override bool SupportsTransparency() {
-                       // We might check with the OS, but I think we're only >=W2k
-                       return true;
+               TransparencySupport support;
+               bool queried_transparency_support;
+               internal override TransparencySupport SupportsTransparency() {
+                       if (queried_transparency_support)
+                               return support;
+
+                       bool flag;
+                       support = TransparencySupport.None;
+
+                       flag = true;
+                       try {
+                               Win32SetLayeredWindowAttributes (IntPtr.Zero, new COLORREF (), 255, LayeredWindowAttributes.LWA_ALPHA);
+                       }
+                       catch (EntryPointNotFoundException) { flag = false; }
+                       catch { /* swallow everything else */ }
+
+                       if (flag) support |= TransparencySupport.Set;
+
+                       flag = true;
+                       try {
+                               LayeredWindowAttributes lwa;
+                               COLORREF clrRef;
+                               byte alpha;
+
+                               Win32GetLayeredWindowAttributes (IntPtr.Zero, out clrRef, out alpha, out lwa);
+                       }
+                       catch (EntryPointNotFoundException) { flag = false; }
+                       catch { /* swallow everything else */ }
+
+                       if (flag) support |= TransparencySupport.Get;
+
+                       queried_transparency_support = true;
+                       return support;
                }
 
                internal override void UpdateWindow(IntPtr handle) {
@@ -2578,6 +2618,9 @@ namespace System.Windows.Forms {
                [DllImport ("user32.dll", EntryPoint="SetLayeredWindowAttributes", CallingConvention=CallingConvention.StdCall)]
                private extern static uint Win32SetLayeredWindowAttributes (IntPtr hwnd, COLORREF crKey, byte bAlpha, LayeredWindowAttributes dwFlags);
 
+               [DllImport ("user32.dll", EntryPoint="GetLayeredWindowAttributes", CallingConvention=CallingConvention.StdCall)]
+               private extern static uint Win32GetLayeredWindowAttributes (IntPtr hwnd, out COLORREF pcrKey, out byte pbAlpha, out LayeredWindowAttributes pwdFlags);
+
                [DllImport ("gdi32.dll", EntryPoint="DeleteObject", CallingConvention=CallingConvention.StdCall)]
                private extern static bool Win32DeleteObject(IntPtr o);
 
index 0996560542a0dba691519086ed65f00a92820a0b..f7f86aa202cf0f00a55ff39a15fa1696a10120af 100644 (file)
@@ -4841,6 +4841,11 @@ namespace System.Windows.Forms {
                        SetWMStyles(hwnd, cp);
                }
 
+               internal override double GetWindowTransparency(IntPtr handle)
+               {
+                       return 1.0;
+               }
+
                internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
                        Hwnd    hwnd;
                        IntPtr  opacity;
@@ -4919,9 +4924,9 @@ namespace System.Windows.Forms {
                        return (Object) ThreadQueue(thread);
                }
 
-               internal override bool SupportsTransparency() {
+               internal override TransparencySupport SupportsTransparency() {
                        // We need to check if the x compositing manager is running
-                       return true;
+                       return TransparencySupport.Set;
                }
 
                internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {