2 // System.Drawing.carbonFunctions.cs
5 // Geoff Norton (gnorton@customerdna.com>
7 // Copyright (C) 2007 Novell, Inc. (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
;
31 using System
.Reflection
;
32 using System
.Runtime
.InteropServices
;
33 using System
.Security
;
35 namespace System
.Drawing
{
37 [SuppressUnmanagedCodeSecurity
]
39 internal static class Carbon
{
41 internal sealed class Carbon
{
43 internal static Hashtable contextReference
= new Hashtable ();
44 internal static object lockobj
= new object ();
46 internal static Delegate hwnd_delegate
;
49 internal static float red
= 1.0f
;
50 internal static float green
= 0.0f
;
51 internal static float blue
= 0.0f
;
52 internal static int debug_threshold
= 1;
56 foreach (Assembly asm
in AppDomain
.CurrentDomain
.GetAssemblies ()) {
57 if (String
.Equals (asm
.GetName ().Name
, "System.Windows.Forms")) {
58 Type driver_type
= asm
.GetType ("System.Windows.Forms.XplatUICarbon");
59 if (driver_type
!= null) {
60 hwnd_delegate
= (Delegate
) driver_type
.GetField ("HwndDelegate", BindingFlags
.NonPublic
| BindingFlags
.Static
).GetValue (null);
66 internal static CarbonContext
GetCGContextForView (IntPtr handle
) {
67 IntPtr context
= IntPtr
.Zero
;
68 IntPtr port
= IntPtr
.Zero
;
69 IntPtr window
= IntPtr
.Zero
;
71 window
= GetControlOwner (handle
);
73 if (handle
== IntPtr
.Zero
|| window
== IntPtr
.Zero
) {
74 // FIXME: Can we actually get a CGContextRef for the desktop? this makes context IntPtr.Zero
75 port
= GetQDGlobalsThePort ();
76 CreateCGContextForPort (port
, ref context
);
78 Rect desktop_bounds
= CGDisplayBounds (CGMainDisplayID ());
80 return new CarbonContext (port
, context
, (int)desktop_bounds
.size
.width
, (int)desktop_bounds
.size
.height
);
83 QDRect window_bounds
= new QDRect ();
84 Rect view_bounds
= new Rect ();
86 port
= GetWindowPort (window
);
88 context
= GetContext (port
);
90 GetWindowBounds (window
, 32, ref window_bounds
);
92 HIViewGetBounds (handle
, ref view_bounds
);
94 HIViewConvertRect (ref view_bounds
, handle
, IntPtr
.Zero
);
96 if (view_bounds
.size
.height
< 0) view_bounds
.size
.height
= 0;
97 if (view_bounds
.size
.width
< 0) view_bounds
.size
.width
= 0;
99 CGContextTranslateCTM (context
, view_bounds
.origin
.x
, (window_bounds
.bottom
- window_bounds
.top
) - (view_bounds
.origin
.y
+ view_bounds
.size
.height
));
101 // Create the original rect path and clip to it
102 Rect rc_clip
= new Rect (0, 0, view_bounds
.size
.width
, view_bounds
.size
.height
);
104 CGContextSaveGState (context
);
106 Rectangle
[] clip_rectangles
= (Rectangle
[]) hwnd_delegate
.DynamicInvoke (new object [] {handle}
);
107 if (clip_rectangles
!= null && clip_rectangles
.Length
> 0) {
108 int length
= clip_rectangles
.Length
;
110 CGContextBeginPath (context
);
111 CGContextAddRect (context
, rc_clip
);
113 for (int i
= 0; i
< length
; i
++) {
114 CGContextAddRect (context
, new Rect (clip_rectangles
[i
].X
, view_bounds
.size
.height
- clip_rectangles
[i
].Y
- clip_rectangles
[i
].Height
, clip_rectangles
[i
].Width
, clip_rectangles
[i
].Height
));
116 CGContextClosePath (context
);
117 CGContextEOClip (context
);
119 if (clip_rectangles
.Length
>= debug_threshold
) {
120 CGContextSetRGBFillColor (context
, red
, green
, blue
, 0.5f
);
121 CGContextFillRect (context
, rc_clip
);
122 CGContextFlush (context
);
123 System
.Threading
.Thread
.Sleep (500);
124 if (red
== 1.0f
) { red = 0.0f; blue = 1.0f; }
125 else if (blue
== 1.0f
) { blue = 0.0f; green = 1.0f; }
126 else if (green
== 1.0f
) { green = 0.0f; red = 1.0f; }
130 CGContextBeginPath (context
);
131 CGContextAddRect (context
, rc_clip
);
132 CGContextClosePath (context
);
133 CGContextClip (context
);
136 return new CarbonContext (port
, context
, (int)view_bounds
.size
.width
, (int)view_bounds
.size
.height
);
139 internal static IntPtr
GetContext (IntPtr port
) {
140 IntPtr context
= IntPtr
.Zero
;
144 if (contextReference
[port
] != null) {
145 CreateCGContextForPort (port
, ref context
);
147 QDBeginCGContext (port
, ref context
);
148 contextReference
[port
] = context
;
151 CreateCGContextForPort (port
, ref context
);
158 internal static void ReleaseContext (IntPtr port
, IntPtr context
) {
159 CGContextRestoreGState (context
);
163 if (contextReference
[port
] != null && context
== (IntPtr
) contextReference
[port
]) {
164 QDEndCGContext (port
, ref context
);
165 contextReference
[port
] = null;
175 #region Cocoa Methods
176 [DllImport("libobjc.dylib")]
177 public static extern IntPtr
objc_getClass(string className
);
178 [DllImport("libobjc.dylib")]
179 public static extern IntPtr
objc_msgSend(IntPtr basePtr
, IntPtr selector
, string argument
);
180 [DllImport("libobjc.dylib")]
181 public static extern IntPtr
objc_msgSend(IntPtr basePtr
, IntPtr selector
);
182 [DllImport("libobjc.dylib")]
183 public static extern void objc_msgSend_stret(ref Rect arect
, IntPtr basePtr
, IntPtr selector
);
184 [DllImport("libobjc.dylib")]
185 public static extern IntPtr
sel_registerName(string selectorName
);
188 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
189 internal static extern IntPtr
CGMainDisplayID ();
190 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
191 internal static extern Rect
CGDisplayBounds (IntPtr display
);
193 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
194 internal static extern int HIViewGetBounds (IntPtr vHnd
, ref Rect r
);
195 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
196 internal static extern int HIViewConvertRect (ref Rect r
, IntPtr a
, IntPtr b
);
198 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
199 internal static extern IntPtr
GetControlOwner (IntPtr aView
);
201 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
202 internal static extern int GetWindowBounds (IntPtr wHnd
, uint reg
, ref QDRect rect
);
203 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
204 internal static extern IntPtr
GetWindowPort (IntPtr hWnd
);
205 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
206 internal static extern IntPtr
GetQDGlobalsThePort ();
207 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
208 internal static extern void CreateCGContextForPort (IntPtr port
, ref IntPtr context
);
209 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
210 internal static extern void CFRelease (IntPtr context
);
211 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
212 internal static extern void QDBeginCGContext (IntPtr port
, ref IntPtr context
);
213 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
214 internal static extern void QDEndCGContext (IntPtr port
, ref IntPtr context
);
215 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
216 internal static extern int CGContextClipToRect (IntPtr context
, Rect clip
);
217 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
218 internal static extern int CGContextClipToRects (IntPtr context
, Rect
[] clip_rects
, int count
);
219 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
220 internal static extern void CGContextTranslateCTM (IntPtr context
, float tx
, float ty
);
221 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
222 internal static extern void CGContextScaleCTM (IntPtr context
, float x
, float y
);
223 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
224 internal static extern void CGContextFlush (IntPtr context
);
225 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
226 internal static extern void CGContextSynchronize (IntPtr context
);
227 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
228 internal static extern IntPtr
CGPathCreateMutable ();
229 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
230 internal static extern void CGPathAddRects (IntPtr path
, IntPtr _void
, Rect
[] rects
, int count
);
231 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
232 internal static extern void CGPathAddRect (IntPtr path
, IntPtr _void
, Rect rect
);
233 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
234 internal static extern void CGContextAddRects (IntPtr context
, Rect
[] rects
, int count
);
235 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
236 internal static extern void CGContextAddRect (IntPtr context
, Rect rect
);
237 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
238 internal static extern void CGContextBeginPath (IntPtr context
);
239 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
240 internal static extern void CGContextClosePath (IntPtr context
);
241 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
242 internal static extern void CGContextAddPath (IntPtr context
, IntPtr path
);
243 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
244 internal static extern void CGContextClip (IntPtr context
);
245 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
246 internal static extern void CGContextEOClip (IntPtr context
);
247 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
248 internal static extern void CGContextEOFillPath (IntPtr context
);
249 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
250 internal static extern void CGContextSaveGState (IntPtr context
);
251 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
252 internal static extern void CGContextRestoreGState (IntPtr context
);
255 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
256 internal static extern void CGContextSetRGBFillColor (IntPtr context
, float red
, float green
, float blue
, float alpha
);
257 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
258 internal static extern void CGContextFillRect (IntPtr context
, Rect rect
);
262 internal struct CGSize
{
267 internal struct CGPoint
{
272 internal struct Rect
{
273 public Rect (float x
, float y
, float width
, float height
) {
276 this.size
.width
= width
;
277 this.size
.height
= height
;
280 public CGPoint origin
;
284 internal struct QDRect
292 internal struct CarbonContext
299 public CarbonContext (IntPtr port
, IntPtr ctx
, int width
, int height
)
304 this.height
= height
;