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

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs252
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs1275
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs136
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs292
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs260
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs116
25 files changed, 2360 insertions, 25 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
index 0b948cd7d0..3a21270833 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
@@ -33,7 +33,6 @@ using System.Runtime.InteropServices;
using Gdk;
using Cairo;
using MonoDevelop.Core;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
index aef0dcf873..e6f0c23f4b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
index 52607bf131..035a36cb79 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
@@ -50,7 +50,7 @@ namespace MonoDevelop.Components
if (menu == null)
throw new ArgumentNullException ("menu");
- Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, evt);
+ GtkWorkarounds.ShowContextMenu (menu, parent, evt);
}
static Gtk.MenuItem CreateMenuItem (ContextMenuItem item)
@@ -93,7 +93,7 @@ namespace MonoDevelop.Components
var img = new ImageView (item.Image);
img.ShowAll ();
imageItem.Image = img;
- GtkWorkarounds.ForceImageOnMenuItem (imageItem);
+ Xwt.GtkBackend.GtkWorkarounds.ForceImageOnMenuItem (imageItem);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
index a0e32d669e..c6ea099579 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
@@ -24,7 +24,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
index dda73fc351..2cd9d466c5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
@@ -43,6 +43,8 @@ namespace MonoDevelop.Components
public Control (object widget)
{
+ if (widget == null)
+ throw new ArgumentNullException ("widget");
this.nativeWidget = widget;
}
@@ -63,7 +65,9 @@ namespace MonoDevelop.Components
if (!(w is T))
w = ConvertToType (typeof(T), w);
if (w is Gtk.Widget) {
- var c = new CommandRouterContainer ((Gtk.Widget)w, this, true);
+ var gtkWidget = (Gtk.Widget)w;
+ var c = new CommandRouterContainer (gtkWidget, this, true);
+ c.FocusChain = new [] { gtkWidget };
c.Show ();
nativeWidget = c;
c.Destroyed += delegate {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
index 1f02fdce8a..df6e49c424 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
@@ -29,7 +29,6 @@ using System.ComponentModel;
using Gtk;
using MonoDevelop.Ide;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs
new file mode 100644
index 0000000000..a819fc0f74
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs
@@ -0,0 +1,252 @@
+//
+// GtkGestures.cs
+//
+// Author:
+// Michael Hutchinson <mhutch@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+using Gdk;
+
+namespace MonoDevelop.Components
+{
+ public static class GtkGestures
+ {
+ const int GDK_GESTURE_MAGNIFY = 37;
+ const int GDK_GESTURE_ROTATE = 38;
+ const int GDK_GESTURE_SWIPE = 39;
+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern bool gdk_quartz_supports_gesture_events ();
+
+ static bool isSupported;
+
+ static GtkGestures ()
+ {
+ if (MonoDevelop.Core.Platform.IsMac) {
+ try {
+ isSupported = gdk_quartz_supports_gesture_events ();
+ } catch (EntryPointNotFoundException) {
+ }
+ }
+ }
+
+ public static bool IsSupported { get { return isSupported; } }
+
+ public static void AddGestureMagnifyHandler (this Gtk.Widget widget, EventHandler<GestureMagnifyEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-magnify-event", typeof(GestureMagnifyEventArgs));
+ signal.AddDelegate (new EventHandler<GestureMagnifyEventArgs> (handler));
+ }
+
+ public static void AddGestureRotateHandler (this Gtk.Widget widget, EventHandler<GestureRotateEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-rotate-event", typeof(GestureRotateEventArgs));
+ signal.AddDelegate (new EventHandler<GestureRotateEventArgs> (handler));
+ }
+
+ public static void AddGestureSwipeHandler (this Gtk.Widget widget, EventHandler<GestureSwipeEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-swipe-event", typeof(GestureSwipeEventArgs));
+ signal.AddDelegate (new EventHandler<GestureSwipeEventArgs> (handler));
+ }
+ }
+
+ public unsafe class GestureMagnifyEventArgs : GLib.SignalArgs
+ {
+ //have to force pack=4, or Mono aligns doubles to 8 bytes
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureMagnify
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double magnification;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ // I tried to mimic the GTK# pattern of having a subclassed Event object on the EventArgs, but I gave up on
+ // figuring out how to get GTK# to marshal the event to a custom GestureMagnifyEvent class. Instead we just
+ // lift all the accessors up to the args class and dereference the handle directly.
+ GdkEventGestureMagnify *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureMagnify *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double Magnification { get { return evt->magnification; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ public unsafe class GestureRotateEventArgs : GLib.SignalArgs
+ {
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureRotate
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double rotation;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ GdkEventGestureRotate *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureRotate *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double Rotation { get { return evt->rotation; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ public unsafe class GestureSwipeEventArgs : GLib.SignalArgs
+ {
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureSwipe
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double delta_x, delta_y;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ GdkEventGestureSwipe *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureSwipe *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double DeltaX { get { return evt->delta_x; } }
+ public double DeltaY { get { return evt->delta_y; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ /*
+ void PrintOffsets ()
+ {
+ GdkEventGestureMagnify *v = (GdkEventGestureMagnify *)0;
+ Console.WriteLine ("type {0}", (int)&(v->type));
+ Console.WriteLine ("window {0}", (int)&(v->window));
+ Console.WriteLine ("send_event {0}", (int)&(v->send_event));
+ Console.WriteLine ("time {0}", (int)&(v->time));
+ Console.WriteLine ("x {0}", (int)&(v->x));
+ Console.WriteLine ("y {0}", (int)&(v->y));
+ Console.WriteLine ("state {0}", (int)&(v->state));
+ Console.WriteLine ("magnification {0}", (int)&(v->magnification));
+ Console.WriteLine ("x_root {0}", (int)&(v->x_root));
+ Console.WriteLine ("y_root {0}", (int)&(v->y_root));
+ }
+
+ // gcc -m32 test.c `pkg-config --cflags gtk+-2.0`
+ #include <gtk/gtk.h>
+
+ int main (int argc, char* argv)
+ {
+ GdkEventGestureMagnify *v = (GdkEventGestureMagnify *)0;
+ printf ("type %d\n", (int)&(v->type));
+ printf ("window %d\n", (int)&(v->window));
+ printf ("send_event %d\n", (int)&(v->send_event));
+ printf ("time %d\n", (int)&(v->time));
+ printf ("x %d\n", (int)&(v->x));
+ printf ("y %d\n", (int)&(v->y));
+ printf ("state %d\n", (int)&(v->state));
+ printf ("magnification %d\n", (int)&(v->magnification));
+ printf ("x_root %d\n", (int)&(v->x_root));
+ printf ("y_root %d\n", (int)&(v->y_root));
+ }
+ */
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
index 5818c33e5b..a083d352f2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
@@ -88,6 +88,19 @@ namespace MonoDevelop.Components
return c.ToGdkColor ();
}
+ /// <summary>
+ /// Makes a color lighter or darker
+ /// </summary>
+ /// <param name='lightAmount'>
+ /// Amount of lightness to add. If the value is positive, the color will be lighter,
+ /// if negative it will be darker. Value must be between 0 and 1.
+ /// </param>
+ public static HslColor AddLight (this HslColor color, double lightAmount)
+ {
+ color.L += lightAmount;
+ return color;
+ }
+
public static Cairo.Color AddLight (this Cairo.Color color, double lightAmount)
{
var c = color.ToXwtColor ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
new file mode 100644
index 0000000000..398ae0e0e9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
@@ -0,0 +1,1275 @@
+//
+// GtkWorkarounds.cs
+//
+// Authors: Jeffrey Stedfast <jeff@xamarin.com>
+//
+// Copyright (C) 2011 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using Gtk;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor.Highlighting;
+using System.Text.RegularExpressions;
+
+namespace MonoDevelop.Components
+{
+ public static class GtkWorkarounds
+ {
+ const string LIBOBJC ="/usr/lib/libobjc.dylib";
+ const string USER32DLL = "User32.dll";
+
+ [DllImport (LIBOBJC, EntryPoint = "sel_registerName")]
+ static extern IntPtr sel_registerName (string selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_getClass")]
+ static extern IntPtr objc_getClass (string klass);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern IntPtr objc_msgSend_IntPtr (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern void objc_msgSend_void_bool (IntPtr klass, IntPtr selector, bool arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern bool objc_msgSend_bool (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern int objc_msgSend_NSInt32_NSInt32 (IntPtr klass, IntPtr selector, int arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern long objc_msgSend_NSInt64_NSInt64 (IntPtr klass, IntPtr selector, long arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern uint objc_msgSend_NSUInt32 (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern ulong objc_msgSend_NSUInt64 (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend_stret")]
+ static extern void objc_msgSend_CGRect32 (out CGRect32 rect, IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend_stret")]
+ static extern void objc_msgSend_CGRect64 (out CGRect64 rect, IntPtr klass, IntPtr selector);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern IntPtr gdk_quartz_window_get_nswindow (IntPtr window);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern bool gdk_window_has_embedded_nsview_focus (IntPtr window);
+
+ struct CGRect32
+ {
+ public float X, Y, Width, Height;
+ }
+
+ struct CGRect64
+ {
+ public double X, Y, Width, Height;
+
+ public CGRect64 (CGRect32 rect32)
+ {
+ X = rect32.X;
+ Y = rect32.Y;
+ Width = rect32.Width;
+ Height = rect32.Height;
+ }
+ }
+
+ static IntPtr cls_NSScreen;
+ static IntPtr sel_screens, sel_objectEnumerator, sel_nextObject, sel_frame, sel_visibleFrame,
+ sel_requestUserAttention, sel_setHasShadow, sel_invalidateShadow;
+ static IntPtr sharedApp;
+ static IntPtr cls_NSEvent;
+ static IntPtr sel_modifierFlags;
+
+ const int NSCriticalRequest = 0;
+ const int NSInformationalRequest = 10;
+
+ static System.Reflection.MethodInfo glibObjectGetProp, glibObjectSetProp;
+
+ public static int GtkMinorVersion = 12, GtkMicroVersion = 0;
+ static bool oldMacKeyHacks = false;
+
+ static GtkWorkarounds ()
+ {
+ if (Platform.IsMac) {
+ InitMac ();
+ }
+
+ var flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
+ glibObjectSetProp = typeof (GLib.Object).GetMethod ("SetProperty", flags);
+ glibObjectGetProp = typeof (GLib.Object).GetMethod ("GetProperty", flags);
+
+ foreach (int i in new [] { 24, 22, 20, 18, 16, 14 }) {
+ if (Gtk.Global.CheckVersion (2, (uint)i, 0) == null) {
+ GtkMinorVersion = i;
+ break;
+ }
+ }
+
+ for (int i = 1; i < 20; i++) {
+ if (Gtk.Global.CheckVersion (2, (uint)GtkMinorVersion, (uint)i) == null) {
+ GtkMicroVersion = i;
+ } else {
+ break;
+ }
+ }
+
+ //opt into the fixes on GTK+ >= 2.24.8
+ if (Platform.IsMac) {
+ try {
+ gdk_quartz_set_fix_modifiers (true);
+ } catch (EntryPointNotFoundException) {
+ oldMacKeyHacks = true;
+ }
+ }
+
+ keymap.KeysChanged += delegate {
+ mappedKeys.Clear ();
+ };
+ }
+
+ static void InitMac ()
+ {
+ cls_NSScreen = objc_getClass ("NSScreen");
+ cls_NSEvent = objc_getClass ("NSEvent");
+ sel_screens = sel_registerName ("screens");
+ sel_objectEnumerator = sel_registerName ("objectEnumerator");
+ sel_nextObject = sel_registerName ("nextObject");
+ sel_visibleFrame = sel_registerName ("visibleFrame");
+ sel_frame = sel_registerName ("frame");
+ sel_requestUserAttention = sel_registerName ("requestUserAttention:");
+ sel_modifierFlags = sel_registerName ("modifierFlags");
+ sel_setHasShadow = sel_registerName ("setHasShadow:");
+ sel_invalidateShadow = sel_registerName ("invalidateShadow");
+ sharedApp = objc_msgSend_IntPtr (objc_getClass ("NSApplication"), sel_registerName ("sharedApplication"));
+ }
+
+ static Gdk.Rectangle MacGetUsableMonitorGeometry (Gdk.Screen screen, int monitor)
+ {
+ IntPtr array = objc_msgSend_IntPtr (cls_NSScreen, sel_screens);
+ IntPtr iter = objc_msgSend_IntPtr (array, sel_objectEnumerator);
+ Gdk.Rectangle ygeometry = screen.GetMonitorGeometry (monitor);
+ Gdk.Rectangle xgeometry = screen.GetMonitorGeometry (0);
+ IntPtr scrn;
+ int i = 0;
+
+ while ((scrn = objc_msgSend_IntPtr (iter, sel_nextObject)) != IntPtr.Zero && i < monitor)
+ i++;
+
+ if (scrn == IntPtr.Zero)
+ return screen.GetMonitorGeometry (monitor);
+
+ CGRect64 visible, frame;
+
+ if (IntPtr.Size == 8) {
+ objc_msgSend_CGRect64 (out visible, scrn, sel_visibleFrame);
+ objc_msgSend_CGRect64 (out frame, scrn, sel_frame);
+ } else {
+ CGRect32 visible32, frame32;
+ objc_msgSend_CGRect32 (out visible32, scrn, sel_visibleFrame);
+ objc_msgSend_CGRect32 (out frame32, scrn, sel_frame);
+ visible = new CGRect64 (visible32);
+ frame = new CGRect64 (frame32);
+ }
+
+ // Note: Frame and VisibleFrame rectangles are relative to monitor 0, but we need absolute
+ // coordinates.
+ visible.X += xgeometry.X;
+ frame.X += xgeometry.X;
+
+ // VisibleFrame.Y is the height of the Dock if it is at the bottom of the screen, so in order
+ // to get the menu height, we just figure out the difference between the visibleFrame height
+ // and the actual frame height, then subtract the Dock height.
+ //
+ // We need to swap the Y offset with the menu height because our callers expect the Y offset
+ // to be from the top of the screen, not from the bottom of the screen.
+ double x, y, width, height;
+
+ if (visible.Height < frame.Height) {
+ double dockHeight = visible.Y - frame.Y;
+ double menubarHeight = (frame.Height - visible.Height) - dockHeight;
+
+ height = frame.Height - menubarHeight - dockHeight;
+ y = ygeometry.Y + menubarHeight;
+ } else {
+ height = frame.Height;
+ y = ygeometry.Y;
+ }
+
+ // Takes care of the possibility of the Dock being positioned on the left or right edge of the screen.
+ width = System.Math.Min (visible.Width, frame.Width);
+ x = System.Math.Max (visible.X, frame.X);
+
+ return new Gdk.Rectangle ((int) x, (int) y, (int) width, (int) height);
+ }
+
+ static void MacRequestAttention (bool critical)
+ {
+ int kind = critical? NSCriticalRequest : NSInformationalRequest;
+ if (IntPtr.Size == 8) {
+ objc_msgSend_NSInt64_NSInt64 (sharedApp, sel_requestUserAttention, kind);
+ } else {
+ objc_msgSend_NSInt32_NSInt32 (sharedApp, sel_requestUserAttention, kind);
+ }
+ }
+
+ // Note: we can't reuse RectangleF because the layout is different...
+ [StructLayout (LayoutKind.Sequential)]
+ struct Rect {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public int X { get { return Left; } }
+ public int Y { get { return Top; } }
+ public int Width { get { return Right - Left; } }
+ public int Height { get { return Bottom - Top; } }
+ }
+
+ const int MonitorInfoFlagsPrimary = 0x01;
+
+ [StructLayout (LayoutKind.Sequential)]
+ unsafe struct MonitorInfo {
+ public int Size;
+ public Rect Frame; // Monitor
+ public Rect VisibleFrame; // Work
+ public int Flags;
+ public fixed byte Device[32];
+ }
+
+ [UnmanagedFunctionPointer (CallingConvention.Winapi)]
+ delegate int EnumMonitorsCallback (IntPtr hmonitor, IntPtr hdc, IntPtr prect, IntPtr user_data);
+
+ [DllImport (USER32DLL)]
+ extern static int EnumDisplayMonitors (IntPtr hdc, IntPtr clip, EnumMonitorsCallback callback, IntPtr user_data);
+
+ [DllImport (USER32DLL)]
+ extern static int GetMonitorInfoA (IntPtr hmonitor, ref MonitorInfo info);
+
+ static Gdk.Rectangle WindowsGetUsableMonitorGeometry (Gdk.Screen screen, int monitor_id)
+ {
+ Gdk.Rectangle geometry = screen.GetMonitorGeometry (monitor_id);
+ List<MonitorInfo> screens = new List<MonitorInfo> ();
+
+ EnumDisplayMonitors (IntPtr.Zero, IntPtr.Zero, delegate (IntPtr hmonitor, IntPtr hdc, IntPtr prect, IntPtr user_data) {
+ var info = new MonitorInfo ();
+
+ unsafe {
+ info.Size = sizeof (MonitorInfo);
+ }
+
+ GetMonitorInfoA (hmonitor, ref info);
+
+ // In order to keep the order the same as Gtk, we need to put the primary monitor at the beginning.
+ if ((info.Flags & MonitorInfoFlagsPrimary) != 0)
+ screens.Insert (0, info);
+ else
+ screens.Add (info);
+
+ return 1;
+ }, IntPtr.Zero);
+
+ MonitorInfo monitor = screens[monitor_id];
+ Rect visible = monitor.VisibleFrame;
+ Rect frame = monitor.Frame;
+
+ // Rebase the VisibleFrame off of Gtk's idea of this monitor's geometry (since they use different coordinate systems)
+ int x = geometry.X + (visible.Left - frame.Left);
+ int width = visible.Width;
+
+ int y = geometry.Y + (visible.Top - frame.Top);
+ int height = visible.Height;
+
+ return new Gdk.Rectangle (x, y, width, height);
+ }
+
+ public static Gdk.Rectangle GetUsableMonitorGeometry (this Gdk.Screen screen, int monitor)
+ {
+ if (Platform.IsWindows)
+ return WindowsGetUsableMonitorGeometry (screen, monitor);
+
+ if (Platform.IsMac)
+ return MacGetUsableMonitorGeometry (screen, monitor);
+
+ return screen.GetMonitorGeometry (monitor);
+ }
+
+ public static int RunDialogWithNotification (Gtk.Dialog dialog)
+ {
+ if (Platform.IsMac)
+ MacRequestAttention (dialog.Modal);
+
+ return dialog.Run ();
+ }
+
+ public static void PresentWindowWithNotification (this Gtk.Window window)
+ {
+ window.Present ();
+
+ if (Platform.IsMac) {
+ var dialog = window as Gtk.Dialog;
+ MacRequestAttention (dialog == null? false : dialog.Modal);
+ }
+ }
+
+ public static GLib.Value GetProperty (this GLib.Object obj, string name)
+ {
+ return (GLib.Value) glibObjectGetProp.Invoke (obj, new object[] { name });
+ }
+
+ public static void SetProperty (this GLib.Object obj, string name, GLib.Value value)
+ {
+ glibObjectSetProp.Invoke (obj, new object[] { name, value });
+ }
+
+ public static bool TriggersContextMenu (this Gdk.EventButton evt)
+ {
+ return evt.Type == Gdk.EventType.ButtonPress && IsContextMenuButton (evt);
+ }
+
+ public static bool IsContextMenuButton (this Gdk.EventButton evt)
+ {
+ if (evt.Button == 3 &&
+ (evt.State & (Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button2Mask)) == 0)
+ return true;
+
+ if (Platform.IsMac) {
+ if (!oldMacKeyHacks &&
+ evt.Button == 1 &&
+ (evt.State & Gdk.ModifierType.ControlMask) != 0 &&
+ (evt.State & (Gdk.ModifierType.Button2Mask | Gdk.ModifierType.Button3Mask)) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static Gdk.ModifierType GetCurrentKeyModifiers ()
+ {
+ if (Platform.IsMac) {
+ Gdk.ModifierType mtype = Gdk.ModifierType.None;
+ ulong mod;
+ if (IntPtr.Size == 8) {
+ mod = objc_msgSend_NSUInt64 (cls_NSEvent, sel_modifierFlags);
+ } else {
+ mod = objc_msgSend_NSUInt32 (cls_NSEvent, sel_modifierFlags);
+ }
+ if ((mod & (1 << 17)) != 0)
+ mtype |= Gdk.ModifierType.ShiftMask;
+ if ((mod & (1 << 18)) != 0)
+ mtype |= Gdk.ModifierType.ControlMask;
+ if ((mod & (1 << 19)) != 0)
+ mtype |= Gdk.ModifierType.Mod1Mask; // Alt key
+ if ((mod & (1 << 20)) != 0)
+ mtype |= Gdk.ModifierType.Mod2Mask; // Command key
+ return mtype;
+ }
+ else {
+ Gdk.ModifierType mtype;
+ Gtk.Global.GetCurrentEventState (out mtype);
+ return mtype;
+ }
+ }
+
+ public static void GetPageScrollPixelDeltas (this Gdk.EventScroll evt, double pageSizeX, double pageSizeY,
+ out double deltaX, out double deltaY)
+ {
+ if (!GetEventScrollDeltas (evt, out deltaX, out deltaY)) {
+ var direction = evt.Direction;
+ deltaX = deltaY = 0;
+ if (pageSizeY != 0 && (direction == Gdk.ScrollDirection.Down || direction == Gdk.ScrollDirection.Up)) {
+ deltaY = System.Math.Pow (pageSizeY, 2.0 / 3.0);
+ deltaX = 0.0;
+ if (direction == Gdk.ScrollDirection.Up)
+ deltaY = -deltaY;
+ } else if (pageSizeX != 0) {
+ deltaX = System.Math.Pow (pageSizeX, 2.0 / 3.0);
+ deltaY = 0.0;
+ if (direction == Gdk.ScrollDirection.Left)
+ deltaX = -deltaX;
+ }
+ }
+ }
+
+ public static void AddValueClamped (this Gtk.Adjustment adj, double value)
+ {
+ adj.Value = System.Math.Max (adj.Lower, System.Math.Min (adj.Value + value, adj.Upper - adj.PageSize));
+ }
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_event_get_scroll_deltas (IntPtr eventScroll, out double deltaX, out double deltaY);
+ static bool scrollDeltasNotSupported;
+
+ public static bool GetEventScrollDeltas (Gdk.EventScroll evt, out double deltaX, out double deltaY)
+ {
+ if (!scrollDeltasNotSupported) {
+ try {
+ return gdk_event_get_scroll_deltas (evt.Handle, out deltaX, out deltaY);
+ } catch (EntryPointNotFoundException) {
+ scrollDeltasNotSupported = true;
+ }
+ }
+ deltaX = deltaY = 0;
+ return false;
+ }
+
+ /// <summary>Shows a context menu.</summary>
+ /// <param name='menu'>The menu.</param>
+ /// <param name='parent'>The parent widget.</param>
+ /// <param name='evt'>The mouse event. May be null if triggered by keyboard.</param>
+ /// <param name='caret'>The caret/selection position within the parent, if the EventButton is null.</param>
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.EventButton evt, Gdk.Rectangle caret)
+ {
+ Gtk.MenuPositionFunc posFunc = null;
+
+ if (parent != null) {
+ menu.AttachToWidget (parent, null);
+ menu.Hidden += (sender, e) => {
+ if (menu.AttachWidget != null)
+ menu.Detach ();
+ };
+ posFunc = delegate (Gtk.Menu m, out int x, out int y, out bool pushIn) {
+ Gdk.Window window = evt != null? evt.Window : parent.GdkWindow;
+ window.GetOrigin (out x, out y);
+ var alloc = parent.Allocation;
+ if (evt != null) {
+ x += (int) evt.X;
+ y += (int) evt.Y;
+ } else if (caret.X >= alloc.X && caret.Y >= alloc.Y) {
+ x += caret.X;
+ y += caret.Y + caret.Height;
+ } else {
+ x += alloc.X;
+ y += alloc.Y;
+ }
+ Gtk.Requisition request = m.SizeRequest ();
+ var screen = parent.Screen;
+ Gdk.Rectangle geometry = GetUsableMonitorGeometry (screen, screen.GetMonitorAtPoint (x, y));
+
+ //whether to push or flip menus that would extend offscreen
+ //FIXME: this is the correct behaviour for mac, check other platforms
+ bool flip_left = true;
+ bool flip_up = false;
+
+ if (x + request.Width > geometry.X + geometry.Width) {
+ if (flip_left) {
+ x -= request.Width;
+ } else {
+ x = geometry.X + geometry.Width - request.Width;
+ }
+
+ if (x < geometry.Left)
+ x = geometry.Left;
+ }
+
+ if (y + request.Height > geometry.Y + geometry.Height) {
+ if (flip_up) {
+ y -= request.Height;
+ } else {
+ y = geometry.Y + geometry.Height - request.Height;
+ }
+
+ if (y < geometry.Top)
+ y = geometry.Top;
+ }
+
+ pushIn = false;
+ };
+ }
+
+ uint time;
+ uint button;
+
+ if (evt == null) {
+ time = Gtk.Global.CurrentEventTime;
+ button = 0;
+ } else {
+ time = evt.Time;
+ button = evt.Button;
+ }
+
+ //HACK: work around GTK menu issues on mac when passing button to menu.Popup
+ //some menus appear and immediately hide, and submenus don't activate
+ if (Platform.IsMac) {
+ button = 0;
+ }
+
+ menu.Popup (null, null, posFunc, button, time);
+ }
+
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.EventButton evt)
+ {
+ ShowContextMenu (menu, parent, evt, Gdk.Rectangle.Zero);
+ }
+
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.Rectangle caret)
+ {
+ ShowContextMenu (menu, parent, null, caret);
+ }
+
+ struct MappedKeys
+ {
+ public Gdk.Key Key;
+ public Gdk.ModifierType State;
+ public KeyboardShortcut[] Shortcuts;
+ }
+
+ //introduced in GTK 2.20
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_keymap_add_virtual_modifiers (IntPtr keymap, ref Gdk.ModifierType state);
+
+ //Custom patch in Mono Mac w/GTK+ 2.24.8+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_quartz_set_fix_modifiers (bool fix);
+
+ static Gdk.Keymap keymap = Gdk.Keymap.Default;
+ static Dictionary<ulong,MappedKeys> mappedKeys = new Dictionary<ulong,MappedKeys> ();
+
+ /// <summary>Map raw GTK key input to work around platform bugs and decompose accelerator keys</summary>
+ /// <param name='evt'>The raw key event</param>
+ /// <param name='key'>The composed key</param>
+ /// <param name='state'>The composed modifiers</param>
+ /// <param name='shortcuts'>All the key/modifier decompositions that can be used as accelerators</param>
+ public static void MapKeys (Gdk.EventKey evt, out Gdk.Key key, out Gdk.ModifierType state,
+ out KeyboardShortcut[] shortcuts)
+ {
+ //this uniquely identifies the raw key
+ ulong id;
+ unchecked {
+ id = (((ulong)(uint)evt.State) | (((ulong)evt.HardwareKeycode) << 32) | (((ulong)evt.Group) << 48));
+ }
+
+ bool remapKey = Platform.IsWindows && evt.HardwareKeycode == 0;
+ MappedKeys mapped;
+ if (remapKey || !mappedKeys.TryGetValue (id, out mapped))
+ mappedKeys[id] = mapped = MapKeys (evt);
+
+ shortcuts = mapped.Shortcuts;
+ state = mapped.State;
+ key = mapped.Key;
+
+ if (remapKey) {
+ key = (Gdk.Key)evt.KeyValue;
+ }
+ }
+
+ static MappedKeys MapKeys (Gdk.EventKey evt)
+ {
+ MappedKeys mapped;
+ Gdk.ModifierType modifier = evt.State;
+ byte grp = evt.Group;
+
+ if (GtkMinorVersion >= 20) {
+ gdk_keymap_add_virtual_modifiers (keymap.Handle, ref modifier);
+ }
+
+ //full key mapping
+ uint keyval;
+ int effectiveGroup, level;
+ Gdk.ModifierType consumedModifiers;
+ TranslateKeyboardState (evt, modifier, grp, out keyval, out effectiveGroup,
+ out level, out consumedModifiers);
+ mapped.Key = (Gdk.Key)keyval;
+ mapped.State = FixMacModifiers (evt.State & ~consumedModifiers, grp);
+
+ //decompose the key into accel combinations
+ var accelList = new List<KeyboardShortcut> ();
+
+ const Gdk.ModifierType accelMods = Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask
+ | Gdk.ModifierType.ControlMask | Gdk.ModifierType.SuperMask |Gdk.ModifierType.MetaMask;
+
+ //all accels ignore the lock key
+ modifier &= ~Gdk.ModifierType.LockMask;
+
+ //fully decomposed
+ TranslateKeyboardState (evt, Gdk.ModifierType.None, 0,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+ accelList.Add (new KeyboardShortcut ((Gdk.Key)keyval, FixMacModifiers (modifier, grp) & accelMods));
+
+ //with shift composed
+ if ((modifier & Gdk.ModifierType.ShiftMask) != 0) {
+ keymap.TranslateKeyboardState (evt.HardwareKeycode, Gdk.ModifierType.ShiftMask, 0,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+
+ if (Platform.IsWindows && evt.HardwareKeycode == 0) {
+ keyval = (ushort)evt.KeyValue;
+ }
+
+ // Prevent consumption of non-Shift modifiers (that we didn't even provide!)
+ consumedModifiers &= Gdk.ModifierType.ShiftMask;
+
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), grp) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //with group 1 composed
+ if (grp == 1) {
+ TranslateKeyboardState (evt, modifier & ~Gdk.ModifierType.ShiftMask, 1,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+
+ // Prevent consumption of Shift modifier (that we didn't even provide!)
+ consumedModifiers &= ~Gdk.ModifierType.ShiftMask;
+
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), 0) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //with group 1 and shift composed
+ if (grp == 1 && (modifier & Gdk.ModifierType.ShiftMask) != 0) {
+ TranslateKeyboardState (evt, modifier, 1,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), 0) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //and also allow the fully mapped key as an accel
+ AddIfNotDuplicate (accelList, new KeyboardShortcut (mapped.Key, mapped.State & accelMods));
+
+ mapped.Shortcuts = accelList.ToArray ();
+ return mapped;
+ }
+
+ // Workaround for bug "Bug 688247 - Ctrl+Alt key not work on windows7 with bootcamp on a Mac Book Pro"
+ // Ctrl+Alt should behave like right alt key - unfortunately TranslateKeyboardState doesn't handle it.
+ static void TranslateKeyboardState (Gdk.EventKey evt, Gdk.ModifierType state, int group, out uint keyval,
+ out int effective_group, out int level, out Gdk.ModifierType consumed_modifiers)
+ {
+ uint hardware_keycode = evt.HardwareKeycode;
+
+ if (Platform.IsWindows) {
+ const Gdk.ModifierType ctrlAlt = Gdk.ModifierType.ControlMask | Gdk.ModifierType.Mod1Mask;
+ if ((state & ctrlAlt) == ctrlAlt) {
+ state = (state & ~ctrlAlt) | Gdk.ModifierType.Mod2Mask;
+ group = 1;
+ }
+ // Case: Caps lock on + shift + key
+ // See: Bug 8069 - [UI Refresh] If caps lock is on, holding the shift key prevents typed characters from appearing
+ if (state.HasFlag (Gdk.ModifierType.ShiftMask)) {
+ state &= ~Gdk.ModifierType.ShiftMask;
+ }
+ }
+
+ keymap.TranslateKeyboardState (hardware_keycode, state, group, out keyval, out effective_group,
+ out level, out consumed_modifiers);
+
+ if (Platform.IsWindows && hardware_keycode == 0) {
+ keyval = evt.KeyValue;
+ }
+ }
+
+ static Gdk.ModifierType FixMacModifiers (Gdk.ModifierType mod, byte grp)
+ {
+ if (!oldMacKeyHacks)
+ return mod;
+
+ // Mac GTK+ maps the command key to the Mod1 modifier, which usually means alt/
+ // We map this instead to meta, because the Mac GTK+ has mapped the cmd key
+ // to the meta key (yay inconsistency!). IMO super would have been saner.
+ if ((mod & Gdk.ModifierType.Mod1Mask) != 0) {
+ mod ^= Gdk.ModifierType.Mod1Mask;
+ mod |= Gdk.ModifierType.MetaMask;
+ }
+
+ //some versions of GTK map opt as mod5, which converts to the virtual super modifier
+ if ((mod & (Gdk.ModifierType.Mod5Mask | Gdk.ModifierType.SuperMask)) != 0) {
+ mod ^= (Gdk.ModifierType.Mod5Mask | Gdk.ModifierType.SuperMask);
+ mod |= Gdk.ModifierType.Mod1Mask;
+ }
+
+ // When opt modifier is active, we need to decompose this to make the command appear correct for Mac.
+ // In addition, we can only inspect whether the opt/alt key is pressed by examining
+ // the key's "group", because the Mac GTK+ treats opt as a group modifier and does
+ // not expose it as an actual GDK modifier.
+ if (grp == (byte) 1) {
+ mod |= Gdk.ModifierType.Mod1Mask;
+ }
+
+ return mod;
+ }
+
+ static void AddIfNotDuplicate<T> (List<T> list, T item) where T : IEquatable<T>
+ {
+ for (int i = 0; i < list.Count; i++) {
+ if (list[i].Equals (item))
+ return;
+ }
+ list.Add (item);
+ }
+
+ [System.Runtime.InteropServices.DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr gdk_win32_drawable_get_handle (IntPtr drawable);
+
+ enum DwmWindowAttribute
+ {
+ NcRenderingEnabled = 1,
+ NcRenderingPolicy,
+ TransitionsForceDisabled,
+ AllowNcPaint,
+ CaptionButtonBounds,
+ NonClientRtlLayout,
+ ForceIconicRepresentation,
+ Flip3DPolicy,
+ ExtendedFrameBounds,
+ HasIconicBitmap,
+ DisallowPeek,
+ ExcludedFromPeek,
+ Last,
+ }
+
+ struct Win32Rect
+ {
+ public int Left, Top, Right, Bottom;
+
+ public Win32Rect (int left, int top, int right, int bottom)
+ {
+ this.Left = left;
+ this.Top = top;
+ this.Right = right;
+ this.Bottom = bottom;
+ }
+ }
+
+ [DllImport ("dwmapi.dll")]
+ static extern int DwmGetWindowAttribute (IntPtr hwnd, DwmWindowAttribute attribute, out Win32Rect value, int valueSize);
+
+ [DllImport ("dwmapi.dll")]
+ static extern int DwmIsCompositionEnabled (out bool enabled);
+
+ [DllImport (USER32DLL)]
+ static extern bool GetWindowRect (IntPtr hwnd, out Win32Rect rect);
+
+ public static void SetImCursorLocation (Gtk.IMContext ctx, Gdk.Window clientWindow, Gdk.Rectangle cursor)
+ {
+ // work around GTK+ Bug 663096 - Windows IME position is wrong when Aero glass is enabled
+ // https://bugzilla.gnome.org/show_bug.cgi?id=663096
+ if (Platform.IsWindows && System.Environment.OSVersion.Version.Major >= 6) {
+ bool enabled;
+ if (DwmIsCompositionEnabled (out enabled) == 0 && enabled) {
+ var hwnd = gdk_win32_drawable_get_handle (clientWindow.Toplevel.Handle);
+ Win32Rect rect;
+ // this module gets the WINVER=6 version of GetWindowRect, which returns the correct value
+ if (GetWindowRect (hwnd, out rect)) {
+ int x, y;
+ clientWindow.Toplevel.GetPosition (out x, out y);
+ cursor.X = cursor.X - x + rect.Left;
+ cursor.Y = cursor.Y - y + rect.Top - cursor.Height;
+ }
+ }
+ }
+ ctx.CursorLocation = cursor;
+ }
+
+ /// <summary>X coordinate of the pixels inside the right edge of the rectangle</summary>
+ /// <remarks>Workaround for inconsistency of Right property between GTK# versions</remarks>
+ public static int RightInside (this Gdk.Rectangle rect)
+ {
+ return rect.X + rect.Width - 1;
+ }
+
+ /// <summary>Y coordinate of the pixels inside the bottom edge of the rectangle</summary>
+ /// <remarks>Workaround for inconsistency of Bottom property between GTK# versions#</remarks>
+ public static int BottomInside (this Gdk.Rectangle rect)
+ {
+ return rect.Y + rect.Height - 1;
+ }
+
+ /// <summary>
+ /// Shows or hides the shadow of the window rendered by the native toolkit
+ /// </summary>
+ public static void ShowNativeShadow (Gtk.Window window, bool show)
+ {
+ if (Platform.IsMac) {
+ var ptr = gdk_quartz_window_get_nswindow (window.GdkWindow.Handle);
+ objc_msgSend_void_bool (ptr, sel_setHasShadow, show);
+ }
+ }
+
+ public static void UpdateNativeShadow (Gtk.Window window)
+ {
+ if (!Platform.IsMac)
+ return;
+
+ var ptr = gdk_quartz_window_get_nswindow (window.GdkWindow.Handle);
+ objc_msgSend_IntPtr (ptr, sel_invalidateShadow);
+ }
+
+ public static bool HasNSTextFieldFocus (Gdk.Window window)
+ {
+ if (Platform.IsMac) {
+ try {
+ return gdk_window_has_embedded_nsview_focus (window.Handle);
+ } catch (Exception e) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ [DllImport (PangoUtil.LIBGTKGLUE, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtksharp_container_leak_fixed_marker ();
+
+ static HashSet<Type> fixedContainerTypes;
+ static Dictionary<IntPtr,ForallDelegate> forallCallbacks;
+ static bool containerLeakFixed;
+
+ // Works around BXC #3801 - Managed Container subclasses are incorrectly resurrected, then leak.
+ // It does this by registering an alternative callback for gtksharp_container_override_forall, which
+ // ignores callbacks if the wrapper no longer exists. This means that the objects no longer enter a
+ // finalized->release->dispose->re-wrap resurrection cycle.
+ // We use a dynamic method to access internal/private GTK# API in a performant way without having to track
+ // per-instance delegates.
+ public static void FixContainerLeak (Gtk.Container c)
+ {
+ if (containerLeakFixed) {
+ return;
+ }
+
+ FixContainerLeak (c.GetType ());
+ }
+
+ static void FixContainerLeak (Type t)
+ {
+ if (containerLeakFixed) {
+ return;
+ }
+
+ if (fixedContainerTypes == null) {
+ try {
+ gtksharp_container_leak_fixed_marker ();
+ containerLeakFixed = true;
+ return;
+ } catch (EntryPointNotFoundException) {
+ }
+ fixedContainerTypes = new HashSet<Type>();
+ forallCallbacks = new Dictionary<IntPtr, ForallDelegate> ();
+ }
+
+ if (!fixedContainerTypes.Add (t)) {
+ return;
+ }
+
+ //need to fix the callback for the type and all the managed supertypes
+ var lookupGType = typeof (GLib.Object).GetMethod ("LookupGType", BindingFlags.Static | BindingFlags.NonPublic);
+ do {
+ var gt = (GLib.GType) lookupGType.Invoke (null, new[] { t });
+ var cb = CreateForallCallback (gt.Val);
+ forallCallbacks[gt.Val] = cb;
+ gtksharp_container_override_forall (gt.Val, cb);
+ t = t.BaseType;
+ } while (fixedContainerTypes.Add (t) && t.Assembly != typeof (Gtk.Container).Assembly);
+ }
+
+ static ForallDelegate CreateForallCallback (IntPtr gtype)
+ {
+ var dm = new DynamicMethod (
+ "ContainerForallCallback",
+ typeof(void),
+ new Type[] { typeof(IntPtr), typeof(bool), typeof(IntPtr), typeof(IntPtr) },
+ typeof(GtkWorkarounds).Module,
+ true);
+
+ var invokerType = typeof(Gtk.Container.CallbackInvoker);
+
+ //this was based on compiling a similar method and disassembling it
+ ILGenerator il = dm.GetILGenerator ();
+ var IL_002b = il.DefineLabel ();
+ var IL_003f = il.DefineLabel ();
+ var IL_0060 = il.DefineLabel ();
+ var label_return = il.DefineLabel ();
+
+ var loc_container = il.DeclareLocal (typeof(Gtk.Container));
+ var loc_obj = il.DeclareLocal (typeof(object));
+ var loc_invoker = il.DeclareLocal (invokerType);
+ var loc_ex = il.DeclareLocal (typeof(Exception));
+
+ //check that the type is an exact match
+ // prevent stack overflow, because the callback on a more derived type will handle everything
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Call, typeof(GLib.ObjectManager).GetMethod ("gtksharp_get_type_id", BindingFlags.Static | BindingFlags.NonPublic));
+
+ il.Emit (OpCodes.Ldc_I8, gtype.ToInt64 ());
+ il.Emit (OpCodes.Newobj, typeof (IntPtr).GetConstructor (new Type[] { typeof (Int64) }));
+ il.Emit (OpCodes.Call, typeof (IntPtr).GetMethod ("op_Equality", BindingFlags.Static | BindingFlags.Public));
+ il.Emit (OpCodes.Brfalse, label_return);
+
+ il.BeginExceptionBlock ();
+ il.Emit (OpCodes.Ldnull);
+ il.Emit (OpCodes.Stloc, loc_container);
+ il.Emit (OpCodes.Ldsfld, typeof (GLib.Object).GetField ("Objects", BindingFlags.Static | BindingFlags.NonPublic));
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Box, typeof (IntPtr));
+ il.Emit (OpCodes.Callvirt, typeof (System.Collections.Hashtable).GetProperty ("Item").GetGetMethod ());
+ il.Emit (OpCodes.Stloc, loc_obj);
+ il.Emit (OpCodes.Ldloc, loc_obj);
+ il.Emit (OpCodes.Brfalse, IL_002b);
+
+ var tref = typeof (GLib.Object).Assembly.GetType ("GLib.ToggleRef");
+ il.Emit (OpCodes.Ldloc, loc_obj);
+ il.Emit (OpCodes.Castclass, tref);
+ il.Emit (OpCodes.Callvirt, tref.GetProperty ("Target").GetGetMethod ());
+ il.Emit (OpCodes.Isinst, typeof (Gtk.Container));
+ il.Emit (OpCodes.Stloc, loc_container);
+
+ il.MarkLabel (IL_002b);
+ il.Emit (OpCodes.Ldloc, loc_container);
+ il.Emit (OpCodes.Brtrue, IL_003f);
+
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Ldarg_1);
+ il.Emit (OpCodes.Ldarg_2);
+ il.Emit (OpCodes.Ldarg_3);
+ il.Emit (OpCodes.Call, typeof (Gtk.Container).GetMethod ("gtksharp_container_base_forall", BindingFlags.Static | BindingFlags.NonPublic));
+ il.Emit (OpCodes.Br, IL_0060);
+
+ il.MarkLabel (IL_003f);
+ il.Emit (OpCodes.Ldloca_S, 2);
+ il.Emit (OpCodes.Ldarg_2);
+ il.Emit (OpCodes.Ldarg_3);
+ il.Emit (OpCodes.Call, invokerType.GetConstructor (
+ BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (IntPtr), typeof (IntPtr) }, null));
+ il.Emit (OpCodes.Ldloc, loc_container);
+ il.Emit (OpCodes.Ldarg_1);
+ il.Emit (OpCodes.Ldloc, loc_invoker);
+ il.Emit (OpCodes.Box, invokerType);
+ il.Emit (OpCodes.Ldftn, invokerType.GetMethod ("Invoke"));
+ il.Emit (OpCodes.Newobj, typeof (Gtk.Callback).GetConstructor (
+ BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof (object), typeof (IntPtr) }, null));
+ var forallMeth = typeof (Gtk.Container).GetMethod ("ForAll",
+ BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (bool), typeof (Gtk.Callback) }, null);
+ il.Emit (OpCodes.Callvirt, forallMeth);
+
+ il.MarkLabel (IL_0060);
+
+ il.BeginCatchBlock (typeof (Exception));
+ il.Emit (OpCodes.Stloc, loc_ex);
+ il.Emit (OpCodes.Ldloc, loc_ex);
+ il.Emit (OpCodes.Ldc_I4_0);
+ il.Emit (OpCodes.Call, typeof (GLib.ExceptionManager).GetMethod ("RaiseUnhandledException"));
+ il.Emit (OpCodes.Leave, label_return);
+ il.EndExceptionBlock ();
+
+ il.MarkLabel (label_return);
+ il.Emit (OpCodes.Ret);
+
+ return (ForallDelegate) dm.CreateDelegate (typeof (ForallDelegate));
+ }
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data);
+
+ [DllImport(PangoUtil.LIBGTKGLUE, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtksharp_container_override_forall (IntPtr gtype, ForallDelegate cb);
+
+ const string urlRegexStr = @"(http|ftp)s?\:\/\/[\w\d\.,;_/\-~%@()+:?&^=#!]*[\w\d/]";
+ static readonly Regex UrlRegex = new Regex (urlRegexStr, RegexOptions.Compiled | RegexOptions.ExplicitCapture);
+
+ public static string MarkupLinks (string text)
+ {
+ if (GtkMinorVersion < 18)
+ return text;
+ return UrlRegex.Replace (text, MatchToUrl);
+ }
+
+ static string MatchToUrl (System.Text.RegularExpressions.Match m)
+ {
+ var s = m.ToString ();
+ return String.Format ("<a href='{0}'>{1}</a>", s, s.Replace ("_", "__"));
+ }
+
+ public static void SetLinkHandler (this Gtk.Label label, Action<string> urlHandler)
+ {
+ if (GtkMinorVersion >= 18)
+ new UrlHandlerClosure (urlHandler).ConnectTo (label);
+ }
+
+ //create closure manually so we can apply ConnectBefore
+ class UrlHandlerClosure
+ {
+ Action<string> urlHandler;
+
+ public UrlHandlerClosure (Action<string> urlHandler)
+ {
+ this.urlHandler = urlHandler;
+ }
+
+ [GLib.ConnectBefore]
+ void HandleLink (object sender, ActivateLinkEventArgs args)
+ {
+ urlHandler (args.Url);
+ args.RetVal = true;
+ }
+
+ public void ConnectTo (Gtk.Label label)
+ {
+ var signal = GLib.Signal.Lookup (label, "activate-link", typeof(ActivateLinkEventArgs));
+ signal.AddDelegate (new EventHandler<ActivateLinkEventArgs> (HandleLink));
+ }
+
+ class ActivateLinkEventArgs : GLib.SignalArgs
+ {
+ public string Url { get { return (string)base.Args [0]; } }
+ }
+ }
+
+ static bool canSetOverlayScrollbarPolicy = true;
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern void gtk_scrolled_window_set_overlay_policy (IntPtr sw, Gtk.PolicyType hpolicy, Gtk.PolicyType vpolicy);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern void gtk_scrolled_window_get_overlay_policy (IntPtr sw, out Gtk.PolicyType hpolicy, out Gtk.PolicyType vpolicy);
+
+ public static void SetOverlayScrollbarPolicy (Gtk.ScrolledWindow sw, Gtk.PolicyType hpolicy, Gtk.PolicyType vpolicy)
+ {
+ if (!canSetOverlayScrollbarPolicy) {
+ return;
+ }
+ try {
+ gtk_scrolled_window_set_overlay_policy (sw.Handle, hpolicy, vpolicy);
+ return;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ }
+
+ public static void GetOverlayScrollbarPolicy (Gtk.ScrolledWindow sw, out Gtk.PolicyType hpolicy, out Gtk.PolicyType vpolicy)
+ {
+ if (!canSetOverlayScrollbarPolicy) {
+ hpolicy = vpolicy = 0;
+ return;
+ }
+ try {
+ gtk_scrolled_window_get_overlay_policy (sw.Handle, out hpolicy, out vpolicy);
+ return;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ hpolicy = vpolicy = 0;
+ canSetOverlayScrollbarPolicy = false;
+ }
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern bool gtk_tree_view_get_tooltip_context (IntPtr raw, ref int x, ref int y, bool keyboard_tip, out IntPtr model, out IntPtr path, IntPtr iter);
+
+ //the GTK# version of this has 'out' instead of 'ref', preventing passing the x,y values in
+ public static bool GetTooltipContext (this TreeView tree, ref int x, ref int y, bool keyboardTip,
+ out TreeModel model, out TreePath path, out Gtk.TreeIter iter)
+ {
+ IntPtr intPtr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof(TreeIter)));
+ IntPtr handle;
+ IntPtr intPtr2;
+ bool result = gtk_tree_view_get_tooltip_context (tree.Handle, ref x, ref y, keyboardTip, out handle, out intPtr2, intPtr);
+ model = TreeModelAdapter.GetObject (handle, false);
+ path = intPtr2 == IntPtr.Zero ? null : ((TreePath)GLib.Opaque.GetOpaque (intPtr2, typeof(TreePath), false));
+ iter = TreeIter.New (intPtr);
+ Marshal.FreeHGlobal (intPtr);
+ return result;
+ }
+
+ static bool supportsHiResIcons = true;
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtk_icon_source_set_scale (IntPtr source, double scale);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtk_icon_source_set_scale_wildcarded (IntPtr source, bool setting);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern double gtk_widget_get_scale_factor (IntPtr widget);
+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern double gdk_screen_get_monitor_scale_factor (IntPtr widget, int monitor);
+
+ [DllImport (PangoUtil.LIBGOBJECT, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr g_object_get_data (IntPtr source, string name);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr gtk_icon_set_render_icon_scaled (IntPtr handle, IntPtr style, int direction, int state, int size, IntPtr widget, IntPtr intPtr, ref double scale);
+
+ public static bool SetSourceScale (Gtk.IconSource source, double scale)
+ {
+ if (!supportsHiResIcons)
+ return false;
+
+ try {
+ gtk_icon_source_set_scale (source.Handle, scale);
+ return true;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return false;
+ }
+
+ public static bool SetSourceScaleWildcarded (Gtk.IconSource source, bool setting)
+ {
+ if (!supportsHiResIcons)
+ return false;
+
+ try {
+ gtk_icon_source_set_scale_wildcarded (source.Handle, setting);
+ return true;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return false;
+ }
+
+ public static Gdk.Pixbuf Get2xVariant (Gdk.Pixbuf px)
+ {
+ if (!supportsHiResIcons)
+ return null;
+
+ try {
+ IntPtr res = g_object_get_data (px.Handle, "gdk-pixbuf-2x-variant");
+ if (res != IntPtr.Zero && res != px.Handle)
+ return (Gdk.Pixbuf) GLib.Object.GetObject (res);
+ else
+ return null;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return null;
+ }
+
+ public static void Set2xVariant (Gdk.Pixbuf px, Gdk.Pixbuf variant2x)
+ {
+ }
+
+ public static double GetScaleFactor (Gtk.Widget w)
+ {
+ if (!supportsHiResIcons)
+ return 1;
+
+ try {
+ return gtk_widget_get_scale_factor (w.Handle);
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return 1;
+ }
+
+ public static double GetScaleFactor (this Gdk.Screen screen, int monitor)
+ {
+ if (!supportsHiResIcons)
+ return 1;
+
+ try {
+ return gdk_screen_get_monitor_scale_factor (screen.Handle, monitor);
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return 1;
+ }
+
+ public static double GetScaleFactor ()
+ {
+ return GetScaleFactor (Gdk.Screen.Default, 0);
+ }
+
+ public static double GetPixelScale ()
+ {
+ if (Platform.IsWindows)
+ return GetScaleFactor ();
+ else
+ return 1d;
+ }
+
+ public static Gdk.Pixbuf RenderIcon (this Gtk.IconSet iconset, Gtk.Style style, Gtk.TextDirection direction, Gtk.StateType state, Gtk.IconSize size, Gtk.Widget widget, string detail, double scale)
+ {
+ if (scale == 1d)
+ return iconset.RenderIcon (style, direction, state, size, widget, detail);
+
+ if (!supportsHiResIcons)
+ return null;
+
+ try {
+ IntPtr intPtr = GLib.Marshaller.StringToPtrGStrdup (detail);
+ IntPtr o = gtk_icon_set_render_icon_scaled (iconset.Handle, (style != null) ? style.Handle : IntPtr.Zero, (int)direction, (int)state, (int)size, (widget != null) ? widget.Handle : IntPtr.Zero, intPtr, ref scale);
+ Gdk.Pixbuf result = (Gdk.Pixbuf) GLib.Object.GetObject (o);
+ GLib.Marshaller.Free (intPtr);
+ return result;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return null;
+ }
+ }
+
+ public struct KeyboardShortcut : IEquatable<KeyboardShortcut>
+ {
+ public static readonly KeyboardShortcut Empty = new KeyboardShortcut ((Gdk.Key) 0, (Gdk.ModifierType) 0);
+
+ Gdk.ModifierType modifier;
+ Gdk.Key key;
+
+ public KeyboardShortcut (Gdk.Key key, Gdk.ModifierType modifier)
+ {
+ this.modifier = modifier;
+ this.key = key;
+ }
+
+ public Gdk.Key Key {
+ get { return key; }
+ }
+
+ public Gdk.ModifierType Modifier {
+ get { return modifier; }
+ }
+
+ public bool IsEmpty {
+ get { return Key == (Gdk.Key) 0; }
+ }
+
+ public override bool Equals (object obj)
+ {
+ return obj is KeyboardShortcut && this.Equals ((KeyboardShortcut) obj);
+ }
+
+ public override int GetHashCode ()
+ {
+ //FIXME: we're only using a few bits of mod and mostly the lower bits of key - distribute it better
+ return (int) Key ^ (int) Modifier;
+ }
+
+ public bool Equals (KeyboardShortcut other)
+ {
+ return other.Key == Key && other.Modifier == Modifier;
+ }
+ }
+
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
index d1de2f1c9f..a4f1fec7b4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
@@ -37,7 +37,7 @@ namespace MonoDevelop.Components
public HPanedThin ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
handle = new CustomPanedHandle (this);
handle.Parent = this;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
index 6edbdf9213..c34e0eda46 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs
new file mode 100644
index 0000000000..5b758e5a50
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs
@@ -0,0 +1,136 @@
+// HelperMethods.cs
+//
+// Cut & paste from PangoCairoHelper.
+//
+// Author:
+// Aaron Bockover <abockover@novell.com>
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Components
+{
+ public static class HelperMethods
+ {
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_show_layout (IntPtr cr, IntPtr layout);
+
+ public static void ShowLayout (this Cairo.Context cr, Pango.Layout layout)
+ {
+ pango_cairo_show_layout (cr == null ? IntPtr.Zero : cr.Handle, layout == null ? IntPtr.Zero : layout.Handle);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_cairo_create_layout (IntPtr cr);
+
+ public static Pango.Layout CreateLayout (this Cairo.Context cr)
+ {
+ IntPtr raw_ret = pango_cairo_create_layout (cr == null ? IntPtr.Zero : cr.Handle);
+ return GLib.Object.GetObject (raw_ret) as Pango.Layout;
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_layout_path (IntPtr cr, IntPtr layout);
+
+ public static void LayoutPath (this Cairo.Context cr, Pango.Layout layout)
+ {
+ pango_cairo_layout_path (cr == null ? IntPtr.Zero : cr.Handle, layout == null ? IntPtr.Zero : layout.Handle);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_context_set_resolution (IntPtr pango_context, double dpi);
+
+ public static void ContextSetResolution (this Pango.Context context, double dpi)
+ {
+ pango_cairo_context_set_resolution (context == null ? IntPtr.Zero : context.Handle, dpi);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_layout_get_context (IntPtr layout);
+
+ public static string GetColorString (Gdk.Color color)
+ {
+ return string.Format ("#{0:X02}{1:X02}{2:X02}", color.Red / 256, color.Green / 256, color.Blue / 256);
+ }
+
+ public static Pango.Context LayoutGetContext (this Pango.Layout layout)
+ {
+ IntPtr handle = pango_layout_get_context (layout.Handle);
+ return handle.Equals (IntPtr.Zero) ? null : GLib.Object.GetObject (handle) as Pango.Context;
+ }
+
+ public static void DrawLine (this Cairo.Context cr, Cairo.Color color, double x1, double y1, double x2, double y2)
+ {
+ cr.SetSourceColor (color);
+ cr.MoveTo (x1, y1);
+ cr.LineTo (x2, y2);
+ cr.Stroke ();
+ }
+
+ public static void Line (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1, y1);
+ cr.LineTo (x2, y2);
+ }
+
+ public static void SharpLineX (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1 + 0.5, y1);
+ cr.LineTo (x2 + 0.5, y2);
+ }
+
+ public static void SharpLineY (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1, y1 + 0.5);
+ cr.LineTo (x2, y2 + 0.5);
+ }
+
+ public static void SetSourceColor (this Cairo.Context cr, Cairo.Color color)
+ {
+ cr.SetSourceRGBA (color.R, color.G, color.B, color.A);
+ }
+
+ //this is needed for building against old Mono.Cairo versions
+ [Obsolete]
+ public static void SetSource (this Cairo.Context cr, Cairo.Pattern pattern)
+ {
+ cr.Pattern = pattern;
+ }
+
+ [Obsolete]
+ public static Cairo.Surface GetTarget (this Cairo.Context cr)
+ {
+ return cr.Target;
+ }
+
+ [Obsolete]
+ public static void Dispose (this Cairo.Context cr)
+ {
+ ((IDisposable)cr).Dispose ();
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs
new file mode 100644
index 0000000000..7e56d747d1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs
@@ -0,0 +1,292 @@
+//
+// HslColor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using Gdk;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Components
+{
+ public struct HslColor
+ {
+ public double H {
+ get;
+ set;
+ }
+
+ public double S {
+ get;
+ set;
+ }
+
+ public double L {
+ get;
+ set;
+ }
+
+ public double Alpha {
+ get;
+ set;
+ }
+
+ void ToRgb(out double r, out double g, out double b)
+ {
+ if (L == 0) {
+ r = g = b = 0;
+ return;
+ }
+
+ if (S == 0) {
+ r = g = b = L;
+ } else {
+ double temp2 = L <= 0.5 ? L * (1.0 + S) : L + S -(L * S);
+ double temp1 = 2.0 * L - temp2;
+
+ double[] t3 = new double[] { H + 1.0 / 3.0, H, H - 1.0 / 3.0};
+ double[] clr= new double[] { 0, 0, 0};
+ for (int i = 0; i < 3; i++) {
+ if (t3[i] < 0)
+ t3[i] += 1.0;
+ if (t3[i] > 1)
+ t3[i]-=1.0;
+ if (6.0 * t3[i] < 1.0)
+ clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;
+ else if (2.0 * t3[i] < 1.0)
+ clr[i] = temp2;
+ else if (3.0 * t3[i] < 2.0)
+ clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);
+ else
+ clr[i] = temp1;
+ }
+
+ r = clr[0];
+ g = clr[1];
+ b = clr[2];
+ }
+ }
+
+ public static implicit operator Color (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new Color ((byte)(255 * r),
+ (byte)(255 * g),
+ (byte)(255 * b));
+ }
+
+ public static implicit operator Cairo.Color (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new Cairo.Color (r, g, b, hsl.Alpha);
+ }
+
+ public static implicit operator HslColor (Color color)
+ {
+ return new HslColor (color);
+ }
+
+ public static implicit operator HslColor (Cairo.Color color)
+ {
+ return new HslColor (color);
+ }
+
+ #if MAC
+
+ public static implicit operator HslColor (AppKit.NSColor color)
+ {
+ return new HslColor ((double)color.RedComponent, (double)color.GreenComponent, (double)color.BlueComponent);
+ }
+
+ public static implicit operator AppKit.NSColor (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return AppKit.NSColor.FromDeviceRgba ((nfloat)r, (nfloat)g, (nfloat)b, (nfloat)hsl.Alpha);
+ }
+
+
+ public static implicit operator CoreGraphics.CGColor (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new CoreGraphics.CGColor ((nfloat)r, (nfloat)g, (nfloat)b, (nfloat)hsl.Alpha);
+ }
+ #endif
+
+
+ public static HslColor FromHsl (double h, double s, double l)
+ {
+ return new HslColor {
+ H = h,
+ S = s,
+ L = l,
+ Alpha = 1.0d
+ };
+ }
+
+ public uint ToPixel ()
+ {
+ double r, g, b;
+ ToRgb(out r, out g, out b);
+ uint rv = (uint)(r * 255);
+ uint gv = (uint)(g * 255);
+ uint bv = (uint)(b * 255);
+ return rv << 16 | gv << 8 | bv;
+ }
+
+ public static HslColor FromPixel (uint pixel)
+ {
+ var r = ((pixel >> 16) & 0xFF) / 255.0;
+ var g = ((pixel >> 8) & 0xFF) / 255.0;
+ var b = (pixel & 0xFF) / 255.0;
+ return new HslColor (r, g, b);
+ }
+
+ public HslColor (double r, double g, double b, double a = 1.0) : this ()
+ {
+ double v = System.Math.Max (r, g);
+ v = System.Math.Max (v, b);
+
+ double m = System.Math.Min (r, g);
+ m = System.Math.Min (m, b);
+
+ this.L = (m + v) / 2.0;
+ if (this.L <= 0.0)
+ return;
+ double vm = v - m;
+ this.S = vm;
+
+ if (this.S > 0.0) {
+ this.S /= (this.L <= 0.5) ? (v + m) : (2.0 - v - m);
+ } else {
+ return;
+ }
+
+ double r2 = (v - r) / vm;
+ double g2 = (v - g) / vm;
+ double b2 = (v - b) / vm;
+
+ if (r == v) {
+ this.H = (g == m ? 5.0 + b2 : 1.0 - g2);
+ } else if (g == v) {
+ this.H = (b == m ? 1.0 + r2 : 3.0 - b2);
+ } else {
+ this.H = (r == m ? 3.0 + g2 : 5.0 - r2);
+ }
+ this.H /= 6.0;
+
+ this.Alpha = a;
+ }
+
+ public HslColor (Color color) : this (color.Red / (double)ushort.MaxValue, color.Green / (double)ushort.MaxValue, color.Blue / (double)ushort.MaxValue)
+ {
+ Alpha = 1.0;
+ }
+
+ public HslColor (Cairo.Color color) : this (color.R, color.G, color.B, color.A)
+ {
+ }
+
+ public static HslColor Parse (string color)
+ {
+ Gdk.Color col = new Gdk.Color (0, 0, 0);
+ Gdk.Color.Parse (color, ref col);
+ return (HslColor)col;
+ }
+
+ public static double Brightness (HslColor c)
+ {
+ return Brightness ((Cairo.Color)c);
+ }
+
+ public static double Brightness (Cairo.Color c)
+ {
+ double r = c.R;
+ double g = c.G;
+ double b = c.B;
+ return System.Math.Sqrt (r * .241 + g * .691 + b * .068);
+ }
+
+ public static double Brightness (Gdk.Color c)
+ {
+ double r = c.Red / (double)ushort.MaxValue;
+ double g = c.Green / (double)ushort.MaxValue;
+ double b = c.Blue / (double)ushort.MaxValue;
+ return System.Math.Sqrt (r * .241 + g * .691 + b * .068);
+ }
+
+ public static List<HslColor> GenerateHighlightColors (HslColor backGround, HslColor foreGround, int n)
+ {
+ double bgH = (backGround.H == 0 && backGround.S == 0) ? 2 / 3.0 : backGround.H;
+ var result = new List<HslColor> ();
+ for (int i = 0; i < n; i++) {
+ double h = bgH + (i + 1.0) / (double)n;
+
+ // for monochromatic backround the h value doesn't matter
+ if (i + 1 == n && !(backGround.H == 0 && backGround.S == 0))
+ h = bgH + 0.5;
+
+ if (h > 1.0)
+ h -= 1.0;
+
+ double s = 0.85;
+ double l = 0.5;
+ if (backGround.H == 0 && backGround.S == 0 && backGround.L < 0.5)
+ l = 0.8;
+ result.Add (HslColor.FromHsl (h, s, l));
+ }
+ return result;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[HslColor: H={0}, S={1}, L={2}, A={3}]", H, S, L, Alpha);
+ }
+
+ public string ToPangoString ()
+ {
+ var resultColor = (Cairo.Color)this;
+ return string.Format ("#{0:x2}{1:x2}{2:x2}",
+ (int)(resultColor.R * 255),
+ (int)(resultColor.G * 255),
+ (int)(resultColor.B * 255));
+ }
+
+
+ public string ToMarkup ()
+ {
+ if (Alpha == 1.0)
+ return ToPangoString ();
+ var resultColor = (Cairo.Color)this;
+ return string.Format ("#{0:x2}{1:x2}{2:x2}{3:x2}",
+ (int)(resultColor.R * 255),
+ (int)(resultColor.G * 255),
+ (int)(resultColor.B * 255),
+ (int)(resultColor.A * 255));
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
index 5851edf92f..8b9bc5a851 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
@@ -70,7 +70,7 @@ namespace MonoDevelop.Components
}
double IconScale {
- get { return Mono.TextEditor.GtkWorkarounds.GetPixelScale (); }
+ get { return GtkWorkarounds.GetPixelScale (); }
}
protected override void OnSizeRequested (ref Gtk.Requisition requisition)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
index 34a646b8e4..715045bf8c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
@@ -26,7 +26,6 @@
using System;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs
new file mode 100644
index 0000000000..86de702f7f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs
@@ -0,0 +1,260 @@
+//
+// PangoUtils.cs
+//
+// Author:
+// Michael Hutchinson <mhutchinson@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using Gtk;
+using System.Runtime.InteropServices;
+
+namespace MonoDevelop.Components
+{
+ public static class PangoUtil
+ {
+ internal const string LIBGTK = "libgtk-win32-2.0-0.dll";
+ internal const string LIBATK = "libatk-1.0-0.dll";
+ internal const string LIBGLIB = "libglib-2.0-0.dll";
+ internal const string LIBGDK = "libgdk-win32-2.0-0.dll";
+ internal const string LIBGOBJECT = "libgobject-2.0-0.dll";
+ internal const string LIBPANGO = "libpango-1.0-0.dll";
+ internal const string LIBPANGOCAIRO = "libpangocairo-1.0-0.dll";
+ internal const string LIBQUARTZ = "libgtk-quartz-2.0.dylib";
+ internal const string LIBGTKGLUE = "gtksharpglue-2";
+
+ /// <summary>
+ /// This doesn't leak Pango layouts, unlike some other ways to create them in GTK# &lt;= 2.12.11
+ /// </summary>
+ public static Pango.Layout CreateLayout (Widget widget)
+ {
+ var ptr = gtk_widget_create_pango_layout (widget.Handle, IntPtr.Zero);
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ public static Pango.Layout CreateLayout (Widget widget, string text)
+ {
+ IntPtr textPtr = text == null? IntPtr.Zero : GLib.Marshaller.StringToPtrGStrdup (text);
+
+ var ptr = gtk_widget_create_pango_layout (widget.Handle, textPtr);
+
+ if (textPtr != IntPtr.Zero)
+ GLib.Marshaller.Free (textPtr);
+
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ public static Pango.Layout CreateLayout (PrintContext context)
+ {
+ var ptr = gtk_print_context_create_pango_layout (context.Handle);
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ [DllImport (LIBGTK, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr gtk_widget_create_pango_layout (IntPtr widget, IntPtr text);
+
+ [DllImport (LIBGTK, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr gtk_print_context_create_pango_layout (IntPtr context);
+ }
+
+ /// <summary>
+ /// This creates a Pango list and applies attributes to it with *much* less overhead than the GTK# version.
+ /// </summary>
+ class FastPangoAttrList : IDisposable
+ {
+ IntPtr list;
+
+ public FastPangoAttrList ()
+ {
+ list = pango_attr_list_new ();
+ }
+
+ public void AddStyleAttribute (Pango.Style style, uint start, uint end)
+ {
+ Add (pango_attr_style_new (style), start, end);
+ }
+
+ public void AddWeightAttribute (Pango.Weight weight, uint start, uint end)
+ {
+ Add (pango_attr_weight_new (weight), start, end);
+ }
+
+ public void AddForegroundAttribute (Gdk.Color color, uint start, uint end)
+ {
+ Add (pango_attr_foreground_new (color.Red, color.Green, color.Blue), start, end);
+ }
+
+ public void AddBackgroundAttribute (Gdk.Color color, uint start, uint end)
+ {
+ Add (pango_attr_background_new (color.Red, color.Green, color.Blue), start, end);
+ }
+
+ public void AddUnderlineAttribute (Pango.Underline underline, uint start, uint end)
+ {
+ Add (pango_attr_underline_new (underline), start, end);
+ }
+
+ void Add (IntPtr attribute, uint start, uint end)
+ {
+ unsafe {
+ PangoAttribute *attPtr = (PangoAttribute *) attribute;
+ attPtr->start_index = start;
+ attPtr->end_index = end;
+ }
+ pango_attr_list_insert (list, attribute);
+ }
+
+ /// <summary>
+ /// Like Splice, except it only offsets/clamps the inserted items, doesn't affect items already in the list.
+ /// </summary>
+ public void InsertOffsetList (Pango.AttrList atts, uint startOffset, uint endOffset)
+ {
+ //HACK: atts.Iterator.Attrs broken (throws NRE), so manually P/Invoke
+ var iter = pango_attr_list_get_iterator (atts.Handle);
+ try {
+ do {
+ IntPtr list = pango_attr_iterator_get_attrs (iter);
+ try {
+ int len = g_slist_length (list);
+ for (uint i = 0; i < len; i++) {
+ IntPtr val = g_slist_nth_data (list, i);
+ AddOffsetCopy (val, startOffset, endOffset);
+ }
+ } finally {
+ g_slist_free (list);
+ }
+ } while (pango_attr_iterator_next (iter));
+ } finally {
+ pango_attr_iterator_destroy (iter);
+ }
+ }
+
+ void AddOffsetCopy (IntPtr attr, uint startOffset, uint endOffset)
+ {
+ var copy = pango_attribute_copy (attr);
+ unsafe {
+ PangoAttribute *attPtr = (PangoAttribute *) copy;
+ attPtr->start_index = startOffset + attPtr->start_index;
+ attPtr->end_index = System.Math.Min (endOffset, startOffset + attPtr->end_index);
+ }
+ pango_attr_list_insert (list, copy);
+ }
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_style_new (Pango.Style style);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_stretch_new (Pango.Stretch stretch);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_weight_new (Pango.Weight weight);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_foreground_new (ushort red, ushort green, ushort blue);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_background_new (ushort red, ushort green, ushort blue);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_underline_new (Pango.Underline underline);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_list_new ();
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_unref (IntPtr list);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_insert (IntPtr list, IntPtr attr);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_layout_set_attributes (IntPtr layout, IntPtr attrList);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_splice (IntPtr attr_list, IntPtr other, Int32 pos, Int32 len);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attribute_copy (IntPtr attr);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_list_get_iterator (IntPtr list);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern bool pango_attr_iterator_next (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_iterator_destroy (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_iterator_get_attrs (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int g_slist_length (IntPtr l);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr g_slist_nth_data (IntPtr l, uint n);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern void g_slist_free (IntPtr l);
+
+ public void Splice (Pango.AttrList attrs, int pos, int len)
+ {
+ pango_attr_list_splice (list, attrs.Handle, pos, len);
+ }
+
+ public void AssignTo (Pango.Layout layout)
+ {
+ pango_layout_set_attributes (layout.Handle, list);
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct PangoAttribute
+ {
+ public IntPtr klass;
+ public uint start_index;
+ public uint end_index;
+ }
+
+ public void Dispose ()
+ {
+ if (list != IntPtr.Zero) {
+ GC.SuppressFinalize (this);
+ Destroy ();
+ }
+ }
+
+ //NOTE: the list destroys all its attributes when the ref count reaches zero
+ void Destroy ()
+ {
+ pango_attr_list_unref (list);
+ list = IntPtr.Zero;
+ }
+
+ ~FastPangoAttrList ()
+ {
+ GLib.Idle.Add (delegate {
+ Destroy ();
+ return false;
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
index 8ff221923e..d90d8d8a81 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
@@ -25,15 +25,13 @@
// THE SOFTWARE.
using System;
-using System.Collections.Generic;
using System.Linq;
using Gtk;
using Gdk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
-using ICSharpCode.NRefactory;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
index 04d0d9f32b..97423f16c6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
@@ -27,7 +27,6 @@ using System;
using Gtk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
using Gdk;
using Xwt.Motion;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
index d477f4700b..29bf1dcc25 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
@@ -27,8 +27,9 @@ using System;
using Gtk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
using Gdk;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
namespace MonoDevelop.Components
{
@@ -264,7 +265,7 @@ namespace MonoDevelop.Components
Font = Pango.FontDescription.FromString ("Normal");
}
- public void SetSchemeColors (Mono.TextEditor.Highlighting.ColorScheme scheme)
+ public void SetSchemeColors (ColorScheme scheme)
{
TopColor = scheme.TooltipText.Background.AddLight (0.03);
BottomColor = scheme.TooltipText.Background;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
index 44bd4e78ed..188f400dd3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
@@ -31,7 +31,6 @@ using System;
using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
index 02688602d0..6ea647114b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
@@ -29,7 +29,6 @@ using System.Collections.Generic;
using Gtk;
using Gdk;
using Cairo;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
@@ -91,7 +90,7 @@ namespace MonoDevelop.Components
public SectionList ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
this.WidgetFlags |= WidgetFlags.NoWindow;
WidthRequest = 100;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
index d6c04f907a..a60edb358e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
@@ -30,7 +30,6 @@ using System.ComponentModel;
using System.Drawing.Design;
using Cairo;
using Gtk;
-using Mono.TextEditor;
using System.Linq;
namespace MonoDevelop.Components
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
index e5685f27af..95036e0cbe 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
@@ -26,12 +26,10 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using MonoDevelop.Ide;
using Gtk;
using Gdk;
-using Mono.TextEditor.PopupWindow;
namespace MonoDevelop.Components
{
@@ -41,7 +39,7 @@ namespace MonoDevelop.Components
public string LinkColor {
get {
- var color = Mono.TextEditor.HslColor.GenerateHighlightColors (Style.Background (State), Style.Text (State), 3)[2];
+ var color = HslColor.GenerateHighlightColors (Style.Background (State), Style.Text (State), 3)[2];
return color.ToPangoString ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
index 838c04f970..ac607fda01 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
@@ -34,7 +34,7 @@ namespace MonoDevelop.Components
public VPanedThin ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
handle = new CustomPanedHandle (this);
handle.Parent = this;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs
new file mode 100644
index 0000000000..9b8e8526d8
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs
@@ -0,0 +1,116 @@
+//
+// WindowTransparencyDecorator.cs
+//
+// Author:
+// Michael Hutchinson <mhutch@xamarin.com>
+//
+// Based on code derived from Banshee.Widgets.EllipsizeLabel
+// by Aaron Bockover (aaron@aaronbock.net)
+//
+// Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+using Gtk;
+using Gdk;
+
+namespace MonoDevelop.Components
+{
+ public class WindowTransparencyDecorator
+ {
+ Gtk.Window window;
+ bool semiTransparent;
+ bool snooperInstalled;
+ uint snooperID;
+ const double opacity = 0.2;
+
+ WindowTransparencyDecorator (Gtk.Window window)
+ {
+ this.window = window;
+
+ window.Shown += ShownHandler;
+ window.Hidden += HiddenHandler;
+ window.Destroyed += DestroyedHandler;
+ }
+
+ public static WindowTransparencyDecorator Attach (Gtk.Window window)
+ {
+ return new WindowTransparencyDecorator (window);
+ }
+
+ public void Detach ()
+ {
+ if (window == null)
+ return;
+
+ //remove the snooper
+ HiddenHandler (null, null);
+
+ //annul allreferences between this and the window
+ window.Shown -= ShownHandler;
+ window.Hidden -= HiddenHandler;
+ window.Destroyed -= DestroyedHandler;
+ window = null;
+ }
+
+ void ShownHandler (object sender, EventArgs args)
+ {
+ if (!snooperInstalled)
+ snooperID = Gtk.Key.SnooperInstall (TransparencyKeySnooper);
+ snooperInstalled = true;
+
+ //NOTE: we unset transparency when showing, instead of when hiding
+ //because the latter case triggers a metacity+compositing bug that shows the window again
+ SemiTransparent = false;
+ }
+
+ void HiddenHandler (object sender, EventArgs args)
+ {
+ if (snooperInstalled)
+ Gtk.Key.SnooperRemove (snooperID);
+ snooperInstalled = false;
+ }
+
+ void DestroyedHandler (object sender, EventArgs args)
+ {
+ Detach ();
+ }
+
+ int TransparencyKeySnooper (Gtk.Widget widget, EventKey evnt)
+ {
+ if (evnt != null && evnt.Key == Gdk.Key.Control_L || evnt.Key == Gdk.Key.Control_R)
+ SemiTransparent = (evnt.Type == Gdk.EventType.KeyPress);
+ return 0; //FALSE
+ }
+
+ bool SemiTransparent {
+ set {
+ if (semiTransparent != value) {
+ semiTransparent = value;
+ window.Opacity = semiTransparent? opacity : 1.0;
+ }
+ }
+ }
+ }
+}