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 internal static class MacSupport {
38 internal static Hashtable contextReference = new Hashtable ();
39 internal static object lockobj = new object ();
41 internal static Delegate hwnd_delegate;
44 internal static float red = 1.0f;
45 internal static float green = 0.0f;
46 internal static float blue = 0.0f;
47 internal static int debug_threshold = 1;
50 static MacSupport () {
51 foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ()) {
52 if (String.Equals (asm.GetName ().Name, "System.Windows.Forms")) {
53 Type driver_type = asm.GetType ("System.Windows.Forms.XplatUICarbon");
54 if (driver_type != null) {
55 hwnd_delegate = (Delegate) driver_type.GetField ("HwndDelegate", BindingFlags.NonPublic | BindingFlags.Static).GetValue (null);
61 internal static CocoaContext GetCGContextForNSView (IntPtr handle) {
62 IntPtr graphicsContext = objc_msgSend (objc_getClass ("NSGraphicsContext"), sel_registerName ("currentContext"));
63 IntPtr ctx = objc_msgSend (graphicsContext, sel_registerName ("graphicsPort"));
64 Rect bounds = new Rect ();
66 CGContextSaveGState (ctx);
68 objc_msgSend_stret (ref bounds, handle, sel_registerName ("bounds"));
70 var isFlipped = bool_objc_msgSend (handle, sel_registerName ("isFlipped"));
72 CGContextTranslateCTM (ctx, bounds.origin.x, bounds.size.height);
73 CGContextScaleCTM (ctx,1.0f,-1.0f);
76 return new CocoaContext (ctx, (int) bounds.size.width, (int) bounds.size.height);
79 internal static CarbonContext GetCGContextForView (IntPtr handle) {
80 IntPtr context = IntPtr.Zero;
81 IntPtr port = IntPtr.Zero;
82 IntPtr window = IntPtr.Zero;
84 window = GetControlOwner (handle);
86 if (handle == IntPtr.Zero || window == IntPtr.Zero) {
87 // FIXME: Can we actually get a CGContextRef for the desktop? this makes context IntPtr.Zero
88 port = GetQDGlobalsThePort ();
89 CreateCGContextForPort (port, ref context);
91 Rect desktop_bounds = CGDisplayBounds (CGMainDisplayID ());
93 return new CarbonContext (port, context, (int)desktop_bounds.size.width, (int)desktop_bounds.size.height);
96 QDRect window_bounds = new QDRect ();
97 Rect view_bounds = new Rect ();
99 port = GetWindowPort (window);
101 context = GetContext (port);
103 GetWindowBounds (window, 32, ref window_bounds);
105 HIViewGetBounds (handle, ref view_bounds);
107 HIViewConvertRect (ref view_bounds, handle, IntPtr.Zero);
109 if (view_bounds.size.height < 0) view_bounds.size.height = 0;
110 if (view_bounds.size.width < 0) view_bounds.size.width = 0;
112 CGContextTranslateCTM (context, view_bounds.origin.x, (window_bounds.bottom - window_bounds.top) - (view_bounds.origin.y + view_bounds.size.height));
114 // Create the original rect path and clip to it
115 Rect rc_clip = new Rect (0, 0, view_bounds.size.width, view_bounds.size.height);
117 CGContextSaveGState (context);
119 Rectangle [] clip_rectangles = (Rectangle []) hwnd_delegate.DynamicInvoke (new object [] {handle});
120 if (clip_rectangles != null && clip_rectangles.Length > 0) {
121 int length = clip_rectangles.Length;
123 CGContextBeginPath (context);
124 CGContextAddRect (context, rc_clip);
126 for (int i = 0; i < length; i++) {
127 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));
129 CGContextClosePath (context);
130 CGContextEOClip (context);
132 if (clip_rectangles.Length >= debug_threshold) {
133 CGContextSetRGBFillColor (context, red, green, blue, 0.5f);
134 CGContextFillRect (context, rc_clip);
135 CGContextFlush (context);
136 System.Threading.Thread.Sleep (500);
137 if (red == 1.0f) { red = 0.0f; blue = 1.0f; }
138 else if (blue == 1.0f) { blue = 0.0f; green = 1.0f; }
139 else if (green == 1.0f) { green = 0.0f; red = 1.0f; }
143 CGContextBeginPath (context);
144 CGContextAddRect (context, rc_clip);
145 CGContextClosePath (context);
146 CGContextClip (context);
149 return new CarbonContext (port, context, (int)view_bounds.size.width, (int)view_bounds.size.height);
152 internal static IntPtr GetContext (IntPtr port) {
153 IntPtr context = IntPtr.Zero;
157 if (contextReference [port] != null) {
158 CreateCGContextForPort (port, ref context);
160 QDBeginCGContext (port, ref context);
161 contextReference [port] = context;
164 CreateCGContextForPort (port, ref context);
171 internal static void ReleaseContext (IntPtr port, IntPtr context) {
172 CGContextRestoreGState (context);
176 if (contextReference [port] != null && context == (IntPtr) contextReference [port]) {
177 QDEndCGContext (port, ref context);
178 contextReference [port] = null;
188 #region Cocoa Methods
189 [DllImport("libobjc.dylib")]
190 public static extern IntPtr objc_getClass(string className);
191 [DllImport("libobjc.dylib")]
192 public static extern IntPtr objc_msgSend(IntPtr basePtr, IntPtr selector, string argument);
193 [DllImport("libobjc.dylib")]
194 public static extern IntPtr objc_msgSend(IntPtr basePtr, IntPtr selector);
195 [DllImport("libobjc.dylib")]
196 public static extern void objc_msgSend_stret(ref Rect arect, IntPtr basePtr, IntPtr selector);
197 [DllImport ("libobjc.dylib", EntryPoint = "objc_msgSend")]
198 public static extern bool bool_objc_msgSend (IntPtr handle, IntPtr selector);
199 [DllImport("libobjc.dylib")]
200 public static extern IntPtr sel_registerName(string selectorName);
203 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
204 internal static extern IntPtr CGMainDisplayID ();
205 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
206 internal static extern Rect CGDisplayBounds (IntPtr display);
208 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
209 internal static extern int HIViewGetBounds (IntPtr vHnd, ref Rect r);
210 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
211 internal static extern int HIViewConvertRect (ref Rect r, IntPtr a, IntPtr b);
213 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
214 internal static extern IntPtr GetControlOwner (IntPtr aView);
216 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
217 internal static extern int GetWindowBounds (IntPtr wHnd, uint reg, ref QDRect rect);
218 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
219 internal static extern IntPtr GetWindowPort (IntPtr hWnd);
220 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
221 internal static extern IntPtr GetQDGlobalsThePort ();
222 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
223 internal static extern void CreateCGContextForPort (IntPtr port, ref IntPtr context);
224 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
225 internal static extern void CFRelease (IntPtr context);
226 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
227 internal static extern void QDBeginCGContext (IntPtr port, ref IntPtr context);
228 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
229 internal static extern void QDEndCGContext (IntPtr port, ref IntPtr context);
230 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
231 internal static extern int CGContextClipToRect (IntPtr context, Rect clip);
232 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
233 internal static extern int CGContextClipToRects (IntPtr context, Rect [] clip_rects, int count);
234 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
235 internal static extern void CGContextTranslateCTM (IntPtr context, float tx, float ty);
236 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
237 internal static extern void CGContextScaleCTM (IntPtr context, float x, float y);
238 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
239 internal static extern void CGContextFlush (IntPtr context);
240 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
241 internal static extern void CGContextSynchronize (IntPtr context);
242 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
243 internal static extern IntPtr CGPathCreateMutable ();
244 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
245 internal static extern void CGPathAddRects (IntPtr path, IntPtr _void, Rect [] rects, int count);
246 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
247 internal static extern void CGPathAddRect (IntPtr path, IntPtr _void, Rect rect);
248 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
249 internal static extern void CGContextAddRects (IntPtr context, Rect [] rects, int count);
250 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
251 internal static extern void CGContextAddRect (IntPtr context, Rect rect);
252 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
253 internal static extern void CGContextBeginPath (IntPtr context);
254 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
255 internal static extern void CGContextClosePath (IntPtr context);
256 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
257 internal static extern void CGContextAddPath (IntPtr context, IntPtr path);
258 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
259 internal static extern void CGContextClip (IntPtr context);
260 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
261 internal static extern void CGContextEOClip (IntPtr context);
262 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
263 internal static extern void CGContextEOFillPath (IntPtr context);
264 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
265 internal static extern void CGContextSaveGState (IntPtr context);
266 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
267 internal static extern void CGContextRestoreGState (IntPtr context);
270 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
271 internal static extern void CGContextSetRGBFillColor (IntPtr context, float red, float green, float blue, float alpha);
272 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
273 internal static extern void CGContextFillRect (IntPtr context, Rect rect);
277 internal struct CGSize {
282 internal struct CGPoint {
287 internal struct Rect {
288 public Rect (float x, float y, float width, float height) {
291 this.size.width = width;
292 this.size.height = height;
295 public CGPoint origin;
299 internal struct QDRect
307 internal struct CarbonContext : IMacContext
314 public CarbonContext (IntPtr port, IntPtr ctx, int width, int height)
319 this.height = height;
322 public void Synchronize ()
324 MacSupport.CGContextSynchronize (ctx);
327 public void Release ()
329 MacSupport.ReleaseContext (port, ctx);
333 internal struct CocoaContext : IMacContext
339 public CocoaContext (IntPtr ctx, int width, int height)
343 this.height = height;
346 public void Synchronize ()
348 MacSupport.CGContextSynchronize (ctx);
351 public void Release ()
353 MacSupport.CGContextRestoreGState(ctx);
357 internal interface IMacContext