2006-01-26 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.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-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26
27 // NOTE:
28 //      This driver understands the following environment variables: (Set the var to enable feature)
29 //
30 //      MONO_XEXCEPTIONS        = throw an exception when a X11 error is encountered;
31 //                                by default a message is displayed but execution continues
32 //
33 //      MONO_XSYNC              = perform all X11 commands synchronous; this is slower but
34 //                                helps in debugging errors
35 //
36
37 // NOT COMPLETE
38
39 // define to log Window handles and relationships to stdout
40 #undef DriverDebug
41
42 // Extra detailed debug
43 #undef  DriverDebugExtra
44
45 using System;
46 using System.ComponentModel;
47 using System.Collections;
48 using System.Diagnostics;
49 using System.Drawing;
50 using System.Drawing.Drawing2D;
51 using System.Drawing.Imaging;
52 using System.IO;
53 using System.Net;
54 using N = System.Net;
55 using System.Net.Sockets;
56 using System.Reflection;
57 using System.Runtime.InteropServices;
58 using System.Text;
59 using System.Threading;
60
61 // Only do the poll when building with mono for now
62 #if __MonoCS__
63 using Mono.Unix.Native;
64 #endif
65
66 /// X11 Version
67 namespace System.Windows.Forms {
68         internal class XplatUIX11 : XplatUIDriver {
69                 #region Local Variables
70                 // General
71                 static volatile XplatUIX11      Instance;
72                 private static int              RefCount;
73                 private static object           XlibLock;               // Our locking object
74                 private static bool             ThemesEnabled;
75
76                 // General X11
77                 private static IntPtr           DisplayHandle;          // X11 handle to display
78                 private static int              ScreenNo;               // Screen number used
79                 private static IntPtr           DefaultColormap;        // Colormap for screen
80                 private static IntPtr           CustomVisual;           // Visual for window creation
81                 private static IntPtr           CustomColormap;         // Colormap for window creation
82                 private static IntPtr           RootWindow;             // Handle of the root window for the screen/display
83                 private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
84                 private static XErrorHandler    ErrorHandler;           // Error handler delegate
85                 private static bool             ErrorExceptions;        // Throw exceptions on X errors
86                 private static bool             PostQuitState;          // True if we've got an pending exit
87
88                 // Clipboard
89                 private static IntPtr           ClipMagic = new IntPtr(27051977);
90                 private static ClipboardStruct  Clipboard;              // Our clipboard
91
92                 // Communication
93                 private static int              PostAtom;               // PostMessage atom
94                 private static int              AsyncAtom;              // Support for async messages
95
96                 // Message Loop
97                 private static XEventQueue      MessageQueue;           // Holds our queued up events
98                 #if __MonoCS__                                          //
99                 private static Pollfd[]         pollfds;                // For watching the X11 socket
100                 #endif                                                  //
101                 private static X11Keyboard      Keyboard;               //
102                 private static X11Dnd           Dnd;
103                 private static Socket           listen;                 //
104                 private static Socket           wake;                   //
105                 private static Socket           wake_receive;           //
106                 private static byte[]           network_buffer;         //
107
108
109                 // Focus tracking
110                 private static IntPtr           ActiveWindow;           // Handle of the active window
111                 private static IntPtr           FocusWindow;            // Handle of the window with keyboard focus (if any)
112
113                 // Modality support
114                 private static Stack            ModalWindows;           // Stack of our modal windows
115
116                 // Systray
117                 private static IntPtr           SystrayMgrWindow;       // Handle of the Systray Manager window
118
119                 // Cursors
120                 private static IntPtr           LastCursorWindow;       // The last window we set the cursor on
121                 private static IntPtr           LastCursorHandle;       // The handle that was last set on LastCursorWindow
122                 private static IntPtr           OverrideCursorHandle;   // The cursor that is set to override any other cursors
123
124                 // Caret
125                 private static CaretStruct      Caret;                  //
126
127                 // Support for Window Styles
128                 private static int[]            NetAtoms;               // All atoms we know
129
130                 // mouse hover message generation
131                 private static HoverStruct      HoverState;             //
132
133                 // double click message generation
134                 private static ClickStruct      ClickPending;           //
135
136                 // Support for mouse grab
137                 private static GrabStruct       Grab;                   //
138
139                 // State
140                 private static Point            MousePosition;          // Last position of mouse, in screen coords
141                 internal static MouseButtons    MouseState;             // Last state of mouse buttons
142
143                 // Timers
144                 private static ArrayList        TimerList;              // Holds SWF.Timers
145
146                 // 'Constants'
147                 private static int              DoubleClickInterval;    // msec; max interval between clicks to count as double click
148
149                 const EventMask SelectInputMask = EventMask.ButtonPressMask | 
150                                                   EventMask.ButtonReleaseMask | 
151                                                   EventMask.KeyPressMask | 
152                                                   EventMask.KeyReleaseMask | 
153                                                   EventMask.EnterWindowMask | 
154                                                   EventMask.LeaveWindowMask |
155                                                   EventMask.ExposureMask |
156                                                   EventMask.FocusChangeMask |
157                                                   EventMask.PointerMotionMask | 
158                                                   EventMask.VisibilityChangeMask |
159                                                   EventMask.SubstructureNotifyMask |
160                                                   EventMask.StructureNotifyMask;
161
162                 static readonly object lockobj = new object ();
163
164                 #endregion      // Local Variables
165                 #region Constructors
166                 private XplatUIX11() {
167                         // Handle singleton stuff first
168                         RefCount = 0;
169
170                         // Now regular initialization
171                         XlibLock = new object ();
172                         MessageQueue = new XEventQueue ();
173                         TimerList = new ArrayList ();
174                         XInitThreads();
175
176                         ErrorExceptions = false;
177
178                         // X11 Initialization
179                         SetDisplay(XOpenDisplay(IntPtr.Zero));
180                         X11DesktopColors.Initialize();
181
182                         // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
183                         ErrorHandler = new XErrorHandler(HandleError);
184                         XSetErrorHandler(ErrorHandler);
185                 }
186                 #endregion      // Constructors
187
188                 #region Singleton Specific Code
189                 public static XplatUIX11 GetInstance() {
190                         lock (lockobj) {
191                                 if (Instance == null) {
192                                         Instance=new XplatUIX11();
193                                 }
194                                 RefCount++;
195                         }
196                         return Instance;
197                 }
198
199                 public int Reference {
200                         get {
201                                 return RefCount;
202                         }
203                 }
204                 #endregion
205
206                 #region Internal Properties
207                 internal static IntPtr Display {
208                         get {
209                                 return DisplayHandle;
210                         }
211
212                         set {
213                                 XplatUIX11.GetInstance().SetDisplay(value);
214                         }
215                 }
216
217                 internal static int Screen {
218                         get {
219                                 return ScreenNo;
220                         }
221
222                         set {
223                                 ScreenNo = value;
224                         }
225                 }
226
227                 internal static IntPtr RootWindowHandle {
228                         get {
229                                 return RootWindow;
230                         }
231
232                         set {
233                                 RootWindow = value;
234                         }
235                 }
236
237                 internal static IntPtr Visual {
238                         get {
239                                 return CustomVisual;
240                         }
241
242                         set {
243                                 CustomVisual = value;
244                         }
245                 }
246
247                 internal static IntPtr ColorMap {
248                         get {
249                                 return CustomColormap;
250                         }
251
252                         set {
253                                 CustomColormap = value;
254                         }
255                 }
256                 #endregion
257
258                 #region XExceptionClass
259                 internal class XException : ApplicationException {
260                         IntPtr          Display;
261                         IntPtr          ResourceID;
262                         IntPtr          Serial;
263                         XRequest        RequestCode;
264                         byte            ErrorCode;
265                         byte            MinorCode;
266
267                         public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
268                                 this.Display = Display;
269                                 this.ResourceID = ResourceID;
270                                 this.Serial = Serial;
271                                 this.RequestCode = RequestCode;
272                                 this.ErrorCode = ErrorCode;
273                                 this.MinorCode = MinorCode;
274                         }
275
276                         public override string Message {
277                                 get {
278                                         return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
279                                 }
280                         }
281
282                         public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
283                                 StringBuilder   sb;
284                                 string          x_error_text;
285                                 string          error;
286
287                                 sb = new StringBuilder(160);
288                                 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
289                                 x_error_text = sb.ToString();
290
291                                 error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:x}\n  Serial:      {4}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial);
292                                 return error;
293                         }
294                 }
295                 #endregion      // XExceptionClass
296
297                 #region Internal Methods
298                 internal void SetDisplay(IntPtr display_handle) {
299                         if (display_handle != IntPtr.Zero) {
300                                 Hwnd    hwnd;
301
302                                 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
303                                         hwnd = Hwnd.ObjectFromHandle(FosterParent);
304                                         XDestroyWindow(DisplayHandle, FosterParent);
305                                         hwnd.Dispose();
306                                 }
307
308                                 if (DisplayHandle != IntPtr.Zero) {
309                                         XCloseDisplay(DisplayHandle);
310                                 }
311
312                                 DisplayHandle=display_handle;
313
314                                 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
315                                 // been hacked to do this for us.
316                                 Graphics.FromHdcInternal (DisplayHandle);
317
318                                 // Debugging support
319                                 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
320                                         XSynchronize(DisplayHandle, true);
321                                 }
322
323                                 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
324                                         ErrorExceptions = true;
325                                 }
326
327                                 // Generic X11 setup
328                                 ScreenNo = 0;
329                                 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
330                                 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
331
332                                 // Create the foster parent
333                                 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, 0, 0);
334                                 if (FosterParent==IntPtr.Zero) {
335                                         Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
336                                 }
337
338                                 hwnd = new Hwnd();
339                                 hwnd.WholeWindow = FosterParent;
340                                 hwnd.ClientWindow = FosterParent;
341
342                                 // For sleeping on the X11 socket
343                                 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
344                                 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
345                                 listen.Bind(ep);
346                                 listen.Listen(1);
347
348                                 // To wake up when a timer is ready
349                                 network_buffer = new byte[10];
350
351                                 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
352                                 wake.Connect(listen.LocalEndPoint);
353                                 wake_receive = listen.Accept();
354
355                                 #if __MonoCS__
356                                 pollfds = new Pollfd [2];
357                                 pollfds [0] = new Pollfd ();
358                                 pollfds [0].fd = XConnectionNumber (DisplayHandle);
359                                 pollfds [0].events = PollEvents.POLLIN;
360
361                                 pollfds [1] = new Pollfd ();
362                                 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
363                                 pollfds [1].events = PollEvents.POLLIN;
364                                 #endif
365
366                                 Keyboard = new X11Keyboard(DisplayHandle);
367                                 Dnd = new X11Dnd (DisplayHandle);
368
369                                 PostQuitState = false;
370
371                                 DoubleClickInterval = 500;
372
373                                 HoverState.Interval = 500;
374                                 HoverState.Timer = new Timer();
375                                 HoverState.Timer.Enabled = false;
376                                 HoverState.Timer.Interval = HoverState.Interval;
377                                 HoverState.Timer.Tick +=new EventHandler(MouseHover);
378                                 HoverState.X = -1;
379                                 HoverState.Y = -1;
380
381                                 ActiveWindow = IntPtr.Zero;
382                                 FocusWindow = IntPtr.Zero;
383                                 ModalWindows = new Stack(3);
384
385                                 MouseState = MouseButtons.None;
386                                 MousePosition = new Point(0, 0);
387
388                                 Caret.Timer = new Timer();
389                                 Caret.Timer.Interval = 500;             // FIXME - where should this number come from?
390                                 Caret.Timer.Tick += new EventHandler(CaretCallback);
391
392                                 SetupAtoms();
393
394                                 // Grab atom changes off the root window to catch certain WM events
395                                 XSelectInput(DisplayHandle, RootWindow, EventMask.PropertyChangeMask);
396
397                                 // Handle any upcoming errors
398                                 ErrorHandler = new XErrorHandler(HandleError);
399                                 XSetErrorHandler(ErrorHandler);
400                         } else {
401                                 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
402                         }
403                 }
404
405                 internal static void Where() {
406                         Console.WriteLine("Here: {0}\n", WhereString());
407                 }
408
409                 internal static string WhereString() {
410                         StackTrace      stack;
411                         StackFrame      frame;
412                         string          newline;
413                         string          unknown;
414                         StringBuilder   sb;
415                         MethodBase      method;
416
417                         newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
418                         unknown = Locale.GetText("<unknown method>");
419                         sb = new StringBuilder();
420                         stack = new StackTrace(true);
421
422                         for (int i = 0; i < stack.FrameCount; i++) {
423                                 frame = stack.GetFrame(i);
424                                 sb.Append(newline);
425
426                                 method = frame.GetMethod();
427                                 if (method != null) {
428                                         #if not
429                                                 sb.AppendFormat(frame.ToString());
430                                         #endif
431                                         if (frame.GetFileLineNumber() != 0) {
432                                                 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
433                                         } else {
434                                                 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
435                                         }
436                                 } else { 
437                                         sb.Append(unknown);
438                                 }
439                         }
440                         return sb.ToString();
441                 }
442                 #endregion      // Internal Methods
443
444                 #region Private Methods
445                 private static void SetupAtoms() {
446                         NetAtoms = new int[(int)NA.LAST_NET_ATOM];
447
448                         NetAtoms[(int)NA.WM_PROTOCOLS] = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
449                         NetAtoms[(int)NA.WM_DELETE_WINDOW] = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
450                         NetAtoms[(int)NA.WM_TAKE_FOCUS] = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
451
452                         NetAtoms[(int)NA._NET_SUPPORTED] = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
453                         NetAtoms[(int)NA._NET_CLIENT_LIST] = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
454                         NetAtoms[(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
455                         NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
456                         NetAtoms[(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
457                         NetAtoms[(int)NA._NET_CURRENT_DESKTOP] = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
458                         NetAtoms[(int)NA._NET_DESKTOP_NAMES] = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
459                         NetAtoms[(int)NA._NET_ACTIVE_WINDOW] = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
460                         NetAtoms[(int)NA._NET_WORKAREA] = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
461                         NetAtoms[(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
462                         NetAtoms[(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
463                         NetAtoms[(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
464                         NetAtoms[(int)NA._NET_SHOWING_DESKTOP] = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
465
466                         NetAtoms[(int)NA._NET_CLOSE_WINDOW] = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
467                         NetAtoms[(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
468                         NetAtoms[(int)NA._NET_WM_MOVERESIZE] = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
469                         NetAtoms[(int)NA._NET_RESTACK_WINDOW] = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
470                         NetAtoms[(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
471
472                         NetAtoms[(int)NA._NET_WM_NAME] = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
473                         NetAtoms[(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
474                         NetAtoms[(int)NA._NET_WM_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
475                         NetAtoms[(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
476                         NetAtoms[(int)NA._NET_WM_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
477                         NetAtoms[(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
478                         NetAtoms[(int)NA._NET_WM_STATE] = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
479                         NetAtoms[(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
480                         NetAtoms[(int)NA._NET_WM_STRUT] = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
481                         NetAtoms[(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
482                         NetAtoms[(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
483                         NetAtoms[(int)NA._NET_WM_ICON] = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
484                         NetAtoms[(int)NA._NET_WM_PID] = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
485                         NetAtoms[(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
486                         NetAtoms[(int)NA._NET_WM_USER_TIME] = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
487                         NetAtoms[(int)NA._NET_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
488
489                         NetAtoms[(int)NA._NET_WM_PING] = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
490                         NetAtoms[(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
491
492                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
493                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
494                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
495
496                         NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
497                         NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
498                         NetAtoms[(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
499
500                         NetAtoms[(int)NA._XEMBED] = XInternAtom(DisplayHandle, "_XEMBED", false);
501                         NetAtoms[(int)NA._XEMBED_INFO] = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
502
503                         NetAtoms[(int)NA._MOTIF_WM_HINTS] = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
504
505                         NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
506                         NetAtoms[(int)NA._NET_WM_STATE_ABOVE] = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
507                         NetAtoms[(int)NA._NET_WM_STATE_MODAL] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
508                         NetAtoms[(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
509                         NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
510
511                         // Clipboard support
512                         NetAtoms[(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
513                         NetAtoms[(int)NA.DIB] = (int)Atom.XA_PIXMAP;
514                         NetAtoms[(int)NA.OEMTEXT] = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
515                         NetAtoms[(int)NA.UNICODETEXT] = XInternAtom(DisplayHandle, "UTF8_STRING", false);
516                         NetAtoms[(int)NA.TARGETS] = XInternAtom(DisplayHandle, "TARGETS", false);
517
518                         // Special Atoms
519                         AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
520                         PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
521                         HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
522                 }
523
524                 private void GetSystrayManagerWindow() {
525                         XGrabServer(DisplayHandle);
526                         SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA._NET_SYSTEM_TRAY_S]);
527                         XUngrabServer(DisplayHandle);
528                         XFlush(DisplayHandle);
529                 }
530
531                 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
532                         XEvent  xev;
533
534                         xev = new XEvent();
535                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
536                         xev.ClientMessageEvent.send_event = true;
537                         xev.ClientMessageEvent.window = window;
538                         xev.ClientMessageEvent.message_type = message_type;
539                         xev.ClientMessageEvent.format = 32;
540                         xev.ClientMessageEvent.ptr1 = l0;
541                         xev.ClientMessageEvent.ptr2 = l1;
542                         xev.ClientMessageEvent.ptr3 = l2;
543                         XSendEvent(DisplayHandle, RootWindow, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
544                 }
545
546                 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
547                         XEvent  xev;
548
549                         xev = new XEvent();
550                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
551                         xev.ClientMessageEvent.send_event = true;
552                         xev.ClientMessageEvent.window = window;
553                         xev.ClientMessageEvent.message_type = message_type;
554                         xev.ClientMessageEvent.format = 32;
555                         xev.ClientMessageEvent.ptr1 = l0;
556                         xev.ClientMessageEvent.ptr2 = l1;
557                         xev.ClientMessageEvent.ptr3 = l2;
558                         XSendEvent(DisplayHandle, window, false, EventMask.NoEventMask, ref xev);
559                 }
560
561                 private void DeriveStyles(IntPtr handle, int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
562
563                         // Only MDI windows get caption_heights
564                         caption_height = 0;
565                         tool_caption_height = 19;
566
567                         if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
568                                 if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
569                                         border_style = FormBorderStyle.None;
570                                 } else if ((ExStyle & (int) WindowStyles.WS_EX_CLIENTEDGE) != 0) {
571                                         border_style = FormBorderStyle.Fixed3D;
572                                 } else {
573                                         border_style = FormBorderStyle.FixedSingle;
574                                 }
575                                 title_style = TitleStyle.None;
576                         } else {
577                                 bool is_mdi = false;
578
579                                 if ((ExStyle & (int) WindowStyles.WS_EX_MDICHILD) != 0) {
580                                         caption_height = 26;
581                                         is_mdi = true;
582                                 }
583
584                                 title_style = TitleStyle.None;
585                                 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
586                                         if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
587                                                 title_style = TitleStyle.Tool;
588                                         } else {
589                                                 title_style = TitleStyle.Normal;
590                                         }
591                                 }
592
593                                 if (!is_mdi) {
594                                         border_style = FormBorderStyle.None;
595
596                                         if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
597                                                 if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
598                                                         border_style = FormBorderStyle.SizableToolWindow;
599                                                 } else {
600                                                         border_style = FormBorderStyle.Sizable;
601                                                 }
602                                         } else {
603                                                 if ((ExStyle & (int)WindowStyles.WS_EX_CLIENTEDGE) != 0) {
604                                                         border_style = FormBorderStyle.Fixed3D;
605                                                 } else if ((ExStyle & (int)WindowStyles.WS_EX_DLGMODALFRAME) != 0) {
606                                                         border_style = FormBorderStyle.FixedDialog;
607                                                 } else if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
608                                                         border_style = FormBorderStyle.FixedToolWindow;
609                                                 } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
610                                                         border_style = FormBorderStyle.Sizable;
611                                                 } else {
612                                                         border_style = FormBorderStyle.None;
613                                                 }
614                                         }
615                                 } else {
616                                         if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
617                                                         (ExStyle & (int) WindowStyles.WS_EX_TOOLWINDOW) != 0) {
618                                                 border_style = (FormBorderStyle) 0xFFFF;
619                                         } else {
620                                                 border_style = FormBorderStyle.None;
621                                         }
622                                 }
623                         }
624                 }
625
626                 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
627                         DeriveStyles(hwnd.Handle, cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
628                 }
629
630                 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
631                         MotifWmHints            mwmHints;
632                         MotifFunctions          functions;
633                         MotifDecorations        decorations;
634                         uint[]                  atoms;
635                         int                     atom_count;
636                         Rectangle               client_rect;
637
638                         mwmHints = new MotifWmHints();
639                         functions = 0;
640                         decorations = 0;
641
642                         mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
643                         mwmHints.functions = (IntPtr)0;
644                         mwmHints.decorations = (IntPtr)0;
645
646                         if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
647                                 functions |= MotifFunctions.Move;
648                                 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
649                         }
650
651                         if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
652                                 functions |= MotifFunctions.Move | MotifFunctions.Resize;
653                                 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
654                         }
655                         if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
656                                 functions |= MotifFunctions.Minimize;
657                                 decorations |= MotifDecorations.Minimize;
658                         }
659
660                         if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
661                                 functions |= MotifFunctions.Maximize;
662                                 decorations |= MotifDecorations.Maximize;
663                         }
664
665                         if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
666                                 functions |= MotifFunctions.Close;
667                         }
668
669                         if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
670                                 decorations |= MotifDecorations.Border;
671                         }
672
673                         if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
674                                 decorations |= MotifDecorations.Border;
675                         }
676
677                         if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
678                                 decorations |= MotifDecorations.Border;
679                         }
680
681                         if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
682                                 functions = 0;
683                                 decorations = 0;
684                         }
685
686                         mwmHints.functions = (IntPtr)functions;
687                         mwmHints.decorations = (IntPtr)decorations;
688
689                         client_rect = hwnd.ClientRect;
690                         lock (XlibLock) {
691                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._MOTIF_WM_HINTS], NetAtoms[(int)NA._MOTIF_WM_HINTS], 32, PropertyMode.Replace, ref mwmHints, 5);
692
693                                 if (((cp.Style & (int)WindowStyles.WS_POPUP) != 0)  && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
694                                         XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
695                                 }
696                                 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
697
698                                 atoms = new uint[8];
699                                 atom_count = 0;
700
701                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
702                                         atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR];
703                                 }
704
705                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
706
707                                 atom_count = 0;
708                                 atoms[atom_count++] = (uint)NetAtoms[(int)NA.WM_DELETE_WINDOW];
709                                 if ((cp.ExStyle & (int)WindowStyles.WS_EX_CONTEXTHELP) != 0) {
710                                         atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
711                                 }
712
713                                 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atoms, atom_count);
714                         }
715                 }
716
717                 private void SetIcon(Hwnd hwnd, Icon icon) {
718                         Bitmap          bitmap;
719                         int             size;
720                         uint[]          data;
721                         int             index;
722
723                         bitmap = icon.ToBitmap();
724                         index = 0;
725                         size = bitmap.Width * bitmap.Height + 2;
726                         data = new uint[size];
727
728                         data[index++] = (uint)bitmap.Width;
729                         data[index++] = (uint)bitmap.Height;
730
731                         for (int y = 0; y < bitmap.Height; y++) {
732                                 for (int x = 0; x < bitmap.Width; x++) {
733                                         data[index++] = (uint)bitmap.GetPixel(x, y).ToArgb();
734                                 }
735                         }
736                         XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
737                 }
738
739                 private IntPtr ImageToPixmap(Image image) {
740                         return IntPtr.Zero;
741                 }
742
743                 private void WakeupMain () {
744                         wake.Send (new byte [] { 0xFF });
745                 }
746
747                 private void TranslatePropertyToClipboard(int property) {
748                         Atom                    actual_atom;
749                         int                     actual_format;
750                         int                     nitems;
751                         int                     bytes_after;
752                         IntPtr                  prop = IntPtr.Zero;
753
754                         Clipboard.Item = null;
755
756                         XGetWindowProperty(DisplayHandle, FosterParent, property, 0, 0x7fffffff, true, Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
757
758                         if (nitems > 0) {
759                                 if (property == (int)Atom.XA_STRING) {
760                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
761                                 } else if (property == (int)Atom.XA_BITMAP) {
762                                         // FIXME - convert bitmap to image
763                                 } else if (property == (int)Atom.XA_PIXMAP) {
764                                         // FIXME - convert pixmap to image
765                                 } else if (property == NetAtoms[(int)NA.OEMTEXT]) {
766                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
767                                 } else if (property == NetAtoms[(int)NA.UNICODETEXT]) {
768                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
769                                 }
770
771                                 XFree(prop);
772                         }
773                 }
774
775                 private void AddExpose (XEvent xevent) {
776                         Hwnd    hwnd;
777
778                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
779
780                         // Don't waste time
781                         if (hwnd == null) {     
782                                 return;
783                         }
784
785                         if (xevent.AnyEvent.window == hwnd.client_window) {
786                                 hwnd.AddInvalidArea(xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
787                                 if (!hwnd.expose_pending) {
788                                         MessageQueue.Enqueue(xevent);
789                                         hwnd.expose_pending = true;
790                                 }
791                         } else {
792                                 if (!hwnd.nc_expose_pending) {
793                                         MessageQueue.Enqueue(xevent);
794                                         hwnd.nc_expose_pending = true;
795                                 }
796                         }
797                 }
798
799                 private void InvalidateWholeWindow(IntPtr handle) {
800                         Hwnd    hwnd;
801
802                         hwnd = Hwnd.ObjectFromHandle(handle);
803
804                         InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
805                 }
806
807                 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
808                         Hwnd    hwnd;
809                         XEvent  xevent;
810
811                         hwnd = Hwnd.ObjectFromHandle(handle);
812
813
814                         xevent = new XEvent ();
815                         xevent.type = XEventName.Expose;
816                         xevent.ExposeEvent.display = DisplayHandle;
817                         xevent.ExposeEvent.window = hwnd.whole_window;
818
819                         xevent.ExposeEvent.x = rectangle.X;
820                         xevent.ExposeEvent.y = rectangle.Y;
821                         xevent.ExposeEvent.width = rectangle.Width;
822                         xevent.ExposeEvent.height = rectangle.Height;
823
824                         AddExpose (xevent);
825                 }
826
827                 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
828                         int     dest_x_return;
829                         int     dest_y_return;
830                         IntPtr  child;
831                         Hwnd    hwnd;
832
833                         hwnd = Hwnd.ObjectFromHandle(handle);
834
835                         lock (XlibLock) {
836                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
837                         }
838
839                         x = dest_x_return;
840                         y = dest_y_return;
841                 }
842
843                 private void AddConfigureNotify (XEvent xevent) {
844                         Hwnd    hwnd;
845
846                         hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
847
848                         // Don't waste time
849                         if (hwnd == null) {
850                                 return;
851                         }
852
853                         if (xevent.ConfigureEvent.window == hwnd.whole_window) {
854                                 if (!hwnd.reparented) {
855                                         hwnd.x = xevent.ConfigureEvent.x;
856                                         hwnd.y = xevent.ConfigureEvent.y;
857                                 } else {
858                                         int     dummy_int;
859                                         IntPtr  dummy_ptr;
860
861                                         XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
862                                 }
863
864                                 hwnd.width = xevent.ConfigureEvent.width;
865                                 hwnd.height = xevent.ConfigureEvent.height;
866
867                                 if (!hwnd.configure_pending) {
868                                         MessageQueue.Enqueue(xevent);
869                                         hwnd.configure_pending = true;
870                                 }
871                         }
872                         // We drop configure events for Client windows
873                 }
874
875                 private void ShowCaret() {
876                         if ((Caret.gc == IntPtr.Zero) || Caret.On) {
877                                 return;
878                         }
879                         Caret.On = true;
880
881                         lock (XlibLock) {
882                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
883                         }
884                 }
885
886                 private void HideCaret() {
887                         if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
888                                 return;
889                         }
890                         Caret.On = false;
891
892                         lock (XlibLock) {
893                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
894                         }
895                 }
896
897                 private int NextTimeout (DateTime now) {
898                         int timeout = Int32.MaxValue; 
899                         lock (TimerList) {
900                                 foreach (Timer timer in TimerList) {
901                                         int next = (int) (timer.Expires - now).TotalMilliseconds;
902                                         if (next < 0) {
903                                                 return 0; // Have a timer that has already expired
904                                         }
905
906                                         if (next < timeout) {
907                                                 timeout = next;
908                                         }
909                                 }
910                         }
911                         if (timeout < Timer.Minimum) {
912                                 timeout = Timer.Minimum;
913                         }
914
915                         return timeout;
916                 }
917
918                 private void CheckTimers (DateTime now) {
919                         lock (TimerList) {
920                                 int count;
921
922                                 count = TimerList.Count;
923
924                                 if (count == 0) {
925                                         return;
926                                 }
927
928                                 for (int i = 0; i < TimerList.Count; i++) {
929                                         Timer timer;
930
931                                         timer = (Timer) TimerList[i];
932
933                                         if (timer.Enabled && timer.Expires <= now) {
934                                                 timer.Update (now);
935                                                 timer.FireTick ();
936                                         }
937                                 }
938                         }
939                 }
940
941                 private void UpdateMessageQueue () {
942                         DateTime        now;
943                         int             pending;
944
945                         now = DateTime.Now;
946
947                         lock (XlibLock) {
948                                 pending = XPending (DisplayHandle);
949                         }
950
951                         if (pending == 0) {
952                                 if (Idle != null) {
953                                         Idle (this, EventArgs.Empty);
954                                 }
955
956                                 lock (XlibLock) {
957                                         pending = XPending (DisplayHandle);
958                                 }
959                         }
960
961                         if (pending == 0) {
962                                 int     timeout;
963
964                                 timeout = NextTimeout (now);
965                                 if (timeout > 0) {
966                                         #if __MonoCS__
967                                         Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
968                                         // Clean out buffer, so we're not busy-looping on the same data
969                                         if (pollfds[1].revents != 0) {
970                                                 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
971                                         }
972                                         #endif
973                                         lock (XlibLock) {
974                                                 pending = XPending (DisplayHandle);
975                                         }
976                                 }
977                         }
978
979                         CheckTimers (now);
980
981                         if (pending == 0) {
982                                 lock (XlibLock) {
983                                         pending = XPending (DisplayHandle);
984                                 }
985                         }
986
987                         while (pending > 0) {
988                                 XEvent xevent = new XEvent ();
989
990                                 lock (XlibLock) {
991                                         XNextEvent (DisplayHandle, ref xevent);
992                                 }
993 //Console.WriteLine("Got x event {0}", xevent);
994                                 switch (xevent.type) {
995                                         case XEventName.Expose:
996                                                 AddExpose (xevent);
997                                                 break;
998
999                                         case XEventName.SelectionClear: {
1000                                                 // Should we do something?
1001                                                 break;
1002                                         }
1003
1004                                         case XEventName.SelectionRequest: {
1005                                                 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1006                                                         break;
1007                                                 XEvent sel_event;
1008
1009                                                 sel_event = new XEvent();
1010                                                 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1011                                                 sel_event.SelectionEvent.send_event = true;
1012                                                 sel_event.SelectionEvent.display = DisplayHandle;
1013                                                 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1014                                                 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1015                                                 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1016                                                 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1017                                                 sel_event.SelectionEvent.property = 0;
1018
1019                                                 // Seems that some apps support asking for supported types
1020                                                 if (xevent.SelectionEvent.target == NetAtoms[(int)NA.TARGETS]) {
1021                                                         uint[]  atoms;
1022                                                         int     atom_count;
1023
1024                                                         atoms = new uint[5];
1025                                                         atom_count = 0;
1026
1027                                                         if (Clipboard.Item is String) {
1028                                                                 atoms[atom_count++] = (uint)Atom.XA_STRING;
1029                                                                 atoms[atom_count++] = (uint)NetAtoms[(int)NA.OEMTEXT];
1030                                                                 atoms[atom_count++] = (uint)NetAtoms[(int)NA.UNICODETEXT];
1031                                                         } else if (Clipboard.Item is Image) {
1032                                                                 atoms[atom_count++] = (uint)Atom.XA_PIXMAP;
1033                                                                 atoms[atom_count++] = (uint)Atom.XA_BITMAP;
1034                                                         } else {
1035                                                                 // FIXME - handle other types
1036                                                         }
1037
1038                                                         XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1039                                                 } else if (Clipboard.Item is string) {
1040                                                         IntPtr  buffer;
1041                                                         int     buflen;
1042
1043                                                         buflen = 0;
1044
1045                                                         if (xevent.SelectionRequestEvent.target == (int)Atom.XA_STRING) {
1046                                                                 Byte[] bytes;
1047
1048                                                                 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1049                                                                 buffer = Marshal.AllocHGlobal(bytes.Length);
1050                                                                 buflen = bytes.Length;
1051
1052                                                                 for (int i = 0; i < buflen; i++) {
1053                                                                         Marshal.WriteByte(buffer, i, bytes[i]);
1054                                                                 }
1055                                                         } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.OEMTEXT]) {
1056                                                                 // FIXME - this should encode into ISO2022
1057                                                                 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1058                                                                 while (Marshal.ReadByte(buffer, buflen) != 0) {
1059                                                                         buflen++;
1060                                                                 }
1061                                                         } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.UNICODETEXT]) {
1062                                                                 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1063                                                                 while (Marshal.ReadByte(buffer, buflen) != 0) {
1064                                                                         buflen++;
1065                                                                 }
1066                                                         } else {
1067                                                                 buffer = IntPtr.Zero;
1068                                                         }
1069
1070                                                         if (buffer != IntPtr.Zero) {
1071                                                                 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1072                                                                 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1073                                                                 Marshal.FreeHGlobal(buffer);
1074                                                         }
1075                                                 } else if (Clipboard.Item is Image) {
1076                                                         if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
1077                                                                 // FIXME - convert image and store as property
1078                                                         } else if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
1079                                                                 // FIXME - convert image and store as property
1080                                                         }
1081                                                 }
1082
1083                                                 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, EventMask.NoEventMask, ref sel_event);
1084                                                 break;
1085                                         }
1086
1087                                         case XEventName.SelectionNotify: {
1088                                                 if (Clipboard.Enumerating) {
1089                                                         Clipboard.Enumerating = false;
1090                                                         if (xevent.SelectionEvent.property != 0) {
1091                                                                 XDeleteProperty(DisplayHandle, FosterParent, xevent.SelectionEvent.property);
1092                                                                 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1093                                                                         Clipboard.Formats.Add(xevent.SelectionEvent.property);
1094                                                                         #if DriverDebugExtra
1095                                                                                 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1096                                                                         #endif
1097                                                                 }
1098                                                         }
1099                                                 } else if (Clipboard.Retrieving) {
1100                                                         Clipboard.Retrieving = false;
1101                                                         if (xevent.SelectionEvent.property != 0) {
1102                                                                 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1103                                                         } else {
1104                                                                 Clipboard.Item = null;
1105                                                         }
1106                                                 } else {
1107                                                         Dnd.HandleSelectionNotifyEvent (ref xevent);
1108                                                 }
1109                                                 break;
1110                                         }
1111
1112                                         case XEventName.KeyPress:
1113                                         case XEventName.KeyRelease:
1114                                         case XEventName.ButtonPress:
1115                                         case XEventName.ButtonRelease:
1116                                         case XEventName.MotionNotify:
1117                                         case XEventName.EnterNotify:
1118                                         case XEventName.LeaveNotify:
1119                                         case XEventName.CreateNotify:
1120                                         case XEventName.DestroyNotify:
1121                                         case XEventName.FocusIn:
1122                                         case XEventName.FocusOut:
1123                                         case XEventName.ClientMessage:
1124                                         case XEventName.ReparentNotify:
1125                                                 MessageQueue.Enqueue (xevent);
1126                                                 break;
1127
1128                                         case XEventName.ConfigureNotify:
1129                                                 AddConfigureNotify(xevent);
1130                                                 break;
1131
1132                                         case XEventName.PropertyNotify:
1133                                                 if (xevent.PropertyEvent.atom == NetAtoms[(int)NA._NET_ACTIVE_WINDOW]) {
1134                                                         Atom    actual_atom;
1135                                                         int     actual_format;
1136                                                         int     nitems;
1137                                                         int     bytes_after;
1138                                                         IntPtr  prop = IntPtr.Zero;
1139                                                         IntPtr  prev_active;;
1140
1141                                                         prev_active = ActiveWindow;
1142                                                         XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1143                                                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
1144                                                                 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1145                                                                 XFree(prop);
1146
1147                                                                 if (prev_active != ActiveWindow) {
1148                                                                         if (prev_active != IntPtr.Zero) {
1149                                                                                 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1150                                                                         }
1151                                                                         if (ActiveWindow != IntPtr.Zero) {
1152                                                                                 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1153                                                                         }
1154                                                                 }
1155                                                                 if (ModalWindows.Count == 0) {
1156                                                                         break;
1157                                                                 } else {
1158                                                                         // Modality handling, if we are modal and the new active window is one
1159                                                                         // of ours but not the modal one, switch back to the modal window
1160
1161                                                                         if (NativeWindow.FindWindow(ActiveWindow) != null) {
1162                                                                                 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1163                                                                                         Activate((IntPtr)ModalWindows.Peek());
1164                                                                                 }
1165                                                                         }
1166                                                                         break;
1167                                                                 }
1168                                                         }
1169                                                 }
1170                                                 break;
1171
1172                                 }
1173
1174                                 lock (XlibLock) {
1175                                         pending = XPending (DisplayHandle);
1176                                 }
1177                         }
1178                 }
1179
1180                 private IntPtr GetMousewParam(int Delta) {
1181                         int     result = 0;
1182
1183                         if ((MouseState & MouseButtons.Left) != 0) {
1184                                 result |= (int)MsgButtons.MK_LBUTTON;
1185                         }
1186
1187                         if ((MouseState & MouseButtons.Middle) != 0) {
1188                                 result |= (int)MsgButtons.MK_MBUTTON;
1189                         }
1190
1191                         if ((MouseState & MouseButtons.Right) != 0) {
1192                                 result |= (int)MsgButtons.MK_RBUTTON;
1193                         }
1194
1195                         Keys mods = ModifierKeys;
1196                         if ((mods & Keys.Control) != 0) {
1197                                 result |= (int)MsgButtons.MK_CONTROL;
1198                         }
1199
1200                         if ((mods & Keys.Shift) != 0) {
1201                                 result |= (int)MsgButtons.MK_SHIFT;
1202                         }
1203
1204                         result |= Delta << 16;
1205
1206                         return (IntPtr)result;
1207                 }
1208                 private IntPtr XGetParent(IntPtr handle) {
1209                         IntPtr  Root;
1210                         IntPtr  Parent;
1211                         IntPtr  Children;
1212                         int     ChildCount;
1213
1214                         lock (XlibLock) {
1215                                 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1216                         }
1217
1218                         if (Children!=IntPtr.Zero) {
1219                                 lock (XlibLock) {
1220                                         XFree(Children);
1221                                 }
1222                         }
1223                         return Parent;
1224                 }
1225
1226                 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1227                         if (ErrorExceptions) {
1228                                 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1229                         } else {
1230                                 Console.WriteLine("X11 Error encountered: {0}{1}\n", XException.GetMessage(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), WhereString());
1231                         }
1232                         return 0;
1233                 }
1234
1235                 private void DestroyChildWindow(Control c) {
1236                         Hwnd            hwnd;
1237                         int             i;
1238                         Control[]       controls;
1239
1240                         if (c != null) {
1241                                 controls = c.child_controls.GetAllControls ();
1242
1243                                 for (i = 0; i < controls.Length; i++) {
1244                                         if (controls[i].IsHandleCreated) {
1245                                                 hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
1246                                                 SendMessage(controls[i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1247                                                 hwnd.Dispose();
1248                                         }
1249                                         DestroyChildWindow(controls[i]);
1250                                 }
1251                         }
1252                 }
1253
1254                 #endregion      // Private Methods
1255
1256                 #region Callbacks
1257                 private void MouseHover(object sender, EventArgs e) {
1258                         if ((HoverState.X == MousePosition.X) && (HoverState.Y == MousePosition.Y)) {
1259                                 XEvent xevent;
1260
1261                                 HoverState.Timer.Enabled = false;
1262
1263                                 if (HoverState.Window != IntPtr.Zero) {
1264                                         xevent = new XEvent ();
1265
1266                                         xevent.type = XEventName.ClientMessage;
1267                                         xevent.ClientMessageEvent.display = DisplayHandle;
1268                                         xevent.ClientMessageEvent.window = (IntPtr)HoverState.Window;
1269                                         xevent.ClientMessageEvent.message_type = (IntPtr)HoverState.Atom;
1270                                         xevent.ClientMessageEvent.format = 32;
1271                                         xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1272
1273                                         MessageQueue.EnqueueLocked (xevent);
1274
1275                                         WakeupMain ();
1276                                 }
1277                         }
1278                 }
1279
1280                 private void CaretCallback(object sender, EventArgs e) {
1281                         if (Caret.Paused) {
1282                                 return;
1283                         }
1284                         Caret.On = !Caret.On;
1285
1286                         XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1287                 }
1288                 #endregion      // Callbacks
1289
1290                 #region Public Properties
1291
1292                 internal override int Caption {
1293                         get {
1294                                 return 25; 
1295                         }
1296                 }
1297
1298                 internal override  Size CursorSize {
1299                         get {
1300                                 int     x;
1301                                 int     y;
1302
1303                                 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1304                                         return new Size(x, y);
1305                                 } else {
1306                                         return new Size(16, 16);
1307                                 }
1308                         }
1309                 } 
1310
1311                 internal override  bool DragFullWindows {
1312                         get {
1313                                 return true;
1314                         }
1315                 } 
1316
1317                 internal override  Size DragSize {
1318                         get {
1319                                 return new Size(4, 4);
1320                         }
1321                 } 
1322
1323                 internal override  Size FrameBorderSize { 
1324                         get {
1325                                 throw new NotImplementedException(); 
1326                         }
1327                 }
1328
1329                 internal override  Size IconSize {
1330                         get {
1331                                 IntPtr          list;
1332                                 XIconSize       size;
1333                                 int             count;
1334
1335                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1336                                         long            current;
1337                                         int             largest;
1338
1339                                         current = (long)list;
1340                                         largest = 0;
1341
1342                                         size = new XIconSize();
1343
1344                                         for (int i = 0; i < count; i++) {
1345                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1346                                                 current += Marshal.SizeOf(size);
1347
1348                                                 // Look for our preferred size
1349                                                 if (size.min_width == 32) {
1350                                                         XFree(list);
1351                                                         return new Size(32, 32);
1352                                                 }
1353
1354                                                 if (size.max_width == 32) {
1355                                                         XFree(list);
1356                                                         return new Size(32, 32);
1357                                                 }
1358
1359                                                 if (size.min_width < 32 && size.max_width > 32) {
1360                                                         int     x;
1361
1362                                                         // check if we can fit one
1363                                                         x = size.min_width;
1364                                                         while (x < size.max_width) {
1365                                                                 x += size.width_inc;
1366                                                                 if (x == 32) {
1367                                                                         XFree(list);
1368                                                                         return new Size(32, 32);
1369                                                                 }
1370                                                         }
1371                                                 }
1372
1373                                                 if (largest < size.max_width) {
1374                                                         largest = size.max_width;
1375                                                 }
1376                                         }
1377
1378                                         // We didn't find a match or we wouldn't be here
1379                                         return new Size(largest, largest);
1380
1381                                 } else {
1382                                         return new Size(32, 32);
1383                                 }
1384                         }
1385                 } 
1386
1387                 internal override int KeyboardSpeed {
1388                         get{
1389                                 //
1390                                 // A lot harder: need to do:
1391                                 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)       = 1
1392                                 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)        = 0x080517a8
1393                                 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58)                   = 0
1394                                 //
1395                                 // And from that we can tell the repetition rate
1396                                 //
1397                                 // Notice, the values must map to:
1398                                 //   [0, 31] which maps to 2.5 to 30 repetitions per second.
1399                                 //
1400                                 return 0;
1401                         }
1402                 }
1403
1404                 internal override int KeyboardDelay {
1405                         get {
1406                                 //
1407                                 // Return values must range from 0 to 4, 0 meaning 250ms,
1408                                 // and 4 meaning 1000 ms.
1409                                 //
1410                                 return 1; // ie, 500 ms
1411                         }
1412                 } 
1413
1414                 internal override  Size MaxWindowTrackSize {
1415                         get {
1416                                 return new Size (WorkingArea.Width, WorkingArea.Height);
1417                         }
1418                 } 
1419
1420                 internal override  Size MinimizedWindowSize {
1421                         get {
1422                                 return new Size(1, 1);
1423                         }
1424                 } 
1425
1426                 internal override  Size MinimizedWindowSpacingSize {
1427                         get {
1428                                 return new Size(1, 1);
1429                         }
1430                 } 
1431
1432                 internal override  Size MinimumWindowSize {
1433                         get {
1434                                 return new Size(1, 1);
1435                         }
1436                 } 
1437
1438                 internal override  Size MinWindowTrackSize {
1439                         get {
1440                                 return new Size(1, 1);
1441                         }
1442                 }
1443
1444                 internal override Keys ModifierKeys {
1445                         get {
1446                                 return Keyboard.ModifierKeys;
1447                         }
1448                 }
1449
1450                 internal override  Size SmallIconSize {
1451                         get {
1452                                 IntPtr          list;
1453                                 XIconSize       size;
1454                                 int             count;
1455
1456                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1457                                         long            current;
1458                                         int             smallest;
1459
1460                                         current = (long)list;
1461                                         smallest = 0;
1462
1463                                         size = new XIconSize();
1464
1465                                         for (int i = 0; i < count; i++) {
1466                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1467                                                 current += Marshal.SizeOf(size);
1468
1469                                                 // Look for our preferred size
1470                                                 if (size.min_width == 16) {
1471                                                         XFree(list);
1472                                                         return new Size(16, 16);
1473                                                 }
1474
1475                                                 if (size.max_width == 16) {
1476                                                         XFree(list);
1477                                                         return new Size(16, 16);
1478                                                 }
1479
1480                                                 if (size.min_width < 16 && size.max_width > 16) {
1481                                                         int     x;
1482
1483                                                         // check if we can fit one
1484                                                         x = size.min_width;
1485                                                         while (x < size.max_width) {
1486                                                                 x += size.width_inc;
1487                                                                 if (x == 16) {
1488                                                                         XFree(list);
1489                                                                         return new Size(16, 16);
1490                                                                 }
1491                                                         }
1492                                                 }
1493
1494                                                 if (smallest == 0 || smallest > size.min_width) {
1495                                                         smallest = size.min_width;
1496                                                 }
1497                                         }
1498
1499                                         // We didn't find a match or we wouldn't be here
1500                                         return new Size(smallest, smallest);
1501
1502                                 } else {
1503                                         return new Size(16, 16);
1504                                 }
1505                         }
1506                 } 
1507
1508                 internal override  int MouseButtonCount {
1509                         get {
1510                                 return 3;
1511                         }
1512                 } 
1513
1514                 internal override  bool MouseButtonsSwapped {
1515                         get {
1516                                 return false;   // FIXME - how to detect?
1517                         }
1518                 } 
1519
1520                 internal override  bool MouseWheelPresent {
1521                         get {
1522                                 return true;    // FIXME - how to detect?
1523                         }
1524                 } 
1525
1526                 internal override  Rectangle VirtualScreen {
1527                         get {
1528                                 return WorkingArea;
1529                         }
1530                 } 
1531
1532                 internal override  Rectangle WorkingArea {
1533                         get {
1534                                 Atom                    actual_atom;
1535                                 int                     actual_format;
1536                                 int                     nitems;
1537                                 int                     bytes_after;
1538                                 IntPtr                  prop = IntPtr.Zero;
1539                                 int                     width;
1540                                 int                     height;
1541
1542                                 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY], 0, 256, false, Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1543                                 if ((nitems == 2) && (prop != IntPtr.Zero)) {
1544                                         width = Marshal.ReadInt32(prop, 0);
1545                                         height = Marshal.ReadInt32(prop, 4);
1546
1547                                         XFree(prop);
1548                                         return new Rectangle(0, 0, width, height);
1549                                 } else {
1550                                         XWindowAttributes       attributes=new XWindowAttributes();
1551
1552                                         lock (XlibLock) {
1553                                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1554                                         }
1555
1556                                         return new Rectangle(0, 0, attributes.width, attributes.height);
1557                                 }
1558                         }
1559                 } 
1560                 #endregion      // Public properties
1561
1562                 #region Public Static Methods
1563                 internal override IntPtr InitializeDriver() {
1564                         lock (this) {
1565                                 if (DisplayHandle==IntPtr.Zero) {
1566                                         SetDisplay(XOpenDisplay(IntPtr.Zero));
1567                                 }
1568                         }
1569                         return IntPtr.Zero;
1570                 }
1571
1572                 internal override void ShutdownDriver(IntPtr token) {
1573                         lock (this) {
1574                                 if (DisplayHandle!=IntPtr.Zero) {
1575                                         XCloseDisplay(DisplayHandle);
1576                                         DisplayHandle=IntPtr.Zero;
1577                                 }
1578                         }
1579                 }
1580
1581                 internal override void EnableThemes() {
1582                         ThemesEnabled = true;
1583                 }
1584
1585
1586                 internal override void Activate(IntPtr handle) {
1587                         Hwnd hwnd;
1588
1589                         hwnd = Hwnd.ObjectFromHandle(handle);
1590
1591                         if (hwnd != null) lock (XlibLock) {
1592                                 SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
1593                                 //XRaiseWindow(DisplayHandle, handle);
1594                         }
1595                         return;
1596                 }
1597
1598                 internal override void AudibleAlert() {
1599                         XBell(DisplayHandle, 0);
1600                         return;
1601                 }
1602
1603
1604                 internal override void CaretVisible(IntPtr handle, bool visible) {
1605                         // Visible is cumulative; two hides require two shows before the caret is visible again
1606                         if (Caret.Hwnd == handle) {
1607                                 if (visible) {
1608                                         if (Caret.Visible < 1) {
1609                                                 Caret.Visible++;
1610                                                 Caret.On = false;
1611                                                 if (Caret.Visible == 1) {
1612                                                         ShowCaret();
1613                                                         Caret.Timer.Start();
1614                                                 }
1615                                         }
1616                                 } else {
1617                                         Caret.Visible--;
1618                                         if (Caret.Visible == 0) {
1619                                                 Caret.Timer.Stop();
1620                                                 HideCaret();
1621                                         }
1622                                 }
1623                         }
1624                 }
1625
1626                 internal override bool CalculateWindowRect(IntPtr handle, ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
1627                         FormBorderStyle border_style;
1628                         TitleStyle      title_style;
1629                         int caption_height;
1630                         int tool_caption_height;
1631
1632                         DeriveStyles(handle, Style, ExStyle, out border_style, out title_style,
1633                                 out caption_height, out tool_caption_height);
1634
1635                         WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
1636                                         caption_height, tool_caption_height,
1637                                         ClientRect);
1638
1639                         return true;
1640                 }
1641
1642                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
1643                         int     dest_x_return;
1644                         int     dest_y_return;
1645                         IntPtr  child;
1646                         Hwnd    hwnd;
1647
1648                         hwnd = Hwnd.ObjectFromHandle(handle);
1649
1650                         lock (XlibLock) {
1651                                 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1652                         }
1653
1654                         x = dest_x_return;
1655                         y = dest_y_return;
1656                 }
1657
1658                 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
1659                         DataFormats.Format      f;
1660                         int[]                   result;
1661
1662                         f = DataFormats.Format.List;
1663
1664                         if (XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD]) == IntPtr.Zero) {
1665                                 return null;
1666                         }
1667
1668                         Clipboard.Formats = new ArrayList();
1669
1670                         while (f != null) {
1671                                 XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], f.Id, f.Id, FosterParent, IntPtr.Zero);
1672
1673                                 Clipboard.Enumerating = true;
1674                                 while (Clipboard.Enumerating) {
1675                                         UpdateMessageQueue();
1676                                 }
1677                                 f = f.Next;
1678                         }
1679
1680                         result = new int[Clipboard.Formats.Count];
1681
1682                         for (int i = 0; i < Clipboard.Formats.Count; i++) {
1683                                 result[i] = (int)Clipboard.Formats[i];
1684                         }
1685
1686                         Clipboard.Formats = null;
1687                         return result;
1688                 }
1689
1690                 internal override void ClipboardClose(IntPtr handle) {
1691                         if (handle != ClipMagic) {
1692                                 throw new ArgumentException("handle is not a valid clipboard handle");
1693                         }
1694                         return;
1695                 }
1696
1697                 internal override int ClipboardGetID(IntPtr handle, string format) {
1698                         if (handle != ClipMagic) {
1699                                 throw new ArgumentException("handle is not a valid clipboard handle");
1700                         }
1701
1702                         if (format == "Text" ) return (int)Atom.XA_STRING;
1703                         else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
1704                         //else if (format == "MetaFilePict" ) return 3;
1705                         //else if (format == "SymbolicLink" ) return 4;
1706                         //else if (format == "DataInterchangeFormat" ) return 5;
1707                         //else if (format == "Tiff" ) return 6;
1708                         else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
1709                         else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
1710                         else if (format == "Palette" ) return (int)Atom.XA_COLORMAP;    // Useless
1711                         //else if (format == "PenData" ) return 10;
1712                         //else if (format == "RiffAudio" ) return 11;
1713                         //else if (format == "WaveAudio" ) return 12;
1714                         else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false);
1715                         //else if (format == "EnhancedMetafile" ) return 14;
1716                         //else if (format == "FileDrop" ) return 15;
1717                         //else if (format == "Locale" ) return 16;
1718
1719                         return XInternAtom(DisplayHandle, format, false);
1720                 }
1721
1722                 internal override IntPtr ClipboardOpen() {
1723                         return ClipMagic;
1724                 }
1725
1726                 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
1727                         XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], type, type, FosterParent, IntPtr.Zero);
1728
1729                         Clipboard.Retrieving = true;
1730                         while (Clipboard.Retrieving) {
1731                                 UpdateMessageQueue();
1732                         }
1733
1734                         return Clipboard.Item;
1735                 }
1736
1737                 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
1738                         Clipboard.Item = obj;
1739                         Clipboard.Type = type;
1740                         Clipboard.Converter = converter;
1741
1742                         if (obj != null) {
1743                                 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], FosterParent, IntPtr.Zero);
1744                         } else {
1745                                 // Clearing the selection
1746                                 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], IntPtr.Zero, IntPtr.Zero);
1747                         }
1748                 }
1749
1750                 internal override void CreateCaret(IntPtr handle, int width, int height) {
1751                         XGCValues       gc_values;
1752                         Hwnd            hwnd;
1753
1754                         hwnd = Hwnd.ObjectFromHandle(handle);
1755
1756                         if (Caret.Hwnd != IntPtr.Zero) {
1757                                 DestroyCaret(Caret.Hwnd);
1758                         }
1759
1760                         Caret.Hwnd = handle;
1761                         Caret.Window = hwnd.client_window;
1762                         Caret.Width = width;
1763                         Caret.Height = height;
1764                         Caret.Visible = 0;
1765                         Caret.On = false;
1766
1767                         gc_values = new XGCValues();
1768                         gc_values.line_width = width;
1769
1770                         Caret.gc = XCreateGC(DisplayHandle, Caret.Window, GCFunction.GCLineWidth, ref gc_values);
1771                         if (Caret.gc == IntPtr.Zero) {
1772                                 Caret.Hwnd = IntPtr.Zero;
1773                                 return;
1774                         }
1775
1776                         XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
1777                 }
1778
1779                 internal override IntPtr CreateWindow(CreateParams cp) {
1780                         XSetWindowAttributes    Attributes;
1781                         Hwnd                    hwnd;
1782                         int                     X;
1783                         int                     Y;
1784                         int                     Width;
1785                         int                     Height;
1786                         IntPtr                  ParentHandle;
1787                         IntPtr                  WholeWindow;
1788                         IntPtr                  ClientWindow;
1789                         Rectangle               ClientRect;
1790                         SetWindowValuemask      ValueMask;
1791
1792
1793                         hwnd = new Hwnd();
1794
1795                         Attributes = new XSetWindowAttributes();
1796                         X = cp.X;
1797                         Y = cp.Y;
1798                         Width = cp.Width;
1799                         Height = cp.Height;
1800
1801                         if (Width<1) Width=1;
1802                         if (Height<1) Height=1;
1803
1804                         if (cp.Parent != IntPtr.Zero) {
1805                                 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
1806                         } else {
1807                                 if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
1808                                         // We need to use our foster parent window until this poor child gets it's parent assigned
1809                                         ParentHandle=FosterParent;
1810                                 } else if ((cp.Style & (int)WindowStyles.WS_POPUP) != 0) {
1811                                         ParentHandle=RootWindow;
1812                                 } else {
1813                                         // Default position on screen, if window manager doesn't place us somewhere else
1814                                         if (X<1) X = 50;
1815                                         if (Y<1) Y = 50;
1816                                         ParentHandle=RootWindow;
1817                                 }
1818                         }
1819
1820                         ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
1821
1822                         Attributes.bit_gravity = Gravity.NorthWestGravity;
1823                         Attributes.win_gravity = Gravity.NorthWestGravity;
1824
1825                         // Save what's under the toolwindow
1826                         if ((cp.ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
1827                                 Attributes.save_under = true;
1828                                 ValueMask |= SetWindowValuemask.SaveUnder;
1829                         }
1830
1831
1832                         // If we're a popup without caption we override the WM
1833                         if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
1834                                 if ((cp.Style & (int)WindowStyles.WS_CAPTION) == 0) {
1835                                         Attributes.override_redirect = true;
1836                                         ValueMask |= SetWindowValuemask.OverrideRedirect;
1837                                 }
1838                         }
1839
1840                         hwnd.x = X;
1841                         hwnd.y = Y;
1842                         hwnd.width = Width;
1843                         hwnd.height = Height;
1844                         hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
1845
1846                         if ((cp.Style & ((int)WindowStyles.WS_DISABLED)) != 0) {
1847                                 hwnd.enabled = false;
1848                         }
1849
1850                         ClientRect = hwnd.ClientRect;
1851                         ClientWindow = IntPtr.Zero;
1852
1853                         lock (XlibLock) {
1854                                 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, ValueMask, ref Attributes);
1855                                 if (WholeWindow != IntPtr.Zero) {
1856                                         ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
1857
1858                                         if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
1859                                                 ValueMask = SetWindowValuemask.ColorMap;
1860                                                 Attributes.colormap = CustomColormap;
1861                                         }
1862                                         ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, ValueMask, ref Attributes);
1863                                 }
1864                         }
1865
1866                         if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
1867                                 throw new Exception("Could not create X11 windows");
1868                         }
1869
1870                         hwnd.WholeWindow = WholeWindow;
1871                         hwnd.ClientWindow = ClientWindow;
1872
1873                         #if DriverDebug
1874                                 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
1875                         #endif
1876                                        
1877                         lock (XlibLock) {
1878                                 XSelectInput(DisplayHandle, hwnd.whole_window, SelectInputMask);
1879                                 XSelectInput(DisplayHandle, hwnd.client_window, SelectInputMask);
1880
1881                                 if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
1882                                         XMapWindow(DisplayHandle, hwnd.whole_window);
1883                                         XMapWindow(DisplayHandle, hwnd.client_window);
1884                                         hwnd.visible = true;
1885                                 }
1886                         }
1887
1888                         SetWMStyles(hwnd, cp);
1889
1890                         if ((cp.Style & (int)WindowStyles.WS_MINIMIZE) != 0) {
1891                                 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
1892                         } else if ((cp.Style & (int)WindowStyles.WS_MAXIMIZE) != 0) {
1893                                 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
1894                         }
1895
1896                         // for now make all windows dnd enabled
1897                         Dnd.SetAllowDrop (hwnd, true);
1898
1899                         // Set caption/window title
1900                         Text(hwnd.Handle, cp.Caption);
1901
1902                         return hwnd.Handle;
1903                 }
1904
1905                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
1906                         CreateParams create_params = new CreateParams();
1907
1908                         create_params.Caption = "";
1909                         create_params.X = X;
1910                         create_params.Y = Y;
1911                         create_params.Width = Width;
1912                         create_params.Height = Height;
1913
1914                         create_params.ClassName=XplatUI.DefaultClassName;
1915                         create_params.ClassStyle = 0;
1916                         create_params.ExStyle=0;
1917                         create_params.Parent=IntPtr.Zero;
1918                         create_params.Param=0;
1919
1920                         return CreateWindow(create_params);
1921                 }
1922
1923                 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
1924                         IntPtr  cursor;
1925                         Bitmap  cursor_bitmap;
1926                         Bitmap  cursor_mask;
1927                         Byte[]  cursor_bits;
1928                         Byte[]  mask_bits;
1929                         Color   c_pixel;
1930                         Color   m_pixel;
1931                         int     width;
1932                         int     height;
1933                         IntPtr  cursor_pixmap;
1934                         IntPtr  mask_pixmap;
1935                         XColor  fg;
1936                         XColor  bg;
1937                         bool    and;
1938                         bool    xor;
1939
1940                         if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
1941                                 return IntPtr.Zero;
1942                         }
1943
1944                         // Win32 only allows creation cursors of a certain size
1945                         if ((bitmap.Width != width) || (bitmap.Width != height)) {
1946                                 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
1947                                 cursor_mask = new Bitmap(mask, new Size(width, height));
1948                         } else {
1949                                 cursor_bitmap = bitmap;
1950                                 cursor_mask = mask;
1951                         }
1952
1953                         width = cursor_bitmap.Width;
1954                         height = cursor_bitmap.Height;
1955
1956                         cursor_bits = new Byte[(width / 8) * height];
1957                         mask_bits = new Byte[(width / 8) * height];
1958
1959                         for (int y = 0; y < height; y++) {
1960                                 for (int x = 0; x < width; x++) {
1961                                         c_pixel = cursor_bitmap.GetPixel(x, y);
1962                                         m_pixel = cursor_mask.GetPixel(x, y);
1963
1964                                         and = c_pixel == cursor_pixel;
1965                                         xor = m_pixel == mask_pixel;
1966
1967                                         if (!and && !xor) {
1968                                                 // Black
1969                                                 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));       // The bit already is 0
1970                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1971                                         } else if (and && !xor) {
1972                                                 // White
1973                                                 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1974                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1975 #if notneeded
1976                                         } else if (and && !xor) {
1977                                                 // Screen
1978                                         } else if (and && xor) {
1979                                                 // Inverse Screen
1980
1981                                                 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
1982                                                 // we want both to be 0 so nothing to be done
1983                                                 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
1984                                                 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
1985 #endif
1986                                         }
1987                                 }
1988                         }
1989
1990                         cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
1991                         mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
1992                         fg = new XColor();
1993                         bg = new XColor();
1994
1995                         fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
1996                         fg.red = (ushort)65535;
1997                         fg.green = (ushort)65535;
1998                         fg.blue = (ushort)65535;
1999
2000                         bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2001
2002                         cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2003
2004                         XFreePixmap(DisplayHandle, cursor_pixmap);
2005                         XFreePixmap(DisplayHandle, mask_pixmap);
2006
2007                         return cursor;
2008                 }
2009
2010                 internal override IntPtr DefineStdCursor(StdCursor id) {
2011                         CursorFontShape shape;
2012                         IntPtr          cursor;
2013
2014                         // FIXME - define missing shapes
2015
2016                         switch (id) {
2017                                 case StdCursor.AppStarting: {
2018                                         shape = CursorFontShape.XC_watch;
2019                                         break;
2020                                 }
2021
2022                                 case StdCursor.Arrow: {
2023                                         return IntPtr.Zero;
2024                                 }
2025
2026                                 case StdCursor.Cross: {
2027                                         shape = CursorFontShape.XC_crosshair;
2028                                         break;
2029                                 }
2030
2031                                 case StdCursor.Default: {
2032                                         return IntPtr.Zero;
2033                                 }
2034
2035                                 case StdCursor.Hand: {
2036                                         shape = CursorFontShape.XC_hand1;
2037                                         break;
2038                                 }
2039
2040                                 case StdCursor.Help: {
2041                                         shape = CursorFontShape.XC_question_arrow;
2042                                         break;
2043                                 }
2044
2045                                 case StdCursor.HSplit: {
2046                                         shape = CursorFontShape.XC_sb_v_double_arrow; 
2047                                         break;
2048                                 }
2049
2050                                 case StdCursor.IBeam: {
2051                                         shape = CursorFontShape.XC_xterm; 
2052                                         break;
2053                                 }
2054
2055                                 case StdCursor.No: {
2056                                         shape = CursorFontShape.XC_circle; 
2057                                         break;
2058                                 }
2059
2060                                 case StdCursor.NoMove2D: {
2061                                         shape = CursorFontShape.XC_fleur; 
2062                                         break;
2063                                 }
2064
2065                                 case StdCursor.NoMoveHoriz: {
2066                                         shape = CursorFontShape.XC_fleur; 
2067                                         break;
2068                                 }
2069
2070                                 case StdCursor.NoMoveVert: {
2071                                         shape = CursorFontShape.XC_fleur; 
2072                                         break;
2073                                 }
2074
2075                                 case StdCursor.PanEast: {
2076                                         shape = CursorFontShape.XC_fleur; 
2077                                         break;
2078                                 }
2079
2080                                 case StdCursor.PanNE: {
2081                                         shape = CursorFontShape.XC_fleur; 
2082                                         break;
2083                                 }
2084
2085                                 case StdCursor.PanNorth: {
2086                                         shape = CursorFontShape.XC_fleur; 
2087                                         break;
2088                                 }
2089
2090                                 case StdCursor.PanNW: {
2091                                         shape = CursorFontShape.XC_fleur; 
2092                                         break;
2093                                 }
2094
2095                                 case StdCursor.PanSE: {
2096                                         shape = CursorFontShape.XC_fleur; 
2097                                         break;
2098                                 }
2099
2100                                 case StdCursor.PanSouth: {
2101                                         shape = CursorFontShape.XC_fleur; 
2102                                         break;
2103                                 }
2104
2105                                 case StdCursor.PanSW: {
2106                                         shape = CursorFontShape.XC_fleur; 
2107                                         break;
2108                                 }
2109
2110                                 case StdCursor.PanWest: {
2111                                         shape = CursorFontShape.XC_sizing; 
2112                                         break;
2113                                 }
2114
2115                                 case StdCursor.SizeAll: {
2116                                         shape = CursorFontShape.XC_fleur; 
2117                                         break;
2118                                 }
2119
2120                                 case StdCursor.SizeNESW: {
2121                                         shape = CursorFontShape.XC_top_right_corner; 
2122                                         break;
2123                                 }
2124
2125                                 case StdCursor.SizeNS: {
2126                                         shape = CursorFontShape.XC_sb_v_double_arrow;
2127                                         break;
2128                                 }
2129
2130                                 case StdCursor.SizeNWSE: {
2131                                         shape = CursorFontShape.XC_top_left_corner; 
2132                                         break;
2133                                 }
2134
2135                                 case StdCursor.SizeWE: {
2136                                         shape = CursorFontShape.XC_sb_h_double_arrow; 
2137                                         break;
2138                                 }
2139
2140                                 case StdCursor.UpArrow: {
2141                                         shape = CursorFontShape.XC_center_ptr; 
2142                                         break;
2143                                 }
2144
2145                                 case StdCursor.VSplit: {
2146                                         shape = CursorFontShape.XC_sb_h_double_arrow;
2147                                         break;
2148                                 }
2149
2150                                 case StdCursor.WaitCursor: {
2151                                         shape = CursorFontShape.XC_watch; 
2152                                         break;
2153                                 }
2154
2155                                 default: {
2156                                         return IntPtr.Zero;
2157                                 }
2158                         }
2159
2160                         lock (XlibLock) {
2161                                 cursor = XCreateFontCursor(DisplayHandle, shape);
2162                         }
2163                         return cursor;
2164                 }
2165
2166                 internal override IntPtr DefWndProc(ref Message msg) {
2167                         return IntPtr.Zero;
2168                 }
2169
2170                 internal override void DestroyCaret(IntPtr handle) {
2171                         if (Caret.Hwnd == handle) {
2172                                 if (Caret.Visible == 1) {
2173                                         Caret.Timer.Stop();
2174                                         HideCaret();
2175                                 }
2176                                 if (Caret.gc != IntPtr.Zero) {
2177                                         XFreeGC(DisplayHandle, Caret.gc);
2178                                         Caret.gc = IntPtr.Zero;
2179                                 }
2180                                 Caret.Hwnd = IntPtr.Zero;
2181                                 Caret.Visible = 0;
2182                                 Caret.On = false;
2183                         }
2184                 }
2185
2186                 internal override void DestroyCursor(IntPtr cursor) {
2187                         lock (XlibLock) {
2188                                 XFreeCursor(DisplayHandle, cursor);
2189                         }
2190                 }
2191
2192                 internal override void DestroyWindow(IntPtr handle) {
2193                         Hwnd    hwnd;
2194
2195                         hwnd = Hwnd.ObjectFromHandle(handle);
2196
2197                         if (hwnd == null) {
2198                                 #if DriverDebug
2199                                         Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2200                                 #endif
2201                                 return;
2202                         }
2203
2204                         #if DriverDebug
2205                                 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2206                         #endif
2207
2208                         // Make sure if the caret is in the window, that we destroy the caret, too
2209                         if (Caret.Hwnd == hwnd.client_window) {
2210                                 DestroyCaret(handle);
2211                         }
2212
2213                         // Mark our children as gone as well
2214                         DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
2215
2216                         // Send destroy message
2217                         SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2218
2219                         lock (XlibLock) {
2220                                 if (hwnd.client_window != IntPtr.Zero) {
2221                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
2222                                 }
2223
2224                                 if ((hwnd.whole_window != IntPtr.Zero) && (hwnd.whole_window != hwnd.client_window)) {
2225                                         XDestroyWindow(DisplayHandle, hwnd.whole_window);
2226                                 }
2227                         }
2228                         hwnd.Dispose();
2229                 }
2230
2231                 internal override IntPtr DispatchMessage(ref MSG msg) {
2232                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2233                 }
2234
2235                 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2236                         Hwnd            hwnd;
2237                         XGCValues       gc_values;
2238                         IntPtr          gc;
2239
2240                         hwnd = Hwnd.ObjectFromHandle(handle);
2241
2242                         gc_values = new XGCValues();
2243
2244                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2245                         gc_values.line_width = line_width;
2246                         gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2247
2248                         // This logic will give us true rubber bands: (libsx, SANE_XOR)
2249                         //mask = foreground ^ background; 
2250                         //XSetForeground(DisplayHandle, gc, 0xffffffff);
2251                         //XSetBackground(DisplayHandle, gc, background);
2252                         //XSetFunction(DisplayHandle,   gc, GXxor);
2253                         //XSetPlaneMask(DisplayHandle,  gc, mask);
2254
2255
2256                         gc = XCreateGC(DisplayHandle, hwnd.client_window, GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground, ref gc_values);
2257                         uint foreground;
2258                         uint background;
2259
2260                         Control control;
2261                         control = Control.FromHandle(handle);
2262
2263                         XColor xcolor = new XColor();
2264
2265                         xcolor.red = (ushort)(control.ForeColor.R * 257);
2266                         xcolor.green = (ushort)(control.ForeColor.G * 257);
2267                         xcolor.blue = (ushort)(control.ForeColor.B * 257);
2268                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2269                         foreground = (uint)xcolor.pixel.ToInt32();
2270
2271                         xcolor.red = (ushort)(control.BackColor.R * 257);
2272                         xcolor.green = (ushort)(control.BackColor.G * 257);
2273                         xcolor.blue = (ushort)(control.BackColor.B * 257);
2274                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2275                         background = (uint)xcolor.pixel.ToInt32();
2276
2277                         uint mask = foreground ^ background; 
2278
2279                         XSetForeground(DisplayHandle, gc, 0xffffffff);
2280                         XSetBackground(DisplayHandle, gc, background);
2281                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
2282                         XSetPlaneMask(DisplayHandle,  gc, mask);
2283
2284                         if ((rect.Width > 0) && (rect.Height > 0)) {
2285                                 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2286                         } else {
2287                                 if (rect.Width > 0) {
2288                                         XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2289                                 } else {
2290                                         XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2291                                 }
2292                         }
2293                         XFreeGC(DisplayHandle, gc);
2294                 }
2295
2296                 internal override void DoEvents() {
2297                         MSG msg = new MSG ();
2298
2299                         if (OverrideCursorHandle != IntPtr.Zero) {
2300                                 OverrideCursorHandle = IntPtr.Zero;
2301                         }
2302
2303                         while (PeekMessage(ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2304                                 TranslateMessage (ref msg);
2305                                 DispatchMessage (ref msg);
2306                         }
2307                 }
2308
2309                 internal override void EnableWindow(IntPtr handle, bool Enable) {
2310                         Hwnd    hwnd;
2311
2312                         hwnd = Hwnd.ObjectFromHandle(handle);
2313                         if (hwnd != null) {
2314                                 hwnd.Enabled = Enable;
2315                         }
2316                 }
2317
2318                 internal override void EndLoop(Thread thread) {
2319                         // This is where we one day will shut down the loop for the thread
2320                 }
2321
2322
2323                 internal override IntPtr GetActive() {
2324                         Atom    actual_atom;
2325                         int     actual_format;
2326                         int     nitems;
2327                         int     bytes_after;
2328                         IntPtr  prop = IntPtr.Zero;
2329                         IntPtr  active = IntPtr.Zero;
2330
2331                         XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2332                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
2333                                 active = (IntPtr)Marshal.ReadInt32(prop);
2334                                 XFree(prop);
2335                         }
2336
2337                         if (active != IntPtr.Zero) {
2338                                 Hwnd    hwnd;
2339
2340                                 hwnd = Hwnd.GetObjectFromWindow(active);
2341                                 if (hwnd != null) {
2342                                         active = hwnd.Handle;
2343                                 } else {
2344                                         active = IntPtr.Zero;
2345                                 }
2346                         }
2347                         return active;
2348                 }
2349
2350                 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2351                         throw new NotImplementedException ();
2352                 }
2353
2354                 internal override void GetDisplaySize(out Size size) {
2355                         XWindowAttributes       attributes=new XWindowAttributes();
2356
2357                         lock (XlibLock) {
2358                                 // FIXME - use _NET_WM messages instead?
2359                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2360                         }
2361
2362                         size = new Size(attributes.width, attributes.height);
2363                 }
2364
2365                 internal override SizeF GetAutoScaleSize(Font font) {
2366                         Graphics        g;
2367                         float           width;
2368                         string          magic_string = "The quick brown fox jumped over the lazy dog.";
2369                         double          magic_number = 44.549996948242189;
2370
2371                         g = Graphics.FromHwnd(FosterParent);
2372
2373                         width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2374                         return new SizeF(width, font.Height);
2375                 }
2376
2377                 internal override IntPtr GetParent(IntPtr handle) {
2378                         Hwnd    hwnd;
2379
2380                         hwnd = Hwnd.ObjectFromHandle(handle);
2381                         if (hwnd != null && hwnd.parent != null) {
2382                                 return hwnd.parent.Handle;
2383                         }
2384                         return IntPtr.Zero;
2385                 }
2386
2387                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
2388                         IntPtr  use_handle;
2389                         IntPtr  root;
2390                         IntPtr  child;
2391                         int     root_x;
2392                         int     root_y;
2393                         int     win_x;
2394                         int     win_y;
2395                         int     keys_buttons;
2396
2397                         if (handle != IntPtr.Zero) {
2398                                 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
2399                         } else {
2400                                 use_handle = RootWindow;
2401                         }
2402
2403                         lock (XlibLock) {
2404                                 XQueryPointer(DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
2405                         }
2406
2407                         if (handle != IntPtr.Zero) {
2408                                 x = win_x;
2409                                 y = win_y;
2410                         } else {
2411                                 x = root_x;
2412                                 y = root_y;
2413                         }
2414                 }
2415
2416                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
2417                         return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
2418                 }
2419
2420                 internal override Point GetMenuOrigin(IntPtr handle) {
2421                         Hwnd    hwnd;
2422
2423                         hwnd = Hwnd.ObjectFromHandle(handle);
2424
2425                         if (hwnd != null) {
2426                                 return hwnd.MenuOrigin;
2427                         }
2428                         return Point.Empty;
2429                 }
2430
2431                 internal override bool GetMessage(ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
2432                         XEvent  xevent;
2433                         bool    client;
2434                         Hwnd    hwnd;
2435
2436                         ProcessNextMessage:
2437
2438                         if (MessageQueue.Count > 0) {
2439                                 xevent = (XEvent) MessageQueue.Dequeue ();
2440                         } else {
2441                                 UpdateMessageQueue ();
2442
2443                                 if (MessageQueue.Count > 0) {
2444                                         xevent = (XEvent) MessageQueue.Dequeue ();
2445                                 } else {
2446                                         if (!PostQuitState) {
2447                                                 msg.hwnd= IntPtr.Zero;
2448                                                 msg.message = Msg.WM_ENTERIDLE;
2449                                                 return true;
2450                                         }
2451
2452                                         // We reset ourselves so GetMessage can be called again
2453                                         PostQuitState = false;
2454
2455                                         return false;
2456                                 }
2457                         }
2458
2459                         // FIXME - handle filtering
2460
2461                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
2462
2463                         // Handle messages for windows that are already or are about to be destroyed
2464                         if (hwnd == null) {
2465                                 #if DriverDebug
2466                                         Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
2467                                 #endif
2468                                 goto ProcessNextMessage;
2469                         }
2470
2471                         if (hwnd.client_window == xevent.AnyEvent.window) {
2472                                 client = true;
2473                                 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2474                         } else {
2475                                 client = false;
2476                                 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2477                         }
2478
2479                         msg.hwnd = hwnd.Handle;
2480
2481                         //
2482                         // If you add a new event to this switch make sure to add it in
2483                         // UpdateMessage also unless it is not coming through the X event system.
2484                         //
2485                         switch(xevent.type) {
2486                                 case XEventName.KeyPress: {
2487                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2488                                         break;
2489                                 }
2490
2491                                 case XEventName.KeyRelease: {
2492                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2493                                         break;
2494                                 }
2495
2496                                 case XEventName.ButtonPress: {
2497                                         switch(xevent.ButtonEvent.button) {
2498                                                 case 1: {
2499                                                         MouseState |= MouseButtons.Left;
2500                                                         if (client) {
2501                                                                 msg.message = Msg.WM_LBUTTONDOWN;
2502                                                         } else {
2503                                                                 msg.message = Msg.WM_NCLBUTTONDOWN;
2504                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2505                                                         }
2506                                                         // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
2507                                                         msg.wParam=GetMousewParam(0);
2508                                                         break;
2509                                                 }
2510
2511                                                 case 2: {
2512                                                         MouseState |= MouseButtons.Middle;
2513                                                         if (client) {
2514                                                                 msg.message = Msg.WM_MBUTTONDOWN;
2515                                                         } else {
2516                                                                 msg.message = Msg.WM_NCMBUTTONDOWN;
2517                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2518                                                         }
2519                                                         msg.wParam=GetMousewParam(0);
2520                                                         break;
2521                                                 }
2522
2523                                                 case 3: {
2524                                                         MouseState |= MouseButtons.Right;
2525                                                         if (client) {
2526                                                                 msg.message = Msg.WM_RBUTTONDOWN;
2527                                                         } else {
2528                                                                 msg.message = Msg.WM_NCRBUTTONDOWN;
2529                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2530                                                         }
2531                                                         msg.wParam=GetMousewParam(0);
2532                                                         break;
2533                                                 }
2534
2535                                                 case 4: {
2536                                                         msg.message=Msg.WM_MOUSEWHEEL;
2537                                                         msg.wParam=GetMousewParam(120);
2538                                                         break;
2539                                                 }
2540
2541                                                 case 5: {
2542                                                         msg.message=Msg.WM_MOUSEWHEEL;
2543                                                         msg.wParam=GetMousewParam(-120);
2544                                                         break;
2545                                                 }
2546
2547                                         }
2548
2549                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2550                                         MousePosition.X = xevent.ButtonEvent.x;
2551                                         MousePosition.Y = xevent.ButtonEvent.y;
2552
2553                                         if (!hwnd.Enabled) {
2554                                                 IntPtr dummy;
2555
2556                                                 msg.hwnd = hwnd.EnabledHwnd;
2557                                                 XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
2558                                                 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2559                                         }
2560
2561                                         if (Grab.Hwnd != IntPtr.Zero) {
2562                                                 msg.hwnd = Grab.Hwnd;
2563                                         }
2564
2565                                         if (!ClickPending.Pending) {
2566                                                 ClickPending.Pending = true;
2567                                                 ClickPending.Hwnd = msg.hwnd;
2568                                                 ClickPending.Message = msg.message;
2569                                                 ClickPending.wParam = msg.wParam;
2570                                                 ClickPending.lParam = msg.lParam;
2571                                                 ClickPending.Time = (long)xevent.ButtonEvent.time;
2572                                         } else {
2573                                                 if ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message)) {
2574                                                         // Looks like a genuine double click, clicked twice on the same spot with the same keys
2575                                                         switch(xevent.ButtonEvent.button) {
2576                                                                 case 1: {
2577                                                                         msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
2578                                                                         break;
2579                                                                 }
2580
2581                                                                 case 2: {
2582                                                                         msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
2583                                                                         break;
2584                                                                 }
2585
2586                                                                 case 3: {
2587                                                                         msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
2588                                                                         break;
2589                                                                 }
2590                                                         }
2591                                                 }
2592                                                 ClickPending.Pending = false;
2593                                         }
2594
2595                                         break;
2596                                 }
2597
2598                                 case XEventName.ButtonRelease: {
2599                                         Dnd.HandleButtonRelease (ref xevent);
2600                                         switch(xevent.ButtonEvent.button) {
2601                                                 case 1: {
2602                                                         MouseState &= ~MouseButtons.Left;
2603                                                         if (client) {
2604                                                                 msg.message = Msg.WM_LBUTTONUP;
2605                                                         } else {
2606                                                                 msg.message = Msg.WM_NCLBUTTONUP;
2607                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2608                                                         }
2609                                                         msg.wParam=GetMousewParam(0);
2610                                                         break;
2611                                                 }
2612
2613                                                 case 2: {
2614                                                         MouseState &= ~MouseButtons.Middle;
2615                                                         if (client) {
2616                                                                 msg.message = Msg.WM_MBUTTONUP;
2617                                                         } else {
2618                                                                 msg.message = Msg.WM_NCMBUTTONUP;
2619                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2620                                                         }
2621                                                         msg.wParam=GetMousewParam(0);
2622                                                         break;
2623                                                 }
2624
2625                                                 case 3: {
2626                                                         MouseState &= ~MouseButtons.Right;
2627                                                         if (client) {
2628                                                                 msg.message = Msg.WM_RBUTTONUP;
2629                                                         } else {
2630                                                                 msg.message = Msg.WM_NCRBUTTONUP;
2631                                                                 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2632                                                         }
2633                                                         msg.wParam=GetMousewParam(0);
2634                                                         break;
2635                                                 }
2636
2637                                                 case 4: {
2638                                                         goto ProcessNextMessage;
2639                                                 }
2640
2641                                                 case 5: {
2642                                                         goto ProcessNextMessage;
2643                                                 }
2644                                         }
2645
2646                                         if (!hwnd.Enabled) {
2647                                                 IntPtr dummy;
2648
2649                                                 msg.hwnd = hwnd.EnabledHwnd;
2650                                                 XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
2651                                                 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2652                                         }
2653
2654                                         if (Grab.Hwnd != IntPtr.Zero) {
2655                                                 msg.hwnd = Grab.Hwnd;
2656                                         }
2657
2658                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2659                                         MousePosition.X = xevent.ButtonEvent.x;
2660                                         MousePosition.Y = xevent.ButtonEvent.y;
2661                                         break;
2662                                 }
2663
2664                                 case XEventName.MotionNotify: {
2665                                         if (client) {
2666                                                 #if DriverDebugExtra
2667                                                         Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
2668                                                 #endif
2669
2670                                                 if (Dnd.HandleMotionNotify (ref xevent))
2671                                                         goto ProcessNextMessage;
2672                                                 if (Grab.Hwnd != IntPtr.Zero) {
2673                                                         msg.hwnd = Grab.Hwnd;
2674                                                 } else {
2675                                                         NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
2676                                                 }
2677
2678                                                 msg.message = Msg.WM_MOUSEMOVE;
2679                                                 msg.wParam = GetMousewParam(0);
2680                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
2681
2682                                                 if (!hwnd.Enabled) {
2683                                                         IntPtr dummy;
2684
2685                                                         msg.hwnd = hwnd.EnabledHwnd;
2686                                                         XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
2687                                                         msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2688                                                 }
2689
2690                                                 HoverState.X = MousePosition.X = xevent.MotionEvent.x;
2691                                                 HoverState.Y = MousePosition.Y = xevent.MotionEvent.y;
2692
2693                                                 break;
2694                                         } else {
2695                                                 #if DriverDebugExtra
2696                                                         Console.WriteLine("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
2697                                                 #endif
2698                                                 msg.message = Msg.WM_NCMOUSEMOVE;
2699                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
2700
2701                                                 if (!hwnd.Enabled) {
2702                                                         IntPtr dummy;
2703
2704                                                         msg.hwnd = hwnd.EnabledHwnd;
2705                                                         XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
2706                                                         msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2707                                                 }
2708
2709                                                 #if notyet
2710                                                         // Not sure we need this...
2711                                                         HitTest ht;
2712                                                         ht = NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, msg.lParam);
2713                                                 #endif
2714
2715                                                 MousePosition.X = xevent.MotionEvent.x;
2716                                                 MousePosition.Y = xevent.MotionEvent.y;
2717                                         }
2718
2719                                         break;
2720                                 }
2721
2722                                 case XEventName.EnterNotify: {
2723                                         if (!hwnd.Enabled) {
2724                                                 goto ProcessNextMessage;
2725                                         }
2726                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2727                                                 goto ProcessNextMessage;
2728                                         }
2729                                         msg.message = Msg.WM_MOUSE_ENTER;
2730                                         HoverState.Timer.Enabled = true;
2731                                         HoverState.Window = xevent.CrossingEvent.window;
2732                                         break;
2733                                 }
2734
2735                                 case XEventName.LeaveNotify: {
2736                                         if (!hwnd.Enabled) {
2737                                                 goto ProcessNextMessage;
2738                                         }
2739                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2740                                                 goto ProcessNextMessage;
2741                                         }
2742                                         msg.message=Msg.WM_MOUSE_LEAVE;
2743                                         HoverState.Timer.Enabled = false;
2744                                         HoverState.Window = IntPtr.Zero;
2745                                         break;
2746                                 }
2747
2748                                 #if later
2749                                 case XEventName.CreateNotify: {
2750                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
2751                                                 msg.message = WM_CREATE;
2752                                                 // Set up CreateStruct
2753                                         } else {
2754                                                 goto ProcessNextMessage;
2755                                         }
2756                                         break;
2757                                 }
2758                                 #endif
2759
2760
2761                                 case XEventName.ReparentNotify: {
2762                                         if (hwnd.parent == null) {      // Toplevel
2763                                                 if (xevent.ReparentEvent.parent != IntPtr.Zero) {
2764                                                         // We need to adjust x/y
2765                                                         int     dummy_int;
2766                                                         IntPtr  dummy_ptr;
2767
2768                                                         hwnd.Reparented = true;
2769
2770                                                         XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
2771                                                         msg.message = Msg.WM_WINDOWPOSCHANGED;
2772                                                         if (hwnd.opacity != 0xffffffff) {
2773                                                                 uint opacity;
2774
2775                                                                 opacity = hwnd.opacity;
2776                                                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
2777                                                         }
2778                                                 } else {
2779                                                         hwnd.Reparented = false;
2780                                                         goto ProcessNextMessage;
2781                                                 }
2782                                         }
2783                                         break;
2784                                 }
2785
2786                                 case XEventName.ConfigureNotify: {
2787                                         if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {        // Ignore events for children (SubstructureNotify) and client areas
2788                                                 XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
2789                                                 IntPtr                          ptr;
2790                                                 Rectangle                       rect;
2791
2792                                                 #if DriverDebugExtra
2793                                                         Console.WriteLine("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}", hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
2794                                                 #endif
2795                                                 msg.message = Msg.WM_WINDOWPOSCHANGED;
2796                                                 hwnd.configure_pending = false;
2797
2798                                                 // We need to adjust our client window to track the resize of whole_window
2799                                                 rect = hwnd.DefaultClientRect;
2800
2801                                                 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
2802                                                 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
2803
2804                                                 ncp.rgrc1.left = rect.Left;
2805                                                 ncp.rgrc1.top = rect.Top;
2806                                                 ncp.rgrc1.right = rect.Right;
2807                                                 ncp.rgrc1.bottom = rect.Bottom;
2808
2809                                                 Marshal.StructureToPtr(ncp, ptr, true);
2810                                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
2811                                                 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
2812                                                 Marshal.FreeHGlobal(ptr);
2813
2814                                                 // FIXME - debug this with Menus, need to set hwnd.ClientRect
2815
2816                                                 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
2817
2818                                                 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
2819                                         } else {
2820                                                 goto ProcessNextMessage;
2821                                         }
2822
2823                                         msg.lParam=IntPtr.Zero;         // FIXME - Generate LPWINDOWPOS structure and pass on
2824                                         break;
2825                                 }
2826
2827                                 case XEventName.FocusIn: {
2828                                         if (!hwnd.Enabled) {
2829                                                 goto ProcessNextMessage;
2830                                         }
2831                                         msg.message=Msg.WM_SETFOCUS;
2832                                         msg.wParam=IntPtr.Zero;
2833                                         break;
2834                                 }
2835
2836                                 case XEventName.FocusOut: {
2837                                         if (!hwnd.Enabled) {
2838                                                 goto ProcessNextMessage;
2839                                         }
2840                                         msg.message=Msg.WM_KILLFOCUS;
2841                                         msg.wParam=IntPtr.Zero;
2842                                         break;
2843                                 }
2844
2845                                 case XEventName.Expose: {
2846                                         if (PostQuitState) {
2847                                                 goto ProcessNextMessage;
2848                                         }
2849
2850
2851                                         if (client) {
2852                                                 if (!hwnd.expose_pending) {
2853                                                         goto ProcessNextMessage;
2854                                                 }
2855                                         } else {
2856                                                 if (!hwnd.nc_expose_pending) {
2857                                                         goto ProcessNextMessage;
2858                                                 }
2859
2860                                                 switch (hwnd.border_style) {
2861                                                         case FormBorderStyle.Fixed3D: {
2862                                                                 Graphics g;
2863
2864                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
2865                                                                 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
2866                                                                 g.Dispose();
2867                                                                 break;
2868                                                         }
2869
2870                                                         case FormBorderStyle.FixedSingle: {
2871                                                                 Graphics g;
2872
2873                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
2874                                                                 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
2875                                                                 g.Dispose();
2876                                                                 break;
2877                                                         }
2878                                                 }
2879                                                 #if DriverDebugExtra
2880                                                         Console.WriteLine("GetMessage(): Window {0:X} Exposed non-client area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
2881                                                 #endif
2882
2883                                                 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
2884                                                 Region region = new Region (rect);
2885                                                 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
2886                                                 msg.message = Msg.WM_NCPAINT;
2887                                                 msg.wParam = hrgn;
2888                                                 hwnd.nc_expose_pending = false;
2889                                                 break;
2890                                         }
2891                                         #if DriverDebugExtra
2892                                                 Console.WriteLine("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
2893                                         #endif
2894                                         if (Caret.Visible == 1) {
2895                                                 Caret.Paused = true;
2896                                                 HideCaret();
2897                                         }
2898
2899                                         if (Caret.Visible == 1) {
2900                                                 ShowCaret();
2901                                                 Caret.Paused = false;
2902                                         }
2903                                         msg.message = Msg.WM_PAINT;
2904                                         break;
2905                                 }
2906
2907                                 case XEventName.DestroyNotify: {
2908
2909                                         // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
2910                                         hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
2911
2912                                         // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
2913                                         if (hwnd.client_window == xevent.DestroyWindowEvent.window) {
2914                                                 msg.hwnd = hwnd.client_window;
2915                                                 msg.message=Msg.WM_DESTROY;
2916                                                 hwnd.Dispose();
2917
2918                                                 #if DriverDebug
2919                                                         Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
2920                                                 #endif
2921                                         } else {
2922                                                 goto ProcessNextMessage;
2923                                         }
2924
2925                                         break;
2926                                 }
2927
2928                                 case XEventName.ClientMessage: {
2929                                         if (Dnd.HandleClientMessage (ref xevent)) {
2930                                                 goto ProcessNextMessage;
2931                                         }
2932
2933                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)AsyncAtom) {
2934                                                 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
2935                                                 break;
2936                                         }
2937
2938                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)HoverState.Atom) {
2939                                                 msg.message = Msg.WM_MOUSEHOVER;
2940                                                 msg.wParam = GetMousewParam(0);
2941                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
2942                                                 break;
2943                                         }
2944
2945                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
2946                                                 msg.hwnd = xevent.ClientMessageEvent.ptr1;
2947                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
2948                                                 msg.wParam = xevent.ClientMessageEvent.ptr3;
2949                                                 msg.lParam = xevent.ClientMessageEvent.ptr4;
2950                                                 break;
2951                                         }
2952
2953                                         #if dontcare
2954                                         if  (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA._XEMBED]) {
2955                                                 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
2956                                                 break;
2957                                         }
2958                                         #endif
2959
2960                                         if  (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA.WM_PROTOCOLS]) {
2961                                                 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
2962                                                         msg.message = Msg.WM_CLOSE;
2963                                                         Graphics.FromHdcInternal (IntPtr.Zero);
2964                                                         break;
2965                                                 }
2966
2967                                                 // We should not get this, but I'll leave the code in case we need it in the future
2968                                                 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
2969                                                         goto ProcessNextMessage;
2970                                                 }
2971                                         }
2972                                         break;
2973                                 }
2974
2975                                 case XEventName.TimerNotify: {
2976                                         xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
2977                                         break;
2978                                 }
2979                                         
2980                                 default: {
2981                                         goto ProcessNextMessage;
2982                                 }
2983                         }
2984
2985                         return true;
2986                 }
2987
2988                 internal override bool GetText(IntPtr handle, out string text) {
2989                         IntPtr  textptr;
2990
2991                         textptr = IntPtr.Zero;
2992
2993                         lock (XlibLock) {
2994                                 // FIXME - use _NET properties
2995                                 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
2996                         }
2997                         if (textptr != IntPtr.Zero) {
2998                                 text = Marshal.PtrToStringAnsi(textptr);
2999                                 XFree(textptr);
3000                                 return true;
3001                         } else {
3002                                 text = "";
3003                                 return false;
3004                         }
3005                 }
3006
3007                 internal override void GetWindowPos(IntPtr handle, bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
3008                         Hwnd            hwnd;
3009                         Rectangle       rect;
3010
3011                         hwnd = Hwnd.ObjectFromHandle(handle);
3012
3013                         if (hwnd != null) {
3014                                 x = hwnd.x;
3015                                 y = hwnd.y;
3016                                 width = hwnd.width;
3017                                 height = hwnd.height;
3018
3019                                 rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
3020
3021                                 client_width = rect.Width;
3022                                 client_height = rect.Height;
3023
3024                                 return;
3025                         }
3026
3027                         // Should we throw an exception or fail silently?
3028                         // throw new ArgumentException("Called with an invalid window handle", "handle");
3029
3030                         x = 0;
3031                         y = 0;
3032                         width = 0;
3033                         height = 0;
3034                         client_width = 0;
3035                         client_height = 0;
3036                 }
3037
3038                 internal override FormWindowState GetWindowState(IntPtr handle) {
3039                         Atom                    actual_atom;
3040                         int                     actual_format;
3041                         int                     nitems;
3042                         int                     bytes_after;
3043                         IntPtr                  prop = IntPtr.Zero;
3044                         IntPtr                  atom;
3045                         int                     maximized;
3046                         bool                    minimized;
3047                         XWindowAttributes       attributes;
3048                         Hwnd                    hwnd;
3049
3050                         hwnd = Hwnd.ObjectFromHandle(handle);
3051
3052                         maximized = 0;
3053                         minimized = false;
3054                         XGetWindowProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], 0, 256, false, Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3055                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
3056                                 for (int i = 0; i < nitems; i++) {
3057                                         atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3058                                         if ((atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
3059                                                 maximized++;
3060                                         } else if (atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_HIDDEN]) {
3061                                                 minimized = true;
3062                                         }
3063                                 }
3064                                 XFree(prop);
3065                         }
3066
3067                         if (minimized) {
3068                                 return FormWindowState.Minimized;
3069                         } else if (maximized == 2) {
3070                                 return FormWindowState.Maximized;
3071                         }
3072
3073                         attributes = new XWindowAttributes();
3074                         XGetWindowAttributes(DisplayHandle, handle, ref attributes);
3075                         if (attributes.map_state == MapState.IsUnmapped) {
3076                                 throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
3077                         }
3078
3079
3080                         return FormWindowState.Normal;
3081                 }
3082
3083                 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3084                         handle = Grab.Hwnd;
3085                         GrabConfined = Grab.Confined;
3086                         GrabArea = Grab.Area;
3087                 }
3088
3089                 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3090                         Hwnd    hwnd;
3091                         IntPtr  confine_to_window;
3092
3093                         confine_to_window = IntPtr.Zero;
3094
3095                         if (confine_to_handle != IntPtr.Zero) {
3096                                 XWindowAttributes       attributes = new XWindowAttributes();
3097
3098                                 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3099
3100                                 lock (XlibLock) {
3101                                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3102                                 }
3103                                 Grab.Area.X = attributes.x;
3104                                 Grab.Area.Y = attributes.y;
3105                                 Grab.Area.Width = attributes.width;
3106                                 Grab.Area.Height = attributes.height;
3107                                 Grab.Confined = true;
3108                                 confine_to_window = hwnd.client_window;
3109                         }
3110
3111                         Grab.Hwnd = handle;
3112
3113                         hwnd = Hwnd.ObjectFromHandle(handle);
3114
3115                         lock (XlibLock) {
3116                                 XGrabPointer(DisplayHandle, hwnd.client_window, false, 
3117                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3118                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3119                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, 0, 0);
3120                         }
3121                 }
3122
3123                 internal override void UngrabWindow(IntPtr hwnd) {
3124                         lock (XlibLock) {
3125                                 XUngrabPointer(DisplayHandle, 0);
3126                                 XFlush(DisplayHandle);
3127                         }
3128                         Grab.Hwnd = IntPtr.Zero;
3129                         Grab.Confined = false;
3130                 }
3131
3132                 internal override void HandleException(Exception e) {
3133                         StackTrace st = new StackTrace(e, true);
3134                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3135                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
3136                 }
3137
3138                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3139                         Hwnd    hwnd;
3140                         XEvent  xevent;
3141
3142                         hwnd = Hwnd.ObjectFromHandle(handle);
3143
3144
3145                         xevent = new XEvent ();
3146                         xevent.type = XEventName.Expose;
3147                         xevent.ExposeEvent.display = DisplayHandle;
3148                         xevent.ExposeEvent.window = hwnd.client_window;
3149
3150                         if (clear) {
3151                                 xevent.ExposeEvent.x = hwnd.X;
3152                                 xevent.ExposeEvent.y = hwnd.Y;
3153                                 xevent.ExposeEvent.width = hwnd.Width;
3154                                 xevent.ExposeEvent.height = hwnd.Height;
3155                         } else {
3156                                 xevent.ExposeEvent.x = rc.X;
3157                                 xevent.ExposeEvent.y = rc.Y;
3158                                 xevent.ExposeEvent.width = rc.Width;
3159                                 xevent.ExposeEvent.height = rc.Height;
3160                         }
3161
3162                         AddExpose (xevent);
3163                 }
3164
3165                 internal override bool IsEnabled(IntPtr handle) {
3166                         return Hwnd.ObjectFromHandle(handle).Enabled;
3167                 }
3168                 
3169                 internal override bool IsVisible(IntPtr handle) {
3170                         return Hwnd.ObjectFromHandle(handle).visible;
3171                 }
3172
3173                 internal override void KillTimer(Timer timer) {
3174                         lock (TimerList) {
3175                                 TimerList.Remove(timer);
3176                         }
3177                 }
3178
3179                 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3180                         int     dest_x_return;
3181                         int     dest_y_return;
3182                         IntPtr  child;
3183                         Hwnd    hwnd;
3184
3185                         hwnd = Hwnd.ObjectFromHandle(handle);
3186
3187                         lock (XlibLock) {
3188                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3189                         }
3190
3191                         x = dest_x_return;
3192                         y = dest_y_return;
3193                 }
3194
3195                 internal override void OverrideCursor(IntPtr cursor) {
3196                         OverrideCursorHandle = cursor;
3197                 }
3198
3199                 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3200                         PaintEventArgs  paint_event;
3201                         Hwnd            hwnd;
3202
3203                         hwnd = Hwnd.ObjectFromHandle(handle);
3204
3205                         if (Caret.Visible == 1) {
3206                                 Caret.Paused = true;
3207                                 HideCaret();
3208                         }
3209
3210                         if (client) {
3211                                 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3212                                 hwnd.client_dc.SetClip(hwnd.invalid);
3213                                 paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.invalid);
3214                                 hwnd.expose_pending = false;
3215
3216                                 return paint_event;
3217                         } else {
3218                                 hwnd.client_dc = Graphics.FromHwnd (hwnd.whole_window);
3219                                 paint_event = new PaintEventArgs(hwnd.client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3220                                 hwnd.nc_expose_pending = false;
3221
3222                                 return paint_event;
3223                         }
3224                 }
3225
3226                 internal override void PaintEventEnd(IntPtr handle, bool client) {
3227                         Hwnd    hwnd;
3228
3229                         hwnd = Hwnd.ObjectFromHandle(handle);
3230
3231                         if (client) {
3232                                 hwnd.ClearInvalidArea();
3233                         }
3234
3235                         hwnd.client_dc.Flush();
3236                         hwnd.client_dc.Dispose();
3237                         hwnd.client_dc = null;
3238
3239                         if (Caret.Visible == 1) {
3240                                 ShowCaret();
3241                                 Caret.Paused = false;
3242                         }
3243                 }
3244
3245                 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3246                         bool    pending;
3247
3248                         // FIXME - imlement filtering
3249
3250                         if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3251                                 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
3252                         }
3253
3254                         pending = false;
3255                         if (MessageQueue.Count > 0) {
3256                                 pending = true;
3257                         } else {
3258                                 // Only call UpdateMessageQueue if real events are pending 
3259                                 // otherwise we go to sleep on the socket
3260                                 if (XPending(DisplayHandle) != 0) {
3261                                         UpdateMessageQueue();
3262                                         pending = true;
3263                                 }
3264                         }
3265
3266                         CheckTimers(DateTime.Now);
3267
3268                         if (!pending) {
3269                                 return false;
3270                         }
3271                         return GetMessage(ref msg, hWnd, wFilterMin, wFilterMax);
3272                 }
3273
3274                 // FIXME - I think this should just enqueue directly
3275                 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3276                         XEvent xevent = new XEvent ();
3277                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
3278
3279                         xevent.type = XEventName.ClientMessage;
3280                         xevent.ClientMessageEvent.display = DisplayHandle;
3281
3282                         if (hwnd != null) {
3283                                 xevent.ClientMessageEvent.window = hwnd.whole_window;
3284                         } else {
3285                                 xevent.ClientMessageEvent.window = IntPtr.Zero;
3286                         }
3287
3288                         xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
3289                         xevent.ClientMessageEvent.format = 32;
3290                         xevent.ClientMessageEvent.ptr1 = handle;
3291                         xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
3292                         xevent.ClientMessageEvent.ptr3 = wparam;
3293                         xevent.ClientMessageEvent.ptr4 = lparam;
3294
3295                         MessageQueue.Enqueue (xevent);
3296
3297                         return true;
3298                 }
3299
3300                 internal override void PostQuitMessage(int exitCode) {
3301                         XFlush(DisplayHandle);
3302                         PostQuitState = true;
3303
3304                         // Remove our display handle from S.D
3305                         Graphics.FromHdcInternal (IntPtr.Zero);
3306                 }
3307
3308                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
3309                         int     dest_x_return;
3310                         int     dest_y_return;
3311                         IntPtr  child;
3312                         Hwnd    hwnd;
3313
3314                         hwnd = Hwnd.ObjectFromHandle(handle);
3315
3316                         lock (XlibLock) {
3317                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
3318                         }
3319
3320                         x = dest_x_return;
3321                         y = dest_y_return;
3322                 }
3323
3324                 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
3325                         int     dest_x_return;
3326                         int     dest_y_return;
3327                         IntPtr  child;
3328                         Hwnd    hwnd;
3329
3330                         hwnd = Hwnd.ObjectFromHandle(handle);
3331
3332                         lock (XlibLock) {
3333                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
3334                         }
3335
3336                         x = dest_x_return;
3337                         y = dest_y_return;
3338                 }
3339
3340                 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
3341                         Hwnd            hwnd;
3342                         IntPtr          gc;
3343                         XGCValues       gc_values;
3344
3345                         hwnd = Hwnd.ObjectFromHandle(handle);
3346
3347                         if (hwnd.invalid != Rectangle.Empty) {
3348                                 // BIG FAT WARNING. This only works with how we use this function right now
3349                                 // where we basically still scroll the whole window, but work around areas
3350                                 // that are covered by our children
3351
3352                                 hwnd.invalid.X += XAmount;
3353                                 hwnd.invalid.Y += YAmount;
3354
3355                                 if (hwnd.invalid.X < 0) {
3356                                         hwnd.invalid.Width += hwnd.invalid.X;
3357                                         hwnd.invalid.X =0;
3358                                 }
3359
3360                                 if (hwnd.invalid.Y < 0) {
3361                                         hwnd.invalid.Height += hwnd.invalid.Y;
3362                                         hwnd.invalid.Y =0;
3363                                 }
3364                         }
3365
3366                         gc_values = new XGCValues();
3367
3368                         if (with_children) {
3369                                 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3370                         }
3371
3372                         gc = XCreateGC(DisplayHandle, hwnd.client_window, 0, ref gc_values);
3373
3374                         XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
3375
3376                         // Generate an expose for the area exposed by the horizontal scroll
3377                         if (XAmount > 0) {
3378                                 hwnd.AddInvalidArea (area.X, area.Y, XAmount, area.Height);
3379                         } else if (XAmount < 0) {
3380                                 hwnd.AddInvalidArea (XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
3381                         }
3382
3383                         // Generate an expose for the area exposed by the vertical scroll
3384                         if (YAmount > 0) {
3385                                 hwnd.AddInvalidArea (area.X, area.Y, area.Width, YAmount);
3386                         } else if (YAmount < 0) {
3387                                 hwnd.AddInvalidArea (area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
3388                         }
3389                         XFreeGC(DisplayHandle, gc);
3390
3391                         UpdateWindow(handle);
3392                 }
3393
3394                 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
3395                         Hwnd    hwnd;
3396
3397                         hwnd = Hwnd.GetObjectFromWindow(handle);
3398
3399                         ScrollWindow(handle, hwnd.ClientRect, XAmount, YAmount, with_children);
3400                 }
3401
3402                 internal override void SendAsyncMethod (AsyncMethodData method) {
3403                         XEvent xevent = new XEvent ();
3404
3405                         xevent.type = XEventName.ClientMessage;
3406                         xevent.ClientMessageEvent.display = DisplayHandle;
3407                         xevent.ClientMessageEvent.window = FosterParent;
3408                         xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
3409                         xevent.ClientMessageEvent.format = 32;
3410                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
3411
3412                         MessageQueue.EnqueueLocked (xevent);
3413
3414                         WakeupMain ();
3415                 }
3416
3417                 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam) {
3418                         return NativeWindow.WndProc(hwnd, message, wParam, lParam);
3419                 }
3420
3421                 internal override void SetAllowDrop (IntPtr handle, bool value)
3422                 {
3423                         // We allow drop on all windows
3424                 }
3425
3426                 internal override DragDropEffects StartDrag (IntPtr handle, object data,
3427                                 DragDropEffects allowed_effects)
3428                 {
3429                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3430
3431                         if (hwnd == null)
3432                                 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
3433
3434                         return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
3435                 }
3436
3437                 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
3438                         Hwnd    hwnd;
3439
3440                         hwnd = Hwnd.ObjectFromHandle(handle);
3441
3442                         hwnd.border_style = border_style;
3443
3444                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, hwnd.ClientRect.X, hwnd.ClientRect.Y, hwnd.ClientRect.Width, hwnd.ClientRect.Height);
3445
3446                         InvalidateWholeWindow(handle);
3447                 }
3448
3449                 internal override void SetCaretPos(IntPtr handle, int x, int y) {
3450                         if (Caret.Hwnd == handle) {
3451                                 Caret.Timer.Stop();
3452                                 HideCaret();
3453
3454                                 Caret.X = x;
3455                                 Caret.Y = y;
3456
3457                                 if (Caret.Visible == 1) {
3458                                         ShowCaret();
3459                                         Caret.Timer.Start();
3460                                 }
3461                         }
3462                 }
3463
3464                 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
3465                         Hwnd    hwnd;
3466
3467                         if (OverrideCursorHandle == IntPtr.Zero) {
3468                                 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
3469                                         return;
3470                                 }
3471
3472                                 LastCursorHandle = cursor;
3473                                 LastCursorWindow = handle;
3474
3475                                 hwnd = Hwnd.ObjectFromHandle(handle);
3476                                 lock (XlibLock) {
3477                                         if (cursor != IntPtr.Zero) {
3478                                                 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
3479                                         } else {
3480                                                 XUndefineCursor(DisplayHandle, hwnd.whole_window);
3481                                         }
3482                                 }
3483                                 return;
3484                         }
3485
3486                         hwnd = Hwnd.ObjectFromHandle(handle);
3487                         lock (XlibLock) {
3488                                 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
3489                         }
3490                 }
3491
3492                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
3493                         if (handle == IntPtr.Zero) {
3494                                 lock (XlibLock) {
3495                                         XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x, y);
3496                                 }
3497                                 return;
3498                         } else {
3499                                 Hwnd    hwnd;
3500
3501                                 hwnd = Hwnd.ObjectFromHandle(handle);
3502                                 lock (XlibLock) {
3503                                         XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
3504                                 }
3505                                 return;
3506                         }
3507                 }
3508
3509                 internal override void SetFocus(IntPtr handle) {
3510                         Hwnd    hwnd;
3511
3512                         hwnd = Hwnd.ObjectFromHandle(handle);
3513
3514                         if (FocusWindow != IntPtr.Zero) {
3515                                 PostMessage(FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
3516                         }
3517                         PostMessage(hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
3518                         FocusWindow = hwnd.client_window;
3519
3520                         //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
3521                 }
3522
3523                 internal override void SetIcon(IntPtr handle, Icon icon) {
3524                         Hwnd    hwnd;
3525
3526                         hwnd = Hwnd.ObjectFromHandle(handle);
3527                         if (hwnd != null) {
3528                                 SetIcon(hwnd, icon);
3529                         }
3530                 }
3531
3532                 internal override void SetMenu(IntPtr handle, Menu menu) {
3533                         Hwnd    hwnd;
3534
3535                         hwnd = Hwnd.ObjectFromHandle(handle);
3536                         hwnd.menu = menu;
3537
3538                         // FIXME - do we need to trigger some resize?
3539                 }
3540
3541                 internal override void SetModal(IntPtr handle, bool Modal) {
3542                         if (Modal) {
3543                                 ModalWindows.Push(handle);
3544                         } else {
3545                                 if (ModalWindows.Contains(handle)) {
3546                                         ModalWindows.Pop();
3547                                 }
3548                                 if (ModalWindows.Count > 0) {
3549                                         Activate((IntPtr)ModalWindows.Peek());
3550                                 }
3551                         }
3552                 }
3553
3554                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
3555                         Hwnd    hwnd;
3556
3557                         hwnd = Hwnd.ObjectFromHandle(handle);
3558                         hwnd.parent = Hwnd.ObjectFromHandle(parent);
3559
3560                         lock (XlibLock) {
3561                                 #if DriverDebug
3562                                         Console.WriteLine("Parent for window {0:X} / {1:X} = {2:X} (Handle:{3:X})", hwnd.ClientWindow.ToInt32(), hwnd.WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, parent.ToInt32());
3563                                 #endif
3564                                 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
3565                         }
3566
3567                         return IntPtr.Zero;
3568                 }
3569
3570                 internal override void SetTimer (Timer timer) {
3571                         lock (TimerList) {
3572                                 TimerList.Add(timer);
3573                         }
3574                         WakeupMain ();
3575                 }
3576
3577                 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
3578                         Hwnd    hwnd;
3579                         Hwnd    hwnd_owner;
3580
3581                         hwnd = Hwnd.ObjectFromHandle(handle);
3582
3583                         if (handle_owner != IntPtr.Zero) {
3584                                 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
3585                         } else {
3586                                 hwnd_owner = null;
3587                         }
3588
3589                         if (enabled) {
3590                                 lock (XlibLock) {
3591                                         if (hwnd_owner != null) {
3592                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
3593                                         } else {
3594                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
3595                                         }
3596                                 }
3597                         } else {
3598                                 lock (XlibLock) {
3599                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, (int)Atom.XA_WM_TRANSIENT_FOR);
3600                                 }
3601                         }
3602                         return true;
3603                 }
3604
3605                 internal override bool SetVisible(IntPtr handle, bool visible) {
3606                         Hwnd    hwnd;
3607
3608                         hwnd = Hwnd.ObjectFromHandle(handle);
3609                         hwnd.visible = visible;
3610
3611                         lock (XlibLock) {
3612                                 if (visible) {
3613                                         if (Control.FromHandle(handle) is Form) {
3614                                                 FormWindowState s;
3615
3616                                                 s = ((Form)Control.FromHandle(handle)).WindowState;
3617
3618                                                 XMapWindow(DisplayHandle, hwnd.whole_window);
3619                                                 XMapWindow(DisplayHandle, hwnd.client_window);
3620
3621                                                 switch(s) {
3622                                                         case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
3623                                                         case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
3624                                                 }
3625                                         } else {
3626                                                 XMapWindow(DisplayHandle, hwnd.whole_window);
3627                                                 XMapWindow(DisplayHandle, hwnd.client_window);
3628                                         }
3629                                 } else {
3630                                         XUnmapWindow(DisplayHandle, hwnd.whole_window);
3631                                 }
3632                         }
3633                         return true;
3634                 }
3635
3636                 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
3637                         Hwnd            hwnd;
3638                         XSizeHints      hints;
3639
3640                         hwnd = Hwnd.ObjectFromHandle(handle);
3641                         if (hwnd == null) {
3642                                 return;
3643                         }
3644
3645                         hints = new XSizeHints();
3646
3647                         if (min != Size.Empty) {
3648                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
3649                                 hints.min_width = min.Width;
3650                                 hints.min_height = min.Height;
3651                         }
3652
3653                         if (max != Size.Empty) {
3654                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
3655                                 hints.max_width = max.Width;
3656                                 hints.max_height = max.Height;
3657                         }
3658
3659                         XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
3660
3661                         if (maximized != Rectangle.Empty) {
3662                                 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
3663                                 hints.x = maximized.X;
3664                                 hints.y = maximized.Y;
3665                                 hints.width = maximized.Width;
3666                                 hints.height = maximized.Height;
3667
3668                                 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
3669                                 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
3670                         }
3671                 }
3672
3673
3674                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
3675                         Hwnd            hwnd;
3676                         Rectangle       client_rect;
3677
3678                         hwnd = Hwnd.ObjectFromHandle(handle);
3679
3680                         // X requires a sanity check for width & height; otherwise it dies
3681                         if (hwnd.zero_sized && width > 0 && height > 0) {
3682                                 if (hwnd.visible) {
3683                                         XMapWindow(DisplayHandle, hwnd.whole_window);
3684                                 }
3685                                 hwnd.zero_sized = false;
3686                         }
3687
3688                         if (width < 1) {
3689                                 hwnd.zero_sized = true;
3690                                 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3691                         }
3692
3693                         if (height < 1) {
3694                                 hwnd.zero_sized = true;
3695                                 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3696                         }
3697
3698                         client_rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
3699
3700                         // Save a server roundtrip (and prevent a feedback loop)
3701                         if ((hwnd.x == x) && (hwnd.y == y) && 
3702                                 (hwnd.width == width) && (hwnd.height == height) &&
3703                                 (hwnd.ClientRect == client_rect)) {
3704                                 return;
3705                         }
3706
3707                         if (!hwnd.zero_sized) {
3708                                 lock (XlibLock) {
3709                                         XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
3710                                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
3711                                 }
3712                         }
3713
3714                         // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
3715                         hwnd.width = width;
3716                         hwnd.height = height;
3717                 }
3718
3719                 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
3720                         FormWindowState current_state;
3721                         Hwnd            hwnd;
3722
3723                         hwnd = Hwnd.ObjectFromHandle(handle);
3724
3725                         current_state = GetWindowState(handle);
3726
3727                         if (current_state == state) {
3728                                 return;
3729                         }
3730
3731                         switch(state) {
3732                                 case FormWindowState.Normal: {
3733                                         lock (XlibLock) {
3734                                                 if (current_state == FormWindowState.Minimized) {
3735                                                         XMapWindow(DisplayHandle, hwnd.whole_window);
3736                                                         XMapWindow(DisplayHandle, hwnd.client_window);
3737                                                 } else if (current_state == FormWindowState.Maximized) {
3738                                                         SendNetWMMessage(hwnd.whole_window, (IntPtr)(uint)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
3739                                                 }
3740                                         }
3741                                         Activate(handle);
3742                                         return;
3743                                 }
3744
3745                                 case FormWindowState.Minimized: {
3746                                         lock (XlibLock) {
3747                                                 if (current_state == FormWindowState.Maximized) {
3748                                                         SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
3749                                                 }
3750                                                 XIconifyWindow(DisplayHandle, hwnd.whole_window, 0);
3751                                         }
3752                                         return;
3753                                 }
3754
3755                                 case FormWindowState.Maximized: {
3756                                         lock (XlibLock) {
3757                                                 if (current_state == FormWindowState.Minimized) {
3758                                                         XMapWindow(DisplayHandle, hwnd.whole_window);
3759                                                         XMapWindow(DisplayHandle, hwnd.client_window);
3760                                                 }
3761
3762                                                 SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
3763                                         }
3764                                         Activate(handle);
3765                                         return;
3766                                 }
3767                         }
3768                 }
3769
3770                 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
3771                         Hwnd    hwnd;
3772
3773                         hwnd = Hwnd.ObjectFromHandle(handle);
3774                         SetHwndStyles(hwnd, cp);
3775                         SetWMStyles(hwnd, cp);
3776                 }
3777
3778                 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
3779                         Hwnd    hwnd;
3780                         uint    opacity;
3781
3782                         hwnd = Hwnd.ObjectFromHandle(handle);
3783
3784                         if (hwnd == null) {
3785                                 return;
3786                         }
3787
3788                         hwnd.opacity = (uint)(0xffffffff * transparency);
3789                         opacity = hwnd.opacity;
3790
3791                         if (hwnd.reparented) {
3792                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3793                         }
3794                 }
3795
3796                 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
3797                         Hwnd    hwnd = Hwnd.ObjectFromHandle(handle);
3798
3799                         if (top) {
3800                                 lock (XlibLock) {
3801                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
3802                                 }
3803                                 return true;
3804                         } else if (!bottom) {
3805                                 Hwnd    after_hwnd = null;
3806
3807                                 if (after_handle != IntPtr.Zero) {
3808                                         after_hwnd = Hwnd.ObjectFromHandle(after_handle);
3809                                 }
3810
3811                                 XWindowChanges  values = new XWindowChanges();
3812
3813                                 if (after_hwnd == null) {
3814                                         throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
3815                                 }
3816                                 values.sibling = after_hwnd.whole_window;
3817                                 values.stack_mode = StackMode.Below;
3818
3819                                 lock (XlibLock) {
3820                                         XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
3821                                 }
3822                         } else {
3823                                 // Bottom
3824                                 lock (XlibLock) {
3825                                         XLowerWindow(DisplayHandle, hwnd.whole_window);
3826                                 }
3827                                 return true;
3828                         }
3829                         return false;
3830                 }
3831
3832                 internal override void ShowCursor(bool show) {
3833                         ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
3834                 }
3835
3836                 internal override void StartLoop(Thread thread) {
3837                         // Future place for prepping a new queue for this specific thread
3838                 }
3839
3840                 internal override bool SupportsTransparency() {
3841                         // We need to check if the x compositing manager is running
3842                         return true;
3843                 }
3844
3845                 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
3846                         GetSystrayManagerWindow();
3847
3848                         if (SystrayMgrWindow != IntPtr.Zero) {
3849                                 uint[]          atoms;
3850                                 XSizeHints      size_hints;
3851                                 Hwnd            hwnd;
3852
3853                                 hwnd = Hwnd.ObjectFromHandle(handle);
3854                                 #if DriverDebug
3855                                         Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
3856                                 #endif
3857
3858                                 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3859                                 XUnmapWindow(DisplayHandle, hwnd.client_window);
3860
3861                                 // Oh boy.
3862                                 XDestroyWindow(DisplayHandle, hwnd.client_window);
3863                                 hwnd.client_window = hwnd.whole_window;
3864
3865                                 size_hints = new XSizeHints();
3866
3867                                 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
3868                                 size_hints.min_width = icon.Width;
3869                                 size_hints.min_height = icon.Height;
3870
3871                                 size_hints.max_width = icon.Width;
3872                                 size_hints.max_height = icon.Height;
3873
3874                                 size_hints.base_width = icon.Width;
3875                                 size_hints.base_height = icon.Height;
3876                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
3877
3878                                 atoms = new uint[2];
3879                                 atoms[0] = 1;   // Version 1
3880                                 atoms[1] = 0;   // We're not mapped
3881
3882                                 // This line cost me 3 days...
3883                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._XEMBED_INFO], NetAtoms[(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
3884
3885                                 // Need to pick some reasonable defaults
3886                                 tt = new ToolTip();
3887                                 tt.AutomaticDelay = 100;
3888                                 tt.InitialDelay = 250;
3889                                 tt.ReshowDelay = 250;
3890                                 tt.ShowAlways = true;
3891
3892                                 if ((tip != null) && (tip != string.Empty)) {
3893                                         tt.SetToolTip(Control.FromHandle(handle), tip);
3894                                         tt.Active = true;
3895                                 } else {
3896                                         tt.Active = false;
3897                                 }
3898
3899                                 // Make sure the window exists
3900                                 XSync(DisplayHandle, hwnd.whole_window);
3901
3902                                 SendNetClientMessage(SystrayMgrWindow, (IntPtr)NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
3903                                 return true;
3904                         }
3905                         tt = null;
3906                         return false;
3907                 }
3908
3909                 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
3910                         Control control;
3911
3912                         control = Control.FromHandle(handle);
3913                         if (control != null && tt != null) {
3914                                 tt.SetToolTip(control, tip);
3915                                 tt.Active = true;
3916                                 return true;
3917                         } else {
3918                                 return false;
3919                         }
3920                 }
3921
3922                 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
3923                         Hwnd    hwnd;
3924
3925                         hwnd = Hwnd.ObjectFromHandle(handle);
3926
3927                         XUnmapWindow(DisplayHandle, hwnd.whole_window);
3928                         SetParent(hwnd.whole_window, FosterParent);
3929
3930                         // The caller can now re-dock it later...
3931                         if (tt != null) {
3932                                 tt.Dispose();
3933                                 tt = null;
3934                         }
3935                 }
3936
3937                 internal override bool Text(IntPtr handle, string text) {
3938                         lock (XlibLock) {
3939                                 // FIXME - use _NET properties
3940                                 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
3941                         }
3942                         return true;
3943                 }
3944
3945                 internal override bool TranslateMessage(ref MSG msg) {
3946                         return Keyboard.TranslateMessage (ref msg);
3947                 }
3948
3949                 internal override void UpdateWindow(IntPtr handle) {
3950                         XEvent  xevent;
3951                         Hwnd    hwnd;
3952
3953                         hwnd = Hwnd.ObjectFromHandle(handle);
3954
3955                         if (!hwnd.visible || hwnd.expose_pending) {
3956                                 return;
3957                         }
3958
3959 #if not
3960                         SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
3961 #else
3962                         xevent = new XEvent();
3963                         xevent.type = XEventName.Expose;
3964                         xevent.ExposeEvent.display = DisplayHandle;
3965                         xevent.ExposeEvent.window = hwnd.client_window;
3966
3967                         MessageQueue.Enqueue(xevent);
3968                         hwnd.expose_pending = true;
3969 #endif
3970                 }
3971                 #endregion      // Public Static Methods
3972
3973                 #region Events
3974                 internal override event EventHandler Idle;
3975                 #endregion      // Events
3976
3977                 #region X11 Imports
3978                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
3979                 internal extern static IntPtr XOpenDisplay(IntPtr display);
3980                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
3981                 internal extern static int XCloseDisplay(IntPtr display);                                                   
3982                 [DllImport ("libX11", EntryPoint="XSynchronize")]
3983                 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
3984
3985                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
3986                 internal extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, SetWindowValuemask valuemask, ref XSetWindowAttributes attributes);
3987                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
3988                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
3989                 [DllImport ("libX11", EntryPoint="XMapWindow")]
3990                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
3991                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
3992                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
3993                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
3994                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
3995                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
3996                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
3997                 [DllImport ("libX11", EntryPoint="XRootWindow")]
3998                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
3999                 [DllImport ("libX11", EntryPoint="XNextEvent")]
4000                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4001                 [DllImport ("libX11")]
4002                 internal extern static int XConnectionNumber (IntPtr diplay);
4003                 [DllImport ("libX11")]
4004                 internal extern static int XPending (IntPtr diplay);
4005                 [DllImport ("libX11")]
4006                 internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
4007                 [DllImport ("libX11")]
4008                 internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
4009                 [DllImport ("libX11", EntryPoint="XSelectInput")]
4010                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
4011
4012                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4013                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4014
4015                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4016                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4017                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4018                 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4019
4020                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4021                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4022
4023                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4024                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4025
4026                 [DllImport ("libX11", EntryPoint="XFlush")]
4027                 internal extern static int XFlush(IntPtr display);
4028
4029                 [DllImport ("libX11", EntryPoint="XSetWMName")]
4030                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4031
4032                 [DllImport ("libX11", EntryPoint="XStoreName")]
4033                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
4034
4035                 [DllImport ("libX11", EntryPoint="XFetchName")]
4036                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
4037
4038                 [DllImport ("libX11", EntryPoint="XSendEvent")]
4039                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
4040
4041                 [DllImport ("libX11", EntryPoint="XQueryTree")]
4042                 internal extern static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
4043
4044                 [DllImport ("libX11", EntryPoint="XFree")]
4045                 internal extern static int XFree(IntPtr data);
4046
4047                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
4048                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
4049
4050                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
4051                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
4052
4053                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
4054                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
4055
4056                 [DllImport ("libX11", EntryPoint="XInternAtom")]
4057                 internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
4058
4059                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
4060                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, uint[] protocols, int count);
4061
4062                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
4063                 internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, uint cursor, uint timestamp);
4064
4065                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
4066                 internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
4067
4068                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
4069                 internal extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
4070
4071                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
4072                 internal extern static bool XTranslateCoordinates (IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return,  out int dest_y_return, out IntPtr child_return);
4073
4074                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4075                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
4076
4077                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4078                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth);
4079
4080                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4081                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth);
4082
4083                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4084                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth);
4085
4086                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
4087                 internal extern static uint XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y);
4088
4089                 [DllImport ("libX11", EntryPoint="XClearWindow")]
4090                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
4091
4092                 [DllImport ("libX11", EntryPoint="XClearArea")]
4093                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
4094
4095                 // Colormaps
4096                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
4097                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
4098
4099                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
4100                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
4101
4102                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
4103                 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
4104
4105                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
4106                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
4107
4108                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
4109                 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
4110
4111                 [DllImport ("libX11", EntryPoint="XLookupColor")]
4112                 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
4113
4114                 [DllImport ("libX11", EntryPoint="XAllocColor")]
4115                 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
4116
4117                 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
4118                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
4119
4120                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4121                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, ref MotifWmHints data, int nelements);
4122
4123                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4124                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode  mode, uint[] atoms, int nelements);
4125
4126                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4127                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode  mode, ref uint value, int nelements);
4128
4129                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4130                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, uint[] atoms, int nelements);
4131
4132                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4133                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
4134
4135                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4136                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
4137
4138                 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
4139                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, string text, int text_length);
4140
4141                 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
4142                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, int property);
4143
4144                 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
4145                 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
4146
4147                 // Drawing
4148                 [DllImport ("libX11", EntryPoint="XCreateGC")]
4149                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, GCFunction valuemask, ref XGCValues values);
4150
4151                 [DllImport ("libX11", EntryPoint="XFreeGC")]
4152                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
4153
4154                 [DllImport ("libX11", EntryPoint="XSetFunction")]
4155                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
4156
4157                 [DllImport ("libX11", EntryPoint="XDrawLine")]
4158                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
4159
4160                 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
4161                 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
4162
4163                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
4164                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
4165
4166                 [DllImport ("libX11", EntryPoint="XCopyArea")]
4167                 internal extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
4168
4169                 [DllImport ("libX11", EntryPoint="XGetAtomName")]
4170                 internal extern static string XGetAtomName(IntPtr display, int atom);
4171
4172                 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
4173                 internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, int atom, int long_offset, int long_length, bool delete, Atom req_type, out Atom actual_type, out int actual_format, out int nitems, out int bytes_after, ref IntPtr prop);
4174
4175                 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
4176                 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
4177
4178                 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
4179                 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
4180
4181                 [DllImport ("libX11", EntryPoint="XDefineCursor")]
4182                 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
4183
4184                 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
4185                 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
4186
4187                 [DllImport ("libX11", EntryPoint="XFreeCursor")]
4188                 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
4189
4190                 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
4191                 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
4192
4193                 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
4194                 internal extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot);
4195
4196                 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
4197                 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
4198
4199                 [DllImport ("libX11", EntryPoint="XFreePixmap")]
4200                 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
4201
4202                 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
4203                 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
4204
4205                 [DllImport ("libX11", EntryPoint="XWhitePixel")]
4206                 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
4207
4208                 [DllImport ("libX11", EntryPoint="XBlackPixel")]
4209                 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
4210
4211                 [DllImport ("libX11", EntryPoint="XGrabServer")]
4212                 internal extern static void XGrabServer(IntPtr display);
4213
4214                 [DllImport ("libX11", EntryPoint="XUngrabServer")]
4215                 internal extern static void XUngrabServer(IntPtr display);
4216
4217                 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
4218                 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4219
4220                 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
4221                 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4222
4223                 [DllImport ("libX11", EntryPoint="XSetWMHints")]
4224                 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
4225
4226                 [DllImport ("libX11", EntryPoint="XSync")]
4227                 internal extern static void XSync(IntPtr display, IntPtr window);
4228
4229                 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
4230                 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
4231
4232                 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
4233                 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
4234
4235                 [DllImport ("libX11", EntryPoint="XGetErrorText")]
4236                 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
4237
4238                 [DllImport ("libX11", EntryPoint="XInitThreads")]
4239                 internal extern static int XInitThreads();
4240
4241                 [DllImport ("libX11", EntryPoint="XConvertSelection")]
4242                 internal extern static int XConvertSelection(IntPtr display, int selection, int target, int property, IntPtr requestor, IntPtr time);
4243
4244                 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
4245                 internal extern static IntPtr XGetSelectionOwner(IntPtr display, int selection);
4246
4247                 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
4248                 internal extern static int XSetSelectionOwner(IntPtr display, int selection, IntPtr owner, IntPtr time);
4249
4250                 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
4251                 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, uint mask);
4252
4253                 [DllImport ("libX11", EntryPoint="XSetForeground")]
4254                 internal extern static int XSetForeground(IntPtr display, IntPtr gc, uint foreground);
4255
4256                 [DllImport ("libX11", EntryPoint="XSetBackground")]
4257                 internal extern static int XSetBackground(IntPtr display, IntPtr gc, uint background);
4258
4259                 [DllImport ("libX11", EntryPoint="XBell")]
4260                 internal extern static int XBell(IntPtr display, int percent);
4261                 #endregion
4262         }
4263 }