2
// WindowTransparencyDecorator.cs
5
// Michael Hutchinson <mhutchinson@novell.com>
7
// Based on code derived from Banshee.Widgets.EllipsizeLabel
8
// by Aaron Bockover (aaron@aaronbock.net)
10
// Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
12
// Permission is hereby granted, free of charge, to any person obtaining
13
// a copy of this software and associated documentation files (the
14
// "Software"), to deal in the Software without restriction, including
15
// without limitation the rights to use, copy, modify, merge, publish,
16
// distribute, sublicense, and/or sell copies of the Software, and to
17
// permit persons to whom the Software is furnished to do so, subject to
18
// the following conditions:
20
// The above copyright notice and this permission notice shall be
21
// included in all copies or substantial portions of the Software.
23
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
using System.Reflection;
34
using System.Runtime.InteropServices;
36
namespace MonoDevelop.Components
38
public class WindowTransparencyDecorator
42
bool snooperInstalled;
44
const double opacity = 0.2;
47
WindowTransparencyDecorator (Gtk.Window window)
50
//HACK: Workaround for GTK# crasher bug where GC collects internal wrapper delegates
51
snoopFunc = TryBindGtkInternals (this);
53
if (snoopFunc != null) {
54
window.Shown += ShownHandler;
55
window.Hidden += HiddenHandler;
56
window.Destroyed += DestroyedHandler;
63
public static WindowTransparencyDecorator Attach (Gtk.Window window)
65
return new WindowTransparencyDecorator (window);
74
HiddenHandler (null, null);
76
//annul allreferences between this and the window
77
window.Shown -= ShownHandler;
78
window.Hidden -= HiddenHandler;
79
window.Destroyed -= DestroyedHandler;
84
void ShownHandler (object sender, EventArgs args)
86
if (!snooperInstalled)
87
snooperID = InstallSnooper (snoopFunc);
88
snooperInstalled = true;
90
//NOTE: we unset transparency when showing, instead of when hiding
91
//because the latter case triggers a metacity+compositing bug that shows the window again
92
SemiTransparent = false;
95
void HiddenHandler (object sender, EventArgs args)
98
RemoveSnooper (snooperID);
99
snooperInstalled = false;
102
void DestroyedHandler (object sender, EventArgs args)
107
#pragma warning disable 0169
109
int TransparencyKeySnooper (IntPtr widget, IntPtr rawEvnt, IntPtr data)
111
if (rawEvnt != IntPtr.Zero) {
112
Gdk.EventKey evnt = new Gdk.EventKey (rawEvnt);
113
if (evnt != null && evnt.Key == Gdk.Key.Control_L || evnt.Key == Gdk.Key.Control_R)
114
SemiTransparent = (evnt.Type == Gdk.EventType.KeyPress);
116
return 0; //gboolean FALSE
119
#pragma warning restore 0169
121
bool SemiTransparent {
123
if (semiTransparent != value) {
124
semiTransparent = value;
125
window.Opacity = semiTransparent? opacity : 1.0;
130
#region Workaround for GTK# crasher bug where GC collects internal wrapper delegates
132
static WindowTransparencyDecorator ()
134
snooper_install = typeof (Gtk.Key).GetMethod ("gtk_key_snooper_install", BindingFlags.NonPublic | BindingFlags.Static);
135
snooper_remove = typeof (Gtk.Key).GetMethod ("gtk_key_snooper_remove", BindingFlags.NonPublic | BindingFlags.Static);
138
static MethodInfo snooper_install;
139
static MethodInfo snooper_remove;
141
delegate int GtkKeySnoopFunc (IntPtr widget, IntPtr rawEvnt, IntPtr func_data);
143
static uint InstallSnooper (Delegate del)
145
return (uint) snooper_install.Invoke (null, new object[] { del, IntPtr.Zero} );
148
static void RemoveSnooper (uint id)
150
snooper_remove.Invoke (null, new object[] { id });
153
static bool internalBindingWorks = true;
154
static bool internalBindingTried = false;
156
static Delegate TryBindGtkInternals (WindowTransparencyDecorator instance)
158
if (internalBindingTried) {
159
if (!internalBindingWorks)
162
internalBindingTried = true;
166
Type delType = typeof(Gtk.Widget).Assembly.GetType ("GtkSharp.KeySnoopFuncNative");
167
System.Reflection.MethodInfo met = typeof (WindowTransparencyDecorator).GetMethod ("TransparencyKeySnooper",
168
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
169
Delegate ret = Delegate.CreateDelegate (delType, instance, met);
174
internalBindingWorks = false;
175
MonoDevelop.Core.LoggingService.LogWarning ("GTK# API has changed, and control-transparency will not be available for popups");