135
135
Gdk.Rectangle geometry = Screen.GetUsableMonitorGeometry (Screen.GetMonitorAtPoint (x, y));
136
136
if (nudgeHorizontal) {
137
if (allocation.Width <= geometry.Width && x + allocation.Width >= geometry.Width - edgeGap)
138
x = geometry.Left + (geometry.Width - allocation.Height - edgeGap);
139
if (x <= geometry.Left)
137
if (allocation.Width <= geometry.Width && x + allocation.Width >= geometry.Left + geometry.Width - edgeGap)
138
x = geometry.Left + (geometry.Width - allocation.Width - edgeGap);
139
if (x <= geometry.Left + edgeGap)
140
x = geometry.Left + edgeGap;
143
143
if (nudgeVertical) {
144
if (allocation.Height <= geometry.Height && y + allocation.Height >= geometry.Height - edgeGap)
144
if (allocation.Height <= geometry.Height && y + allocation.Height >= geometry.Top + geometry.Height - edgeGap)
145
145
y = geometry.Top + (geometry.Height - allocation.Height - edgeGap);
146
if (y <= geometry.Top)
146
if (y <= geometry.Top + edgeGap)
147
y = geometry.Top + edgeGap;
150
150
if (y != oldY || x != oldX)
446
public class WindowTransparencyDecorator
449
bool semiTransparent;
450
bool snooperInstalled;
452
const double opacity = 0.2;
455
WindowTransparencyDecorator (Gtk.Window window)
457
this.window = window;
458
//HACK: Workaround for GTK# crasher bug where GC collects internal wrapper delegates
459
snoopFunc = TryBindGtkInternals (this);
461
if (snoopFunc != null) {
462
window.Shown += ShownHandler;
463
window.Hidden += HiddenHandler;
464
window.Destroyed += DestroyedHandler;
471
public static WindowTransparencyDecorator Attach (Gtk.Window window)
473
return new WindowTransparencyDecorator (window);
476
public void Detach ()
482
HiddenHandler (null, null);
484
//annul allreferences between this and the window
485
window.Shown -= ShownHandler;
486
window.Hidden -= HiddenHandler;
487
window.Destroyed -= DestroyedHandler;
492
void ShownHandler (object sender, EventArgs args)
494
if (!snooperInstalled)
495
snooperID = InstallSnooper (snoopFunc);
496
snooperInstalled = true;
498
//NOTE: we unset transparency when showing, instead of when hiding
499
//because the latter case triggers a metacity+compositing bug that shows the window again
500
SemiTransparent = false;
503
void HiddenHandler (object sender, EventArgs args)
505
if (snooperInstalled)
506
RemoveSnooper (snooperID);
507
snooperInstalled = false;
510
void DestroyedHandler (object sender, EventArgs args)
515
#pragma warning disable 0169
517
int TransparencyKeySnooper (IntPtr widget, IntPtr rawEvnt, IntPtr data)
519
if (rawEvnt != IntPtr.Zero) {
520
Gdk.EventKey evnt = new Gdk.EventKey (rawEvnt);
521
if (evnt != null && evnt.Key == Gdk.Key.Control_L || evnt.Key == Gdk.Key.Control_R)
522
SemiTransparent = (evnt.Type == Gdk.EventType.KeyPress);
524
return 0; //gboolean FALSE
527
#pragma warning restore 0169
529
bool SemiTransparent {
531
if (semiTransparent != value) {
532
semiTransparent = value;
533
window.Opacity = semiTransparent? opacity : 1.0;
538
#region Workaround for GTK# crasher bug where GC collects internal wrapper delegates
540
static WindowTransparencyDecorator ()
542
snooper_install = typeof (Gtk.Key).GetMethod ("gtk_key_snooper_install", BindingFlags.NonPublic | BindingFlags.Static);
543
snooper_remove = typeof (Gtk.Key).GetMethod ("gtk_key_snooper_remove", BindingFlags.NonPublic | BindingFlags.Static);
546
static MethodInfo snooper_install;
547
static MethodInfo snooper_remove;
549
delegate int GtkKeySnoopFunc (IntPtr widget, IntPtr rawEvnt, IntPtr func_data);
551
static uint InstallSnooper (Delegate del)
553
return (uint) snooper_install.Invoke (null, new object[] { del, IntPtr.Zero} );
556
static void RemoveSnooper (uint id)
558
snooper_remove.Invoke (null, new object[] { id });
561
static bool internalBindingWorks = true;
562
static bool internalBindingTried = false;
564
static Delegate TryBindGtkInternals (WindowTransparencyDecorator instance)
566
if (internalBindingTried) {
567
if (!internalBindingWorks)
570
internalBindingTried = true;
574
Type delType = typeof(Gtk.Widget).Assembly.GetType ("GtkSharp.KeySnoopFuncNative");
575
System.Reflection.MethodInfo met = typeof (WindowTransparencyDecorator).GetMethod ("TransparencyKeySnooper",
576
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
577
Delegate ret = Delegate.CreateDelegate (delType, instance, met);
582
internalBindingWorks = false;
583
Console.WriteLine ("GTK# API has changed, and control-transparency will not be available for popups");