* X11Keyboard.cs: Detect and use the num lock mask.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIOSX.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Geoff Norton  <gnorton@customerdna.com>
24 //
25 //
26
27 // This really doesn't work at all; please dont file bugs on it yet.
28
29 using System;
30 using System.Threading;
31 using System.Drawing;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Diagnostics;
35 using System.Runtime.InteropServices;
36
37 /// OSX Version
38 namespace System.Windows.Forms {
39
40         delegate int CarbonEventHandler (IntPtr inCallRef, IntPtr inEvent, IntPtr userData);
41
42         internal class XplatUIOSX : XplatUIDriver {
43                 
44                 private static XplatUIOSX instance;
45                 private static int ref_count;
46
47                 internal static MouseButtons mouse_state;
48                 internal static Point mouse_position;
49
50                 internal static IntPtr mouseInWindow;
51                 private static Hashtable handle_data;
52                 private static Queue carbonEvents;
53                 private CarbonEventHandler viewEventHandler;
54                 private CarbonEventHandler windowEventHandler;
55                 private static Hashtable view_window_mapping;
56                 private static IntPtr grabWindow;
57
58                 private static EventTypeSpec [] viewEvents = new EventTypeSpec [] {
59                                                                         new EventTypeSpec (1668183148, 4) 
60                                                                         };
61                 private static EventTypeSpec [] windowEvents = new EventTypeSpec[] {
62                                                                         new EventTypeSpec (1836021107, 1),
63                                                                         new EventTypeSpec (1836021107, 2),
64                                                                         new EventTypeSpec (1836021107, 5),
65                                                                         new EventTypeSpec (1836021107, 6),
66                                                                         new EventTypeSpec (1836021107, 10),
67                                                                         new EventTypeSpec (2003398244, 27)
68                                                                         };
69
70                 private ArrayList timer_list;
71
72                 [MonoTODO]
73                 internal override Keys ModifierKeys {
74                         get {
75                                 throw new NotImplementedException ();
76                         }
77                 }
78
79                 internal override MouseButtons MouseButtons {
80                         get {
81                                 return mouse_state;
82                         }
83                 }
84
85                 internal override Point MousePosition {
86                         get {
87                                 return mouse_position;
88                         }
89                 }
90
91                 [MonoTODO]
92                 internal override bool DropTarget {
93                         get {
94                                 throw new NotImplementedException ();
95                         }
96                         set {
97                                 throw new NotImplementedException ();
98                         }
99                 }
100
101                 private XplatUIOSX() {
102                         viewEventHandler = new CarbonEventHandler (ViewHandler);
103                         windowEventHandler = new CarbonEventHandler (WindowHandler);
104                         ref_count = 0;
105                         mouseInWindow = IntPtr.Zero;
106                         handle_data = new Hashtable ();
107                         carbonEvents = new Queue ();
108                         grabWindow = IntPtr.Zero;
109                         view_window_mapping = new Hashtable ();
110                         mouse_state=MouseButtons.None;
111                         mouse_position=Point.Empty;
112                         
113                         timer_list = new ArrayList ();
114                 }
115
116                 [MonoTODO]
117                 ~XplatUIOSX() {
118                         throw new NotImplementedException ();
119                 }
120
121                 public static XplatUIOSX GetInstance() {
122                         lock (typeof (XplatUIOSX)) {
123                                 if (instance == null) {
124                                         instance = new XplatUIOSX ();
125                                 }
126                                 ref_count++;
127                         }
128                         return instance;
129                 }
130
131                 internal override event EventHandler Idle;
132
133                 [MonoTODO]
134                 public int Reference {
135                         get {
136                                 throw new NotImplementedException ();
137                         }
138                 }
139
140                 [MonoTODO]
141                 private void MouseHover (object sender, EventArgs e) {
142                         throw new NotImplementedException ();
143                 }
144
145                 [MonoTODO]
146                 internal override IntPtr InitializeDriver() {
147                         throw new NotImplementedException ();
148                 }
149
150                 [MonoTODO]
151                 internal override void ShutdownDriver(IntPtr token) {
152                         throw new NotImplementedException ();
153                 }
154
155                 internal void Version() {
156                         Console.WriteLine("Xplat version $revision: $");
157                 }
158
159                 internal override void Exit() {
160                         Console.WriteLine("XplatUIOSX.Exit");
161                 }
162
163                 [MonoTODO]
164                 internal override void GetDisplaySize(out Size size) {
165                         // FIXME:
166                         size = new Size (1024, 768);
167 //                      throw new NotImplementedException ();
168                 }
169
170                 [MonoTODO]
171                 internal override void EnableThemes() {
172                         throw new NotImplementedException ();
173                 }
174
175                 internal override IntPtr CreateWindow(CreateParams cp) {
176                         IntPtr hWnd = IntPtr.Zero;
177                         IntPtr windowHnd = IntPtr.Zero;
178                         IntPtr parentHnd = cp.Parent;
179                         bool realWindow = false;
180                         
181                         if (parentHnd == IntPtr.Zero) {
182                                 if ((cp.Style & (int)(WindowStyles.WS_CHILD))!=0) {
183                                         // This is a child view that is going to be parentless;
184                                         realWindow = false;
185                                 } else if ((cp.Style & (int)(WindowStyles.WS_POPUP))!=0) {
186                                         // This is a popup window that will be real.
187                                         realWindow = true;
188                                 } else {
189                                         // This is a real root window too
190                                         if (cp.X < 1) cp.X = 0;
191                                         if (cp.Y < 1) cp.Y = 0;
192                                         realWindow = true;
193                                 }
194                         } else {
195                                 realWindow = false;
196                         }
197
198                         if (realWindow) {
199                                 IntPtr rect = IntPtr.Zero;
200                                 IntPtr viewHnd = IntPtr.Zero;
201                                 SetRect (ref rect, (short)cp.X, (short)cp.Y, (short)(cp.Width+cp.X), (short)(cp.Height+cp.Y));
202                                 CheckError (CreateNewWindow (6, 33554432 | 31 | 524288 , ref rect, ref windowHnd), "CreateNewWindow ()");
203                                 CheckError (InstallEventHandler (GetWindowEventTarget (windowHnd), windowEventHandler, (uint)windowEvents.Length, windowEvents, windowHnd, IntPtr.Zero), "InstallEventHandler ()");
204                                 CheckError (HIViewFindByID (HIViewGetRoot (windowHnd), new HIViewID (2003398244, 1), ref viewHnd), "HIViewFindByID ()");
205                                 parentHnd = viewHnd;
206                         }
207                         HIRect r = new HIRect (0, 0, cp.Width, cp.Height);
208                         CheckError (HIObjectCreate (__CFStringMakeConstantString ("com.apple.hiview"), 0, ref hWnd), "HIObjectCreate ()");
209                         CheckError (InstallEventHandler (GetControlEventTarget (hWnd), viewEventHandler, (uint)viewEvents.Length, viewEvents, hWnd, IntPtr.Zero), "InstallEventHandler ()");
210                         CheckError (HIViewChangeFeatures (hWnd, 1 << 1, 0), "HIViewChangeFeatures ()");
211                         CheckError (HIViewSetFrame (hWnd, ref r), "HIViewSetFrame ()");
212                         if (parentHnd != IntPtr.Zero && parentHnd != hWnd) {
213                                 CheckError (HIViewAddSubview (parentHnd, hWnd), "HIViewAddSubview ()");
214                                 if ((cp.Style & (int)(WindowStyles.WS_VISIBLE))!=0) {
215                                         CheckError (HIViewSetVisible (hWnd, true), "HIViewSetVisible ()");
216                                 } else {
217                                         CheckError (HIViewSetVisible (hWnd, IsVisible (parentHnd)), "HIViewSetVisible ()");
218                                 }
219                         }
220                         if (realWindow) {
221                                 view_window_mapping [hWnd] = windowHnd;
222                                 if ((cp.Style & (int)(WindowStyles.WS_VISIBLE))!=0) {
223                                         CheckError (ShowWindow (windowHnd));
224                                         CheckError (HIViewSetVisible (hWnd, true), "HIViewSetVisible ()");
225                                 }
226                         }
227                         return hWnd;
228                 }
229
230                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
231                         CreateParams create_params = new CreateParams();
232
233                         create_params.Caption = "";
234                         create_params.X = X;
235                         create_params.Y = Y;
236                         create_params.Width = Width;
237                         create_params.Height = Height;
238
239                         create_params.ClassName=XplatUI.DefaultClassName;
240                         create_params.ClassStyle = 0;
241                         create_params.ExStyle=0;
242                         create_params.Parent=IntPtr.Zero;
243                         create_params.Param=0;
244
245                         return CreateWindow(create_params);
246                 }
247
248                 [MonoTODO]
249                 internal override void DestroyWindow(IntPtr handle) {
250                         throw new NotImplementedException ();
251                 }
252
253                 [MonoTODO]
254                 internal override void RefreshWindow(IntPtr handle) {
255                         IntPtr outEvent = IntPtr.Zero;
256                         HIViewSetNeedsDisplay (handle, true);
257                 }
258
259                 [MonoTODO("Find a way to make all the views do this; not just the window view")]
260                 internal override void SetWindowBackground(IntPtr handle, Color color) {
261                         if (view_window_mapping [handle] != null) {
262                                 RGBColor backColor = new RGBColor ();
263                                 backColor.red = (short)(color.R * 257); 
264                                 backColor.green = (short)(color.G * 257);
265                                 backColor.blue = (short)(color.B * 257);
266
267                                 CheckError (SetWindowContentColor ((IntPtr) view_window_mapping [handle], ref backColor));
268                         }
269                 }
270
271                 [MonoTODO]
272                 internal override PaintEventArgs PaintEventStart(IntPtr handle) {
273                         PaintEventArgs  paint_event;
274
275                         HandleData data = (HandleData) handle_data [handle];
276                         if (data == null) {
277                                 throw new Exception ("null data on paint event start: " + handle);
278                         }
279
280                         data.DeviceContext = Graphics.FromHwnd (handle);
281                         paint_event = new PaintEventArgs((Graphics)data.DeviceContext, data.InvalidArea);
282
283                         return paint_event;
284                 }
285
286                 [MonoTODO]
287                 internal override void PaintEventEnd(IntPtr handle) {
288                         HandleData data = (HandleData) handle_data [handle];
289                         if (data == null)
290                                 throw new Exception ("null data on PaintEventEnd");
291                         data.ClearInvalidArea ();
292                         Graphics g = (Graphics) data.DeviceContext;
293                         g.Flush ();
294                         g.Dispose ();
295                 }
296
297                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
298                         if (view_window_mapping [handle] != null) {
299                                 if (x == 0 && y == 0) {
300                                         Rect bounds = new Rect ();
301                                         CheckError (GetWindowBounds ((IntPtr) view_window_mapping [handle], 32, ref bounds), "GetWindowBounds ()");
302                                         x += bounds.left;
303                                         y += bounds.top;
304                                 }
305                                 IntPtr rect = IntPtr.Zero;
306                                 SetRect (ref rect, (short)x, (short)y, (short)(x+width), (short)(y+height));
307                                 CheckError (SetWindowBounds ((IntPtr) view_window_mapping [handle], 32, ref rect), "SetWindowBounds ()");
308                                 HIRect r = new HIRect (0, 0, width, height);
309                                 CheckError (HIViewSetFrame (handle, ref r), "HIViewSetFrame ()");
310                         } else {
311                                 HIRect r = new HIRect (x, y, width, height);
312                                 CheckError (HIViewSetFrame (handle, ref r), "HIViewSetFrame ()");
313                         }
314                 }
315
316                 [MonoTODO]
317                 internal override void GetWindowPos(IntPtr handle, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
318                         HIRect r = new HIRect ();
319                         CheckError (HIViewGetFrame (handle, ref r), "HIViewGetFrame ()");
320                         x = (int)r.origin.x;
321                         y = (int)r.origin.y;
322                         width = (int)r.size.width;
323                         height = (int)r.size.height;
324                         client_width = width;
325                         client_height = height;
326                 }
327
328                 [MonoTODO]
329                 internal override void Activate(IntPtr handle) {
330                         throw new NotImplementedException ();
331                 }
332
333                 [MonoTODO]
334                 internal override void EnableWindow(IntPtr handle, bool Enable) {
335                         //throw new NotImplementedException ();
336                 }
337
338                 [MonoTODO]
339                 internal override void SetModal(IntPtr handle, bool Modal) {
340                         // FIXME: What do we do here on OSX?
341                         return;
342                 }
343
344                 [MonoTODO]
345                 internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear) {
346                         // FIXME: What do we do here
347 //                      throw new NotImplementedException ();
348                 }
349
350                 [MonoTODO]
351                 internal override IntPtr DefWndProc(ref Message msg) {
352                         return IntPtr.Zero;
353                 }
354
355                 [MonoTODO]
356                 internal override void HandleException(Exception e) {
357                         throw new NotImplementedException ();
358                 }
359
360                 [MonoTODO]
361                 internal override void DoEvents() {
362                         throw new NotImplementedException ();
363                 }
364
365                 [MonoTODO]
366                 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
367                         throw new NotImplementedException ();
368                 }
369
370                 internal int WindowHandler (IntPtr inCallRef, IntPtr inEvent, IntPtr controlHnd) {
371                         int eventClass = GetEventClass (inEvent);
372                         int eventKind = GetEventKind (inEvent);
373                         MSG msg = new MSG ();
374                         msg.hwnd = IntPtr.Zero; 
375                         lock (carbonEvents) {
376                                 switch (eventClass) {
377                                         case 2003398244: {
378                                                 switch (eventKind) {
379                                                         case 27: {
380                                                                 // This is our real window; so we have to resize the corresponding view as well
381                                                                 IDictionaryEnumerator e = view_window_mapping.GetEnumerator ();
382                                                                 while (e.MoveNext ()) {
383                                                                         if ((IntPtr)e.Value == controlHnd) {
384                                                                                 Rect bounds = new Rect ();
385                                                                                 CheckError (GetWindowBounds (controlHnd, 32, ref bounds), "GetWindowBounds ()");
386                                                                                 HIRect r = new HIRect ();
387                                                                                 CheckError (HIViewGetFrame ((IntPtr)e.Key, ref r), "HIViewGetFrame ()");
388                                                                                 r.size.width = bounds.right-bounds.left;
389                                                                                 r.size.height = bounds.bottom-bounds.top;
390                                                                                 CheckError (HIViewSetFrame ((IntPtr)e.Key, ref r), "HIViewSetFrame ()");
391                                                                                 msg.message = Msg.WM_WINDOWPOSCHANGED;
392                                                                                 msg.hwnd = (IntPtr)e.Key;
393                                                                                 msg.wParam = IntPtr.Zero;
394                                                                                 msg.lParam = IntPtr.Zero;
395                                                                                 carbonEvents.Enqueue (msg);
396                                                                                 return 0;
397                                                                         }
398                                                                 }
399                                                                 break;
400                                                         }
401                                                 }
402                                                 break;
403                                         }
404                                         case 1836021107: {
405                                                 switch (eventKind) {
406                                                         case 1: 
407                                                         case 2: {
408                                                                 QDPoint point = new QDPoint ();
409                                                                 IntPtr pView = IntPtr.Zero;
410                                                                 IntPtr rView = IntPtr.Zero;
411                                                                 int wParam = 0;
412                                                                 ushort btn = 0;
413                                                                 GetEventParameter (inEvent, 1835168878, 1835168878, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (ushort)), IntPtr.Zero, ref btn);
414                                                                 CheckError (GetEventParameter (inEvent, 1835822947, 1363439732, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (QDPoint)), IntPtr.Zero, ref point), "GetEventParameter() MouseLocation");
415                                                                 SetPortWindowPort (controlHnd);
416                                                                 GlobalToLocal (ref point);
417                                                                 // Translate this point
418                                                                 Rect bounds = new Rect ();
419                                                                 CheckError (GetWindowBounds (controlHnd, 32, ref bounds), "GetWindowBounds ()");
420                                                                 // Swizzle it so its pointed at the right control
421                                                                 CGPoint hiPoint = new CGPoint (point.y, point.x);
422                                                                 CheckError (HIViewFindByID (HIViewGetRoot (controlHnd), new HIViewID (2003398244, 1), ref pView), "HIViewFindByID ()");
423                                                                 CheckError (HIViewGetSubviewHit (pView, ref hiPoint, true, ref rView));
424                                                                 HIViewConvertPoint (ref hiPoint, pView, rView);
425                                                                 if (grabWindow == IntPtr.Zero)
426                                                                         msg.hwnd = rView;
427                                                                 else
428                                                                         msg.hwnd = grabWindow;
429                                                                 switch (btn) {
430                                                                         case 1:
431                                                                                 if (eventKind == 1) {
432                                                                                         mouse_state |= MouseButtons.Left;
433                                                                                         msg.message = Msg.WM_LBUTTONDOWN;
434                                                                                         wParam |= (int)MsgButtons.MK_LBUTTON;
435                                                                                 } else {
436                                                                                         mouse_state &= MouseButtons.Left;
437                                                                                         msg.message = Msg.WM_LBUTTONUP;
438                                                                                         wParam |= (int)MsgButtons.MK_LBUTTON;
439                                                                                 }
440                                                                                 break;
441                                                                         case 2:
442                                                                                 if (eventKind == 1) {
443                                                                                         mouse_state |= MouseButtons.Middle;
444                                                                                         msg.message = Msg.WM_MBUTTONDOWN;
445                                                                                         wParam |= (int)MsgButtons.MK_MBUTTON;
446                                                                                 } else {
447                                                                                         mouse_state &= MouseButtons.Middle;
448                                                                                         msg.message = Msg.WM_MBUTTONUP;
449                                                                                         wParam |= (int)MsgButtons.MK_MBUTTON;
450                                                                                 }
451                                                                                 break;
452                                                                         case 3:
453                                                                                 if (eventKind == 1) {
454                                                                                         mouse_state |= MouseButtons.Right;
455                                                                                         msg.message = Msg.WM_RBUTTONDOWN;
456                                                                                         wParam |= (int)MsgButtons.MK_RBUTTON;
457                                                                                 } else {
458                                                                                         mouse_state &= MouseButtons.Right;
459                                                                                         msg.message = Msg.WM_RBUTTONUP;
460                                                                                         wParam |= (int)MsgButtons.MK_RBUTTON;
461                                                                                 }
462                                                                                 break;
463                                                                 }
464                                                                 msg.wParam = (IntPtr)wParam;
465                                                                 msg.lParam = (IntPtr) ((ushort)hiPoint.y << 16 | (ushort)hiPoint.x);
466                                                                 mouse_position.X = (int)hiPoint.x;
467                                                                 mouse_position.Y = (int)hiPoint.y;
468                                                                 carbonEvents.Enqueue (msg);
469                                                                 return -9874;
470                                                         }
471                                                         case 5: {
472                                                                 QDPoint point = new QDPoint ();
473                                                                 IntPtr pView = IntPtr.Zero;
474                                                                 IntPtr rView = IntPtr.Zero;                                                             
475                                                                 ushort btn = 0;
476                                                                 GetEventParameter (inEvent, 1835168878, 1835168878, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (ushort)), IntPtr.Zero, ref btn);
477                                                                 CheckError (GetEventParameter (inEvent, 1835822947, 1363439732, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (QDPoint)), IntPtr.Zero, ref point), "GetEventParameter() MouseLocation");
478                                                                 SetPortWindowPort (controlHnd);
479                                                                 GlobalToLocal (ref point);
480                                                                 // Translate this point
481                                                                 Rect bounds = new Rect ();
482                                                                 CheckError (GetWindowBounds (controlHnd, 32, ref bounds), "GetWindowBounds ()");
483                                                                 // Swizzle it so its pointed at the right control
484                                                                 CGPoint hiPoint = new CGPoint (point.y, point.x);
485                                                                 CheckError (HIViewFindByID (HIViewGetRoot (controlHnd), new HIViewID (2003398244, 1), ref pView), "HIViewFindByID ()");
486                                                                 CheckError (HIViewGetSubviewHit (pView, ref hiPoint, true, ref rView));
487                                                                 HIViewConvertPoint (ref hiPoint, pView, rView);
488                                                                 if (mouseInWindow != rView && grabWindow != IntPtr.Zero) {
489                                                                         msg.hwnd = mouseInWindow;
490                                                                         msg.message = Msg.WM_MOUSE_LEAVE;
491                                                                         carbonEvents.Enqueue (msg);
492                                                                         msg.hwnd = rView;
493                                                                         msg.message = Msg.WM_MOUSE_ENTER;
494                                                                         carbonEvents.Enqueue (msg);
495                                                                         mouseInWindow = rView;
496                                                                         return -9874;
497                                                                 }
498                                                                 return -9874;
499                                                         }
500                                                         case 6: {
501                                                                 QDPoint point = new QDPoint ();
502                                                                 IntPtr pView = IntPtr.Zero;
503                                                                 IntPtr rView = IntPtr.Zero;                                                             
504                                                                 ushort btn = 0;
505                                                                 GetEventParameter (inEvent, 1835168878, 1835168878, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (ushort)), IntPtr.Zero, ref btn);
506                                                                 CheckError (GetEventParameter (inEvent, 1835822947, 1363439732, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (QDPoint)), IntPtr.Zero, ref point), "GetEventParameter() MouseLocation");
507                                                                 SetPortWindowPort (controlHnd);
508                                                                 GlobalToLocal (ref point);
509                                                                 // Translate this point
510                                                                 Rect bounds = new Rect ();
511                                                                 CheckError (GetWindowBounds (controlHnd, 32, ref bounds), "GetWindowBounds ()");
512                                                                 // Swizzle it so its pointed at the right control
513                                                                 CGPoint hiPoint = new CGPoint (point.y, point.x);
514                                                                 CheckError (HIViewFindByID (HIViewGetRoot (controlHnd), new HIViewID (2003398244, 1), ref pView), "HIViewFindByID ()");
515                                                                 CheckError (HIViewGetSubviewHit (pView, ref hiPoint, true, ref rView));
516                                                                 HIViewConvertPoint (ref hiPoint, pView, rView);
517                                                                 if (mouseInWindow != rView && grabWindow != IntPtr.Zero) {
518                                                                         msg.hwnd = mouseInWindow;
519                                                                         msg.message = Msg.WM_MOUSE_LEAVE;
520                                                                         carbonEvents.Enqueue (msg);
521                                                                         msg.hwnd = rView;
522                                                                         msg.message = Msg.WM_MOUSE_ENTER;
523                                                                         carbonEvents.Enqueue (msg);
524                                                                         mouseInWindow = rView;
525                                                                         return -9874;
526                                                                 }
527                                                                 if (grabWindow == IntPtr.Zero)
528                                                                         msg.hwnd = rView;
529                                                                 else
530                                                                         msg.hwnd = grabWindow;
531                                                                 msg.message = Msg.WM_MOUSEMOVE;
532                                                                 msg.lParam = (IntPtr) ((ushort)hiPoint.y << 16 | (ushort)hiPoint.x);
533                                                                 msg.wParam = GetMousewParam (0);
534                                                                 mouse_position.X = (int)hiPoint.x;
535                                                                 mouse_position.Y = (int)hiPoint.y;
536                                                                 carbonEvents.Enqueue (msg);
537                                                                 return -9874;
538                                                         }
539                                                         default:
540                                                                 Console.WriteLine (eventKind);
541                                                                 break;
542                                                 }
543                                                 break;
544                                         }
545                                 }
546                                 msg.message = Msg.WM_ENTERIDLE;
547                                 carbonEvents.Enqueue (msg);
548                         }
549                         return -9874;
550                 }
551                 internal int ViewHandler (IntPtr inCallRef, IntPtr inEvent, IntPtr controlHnd) {
552                         int eventClass = GetEventClass (inEvent);
553                         int eventKind = GetEventKind (inEvent);
554                         MSG msg = new MSG ();
555                         msg.hwnd = controlHnd;
556                         lock (carbonEvents) {
557                                 switch (eventClass) {
558                                         case 1668183148:
559                                                 switch (eventKind) {
560                                                         case 4: {
561                                                                 if (handle_data [controlHnd] == null)
562                                                                         handle_data [controlHnd] = new HandleData ();
563                                                                 HIRect bounds = new HIRect ();
564                                                                 HIViewGetBounds (controlHnd, ref bounds); 
565                                                                 ((HandleData) handle_data [controlHnd]).AddToInvalidArea ((int)bounds.origin.x, (int)bounds.origin.y, (int)bounds.size.width, (int)bounds.size.height);
566                                                                 msg.message = Msg.WM_PAINT;
567                                                                 msg.wParam = IntPtr.Zero;
568                                                                 msg.lParam = IntPtr.Zero;
569                                                                 DispatchMessage (ref msg);
570 ////                                                            carbonEvents.Enqueue (msg);
571                                                                 return 0;
572                                                         }
573                                                 }
574                                                 break;
575                                 }
576                                 msg.message = Msg.WM_ENTERIDLE;
577                                 carbonEvents.Enqueue (msg);
578                         }
579                         
580                         return 0;
581                 }
582
583                 //FIXME: If there are timers; we can loop really hard churning cpu
584                 internal override bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
585                         IntPtr evtRef = IntPtr.Zero;
586                         IntPtr target = GetEventDispatcherTarget();
587                         CheckTimers (DateTime.Now);
588                         ReceiveNextEvent (0, IntPtr.Zero, 0, true, ref evtRef);
589                         if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
590                                 SendEventToEventTarget (evtRef, target);
591                                 ReleaseEvent (evtRef);
592                         }
593                         
594                         lock (carbonEvents) {
595                                 if (carbonEvents.Count <= 0) {
596                                         if (Idle != null) 
597                                                 Idle (this, EventArgs.Empty);
598                                         else if (timer_list.Count == 0) {
599                                                 ReceiveNextEvent (0, IntPtr.Zero, 0x7FFFFFFF, true, ref evtRef);
600                                                 if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
601                                                         SendEventToEventTarget (evtRef, target);
602                                                         ReleaseEvent (evtRef);
603                                                 }
604                                         }
605                                         msg.hwnd = IntPtr.Zero;
606                                         msg.message = Msg.WM_ENTERIDLE;
607                                         return true;
608                                 }
609                                 msg = (MSG) carbonEvents.Dequeue ();
610                         }
611                         return true;
612                 }
613
614                 internal override bool TranslateMessage(ref MSG msg) {
615                         return true;
616                 }
617
618                 internal override IntPtr DispatchMessage(ref MSG msg) {
619                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
620                 }
621
622                 [MonoTODO]
623                 internal override bool SetZOrder(IntPtr hWnd, IntPtr AfterhWnd, bool Top, bool Bottom) {
624                         throw new NotImplementedException ();
625                 }
626
627                 [MonoTODO]
628                 internal override bool SetTopmost(IntPtr hWnd, IntPtr hWndOwner, bool Enabled) {
629                         // FIXME
630                         return true;
631                 }
632
633                 internal override bool Text(IntPtr handle, string text) {
634                         // FIXME: We need to set the window as well if this is the root control.
635                         if (view_window_mapping [handle] != null) {
636                                 CheckError (SetWindowTitleWithCFString ((IntPtr)(view_window_mapping [handle]), __CFStringMakeConstantString (text)));
637                         }
638                         CheckError (SetControlTitleWithCFString (handle, __CFStringMakeConstantString (text)));
639                         return true;
640                 }
641
642                 [MonoTODO]
643                 internal override bool GetText(IntPtr handle, out string text) {
644                         throw new NotImplementedException ();
645                 }
646
647                 internal override bool SetVisible(IntPtr handle, bool visible) {
648                         // We dont have "windows" on OSX, we have views; so we toggle the view visibility here  
649                         HandleData data = (HandleData) handle_data [handle];
650
651                         if (data == null) {
652                                 data = new HandleData ();
653                                 handle_data [handle] = data;
654                         }
655                         if (view_window_mapping [handle] != null && visible == true) {
656                                 ShowWindow ((IntPtr) view_window_mapping [handle]);
657                         }
658                         if (view_window_mapping [handle] != null && visible == false) {
659                                 HideWindow ((IntPtr) view_window_mapping [handle]);
660                         }
661                         data.IsVisible = visible;
662
663                         CheckError (HIViewSetVisible (handle, visible));
664                         // We have to manually reset all children as well
665                         
666                         return true;
667                 }
668
669                 internal override bool IsVisible(IntPtr handle) {
670                         HandleData data = (HandleData) handle_data [handle];
671
672                         if (data == null || data.IsVisible == true) {
673                                 return true;
674                         }
675                         return false;
676                 }
677
678                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
679                         if (HIViewGetSuperview (handle) != IntPtr.Zero)
680                                 CheckError (HIViewRemoveFromSuperview (handle), "HIViewRemoveFromSuperview ()");
681                         HIViewAddSubview (parent, handle);
682                         SetVisible (handle, IsVisible (parent));
683                         return IntPtr.Zero;
684                 }
685
686                 internal override IntPtr GetParent(IntPtr handle) {
687                         return HIViewGetSuperview (handle);
688                 }
689
690                 [MonoTODO]
691                 internal override void GrabWindow(IntPtr hWnd, IntPtr confine_hwnd) {
692                         grabWindow = hWnd;
693                 }
694
695                 [MonoTODO]
696                 internal override void GrabInfo(out IntPtr hWnd, out bool GrabConfined, out Rectangle GrabArea) {
697                         throw new NotImplementedException ();
698                 }
699
700                 internal override void ReleaseWindow(IntPtr hWnd) {
701                         grabWindow = IntPtr.Zero;
702                 }
703
704                 internal override bool CalculateWindowRect(IntPtr hWnd, ref Rectangle ClientRect, int Style, bool HasMenu, out Rectangle WindowRect) {
705                         WindowRect = new Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Width, ClientRect.Height);
706                         return true;
707                 }
708
709                 [MonoTODO]
710                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
711                         throw new NotImplementedException ();
712                 }
713
714                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
715                         x = mouse_position.X;
716                         y = mouse_position.Y;
717                 }
718
719                 [MonoTODO]
720                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
721 //                      throw new NotImplementedException ();
722                 }
723
724                 [MonoTODO]
725                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
726 //                      throw new NotImplementedException ();
727                 }
728
729                 [MonoTODO]
730                 internal override void SendAsyncMethod (AsyncMethodData method) {
731                         throw new NotImplementedException ();
732                 }
733
734                 private IntPtr GetMousewParam(int Delta) {
735                         int     result = 0;
736
737                         if ((mouse_state & MouseButtons.Left) != 0) {
738                                 result |= (int)MsgButtons.MK_LBUTTON;
739                         }
740
741                         if ((mouse_state & MouseButtons.Middle) != 0) {
742                                 result |= (int)MsgButtons.MK_MBUTTON;
743                         }
744
745                         if ((mouse_state & MouseButtons.Right) != 0) {
746                                 result |= (int)MsgButtons.MK_RBUTTON;
747                         }
748
749                         return (IntPtr)result;
750                 }
751
752                 private void CheckTimers (DateTime now)
753                 {
754                         lock (timer_list) {
755                                 int count = timer_list.Count;
756                                 if (count == 0)
757                                         return;
758                                 for (int i = 0; i < timer_list.Count; i++) {
759                                         Timer timer = (Timer) timer_list [i];
760                                         if (timer.Enabled && timer.Expires <= now) {
761                                                 timer.FireTick ();
762                                                 timer.Update (now);
763                                         }
764                                 }
765                         }
766                 }
767
768                 internal override void SetTimer (Timer timer) {
769                         lock (timer_list) {
770                                 timer_list.Add (timer);
771                         }
772                 }
773
774                 internal override void KillTimer (Timer timer)
775                 {
776                         lock (timer_list) {
777                                 timer_list.Remove (timer);
778                         }
779                 }
780
781                 [MonoTODO]
782                 internal override void CreateCaret(IntPtr hwnd, int width, int height) {
783                 }
784
785                 [MonoTODO]
786                 internal override void DestroyCaret(IntPtr hwnd) {
787                 }
788
789                 [MonoTODO]
790                 internal override void SetCaretPos(IntPtr hwnd, int x, int y) {
791                 }
792
793                 [MonoTODO]
794                 internal override void CaretVisible(IntPtr hwnd, bool visible) {
795                 }
796
797
798                 [MonoTODO]
799                 internal override int KeyboardSpeed {
800                         get {
801                                 throw new NotImplementedException ();
802                         }
803                 }
804
805                 [MonoTODO]
806                 internal override int KeyboardDelay {
807                         get {
808                                 throw new NotImplementedException ();
809                         }
810                 }
811
812                 internal void CheckError (int result, string error) {
813                         if (result != 0)
814                                 throw new Exception ("XplatUIOSX.cs::" + error + "() Carbon subsystem threw an error: " + result);
815                 }
816                 internal void CheckError (int result) {
817                         if (result != 0)
818                                 throw new Exception ("XplatUIOSX.cs::Carbon subsystem threw an error: " + result);
819                 }
820
821                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
822                 internal static extern int HIViewGetSubviewHit (IntPtr contentView, ref CGPoint point, bool tval, ref IntPtr outPtr);
823                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
824                 internal static extern int HIViewConvertPoint (ref CGPoint point, IntPtr pView, IntPtr cView);
825                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
826                 internal static extern int HIViewChangeFeatures (IntPtr aView, ulong bitsin, ulong bitsout);
827                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
828                 internal static extern int HIViewFindByID (IntPtr rootWnd, HIViewID id, ref IntPtr outPtr);
829                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
830                 internal static extern IntPtr HIViewGetRoot (IntPtr hWnd);
831                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
832                 internal static extern int HIObjectCreate (IntPtr cfStr, uint what, ref IntPtr hwnd);
833                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
834                 internal static extern int HIViewSetNeedsDisplay (IntPtr viewHnd, bool update);
835                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
836                 internal static extern int HIViewGetFrame (IntPtr viewHnd, ref HIRect rect);
837                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
838                 internal static extern int HIViewSetFrame (IntPtr viewHnd, ref HIRect rect);
839                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
840                 internal static extern int HIViewPlaceInSuperviewAt (IntPtr view, float x, float y);
841                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
842                 internal static extern int HIViewAddSubview (IntPtr parentHnd, IntPtr childHnd);
843                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
844                 internal static extern IntPtr HIViewGetNextView (IntPtr aView);
845                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
846                 internal static extern IntPtr HIViewGetPreviousView (IntPtr aView);
847                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
848                 internal static extern IntPtr HIViewGetSuperview (IntPtr aView);
849                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
850                 internal static extern int HIViewRemoveFromSuperview (IntPtr aView);
851                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
852                 internal static extern int HIViewSetVisible (IntPtr vHnd, bool visible);
853                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
854                 internal static extern bool HIViewIsVisible (IntPtr vHnd);
855                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
856                 internal static extern int HIViewGetBounds (IntPtr vHnd, ref HIRect r);
857                 
858                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
859                 internal static extern void SetRect (ref IntPtr r, short left, short top, short right, short bottom);
860
861                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
862                 static extern int CreateEvent (IntPtr allocator, uint classid, uint kind, double when, uint attributes, ref IntPtr outEvent);
863                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
864                 static extern int InstallEventHandler (IntPtr window, CarbonEventHandler handlerProc, uint numtypes, EventTypeSpec [] typeList, IntPtr userData, IntPtr handlerRef);
865                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
866                 internal static extern IntPtr GetWindowEventTarget (IntPtr window);
867                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
868                 internal static extern IntPtr GetControlEventTarget (IntPtr aControl);
869                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
870                 internal static extern IntPtr GetEventDispatcherTarget ();
871                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
872                 internal static extern int SendEventToEventTarget (IntPtr evt, IntPtr target);
873                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
874                 internal static extern int ReleaseEvent (IntPtr evt);
875                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
876                 internal static extern int ReceiveNextEvent (uint evtCount, IntPtr evtTypes, double timeout, bool processEvt, ref IntPtr evt);
877                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
878                 static extern int GetEventClass (IntPtr eventRef);
879                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
880                 static extern int GetEventKind (IntPtr eventRef);
881                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
882                 static extern int GetEventParameter (IntPtr evt, uint inName, uint inType, IntPtr outActualType, uint bufSize, IntPtr outActualSize, ref IntPtr outData);
883                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
884                 static extern int GetEventParameter (IntPtr evt, uint inName, uint inType, IntPtr outActualType, uint bufSize, IntPtr outActualSize, ref ushort outData);
885                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
886                 static extern int GetEventParameter (IntPtr evt, uint inName, uint inType, IntPtr outActualType, uint bufSize, IntPtr outActualSize, ref QDPoint outData);
887
888                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
889                 static extern int SetPortWindowPort (IntPtr hWnd);
890                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
891                 static extern int GlobalToLocal (ref QDPoint outData);
892
893                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
894                 internal static extern int CreateNewWindow (int klass, uint attributes, ref IntPtr r, ref IntPtr window);
895                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
896                 internal static extern int ShowWindow (IntPtr wHnd);
897                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
898                 internal static extern int HideWindow (IntPtr wHnd);
899                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
900                 internal static extern int SetWindowBounds (IntPtr wHnd, uint reg, ref IntPtr rect);
901                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
902                 internal static extern int GetWindowBounds (IntPtr wHnd, uint reg, ref Rect rect);
903
904                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
905                 internal static extern int SetControlTitleWithCFString (IntPtr hWnd, IntPtr titleCFStr);
906                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
907                 internal static extern int SetWindowTitleWithCFString (IntPtr hWnd, IntPtr titleCFStr);
908                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
909                 internal static extern IntPtr __CFStringMakeConstantString (string cString);
910                 
911                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
912                 internal static extern void CGContextRestoreGState (IntPtr ctx);
913                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
914                 internal static extern void CGContextSaveGState (IntPtr ctx);
915                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
916                 internal static extern void CGContextTranslateCTM (IntPtr ctx, double tx, double ty);
917                 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
918                 internal static extern void CGContextScaleCTM (IntPtr ctx, double tx, double ty);
919
920                 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
921                 static extern int SetWindowContentColor (IntPtr hWnd, ref RGBColor backColor);
922         }
923
924         internal struct CGSize {
925                 public float width;
926                 public float height;
927
928                 public CGSize (int w, int h) {
929                         this.width = (float)w;
930                         this.height = (float)h;
931                 }
932         }
933
934         internal struct QDPoint {
935                 public short x;
936                 public short y;
937
938                 public QDPoint (short x, short y) {
939                         this.x = x;
940                         this.y = y;
941                 }
942         }
943         internal struct CGPoint {
944                 public float x;
945                 public float y;
946
947                 public CGPoint (int x, int y) {
948                         this.x = (float)x;
949                         this.y = (float)y;
950                 }
951         }
952
953         internal struct HIRect {
954                 public CGPoint origin;
955                 public CGSize size;
956
957                 public HIRect (int x, int y, int w, int h) {
958                         this.origin = new CGPoint (x, y);
959                         this.size = new CGSize (w, h);
960                 }
961         }
962
963         internal struct HIViewID {
964                 public uint type;
965                 public uint id;
966
967                 public HIViewID (uint type, uint id) {
968                         this.type = type;
969                         this.id = id;
970                 }
971         }
972         
973         internal struct EventTypeSpec
974         {
975                 public UInt32 eventClass;
976                 public UInt32 eventKind;
977
978                 public EventTypeSpec (UInt32 eventClass, UInt32 eventKind)
979                 {
980                         this.eventClass = eventClass;
981                         this.eventKind = eventKind;
982                 }
983         }
984         
985         internal struct CarbonEvent
986         {
987                 public IntPtr hWnd;
988                 public IntPtr evt;
989
990                 public CarbonEvent (IntPtr hWnd, IntPtr evt)
991                 {
992                         this.hWnd = hWnd;
993                         this.evt = evt;
994                 }
995         }
996         
997         internal struct RGBColor
998         {
999                 public short red;
1000                 public short green;
1001                 public short blue;
1002         }
1003
1004         internal struct Rect
1005         {
1006                 public short top;
1007                 public short left;
1008                 public short bottom;
1009                 public short right;
1010         }
1011
1012 }