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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
90 private int render_major_opcode;
91 private int render_first_event;
92 private int render_first_error;
95 private static IntPtr ClipMagic;
96 private static ClipboardStruct Clipboard; // Our clipboard
99 private static IntPtr PostAtom; // PostMessage atom
100 private static IntPtr AsyncAtom; // Support for async messages
103 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
104 private static ArrayList unattached_timer_list; // holds timers that are enabled but not attached to a window.
106 private static Pollfd[] pollfds; // For watching the X11 socket
107 private static bool wake_waiting;
108 private static object wake_waiting_lock = new object ();
110 private static X11Keyboard Keyboard; //
111 private static X11Dnd Dnd;
112 private static Socket listen; //
113 private static Socket wake; //
114 private static Socket wake_receive; //
115 private static byte[] network_buffer; //
116 private static bool detectable_key_auto_repeat;
119 private static IntPtr ActiveWindow; // Handle of the active window
120 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
123 private static Stack ModalWindows; // Stack of our modal windows
126 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
129 private static IntPtr LastCursorWindow; // The last window we set the cursor on
130 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
131 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
134 private static CaretStruct Caret; //
136 // Last window containing the pointer
137 private static IntPtr LastPointerWindow; // The last window containing the pointer
140 private static IntPtr WM_PROTOCOLS;
141 private static IntPtr WM_DELETE_WINDOW;
142 private static IntPtr WM_TAKE_FOCUS;
143 //private static IntPtr _NET_SUPPORTED;
144 //private static IntPtr _NET_CLIENT_LIST;
145 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
146 private static IntPtr _NET_DESKTOP_GEOMETRY;
147 //private static IntPtr _NET_DESKTOP_VIEWPORT;
148 private static IntPtr _NET_CURRENT_DESKTOP;
149 //private static IntPtr _NET_DESKTOP_NAMES;
150 private static IntPtr _NET_ACTIVE_WINDOW;
151 private static IntPtr _NET_WORKAREA;
152 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
153 //private static IntPtr _NET_VIRTUAL_ROOTS;
154 //private static IntPtr _NET_DESKTOP_LAYOUT;
155 //private static IntPtr _NET_SHOWING_DESKTOP;
156 //private static IntPtr _NET_CLOSE_WINDOW;
157 //private static IntPtr _NET_MOVERESIZE_WINDOW;
158 //private static IntPtr _NET_WM_MOVERESIZE;
159 //private static IntPtr _NET_RESTACK_WINDOW;
160 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
161 private static IntPtr _NET_WM_NAME;
162 //private static IntPtr _NET_WM_VISIBLE_NAME;
163 //private static IntPtr _NET_WM_ICON_NAME;
164 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
165 //private static IntPtr _NET_WM_DESKTOP;
166 private static IntPtr _NET_WM_WINDOW_TYPE;
167 private static IntPtr _NET_WM_STATE;
168 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
169 //private static IntPtr _NET_WM_STRUT;
170 //private static IntPtr _NET_WM_STRUT_PARTIAL;
171 //private static IntPtr _NET_WM_ICON_GEOMETRY;
172 private static IntPtr _NET_WM_ICON;
173 //private static IntPtr _NET_WM_PID;
174 //private static IntPtr _NET_WM_HANDLED_ICONS;
175 private static IntPtr _NET_WM_USER_TIME;
176 private static IntPtr _NET_FRAME_EXTENTS;
177 //private static IntPtr _NET_WM_PING;
178 //private static IntPtr _NET_WM_SYNC_REQUEST;
179 private static IntPtr _NET_SYSTEM_TRAY_S;
180 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
181 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
182 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
183 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
184 private static IntPtr _XEMBED;
185 private static IntPtr _XEMBED_INFO;
186 private static IntPtr _MOTIF_WM_HINTS;
187 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
188 private static IntPtr _NET_WM_STATE_ABOVE;
189 private static IntPtr _NET_WM_STATE_MODAL;
190 private static IntPtr _NET_WM_STATE_HIDDEN;
191 private static IntPtr _NET_WM_CONTEXT_HELP;
192 private static IntPtr _NET_WM_WINDOW_OPACITY;
193 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
194 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
195 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
196 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
197 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
198 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
199 // private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
200 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
201 private static IntPtr CLIPBOARD;
202 private static IntPtr PRIMARY;
203 //private static IntPtr DIB;
204 private static IntPtr OEMTEXT;
205 private static IntPtr UNICODETEXT;
206 private static IntPtr TARGETS;
208 // mouse hover message generation
209 private static HoverStruct HoverState; //
211 // double click message generation
212 private static ClickStruct ClickPending; //
214 // Support for mouse grab
215 private static GrabStruct Grab; //
218 Point mouse_position; // Last position of mouse, in screen coords
219 internal static MouseButtons MouseState; // Last state of mouse buttons
222 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
224 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
225 EventMask.ButtonReleaseMask |
226 EventMask.KeyPressMask |
227 EventMask.KeyReleaseMask |
228 EventMask.EnterWindowMask |
229 EventMask.LeaveWindowMask |
230 EventMask.ExposureMask |
231 EventMask.FocusChangeMask |
232 EventMask.PointerMotionMask |
233 EventMask.PointerMotionHintMask |
234 EventMask.SubstructureNotifyMask);
236 static readonly object lockobj = new object ();
238 #endregion // Local Variables
240 private XplatUIX11() {
241 // Handle singleton stuff first
244 // Now regular initialization
245 XlibLock = new object ();
246 X11Keyboard.XlibLock = XlibLock;
247 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
248 unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
251 ErrorExceptions = false;
253 // X11 Initialization
254 SetDisplay(XOpenDisplay(IntPtr.Zero));
255 X11DesktopColors.Initialize();
258 // Disable keyboard autorepeat
260 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
261 detectable_key_auto_repeat = true;
263 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
264 detectable_key_auto_repeat = false;
267 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
268 ErrorHandler = new XErrorHandler(HandleError);
269 XSetErrorHandler(ErrorHandler);
273 // Remove our display handle from S.D
274 Graphics.FromHdcInternal (IntPtr.Zero);
277 #endregion // Constructors
279 #region Singleton Specific Code
280 public static XplatUIX11 GetInstance() {
282 if (Instance == null) {
283 Instance=new XplatUIX11();
290 public int Reference {
297 #region Internal Properties
298 internal static IntPtr Display {
300 return DisplayHandle;
304 XplatUIX11.GetInstance().SetDisplay(value);
308 internal static int Screen {
318 internal static IntPtr RootWindowHandle {
328 internal static IntPtr Visual {
334 CustomVisual = value;
338 internal static IntPtr ColorMap {
340 return CustomColormap;
344 CustomColormap = value;
349 #region XExceptionClass
350 internal class XException : ApplicationException {
354 XRequest RequestCode;
358 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
359 this.Display = Display;
360 this.ResourceID = ResourceID;
361 this.Serial = Serial;
362 this.RequestCode = RequestCode;
363 this.ErrorCode = ErrorCode;
364 this.MinorCode = MinorCode;
367 public override string Message {
369 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
373 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
382 sb = new StringBuilder(160);
383 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
384 x_error_text = sb.ToString();
385 hwnd = Hwnd.ObjectFromHandle(ResourceID);
387 hwnd_text = hwnd.ToString();
388 c = Control.FromHandle(hwnd.Handle);
390 control_text = c.ToString();
392 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
395 hwnd_text = "<null>";
396 control_text = "<null>";
400 error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
404 #endregion // XExceptionClass
406 #region Internal Methods
407 internal void SetDisplay(IntPtr display_handle) {
408 if (display_handle != IntPtr.Zero) {
411 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
412 hwnd = Hwnd.ObjectFromHandle(FosterParent);
413 XDestroyWindow(DisplayHandle, FosterParent);
417 if (DisplayHandle != IntPtr.Zero) {
418 XCloseDisplay(DisplayHandle);
421 DisplayHandle=display_handle;
423 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
424 // been hacked to do this for us.
425 Graphics.FromHdcInternal (DisplayHandle);
427 // query for the render extension so
428 // we can ignore the spurious
429 // BadPicture errors that are
430 // generated by cairo/render.
431 XQueryExtension (DisplayHandle, "RENDER",
432 ref render_major_opcode, ref render_first_event, ref render_first_error);
435 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
436 XSynchronize(DisplayHandle, true);
439 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
440 ErrorExceptions = true;
444 ScreenNo = XDefaultScreen(DisplayHandle);
445 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
446 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
448 // Create the foster parent
449 // it is important that border_width is kept in synch with the other XCreateWindow calls
450 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
451 if (FosterParent==IntPtr.Zero) {
452 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
456 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
457 hwnd.WholeWindow = FosterParent;
458 hwnd.ClientWindow = FosterParent;
460 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
462 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
463 hwnd.whole_window = RootWindow;
464 hwnd.ClientWindow = RootWindow;
466 // For sleeping on the X11 socket
467 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
468 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
472 // To wake up when a timer is ready
473 network_buffer = new byte[10];
475 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
476 wake.Connect(listen.LocalEndPoint);
477 wake_receive = listen.Accept();
480 pollfds = new Pollfd [2];
481 pollfds [0] = new Pollfd ();
482 pollfds [0].fd = XConnectionNumber (DisplayHandle);
483 pollfds [0].events = PollEvents.POLLIN;
485 pollfds [1] = new Pollfd ();
486 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
487 pollfds [1].events = PollEvents.POLLIN;
490 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
491 Dnd = new X11Dnd (DisplayHandle, Keyboard);
493 DoubleClickInterval = 500;
495 HoverState.Interval = 500;
496 HoverState.Timer = new Timer();
497 HoverState.Timer.Enabled = false;
498 HoverState.Timer.Interval = HoverState.Interval;
499 HoverState.Timer.Tick += new EventHandler(MouseHover);
500 HoverState.Size = new Size(4, 4);
504 ActiveWindow = IntPtr.Zero;
505 FocusWindow = IntPtr.Zero;
506 ModalWindows = new Stack(3);
508 MouseState = MouseButtons.None;
509 mouse_position = new Point(0, 0);
511 Caret.Timer = new Timer();
512 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
513 Caret.Timer.Tick += new EventHandler(CaretCallback);
517 // Grab atom changes off the root window to catch certain WM events
518 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
520 // Handle any upcoming errors
521 ErrorHandler = new XErrorHandler(HandleError);
522 XSetErrorHandler(ErrorHandler);
524 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
527 #endregion // Internal Methods
529 #region Private Methods
530 private int unixtime() {
531 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
533 return (int) t.TotalSeconds;
536 private static void SetupAtoms() {
537 // make sure this array stays in sync with the statements below
538 string [] atom_names = new string[] {
543 //"_NET_CLIENT_LIST",
544 //"_NET_NUMBER_OF_DESKTOPS",
545 "_NET_DESKTOP_GEOMETRY",
546 //"_NET_DESKTOP_VIEWPORT",
547 "_NET_CURRENT_DESKTOP",
548 //"_NET_DESKTOP_NAMES",
549 "_NET_ACTIVE_WINDOW",
551 //"_NET_SUPPORTING_WM_CHECK",
552 //"_NET_VIRTUAL_ROOTS",
553 //"_NET_DESKTOP_LAYOUT",
554 //"_NET_SHOWING_DESKTOP",
555 //"_NET_CLOSE_WINDOW",
556 //"_NET_MOVERESIZE_WINDOW",
557 //"_NET_WM_MOVERESIZE",
558 //"_NET_RESTACK_WINDOW",
559 //"_NET_REQUEST_FRAME_EXTENTS",
561 //"_NET_WM_VISIBLE_NAME",
562 //"_NET_WM_ICON_NAME",
563 //"_NET_WM_VISIBLE_ICON_NAME",
565 "_NET_WM_WINDOW_TYPE",
567 //"_NET_WM_ALLOWED_ACTIONS",
569 //"_NET_WM_STRUT_PARTIAL",
570 //"_NET_WM_ICON_GEOMETRY",
573 //"_NET_WM_HANDLED_ICONS",
575 "_NET_FRAME_EXTENTS",
577 //"_NET_WM_SYNC_REQUEST",
578 "_NET_SYSTEM_TRAY_OPCODE",
579 //"_NET_SYSTEM_TRAY_ORIENTATION",
580 "_NET_WM_STATE_MAXIMIZED_HORZ",
581 "_NET_WM_STATE_MAXIMIZED_VERT",
582 "_NET_WM_STATE_HIDDEN",
586 "_NET_WM_STATE_SKIP_TASKBAR",
587 "_NET_WM_STATE_ABOVE",
588 "_NET_WM_STATE_MODAL",
589 "_NET_WM_CONTEXT_HELP",
590 "_NET_WM_WINDOW_OPACITY",
591 //"_NET_WM_WINDOW_TYPE_DESKTOP",
592 //"_NET_WM_WINDOW_TYPE_DOCK",
593 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
594 //"_NET_WM_WINDOW_TYPE_MENU",
595 "_NET_WM_WINDOW_TYPE_UTILITY",
596 // "_NET_WM_WINDOW_TYPE_DIALOG",
597 //"_NET_WM_WINDOW_TYPE_SPLASH",
598 "_NET_WM_WINDOW_TYPE_NORMAL",
605 "_SWF_PostMessageAtom",
608 IntPtr[] atoms = new IntPtr [atom_names.Length];;
610 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
613 WM_PROTOCOLS = atoms [off++];
614 WM_DELETE_WINDOW = atoms [off++];
615 WM_TAKE_FOCUS = atoms [off++];
616 //_NET_SUPPORTED = atoms [off++];
617 //_NET_CLIENT_LIST = atoms [off++];
618 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
619 _NET_DESKTOP_GEOMETRY = atoms [off++];
620 //_NET_DESKTOP_VIEWPORT = atoms [off++];
621 _NET_CURRENT_DESKTOP = atoms [off++];
622 //_NET_DESKTOP_NAMES = atoms [off++];
623 _NET_ACTIVE_WINDOW = atoms [off++];
624 _NET_WORKAREA = atoms [off++];
625 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
626 //_NET_VIRTUAL_ROOTS = atoms [off++];
627 //_NET_DESKTOP_LAYOUT = atoms [off++];
628 //_NET_SHOWING_DESKTOP = atoms [off++];
629 //_NET_CLOSE_WINDOW = atoms [off++];
630 //_NET_MOVERESIZE_WINDOW = atoms [off++];
631 //_NET_WM_MOVERESIZE = atoms [off++];
632 //_NET_RESTACK_WINDOW = atoms [off++];
633 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
634 _NET_WM_NAME = atoms [off++];
635 //_NET_WM_VISIBLE_NAME = atoms [off++];
636 //_NET_WM_ICON_NAME = atoms [off++];
637 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
638 //_NET_WM_DESKTOP = atoms [off++];
639 _NET_WM_WINDOW_TYPE = atoms [off++];
640 _NET_WM_STATE = atoms [off++];
641 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
642 //_NET_WM_STRUT = atoms [off++];
643 //_NET_WM_STRUT_PARTIAL = atoms [off++];
644 //_NET_WM_ICON_GEOMETRY = atoms [off++];
645 _NET_WM_ICON = atoms [off++];
646 //_NET_WM_PID = atoms [off++];
647 //_NET_WM_HANDLED_ICONS = atoms [off++];
648 _NET_WM_USER_TIME = atoms [off++];
649 _NET_FRAME_EXTENTS = atoms [off++];
650 //_NET_WM_PING = atoms [off++];
651 //_NET_WM_SYNC_REQUEST = atoms [off++];
652 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
653 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
654 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
655 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
656 _NET_WM_STATE_HIDDEN = atoms [off++];
657 _XEMBED = atoms [off++];
658 _XEMBED_INFO = atoms [off++];
659 _MOTIF_WM_HINTS = atoms [off++];
660 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
661 _NET_WM_STATE_ABOVE = atoms [off++];
662 _NET_WM_STATE_MODAL = atoms [off++];
663 _NET_WM_CONTEXT_HELP = atoms [off++];
664 _NET_WM_WINDOW_OPACITY = atoms [off++];
665 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
666 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
667 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
668 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
669 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
670 // _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
671 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
672 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
673 CLIPBOARD = atoms [off++];
674 PRIMARY = atoms [off++];
675 OEMTEXT = atoms [off++];
676 UNICODETEXT = atoms [off++];
677 TARGETS = atoms [off++];
678 AsyncAtom = atoms [off++];
679 PostAtom = atoms [off++];
680 HoverState.Atom = atoms [off++];
682 //DIB = (IntPtr)Atom.XA_PIXMAP;
683 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
686 private void GetSystrayManagerWindow() {
687 XGrabServer(DisplayHandle);
688 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
689 XUngrabServer(DisplayHandle);
690 XFlush(DisplayHandle);
693 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
697 xev.ClientMessageEvent.type = XEventName.ClientMessage;
698 xev.ClientMessageEvent.send_event = true;
699 xev.ClientMessageEvent.window = window;
700 xev.ClientMessageEvent.message_type = message_type;
701 xev.ClientMessageEvent.format = 32;
702 xev.ClientMessageEvent.ptr1 = l0;
703 xev.ClientMessageEvent.ptr2 = l1;
704 xev.ClientMessageEvent.ptr3 = l2;
705 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
708 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
712 xev.ClientMessageEvent.type = XEventName.ClientMessage;
713 xev.ClientMessageEvent.send_event = true;
714 xev.ClientMessageEvent.window = window;
715 xev.ClientMessageEvent.message_type = message_type;
716 xev.ClientMessageEvent.format = 32;
717 xev.ClientMessageEvent.ptr1 = l0;
718 xev.ClientMessageEvent.ptr2 = l1;
719 xev.ClientMessageEvent.ptr3 = l2;
720 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
723 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
724 // WM_CREATE and WM_DESTROY causes
725 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
729 if (child == IntPtr.Zero) {
733 hwnd = Hwnd.GetObjectFromWindow (child);
739 if (hwnd.Handle == IntPtr.Zero) {
743 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
747 if (hwnd.Parent == null) {
751 if (hwnd.Parent.Handle == IntPtr.Zero) {
755 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
756 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
758 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
761 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
764 bool StyleSet (int s, WindowStyles ws)
766 return (s & (int)ws) == (int)ws;
769 bool ExStyleSet (int ex, WindowExStyles exws)
771 return (ex & (int)exws) == (int)exws;
774 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
776 return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
779 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
782 * If this is a form with no window manager, X is handling all the border and caption painting
783 * so remove that from the area (since the area we set of the window here is the part of the window
784 * we're painting in only)
786 Rectangle rect = hwnd.ClientRect;
787 Form form = ctrl as Form;
788 CreateParams cp = null;
791 cp = form.GetCreateParams ();
793 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
794 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
795 Rectangle xrect = rect;
797 xrect.Y -= borders.top;
798 xrect.X -= borders.left;
799 xrect.Width += borders.left + borders.right;
800 xrect.Height += borders.top + borders.bottom;
805 if (rect.Width < 1 || rect.Height < 1) {
815 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
817 return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
820 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
823 * If this is a form with no window manager, X is handling all the border and caption painting
824 * so remove that from the area (since the area we set of the window here is the part of the window
825 * we're painting in only)
827 Form form = cp.control as Form;
828 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
829 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
832 xrect.Width -= borders.left + borders.right;
833 xrect.Height -= borders.top + borders.bottom;
837 if (size.Height == 0)
844 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
847 * If this is a form with no window manager, X is handling all the border and caption painting
848 * so remove that from the area (since the area we set of the window here is the part of the window
849 * we're painting in only)
851 Size rect = new Size (xWidth, xHeight);
852 Form form = cp.control as Form;
853 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
854 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
857 xrect.Width += borders.left + borders.right;
858 xrect.Height += borders.top + borders.bottom;
865 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
871 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
872 frame = FrameExtents (hwnd.whole_window);
877 return new Point (x, y);
880 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
883 tool_caption_height = 19;
884 border_static = false;
886 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
887 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
888 border_style = FormBorderStyle.Fixed3D;
889 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
890 border_style = FormBorderStyle.Fixed3D;
891 border_static = true;
892 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
893 border_style = FormBorderStyle.None;
895 border_style = FormBorderStyle.FixedSingle;
897 title_style = TitleStyle.None;
899 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
901 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
902 title_style = TitleStyle.Tool;
904 title_style = TitleStyle.Normal;
908 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
911 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
912 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
913 border_style = (FormBorderStyle) 0xFFFF;
915 border_style = FormBorderStyle.None;
920 title_style = TitleStyle.None;
921 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
922 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
923 title_style = TitleStyle.Tool;
925 title_style = TitleStyle.Normal;
929 border_style = FormBorderStyle.None;
931 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
932 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
933 border_style = FormBorderStyle.SizableToolWindow;
935 border_style = FormBorderStyle.Sizable;
938 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
939 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
940 border_style = FormBorderStyle.Fixed3D;
941 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
942 border_style = FormBorderStyle.Fixed3D;
943 border_static = true;
944 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
945 border_style = FormBorderStyle.FixedDialog;
946 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
947 border_style = FormBorderStyle.FixedToolWindow;
948 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
949 border_style = FormBorderStyle.FixedSingle;
952 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
953 border_style = FormBorderStyle.FixedSingle;
960 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
961 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.border_static, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
964 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
965 MotifWmHints mwmHints;
966 MotifFunctions functions;
967 MotifDecorations decorations;
970 Rectangle client_rect;
973 bool hide_from_taskbar;
974 IntPtr transient_for_parent;
976 // Windows we manage ourselves don't need WM window styles.
977 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
982 mwmHints = new MotifWmHints();
985 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
986 transient_for_parent = IntPtr.Zero;
988 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
989 mwmHints.functions = (IntPtr)0;
990 mwmHints.decorations = (IntPtr)0;
992 form = cp.control as Form;
994 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
995 /* tool windows get no window manager
999 /* just because the window doesn't get any decorations doesn't
1000 mean we should disable the functions. for instance, without
1001 MotifFunctions.Maximize, changing the windowstate to Maximized
1002 is ignored by metacity. */
1003 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
1004 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
1005 functions |= MotifFunctions.All;
1007 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
1008 functions |= MotifFunctions.Move;
1009 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1012 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1013 functions |= MotifFunctions.Move | MotifFunctions.Resize;
1014 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1017 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1018 functions |= MotifFunctions.Minimize;
1019 decorations |= MotifDecorations.Minimize;
1022 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1023 functions |= MotifFunctions.Maximize;
1024 decorations |= MotifDecorations.Maximize;
1027 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1028 functions |= MotifFunctions.Resize;
1029 decorations |= MotifDecorations.ResizeH;
1032 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1033 decorations |= MotifDecorations.Border;
1036 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1037 decorations |= MotifDecorations.Border;
1040 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1041 decorations |= MotifDecorations.Border;
1044 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1045 functions |= MotifFunctions.Close;
1048 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1049 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1050 if (cp.Caption == "") {
1051 functions &= ~MotifFunctions.Move;
1052 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1057 if ((functions & MotifFunctions.Resize) == 0) {
1058 hwnd.fixed_size = true;
1059 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1060 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1062 hwnd.fixed_size = false;
1065 mwmHints.functions = (IntPtr)functions;
1066 mwmHints.decorations = (IntPtr)decorations;
1069 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1072 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1073 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1074 // and get those windows in front of their parents
1075 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1077 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1080 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1081 hide_from_taskbar = true;
1082 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1083 hide_from_taskbar = true;
1085 hide_from_taskbar = false;
1088 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1089 if (form != null && !hwnd.reparented) {
1090 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1091 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1092 if (owner_hwnd != null)
1093 transient_for_parent = owner_hwnd.whole_window;
1097 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1098 transient_for_parent = hwnd.parent.whole_window;
1101 FormWindowState current_state = GetWindowState (hwnd.Handle);
1102 if (current_state == (FormWindowState)(-1))
1103 current_state = FormWindowState.Normal;
1105 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1110 atoms [0] = window_type.ToInt32 ();
1111 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1113 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1115 if (transient_for_parent != IntPtr.Zero) {
1116 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1119 MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1121 if (hide_from_taskbar) {
1122 /* this line keeps the window from showing up in gnome's taskbar */
1123 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1125 /* we need to add these atoms in the
1126 * event we're maximized, since we're
1127 * replacing the existing
1128 * _NET_WM_STATE here. If we don't
1129 * add them, future calls to
1130 * GetWindowState will return Normal
1131 * for a window which is maximized. */
1132 if (current_state == FormWindowState.Maximized) {
1133 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1134 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1137 if (form != null && form.Modal) {
1138 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1141 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1144 IntPtr[] atom_ptrs = new IntPtr[2];
1145 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1146 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1147 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1150 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1154 private void SetIcon(Hwnd hwnd, Icon icon)
1159 // This really needs to do whatever it
1160 // takes to remove the window manager
1161 // menu, not just delete the ICON
1162 // property. This will cause metacity
1163 // to use the "no icon set" icon, and
1164 // we'll still have an icon.
1165 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1173 bitmap = icon.ToBitmap();
1175 size = bitmap.Width * bitmap.Height + 2;
1176 data = new IntPtr[size];
1178 data[index++] = (IntPtr)bitmap.Width;
1179 data[index++] = (IntPtr)bitmap.Height;
1181 for (int y = 0; y < bitmap.Height; y++) {
1182 for (int x = 0; x < bitmap.Width; x++) {
1183 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1187 XChangeProperty (DisplayHandle, hwnd.whole_window,
1188 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1189 PropertyMode.Replace, data, size);
1193 private void WakeupMain () {
1194 wake.Send (new byte [] { 0xFF });
1197 private XEventQueue ThreadQueue(Thread thread) {
1200 queue = (XEventQueue)MessageQueues[thread];
1201 if (queue == null) {
1202 queue = new XEventQueue(thread);
1203 MessageQueues[thread] = queue;
1209 private void TranslatePropertyToClipboard(IntPtr property) {
1214 IntPtr prop = IntPtr.Zero;
1216 Clipboard.Item = null;
1218 XGetWindowProperty(DisplayHandle, FosterParent, property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1220 if ((long)nitems > 0) {
1221 if (property == (IntPtr)Atom.XA_STRING) {
1222 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1223 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1224 // FIXME - convert bitmap to image
1225 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1226 // FIXME - convert pixmap to image
1227 } else if (property == OEMTEXT) {
1228 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1229 } else if (property == UNICODETEXT) {
1230 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1237 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1239 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1243 // Keep the invalid area as small as needed
1244 if ((x + width) > hwnd.width) {
1245 width = hwnd.width - x;
1248 if ((y + height) > hwnd.height) {
1249 height = hwnd.height - y;
1253 hwnd.AddInvalidArea(x, y, width, height);
1254 if (!hwnd.expose_pending) {
1255 if (!hwnd.nc_expose_pending) {
1256 hwnd.Queue.Paint.Enqueue(hwnd);
1258 hwnd.expose_pending = true;
1261 hwnd.AddNcInvalidArea (x, y, width, height);
1263 if (!hwnd.nc_expose_pending) {
1264 if (!hwnd.expose_pending) {
1265 hwnd.Queue.Paint.Enqueue(hwnd);
1267 hwnd.nc_expose_pending = true;
1272 private static Hwnd.Borders FrameExtents (IntPtr window)
1278 IntPtr prop = IntPtr.Zero;
1279 Hwnd.Borders rect = new Hwnd.Borders ();
1281 XGetWindowProperty (DisplayHandle, window, _NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1282 if (prop != IntPtr.Zero) {
1283 if (nitems.ToInt32 () == 4) {
1284 rect.left = Marshal.ReadInt32 (prop, 0);
1285 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1286 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1287 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1295 private void AddConfigureNotify (XEvent xevent) {
1298 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1301 if (hwnd == null || hwnd.zombie) {
1304 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1305 if (hwnd.parent == null) {
1306 // The location given by the event is not reliable between different wm's,
1307 // so use an alternative way of getting it.
1308 Point location = GetTopLevelWindowLocation (hwnd);
1309 hwnd.x = location.X;
1310 hwnd.y = location.Y;
1313 // XXX this sucks. this isn't thread safe
1314 Control ctrl = Control.FromHandle (hwnd.Handle);
1315 Size TranslatedSize;
1317 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1319 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1321 hwnd.width = TranslatedSize.Width;
1322 hwnd.height = TranslatedSize.Height;
1323 hwnd.ClientRect = Rectangle.Empty;
1326 Console.WriteLine ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})", new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle, new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
1328 lock (hwnd.configure_lock) {
1329 if (!hwnd.configure_pending) {
1330 hwnd.Queue.EnqueueLocked (xevent);
1331 hwnd.configure_pending = true;
1335 // We drop configure events for Client windows
1338 private void ShowCaret() {
1339 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1345 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1349 private void HideCaret() {
1350 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1356 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1360 private int NextTimeout (ArrayList timers, DateTime now) {
1363 foreach (Timer timer in timers) {
1364 int next = (int) (timer.Expires - now).TotalMilliseconds;
1366 return 0; // Have a timer that has already expired
1369 if (next < timeout) {
1373 if (timeout < Timer.Minimum) {
1374 timeout = Timer.Minimum;
1382 private void CheckTimers (ArrayList timers, DateTime now) {
1385 count = timers.Count;
1390 for (int i = 0; i < timers.Count; i++) {
1393 timer = (Timer) timers [i];
1395 if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
1396 // Prevent the Timer from ticking before MainForm.OnLoad has
1397 // completed. This seems to be the case with Win32.
1399 if (Application.MWFThread.Current.Context != null &&
1400 Application.MWFThread.Current.Context.MainForm != null &&
1401 Application.MWFThread.Current.Context.MainForm.IsLoaded) {
1411 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1412 MSG msg = new MSG ();
1415 queue = ThreadQueue(Thread.CurrentThread);
1417 queue.DispatchIdle = false;
1421 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1422 if ((Msg)msg.message == Msg.WM_QUIT) {
1423 PostQuitMessage (0);
1427 if (msg.hwnd == hwnd.Handle) {
1428 if ((Msg)msg.message == message)
1430 else if ((Msg)msg.message == Msg.WM_DESTROY)
1434 TranslateMessage (ref msg);
1435 DispatchMessage (ref msg);
1440 queue.DispatchIdle = true;
1444 private void MapWindow(Hwnd hwnd, WindowType windows) {
1446 Form f = Control.FromHandle(hwnd.Handle) as Form;
1448 if (f.WindowState == FormWindowState.Normal) {
1449 f.waiting_showwindow = true;
1450 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1454 // it's possible that our Hwnd is no
1455 // longer valid after making that
1456 // SendMessage call, so check here.
1460 if ((windows & WindowType.Whole) != 0) {
1461 XMapWindow(DisplayHandle, hwnd.whole_window);
1463 if ((windows & WindowType.Client) != 0) {
1464 XMapWindow(DisplayHandle, hwnd.client_window);
1469 if (f != null && f.waiting_showwindow)
1470 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1474 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1477 if (Control.FromHandle(hwnd.Handle) is Form) {
1478 f = Control.FromHandle(hwnd.Handle) as Form;
1479 if (f.WindowState == FormWindowState.Normal) {
1480 f.waiting_showwindow = true;
1481 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1485 // it's possible that our Hwnd is no
1486 // longer valid after making that
1487 // SendMessage call, so check here.
1488 // FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
1492 if ((windows & WindowType.Client) != 0) {
1493 XUnmapWindow(DisplayHandle, hwnd.client_window);
1495 if ((windows & WindowType.Whole) != 0) {
1496 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1499 hwnd.mapped = false;
1501 if (f != null && f.waiting_showwindow)
1502 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1506 private void UpdateMessageQueue (XEventQueue queue) {
1511 now = DateTime.UtcNow;
1514 pending = XPending (DisplayHandle);
1518 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1519 Idle (this, EventArgs.Empty);
1523 pending = XPending (DisplayHandle);
1530 if (queue != null) {
1531 if (queue.Paint.Count > 0)
1534 timeout = NextTimeout (queue.timer_list, now);
1539 int length = pollfds.Length - 1;
1540 lock (wake_waiting_lock) {
1541 if (wake_waiting == false) {
1543 wake_waiting = true;
1547 Syscall.poll (pollfds, (uint)length, timeout);
1548 // Clean out buffer, so we're not busy-looping on the same data
1549 if (length == pollfds.Length) {
1550 if (pollfds[1].revents != 0)
1551 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1552 lock (wake_waiting_lock) {
1553 wake_waiting = false;
1558 pending = XPending (DisplayHandle);
1564 CheckTimers (queue.timer_list, now);
1567 XEvent xevent = new XEvent ();
1570 if (XPending (DisplayHandle) == 0)
1573 XNextEvent (DisplayHandle, ref xevent);
1575 if (xevent.AnyEvent.type == XEventName.KeyPress ||
1576 xevent.AnyEvent.type == XEventName.KeyRelease) {
1577 // PreFilter() handles "shift key state updates.
1578 Keyboard.PreFilter (xevent);
1579 if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
1580 // probably here we could raise WM_IME_KEYDOWN and
1581 // WM_IME_KEYUP, but I'm not sure it is worthy.
1585 else if (XFilterEvent (ref xevent, IntPtr.Zero))
1589 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1594 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1596 switch (xevent.type) {
1597 case XEventName.Expose:
1598 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1601 case XEventName.SelectionClear: {
1602 // Should we do something?
1606 case XEventName.SelectionRequest: {
1607 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1611 sel_event = new XEvent();
1612 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1613 sel_event.SelectionEvent.send_event = true;
1614 sel_event.SelectionEvent.display = DisplayHandle;
1615 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1616 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1617 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1618 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1619 sel_event.SelectionEvent.property = IntPtr.Zero;
1621 // Seems that some apps support asking for supported types
1622 if (xevent.SelectionEvent.target == TARGETS) {
1629 if (Clipboard.Item is String) {
1630 atoms[atom_count++] = (int)Atom.XA_STRING;
1631 atoms[atom_count++] = (int)OEMTEXT;
1632 atoms[atom_count++] = (int)UNICODETEXT;
1633 } else if (Clipboard.Item is Image) {
1634 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1635 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1637 // FIXME - handle other types
1640 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1641 } else if (Clipboard.Item is string) {
1647 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1650 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1651 buffer = Marshal.AllocHGlobal(bytes.Length);
1652 buflen = bytes.Length;
1654 for (int i = 0; i < buflen; i++) {
1655 Marshal.WriteByte(buffer, i, bytes[i]);
1657 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1658 // FIXME - this should encode into ISO2022
1659 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1660 while (Marshal.ReadByte(buffer, buflen) != 0) {
1663 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1664 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1665 while (Marshal.ReadByte(buffer, buflen) != 0) {
1669 buffer = IntPtr.Zero;
1672 if (buffer != IntPtr.Zero) {
1673 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1674 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1675 Marshal.FreeHGlobal(buffer);
1677 } else if (Clipboard.Item is Image) {
1678 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1679 // FIXME - convert image and store as property
1680 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1681 // FIXME - convert image and store as property
1685 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1689 case XEventName.SelectionNotify: {
1690 if (Clipboard.Enumerating) {
1691 Clipboard.Enumerating = false;
1692 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1693 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1694 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1695 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1696 #if DriverDebugExtra
1697 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1701 } else if (Clipboard.Retrieving) {
1702 Clipboard.Retrieving = false;
1703 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1704 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1706 Clipboard.Item = null;
1709 Dnd.HandleSelectionNotifyEvent (ref xevent);
1714 case XEventName.KeyRelease:
1715 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1716 XEvent nextevent = new XEvent ();
1718 XPeekEvent (DisplayHandle, ref nextevent);
1720 if (nextevent.type == XEventName.KeyPress &&
1721 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1722 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1726 goto case XEventName.KeyPress;
1728 case XEventName.MotionNotify: {
1731 /* we can't do motion compression across threads, so just punt if we don't match up */
1732 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1733 peek = hwnd.Queue.Peek();
1734 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1738 goto case XEventName.KeyPress;
1741 case XEventName.KeyPress:
1742 hwnd.Queue.EnqueueLocked (xevent);
1743 /* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
1744 * single physical keypress are not processed correctly */
1746 case XEventName.ButtonPress:
1747 case XEventName.ButtonRelease:
1748 case XEventName.EnterNotify:
1749 case XEventName.LeaveNotify:
1750 case XEventName.CreateNotify:
1751 case XEventName.DestroyNotify:
1752 case XEventName.FocusIn:
1753 case XEventName.FocusOut:
1754 case XEventName.ClientMessage:
1755 case XEventName.ReparentNotify:
1756 case XEventName.MapNotify:
1757 case XEventName.UnmapNotify:
1758 hwnd.Queue.EnqueueLocked (xevent);
1761 case XEventName.ConfigureNotify:
1762 AddConfigureNotify(xevent);
1765 case XEventName.PropertyNotify:
1767 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1769 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1774 IntPtr prop = IntPtr.Zero;
1777 prev_active = ActiveWindow;
1778 XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1779 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1780 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1783 if (prev_active != ActiveWindow) {
1784 if (prev_active != IntPtr.Zero) {
1785 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1787 if (ActiveWindow != IntPtr.Zero) {
1788 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1791 if (ModalWindows.Count == 0) {
1794 // Modality Handling
1796 // If there is a modal window on the stack and the new active
1797 // window is MWF window, but not the modal one and not a non-modal
1798 // child of the modal one, switch back to the modal window.
1800 // To identify if a non-modal form is child of a modal form
1801 // we match their ApplicationContexts, which will be the same.
1802 // This is because each modal form runs the loop with a
1803 // new ApplicationContext, which is inherited by the non-modal
1806 Form activeForm = Control.FromHandle (ActiveWindow) as Form;
1807 if (activeForm != null) {
1808 Form modalForm = Control.FromHandle ((IntPtr)ModalWindows.Peek()) as Form;
1809 if (ActiveWindow != (IntPtr)ModalWindows.Peek() &&
1810 (modalForm == null || activeForm.context == modalForm.context)) {
1811 Activate((IntPtr)ModalWindows.Peek());
1818 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1819 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1820 hwnd.cached_window_state = (FormWindowState)(-1);
1821 PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
1829 private IntPtr GetMousewParam(int Delta) {
1832 if ((MouseState & MouseButtons.Left) != 0) {
1833 result |= (int)MsgButtons.MK_LBUTTON;
1836 if ((MouseState & MouseButtons.Middle) != 0) {
1837 result |= (int)MsgButtons.MK_MBUTTON;
1840 if ((MouseState & MouseButtons.Right) != 0) {
1841 result |= (int)MsgButtons.MK_RBUTTON;
1844 Keys mods = ModifierKeys;
1845 if ((mods & Keys.Control) != 0) {
1846 result |= (int)MsgButtons.MK_CONTROL;
1849 if ((mods & Keys.Shift) != 0) {
1850 result |= (int)MsgButtons.MK_SHIFT;
1853 result |= Delta << 16;
1855 return (IntPtr)result;
1857 private IntPtr XGetParent(IntPtr handle) {
1864 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1867 if (Children!=IntPtr.Zero) {
1875 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1877 // we need to workaround a problem with the
1878 // ordering of destruction of Drawables and
1879 // Pictures that exists between cairo and
1880 // RENDER on the server.
1881 if (error_event.request_code == (XRequest)render_major_opcode
1882 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1883 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1887 if (ErrorExceptions) {
1888 XUngrabPointer (display, IntPtr.Zero);
1889 throw new XException (error_event.display, error_event.resourceid,
1890 error_event.serial, error_event.error_code,
1891 error_event.request_code, error_event.minor_code);
1893 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1894 XException.GetMessage (error_event.display, error_event.resourceid,
1895 error_event.serial, error_event.error_code,
1896 error_event.request_code, error_event.minor_code),
1897 Environment.StackTrace);
1902 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1905 Control[] controls = c.Controls.GetAllControls ();
1907 if (c.IsHandleCreated && !c.IsDisposed) {
1908 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1910 #if DriverDebug || DriverDebugDestroy
1911 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1912 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1916 CleanupCachedWindows (hwnd);
1919 for (int i = 0; i < controls.Length; i ++) {
1920 AccumulateDestroyedHandles (controls[i], list);
1926 void CleanupCachedWindows (Hwnd hwnd)
1928 if (ActiveWindow == hwnd.Handle) {
1929 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1930 ActiveWindow = IntPtr.Zero;
1933 if (FocusWindow == hwnd.Handle) {
1934 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1935 FocusWindow = IntPtr.Zero;
1938 if (Grab.Hwnd == hwnd.Handle) {
1939 Grab.Hwnd = IntPtr.Zero;
1940 Grab.Confined = false;
1943 DestroyCaret (hwnd.Handle);
1946 private void PerformNCCalc(Hwnd hwnd) {
1947 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1951 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1953 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1954 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1956 ncp.rgrc1.left = rect.Left;
1957 ncp.rgrc1.top = rect.Top;
1958 ncp.rgrc1.right = rect.Right;
1959 ncp.rgrc1.bottom = rect.Bottom;
1961 Marshal.StructureToPtr(ncp, ptr, true);
1962 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1963 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1964 Marshal.FreeHGlobal(ptr);
1967 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1968 hwnd.ClientRect = rect;
1970 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1973 MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1976 AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
1978 #endregion // Private Methods
1981 private void MouseHover(object sender, EventArgs e) {
1985 HoverState.Timer.Enabled = false;
1987 if (HoverState.Window != IntPtr.Zero) {
1988 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1990 xevent = new XEvent ();
1992 xevent.type = XEventName.ClientMessage;
1993 xevent.ClientMessageEvent.display = DisplayHandle;
1994 xevent.ClientMessageEvent.window = HoverState.Window;
1995 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1996 xevent.ClientMessageEvent.format = 32;
1997 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1999 hwnd.Queue.EnqueueLocked (xevent);
2006 private void CaretCallback(object sender, EventArgs e) {
2010 Caret.On = !Caret.On;
2012 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
2014 #endregion // Callbacks
2016 #region Public Properties
2018 internal override int CaptionHeight {
2024 internal override Size CursorSize {
2029 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
2030 return new Size(x, y);
2032 return new Size(16, 16);
2037 internal override bool DragFullWindows {
2043 internal override Size DragSize {
2045 return new Size(4, 4);
2049 internal override Size FrameBorderSize {
2051 return new Size (4, 4);
2055 internal override Size IconSize {
2061 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2065 current = (long)list;
2068 size = new XIconSize();
2070 for (int i = 0; i < count; i++) {
2071 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2072 current += Marshal.SizeOf(size);
2074 // Look for our preferred size
2075 if (size.min_width == 32) {
2077 return new Size(32, 32);
2080 if (size.max_width == 32) {
2082 return new Size(32, 32);
2085 if (size.min_width < 32 && size.max_width > 32) {
2088 // check if we can fit one
2090 while (x < size.max_width) {
2091 x += size.width_inc;
2094 return new Size(32, 32);
2099 if (largest < size.max_width) {
2100 largest = size.max_width;
2104 // We didn't find a match or we wouldn't be here
2105 return new Size(largest, largest);
2108 return new Size(32, 32);
2113 internal override int KeyboardSpeed {
2116 // A lot harder: need to do:
2117 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2118 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2119 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2121 // And from that we can tell the repetition rate
2123 // Notice, the values must map to:
2124 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2130 internal override int KeyboardDelay {
2133 // Return values must range from 0 to 4, 0 meaning 250ms,
2134 // and 4 meaning 1000 ms.
2136 return 1; // ie, 500 ms
2140 internal override Size MaxWindowTrackSize {
2142 return new Size (WorkingArea.Width, WorkingArea.Height);
2146 internal override bool MenuAccessKeysUnderlined {
2152 internal override Size MinimizedWindowSpacingSize {
2154 return new Size(1, 1);
2158 internal override Size MinimumWindowSize {
2160 return new Size(110, 22);
2164 internal override Size MinimumFixedToolWindowSize {
2165 get { return new Size (27, 22); }
2168 internal override Size MinimumSizeableToolWindowSize {
2169 get { return new Size (37, 22); }
2172 internal override Size MinimumNoBorderWindowSize {
2173 get { return new Size (2, 2); }
2176 internal override Keys ModifierKeys {
2178 return Keyboard.ModifierKeys;
2182 internal override Size SmallIconSize {
2188 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2192 current = (long)list;
2195 size = new XIconSize();
2197 for (int i = 0; i < count; i++) {
2198 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2199 current += Marshal.SizeOf(size);
2201 // Look for our preferred size
2202 if (size.min_width == 16) {
2204 return new Size(16, 16);
2207 if (size.max_width == 16) {
2209 return new Size(16, 16);
2212 if (size.min_width < 16 && size.max_width > 16) {
2215 // check if we can fit one
2217 while (x < size.max_width) {
2218 x += size.width_inc;
2221 return new Size(16, 16);
2226 if (smallest == 0 || smallest > size.min_width) {
2227 smallest = size.min_width;
2231 // We didn't find a match or we wouldn't be here
2232 return new Size(smallest, smallest);
2235 return new Size(16, 16);
2240 internal override int MouseButtonCount {
2246 internal override bool MouseButtonsSwapped {
2248 return false; // FIXME - how to detect?
2252 internal override Point MousePosition {
2254 return mouse_position;
2258 internal override Size MouseHoverSize {
2260 return new Size (1, 1);
2264 internal override int MouseHoverTime {
2266 return HoverState.Interval;
2272 internal override bool MouseWheelPresent {
2274 return true; // FIXME - how to detect?
2278 internal override MouseButtons MouseButtons {
2284 internal override Rectangle VirtualScreen {
2290 IntPtr prop = IntPtr.Zero;
2294 XGetWindowProperty(DisplayHandle, RootWindow, _NET_DESKTOP_GEOMETRY, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2295 if ((long)nitems < 2)
2298 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2299 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2303 return new Rectangle(0, 0, width, height);
2306 XWindowAttributes attributes=new XWindowAttributes();
2309 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2312 return new Rectangle(0, 0, attributes.width, attributes.height);
2316 internal override Rectangle WorkingArea {
2322 IntPtr prop = IntPtr.Zero;
2325 int current_desktop;
2329 XGetWindowProperty(DisplayHandle, RootWindow, _NET_CURRENT_DESKTOP, IntPtr.Zero, new IntPtr(1), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2330 if ((long)nitems < 1) {
2334 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2337 XGetWindowProperty(DisplayHandle, RootWindow, _NET_WORKAREA, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2338 if ((long)nitems < 4 * current_desktop) {
2342 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2343 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2344 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2345 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2348 return new Rectangle(x, y, width, height);
2351 XWindowAttributes attributes=new XWindowAttributes();
2354 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2357 return new Rectangle(0, 0, attributes.width, attributes.height);
2361 internal override bool ThemesEnabled {
2363 return XplatUIX11.themes_enabled;
2368 #endregion // Public properties
2370 #region Public Static Methods
2371 internal override void RaiseIdle (EventArgs e)
2377 internal override IntPtr InitializeDriver() {
2379 if (DisplayHandle==IntPtr.Zero) {
2380 SetDisplay(XOpenDisplay(IntPtr.Zero));
2386 internal override void ShutdownDriver(IntPtr token) {
2388 if (DisplayHandle!=IntPtr.Zero) {
2389 XCloseDisplay(DisplayHandle);
2390 DisplayHandle=IntPtr.Zero;
2395 internal override void EnableThemes() {
2396 themes_enabled = true;
2400 internal override void Activate(IntPtr handle) {
2403 hwnd = Hwnd.ObjectFromHandle(handle);
2407 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2408 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2409 XEventQueue q = null;
2410 lock (unattached_timer_list) {
2411 foreach (Timer t in unattached_timer_list) {
2413 q= (XEventQueue) MessageQueues [Thread.CurrentThread];
2414 t.thread = q.Thread;
2415 q.timer_list.Add (t);
2417 unattached_timer_list.Clear ();
2421 // XRaiseWindow(DisplayHandle, handle);
2427 internal override void AudibleAlert() {
2428 XBell(DisplayHandle, 0);
2433 internal override void CaretVisible(IntPtr handle, bool visible) {
2434 if (Caret.Hwnd == handle) {
2436 if (!Caret.Visible) {
2437 Caret.Visible = true;
2439 Caret.Timer.Start();
2442 Caret.Visible = false;
2449 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2450 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2454 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2460 hwnd = Hwnd.ObjectFromHandle(handle);
2463 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2470 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2471 DataFormats.Format f;
2474 f = DataFormats.Format.List;
2476 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2480 Clipboard.Formats = new ArrayList();
2483 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2485 Clipboard.Enumerating = true;
2486 while (Clipboard.Enumerating) {
2487 UpdateMessageQueue(null);
2492 result = new int[Clipboard.Formats.Count];
2494 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2495 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2498 Clipboard.Formats = null;
2502 internal override void ClipboardClose(IntPtr handle) {
2503 if (handle != ClipMagic) {
2504 throw new ArgumentException("handle is not a valid clipboard handle");
2509 internal override int ClipboardGetID(IntPtr handle, string format) {
2510 if (handle != ClipMagic) {
2511 throw new ArgumentException("handle is not a valid clipboard handle");
2514 if (format == "Text" ) return (int)Atom.XA_STRING;
2515 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2516 //else if (format == "MetaFilePict" ) return 3;
2517 //else if (format == "SymbolicLink" ) return 4;
2518 //else if (format == "DataInterchangeFormat" ) return 5;
2519 //else if (format == "Tiff" ) return 6;
2520 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2521 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2522 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2523 //else if (format == "PenData" ) return 10;
2524 //else if (format == "RiffAudio" ) return 11;
2525 //else if (format == "WaveAudio" ) return 12;
2526 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2527 //else if (format == "EnhancedMetafile" ) return 14;
2528 //else if (format == "FileDrop" ) return 15;
2529 //else if (format == "Locale" ) return 16;
2531 return XInternAtom(DisplayHandle, format, false).ToInt32();
2534 internal override IntPtr ClipboardOpen(bool primary_selection) {
2535 if (!primary_selection)
2536 ClipMagic = CLIPBOARD;
2538 ClipMagic = PRIMARY;
2542 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2543 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2545 Clipboard.Retrieving = true;
2546 while (Clipboard.Retrieving) {
2547 UpdateMessageQueue(null);
2550 return Clipboard.Item;
2553 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2554 Clipboard.Item = obj;
2555 Clipboard.Type = type;
2556 Clipboard.Converter = converter;
2559 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2561 // Clearing the selection
2562 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2566 internal override void CreateCaret (IntPtr handle, int width, int height)
2568 XGCValues gc_values;
2571 hwnd = Hwnd.ObjectFromHandle(handle);
2573 if (Caret.Hwnd != IntPtr.Zero) {
2574 DestroyCaret(Caret.Hwnd);
2577 Caret.Hwnd = handle;
2578 Caret.Window = hwnd.client_window;
2579 Caret.Width = width;
2580 Caret.Height = height;
2581 Caret.Visible = false;
2584 gc_values = new XGCValues();
2585 gc_values.line_width = width;
2587 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2588 if (Caret.gc == IntPtr.Zero) {
2589 Caret.Hwnd = IntPtr.Zero;
2593 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2596 internal override IntPtr CreateWindow (CreateParams cp)
2598 XSetWindowAttributes Attributes;
2600 Hwnd parent_hwnd = null;
2605 IntPtr ParentHandle;
2607 IntPtr ClientWindow;
2608 SetWindowValuemask ValueMask;
2613 Attributes = new XSetWindowAttributes();
2619 if (Width<1) Width=1;
2620 if (Height<1) Height=1;
2622 if (cp.Parent != IntPtr.Zero) {
2623 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2624 ParentHandle = parent_hwnd.client_window;
2626 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2627 // We need to use our foster parent window until this poor child gets it's parent assigned
2628 ParentHandle=FosterParent;
2630 ParentHandle=RootWindow;
2634 // Set the default location location for forms.
2636 if (cp.control is Form) {
2637 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2641 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2643 Attributes.bit_gravity = Gravity.NorthWestGravity;
2644 Attributes.win_gravity = Gravity.NorthWestGravity;
2646 // Save what's under the toolwindow
2647 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2648 Attributes.save_under = true;
2649 ValueMask |= SetWindowValuemask.SaveUnder;
2653 // If we're a popup without caption we override the WM
2654 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2655 Attributes.override_redirect = true;
2656 ValueMask |= SetWindowValuemask.OverrideRedirect;
2662 hwnd.height = Height;
2663 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2664 hwnd.initial_style = cp.WindowStyle;
2665 hwnd.initial_ex_style = cp.WindowExStyle;
2667 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2668 hwnd.enabled = false;
2671 ClientWindow = IntPtr.Zero;
2673 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2674 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2677 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2678 if (WholeWindow != IntPtr.Zero) {
2679 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2681 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2682 ValueMask = SetWindowValuemask.ColorMap;
2683 Attributes.colormap = CustomColormap;
2685 ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
2689 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2690 throw new Exception("Could not create X11 windows");
2693 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2694 hwnd.WholeWindow = WholeWindow;
2695 hwnd.ClientWindow = ClientWindow;
2697 #if DriverDebug || DriverDebugCreate
2698 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
2701 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2702 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2705 hints = new XSizeHints();
2708 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2709 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2714 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
2715 if (hwnd.whole_window != hwnd.client_window)
2716 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
2719 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2721 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2722 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2724 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2727 SetWMStyles(hwnd, cp);
2729 // set the group leader
2730 XWMHints wm_hints = new XWMHints ();
2732 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2733 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2734 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2736 if (ParentHandle != RootWindow) {
2737 wm_hints.window_group = hwnd.whole_window;
2739 wm_hints.window_group = ParentHandle;
2743 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2746 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2747 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2748 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2749 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2752 // for now make all windows dnd enabled
2753 Dnd.SetAllowDrop (hwnd, true);
2755 // Set caption/window title
2756 Text(hwnd.Handle, cp.Caption);
2758 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2759 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2761 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2762 hwnd.visible = true;
2763 MapWindow(hwnd, WindowType.Both);
2764 if (!(Control.FromHandle(hwnd.Handle) is Form))
2765 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2771 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2772 CreateParams create_params = new CreateParams();
2774 create_params.Caption = "";
2775 create_params.X = X;
2776 create_params.Y = Y;
2777 create_params.Width = Width;
2778 create_params.Height = Height;
2780 create_params.ClassName=XplatUI.DefaultClassName;
2781 create_params.ClassStyle = 0;
2782 create_params.ExStyle=0;
2783 create_params.Parent=IntPtr.Zero;
2784 create_params.Param=0;
2786 return CreateWindow(create_params);
2789 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2791 Bitmap cursor_bitmap;
2799 IntPtr cursor_pixmap;
2806 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2810 // Win32 only allows creation cursors of a certain size
2811 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2812 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2813 cursor_mask = new Bitmap(mask, new Size(width, height));
2815 cursor_bitmap = bitmap;
2819 width = cursor_bitmap.Width;
2820 height = cursor_bitmap.Height;
2822 cursor_bits = new Byte[(width / 8) * height];
2823 mask_bits = new Byte[(width / 8) * height];
2825 for (int y = 0; y < height; y++) {
2826 for (int x = 0; x < width; x++) {
2827 c_pixel = cursor_bitmap.GetPixel(x, y);
2828 m_pixel = cursor_mask.GetPixel(x, y);
2830 and = c_pixel == cursor_pixel;
2831 xor = m_pixel == mask_pixel;
2835 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2836 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2837 } else if (and && !xor) {
2839 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2840 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2842 } else if (and && !xor) {
2844 } else if (and && xor) {
2847 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2848 // we want both to be 0 so nothing to be done
2849 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2850 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2856 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2857 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2861 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2862 fg.red = (ushort)65535;
2863 fg.green = (ushort)65535;
2864 fg.blue = (ushort)65535;
2866 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2868 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2870 XFreePixmap(DisplayHandle, cursor_pixmap);
2871 XFreePixmap(DisplayHandle, mask_pixmap);
2876 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2877 CursorFontShape shape;
2884 shape = StdCursorToFontShape (id);
2885 name = shape.ToString ().Replace ("XC_", string.Empty);
2886 size = XcursorGetDefaultSize (DisplayHandle);
2887 theme = XcursorGetTheme (DisplayHandle);
2888 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2890 Console.WriteLine ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
2893 if (images_ptr == IntPtr.Zero) {
2897 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2899 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2902 if (images.nimage > 0) {
2903 // We only care about the first image.
2904 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2907 Console.WriteLine ("DefineStdCursorBitmap, loaded image <size={0}, height={1}, width={2}, xhot={3}, yhot={4}, pixels={5}", image.size, image.height, image.width, image.xhot, image.yhot, image.pixels);
2910 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2911 int [] pixels = new int [image.width * image.height];
2912 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2913 bmp = new Bitmap (image.width, image.height);
2914 for (int w = 0; w < image.width; w++) {
2915 for (int h = 0; h < image.height; h++) {
2916 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2922 XcursorImagesDestroy (images_ptr);
2924 } catch (DllNotFoundException ex) {
2925 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2933 internal override IntPtr DefineStdCursor(StdCursor id) {
2934 CursorFontShape shape;
2937 shape = StdCursorToFontShape (id);
2940 cursor = XCreateFontCursor(DisplayHandle, shape);
2945 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2946 CursorFontShape shape;
2947 // FIXME - define missing shapes
2950 case StdCursor.AppStarting: {
2951 shape = CursorFontShape.XC_watch;
2955 case StdCursor.Arrow: {
2956 shape = CursorFontShape.XC_top_left_arrow;
2960 case StdCursor.Cross: {
2961 shape = CursorFontShape.XC_crosshair;
2965 case StdCursor.Default: {
2966 shape = CursorFontShape.XC_top_left_arrow;
2970 case StdCursor.Hand: {
2971 shape = CursorFontShape.XC_hand1;
2975 case StdCursor.Help: {
2976 shape = CursorFontShape.XC_question_arrow;
2980 case StdCursor.HSplit: {
2981 shape = CursorFontShape.XC_sb_v_double_arrow;
2985 case StdCursor.IBeam: {
2986 shape = CursorFontShape.XC_xterm;
2990 case StdCursor.No: {
2991 shape = CursorFontShape.XC_circle;
2995 case StdCursor.NoMove2D: {
2996 shape = CursorFontShape.XC_fleur;
3000 case StdCursor.NoMoveHoriz: {
3001 shape = CursorFontShape.XC_fleur;
3005 case StdCursor.NoMoveVert: {
3006 shape = CursorFontShape.XC_fleur;
3010 case StdCursor.PanEast: {
3011 shape = CursorFontShape.XC_fleur;
3015 case StdCursor.PanNE: {
3016 shape = CursorFontShape.XC_fleur;
3020 case StdCursor.PanNorth: {
3021 shape = CursorFontShape.XC_fleur;
3025 case StdCursor.PanNW: {
3026 shape = CursorFontShape.XC_fleur;
3030 case StdCursor.PanSE: {
3031 shape = CursorFontShape.XC_fleur;
3035 case StdCursor.PanSouth: {
3036 shape = CursorFontShape.XC_fleur;
3040 case StdCursor.PanSW: {
3041 shape = CursorFontShape.XC_fleur;
3045 case StdCursor.PanWest: {
3046 shape = CursorFontShape.XC_sizing;
3050 case StdCursor.SizeAll: {
3051 shape = CursorFontShape.XC_fleur;
3055 case StdCursor.SizeNESW: {
3056 shape = CursorFontShape.XC_top_right_corner;
3060 case StdCursor.SizeNS: {
3061 shape = CursorFontShape.XC_sb_v_double_arrow;
3065 case StdCursor.SizeNWSE: {
3066 shape = CursorFontShape.XC_top_left_corner;
3070 case StdCursor.SizeWE: {
3071 shape = CursorFontShape.XC_sb_h_double_arrow;
3075 case StdCursor.UpArrow: {
3076 shape = CursorFontShape.XC_center_ptr;
3080 case StdCursor.VSplit: {
3081 shape = CursorFontShape.XC_sb_h_double_arrow;
3085 case StdCursor.WaitCursor: {
3086 shape = CursorFontShape.XC_watch;
3091 shape = (CursorFontShape) 0;
3099 internal override IntPtr DefWndProc(ref Message msg) {
3100 switch ((Msg)msg.Msg) {
3102 case Msg.WM_IME_COMPOSITION:
3103 string s = Keyboard.GetCompositionString ();
3104 foreach (char c in s)
3105 SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
3108 case Msg.WM_IME_CHAR:
3109 // On Windows API it sends two WM_CHAR messages for each byte, but
3110 // I wonder if it is worthy to emulate it (also no idea how to
3111 // reconstruct those bytes into chars).
3112 SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
3115 case Msg.WM_PAINT: {
3118 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3120 hwnd.expose_pending = false;
3126 case Msg.WM_NCPAINT: {
3129 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3131 hwnd.nc_expose_pending = false;
3137 case Msg.WM_NCCALCSIZE: {
3140 if (msg.WParam == (IntPtr)1) {
3141 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3143 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3144 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3146 // Add all the stuff X is supposed to draw.
3147 Control ctrl = Control.FromHandle (hwnd.Handle);
3150 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3152 ncp.rgrc1.top += rect.top;
3153 ncp.rgrc1.bottom -= rect.bottom;
3154 ncp.rgrc1.left += rect.left;
3155 ncp.rgrc1.right -= rect.right;
3157 Marshal.StructureToPtr (ncp, msg.LParam, true);
3164 case Msg.WM_CONTEXTMENU: {
3167 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3169 if ((hwnd != null) && (hwnd.parent != null)) {
3170 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3175 case Msg.WM_MOUSEWHEEL: {
3178 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3180 if ((hwnd != null) && (hwnd.parent != null)) {
3181 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3182 if (msg.Result == IntPtr.Zero) {
3189 case Msg.WM_SETCURSOR: {
3192 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3194 break; // not sure how this happens, but it does
3196 // Pass to parent window first
3197 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3199 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3202 if (msg.Result == IntPtr.Zero) {
3205 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3206 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3207 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3208 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3209 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3210 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3213 handle = Cursors.Default.handle;
3216 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3217 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3218 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3219 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3220 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3221 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3224 case HitTest.HTGROWBOX:
3225 case HitTest.HTSIZE:
3226 case HitTest.HTZOOM:
3227 case HitTest.HTVSCROLL:
3228 case HitTest.HTSYSMENU:
3229 case HitTest.HTREDUCE:
3230 case HitTest.HTNOWHERE:
3231 case HitTest.HTMAXBUTTON:
3232 case HitTest.HTMINBUTTON:
3233 case HitTest.HTMENU:
3234 case HitTest.HSCROLL:
3235 case HitTest.HTBOTTOM:
3236 case HitTest.HTCAPTION:
3237 case HitTest.HTCLIENT:
3238 case HitTest.HTCLOSE:
3240 default: handle = Cursors.Default.handle; break;
3242 SetCursor(msg.HWnd, handle);
3250 internal override void DestroyCaret(IntPtr handle) {
3251 if (Caret.Hwnd == handle) {
3252 if (Caret.Visible) {
3256 if (Caret.gc != IntPtr.Zero) {
3257 XFreeGC(DisplayHandle, Caret.gc);
3258 Caret.gc = IntPtr.Zero;
3260 Caret.Hwnd = IntPtr.Zero;
3261 Caret.Visible = false;
3266 internal override void DestroyCursor(IntPtr cursor) {
3268 XFreeCursor(DisplayHandle, cursor);
3272 internal override void DestroyWindow(IntPtr handle) {
3275 hwnd = Hwnd.ObjectFromHandle(handle);
3278 #if DriverDebug || DriverDebugDestroy
3279 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3284 #if DriverDebug || DriverDebugDestroy
3285 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3288 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3290 CleanupCachedWindows (hwnd);
3292 ArrayList windows = new ArrayList ();
3294 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3297 foreach (Hwnd h in windows) {
3298 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3303 if (hwnd.whole_window != IntPtr.Zero) {
3304 #if DriverDebug || DriverDebugDestroy
3305 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3307 Keyboard.DestroyICForWindow (hwnd.whole_window);
3308 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3310 else if (hwnd.client_window != IntPtr.Zero) {
3311 #if DriverDebug || DriverDebugDestroy
3312 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3314 Keyboard.DestroyICForWindow (hwnd.client_window);
3315 XDestroyWindow(DisplayHandle, hwnd.client_window);
3321 internal override IntPtr DispatchMessage(ref MSG msg) {
3322 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3325 IntPtr GetReversibleScreenGC (Color backColor)
3327 XGCValues gc_values;
3331 XColor xcolor = new XColor();
3332 xcolor.red = (ushort)(backColor.R * 257);
3333 xcolor.green = (ushort)(backColor.G * 257);
3334 xcolor.blue = (ushort)(backColor.B * 257);
3335 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3336 pixel = (uint)xcolor.pixel.ToInt32();
3339 gc_values = new XGCValues();
3341 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3342 gc_values.foreground = (IntPtr)pixel;
3344 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3345 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3346 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3351 IntPtr GetReversibleControlGC (Control control, int line_width)
3353 XGCValues gc_values;
3356 gc_values = new XGCValues();
3358 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3359 gc_values.line_width = line_width;
3360 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3362 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3363 //mask = foreground ^ background;
3364 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3365 //XSetBackground(DisplayHandle, gc, background);
3366 //XSetFunction(DisplayHandle, gc, GXxor);
3367 //XSetPlaneMask(DisplayHandle, gc, mask);
3370 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3374 XColor xcolor = new XColor();
3376 xcolor.red = (ushort)(control.ForeColor.R * 257);
3377 xcolor.green = (ushort)(control.ForeColor.G * 257);
3378 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3379 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3380 foreground = (uint)xcolor.pixel.ToInt32();
3382 xcolor.red = (ushort)(control.BackColor.R * 257);
3383 xcolor.green = (ushort)(control.BackColor.G * 257);
3384 xcolor.blue = (ushort)(control.BackColor.B * 257);
3385 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3386 background = (uint)xcolor.pixel.ToInt32();
3388 uint mask = foreground ^ background;
3390 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3391 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3392 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3393 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3398 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3400 if (backColor.GetBrightness() < 0.5)
3401 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3403 IntPtr gc = GetReversibleScreenGC (backColor);
3405 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3407 XFreeGC(DisplayHandle, gc);
3410 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3412 if (backColor.GetBrightness() < 0.5)
3413 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3415 IntPtr gc = GetReversibleScreenGC (backColor);
3417 if (rectangle.Width < 0) {
3418 rectangle.X += rectangle.Width;
3419 rectangle.Width = -rectangle.Width;
3421 if (rectangle.Height < 0) {
3422 rectangle.Y += rectangle.Height;
3423 rectangle.Height = -rectangle.Height;
3427 GCLineStyle line_style = GCLineStyle.LineSolid;
3428 GCCapStyle cap_style = GCCapStyle.CapButt;
3429 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3432 case FrameStyle.Dashed:
3433 line_style = GCLineStyle.LineOnOffDash;
3435 case FrameStyle.Thick:
3440 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3442 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3444 XFreeGC(DisplayHandle, gc);
3447 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3449 if (backColor.GetBrightness() < 0.5)
3450 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3452 IntPtr gc = GetReversibleScreenGC (backColor);
3454 if (rectangle.Width < 0) {
3455 rectangle.X += rectangle.Width;
3456 rectangle.Width = -rectangle.Width;
3458 if (rectangle.Height < 0) {
3459 rectangle.Y += rectangle.Height;
3460 rectangle.Height = -rectangle.Height;
3462 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3464 XFreeGC(DisplayHandle, gc);
3467 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3470 Control control = Control.FromHandle(handle);
3472 gc = GetReversibleControlGC (control, line_width);
3474 if ((rect.Width > 0) && (rect.Height > 0)) {
3475 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3477 if (rect.Width > 0) {
3478 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3480 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3483 XFreeGC(DisplayHandle, gc);
3486 internal override void DoEvents() {
3487 MSG msg = new MSG ();
3490 if (OverrideCursorHandle != IntPtr.Zero) {
3491 OverrideCursorHandle = IntPtr.Zero;
3494 queue = ThreadQueue(Thread.CurrentThread);
3496 queue.DispatchIdle = false;
3498 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3499 TranslateMessage (ref msg);
3500 DispatchMessage (ref msg);
3503 queue.DispatchIdle = true;
3506 internal override void EnableWindow(IntPtr handle, bool Enable) {
3509 hwnd = Hwnd.ObjectFromHandle(handle);
3511 hwnd.Enabled = Enable;
3515 internal override void EndLoop(Thread thread) {
3516 // This is where we one day will shut down the loop for the thread
3519 internal override IntPtr GetActive() {
3524 IntPtr prop = IntPtr.Zero;
3525 IntPtr active = IntPtr.Zero;
3527 XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3528 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3529 active = (IntPtr)Marshal.ReadInt32(prop);
3533 if (active != IntPtr.Zero) {
3536 hwnd = Hwnd.GetObjectFromWindow(active);
3538 active = hwnd.Handle;
3540 active = IntPtr.Zero;
3546 internal override Region GetClipRegion(IntPtr handle) {
3549 hwnd = Hwnd.ObjectFromHandle(handle);
3551 return hwnd.UserClip;
3557 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3564 internal override void GetDisplaySize(out Size size) {
3565 XWindowAttributes attributes=new XWindowAttributes();
3568 // FIXME - use _NET_WM messages instead?
3569 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3572 size = new Size(attributes.width, attributes.height);
3575 internal override SizeF GetAutoScaleSize(Font font) {
3578 string magic_string = "The quick brown fox jumped over the lazy dog.";
3579 double magic_number = 44.549996948242189;
3581 g = Graphics.FromHwnd(FosterParent);
3583 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3584 return new SizeF(width, font.Height);
3587 internal override IntPtr GetParent(IntPtr handle) {
3590 hwnd = Hwnd.ObjectFromHandle(handle);
3591 if (hwnd != null && hwnd.parent != null) {
3592 return hwnd.parent.Handle;
3597 // This is a nop on win32 and x11
3598 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3602 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3612 if (handle != IntPtr.Zero) {
3613 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3615 use_handle = RootWindow;
3619 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3622 if (handle != IntPtr.Zero) {
3631 internal override IntPtr GetFocus() {
3636 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3637 FontFamily ff = font.FontFamily;
3638 ascent = ff.GetCellAscent (font.Style);
3639 descent = ff.GetCellDescent (font.Style);
3643 internal override Point GetMenuOrigin(IntPtr handle) {
3646 hwnd = Hwnd.ObjectFromHandle(handle);
3649 return hwnd.MenuOrigin;
3654 [MonoTODO("Implement filtering")]
3655 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3662 if (((XEventQueue)queue_id).Count > 0) {
3663 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3665 UpdateMessageQueue ((XEventQueue)queue_id);
3667 if (((XEventQueue)queue_id).Count > 0) {
3668 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3669 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3670 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3672 msg.hwnd= IntPtr.Zero;
3673 msg.message = Msg.WM_ENTERIDLE;
3678 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3680 // Handle messages for windows that are already or are about to be destroyed.
3682 // we need a special block for this because unless we remove the hwnd from the paint
3683 // queue it will always stay there (since we don't handle the expose), and we'll
3684 // effectively loop infinitely trying to repaint a non-existant window.
3685 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3686 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3687 hwnd.Queue.Paint.Remove (hwnd);
3688 goto ProcessNextMessage;
3691 // We need to make sure we only allow DestroyNotify events through for zombie
3692 // hwnds, since much of the event handling code makes requests using the hwnd's
3693 // client_window, and that'll result in BadWindow errors if there's some lag
3694 // between the XDestroyWindow call and the DestroyNotify event.
3695 if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
3696 #if DriverDebug || DriverDebugDestroy
3697 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3699 goto ProcessNextMessage;
3702 if (hwnd.client_window == xevent.AnyEvent.window) {
3704 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3707 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3710 msg.hwnd = hwnd.Handle;
3712 // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE
3713 // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
3714 // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
3715 // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
3717 // - There is no way for us to know which is the last Configure event. We can't traverse the events
3718 // queue, because the next configure event might not be pending yet.
3719 // - We can't get ButtonPress/Release events for the window decorations, because they are not part
3720 // of the window(s) we manage.
3721 // - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
3723 // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure
3724 // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
3726 if (hwnd.resizing_or_moving) {
3727 int root_x, root_y, win_x, win_y, keys_buttons;
3729 XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y,
3730 out win_x, out win_y, out keys_buttons);
3731 if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
3732 (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
3733 (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
3734 hwnd.resizing_or_moving = false;
3735 SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
3740 // If you add a new event to this switch make sure to add it in
3741 // UpdateMessage also unless it is not coming through the X event system.
3743 switch(xevent.type) {
3744 case XEventName.KeyPress: {
3745 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3747 // F1 key special case - WM_HELP sending
3748 if (msg.wParam == (IntPtr)VirtualKeys.VK_F1 || msg.wParam == (IntPtr)VirtualKeys.VK_HELP) {
3749 // Send the keypress message first
3750 NativeWindow.WndProc (hwnd.client_window, msg.message, msg.wParam, msg.lParam);
3753 HELPINFO helpInfo = new HELPINFO ();
3754 GetCursorPos (IntPtr.Zero, out helpInfo.MousePos.x, out helpInfo.MousePos.y);
3755 IntPtr helpInfoPtr = Marshal.AllocHGlobal (Marshal.SizeOf (helpInfo));
3756 Marshal.StructureToPtr (helpInfo, helpInfoPtr, true);
3757 NativeWindow.WndProc (hwnd.client_window, Msg.WM_HELP, IntPtr.Zero, helpInfoPtr);
3758 Marshal.FreeHGlobal (helpInfoPtr);
3760 goto ProcessNextMessage;
3765 case XEventName.KeyRelease: {
3766 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3770 case XEventName.ButtonPress: {
3771 switch(xevent.ButtonEvent.button) {
3773 MouseState |= MouseButtons.Left;
3775 msg.message = Msg.WM_LBUTTONDOWN;
3776 msg.wParam = GetMousewParam (0);
3778 msg.message = Msg.WM_NCLBUTTONDOWN;
3779 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3780 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3786 MouseState |= MouseButtons.Middle;
3788 msg.message = Msg.WM_MBUTTONDOWN;
3789 msg.wParam = GetMousewParam (0);
3791 msg.message = Msg.WM_NCMBUTTONDOWN;
3792 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3793 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3799 MouseState |= MouseButtons.Right;
3801 msg.message = Msg.WM_RBUTTONDOWN;
3802 msg.wParam = GetMousewParam (0);
3804 msg.message = Msg.WM_NCRBUTTONDOWN;
3805 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3806 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3812 msg.hwnd = FocusWindow;
3813 msg.message=Msg.WM_MOUSEWHEEL;
3814 msg.wParam=GetMousewParam(120);
3819 msg.hwnd = FocusWindow;
3820 msg.message=Msg.WM_MOUSEWHEEL;
3821 msg.wParam=GetMousewParam(-120);
3827 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3828 mouse_position.X = xevent.ButtonEvent.x;
3829 mouse_position.Y = xevent.ButtonEvent.y;
3831 if (!hwnd.Enabled) {
3834 msg.hwnd = hwnd.EnabledHwnd;
3835 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);
3836 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3839 if (Grab.Hwnd != IntPtr.Zero) {
3840 msg.hwnd = Grab.Hwnd;
3843 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3844 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3845 switch(xevent.ButtonEvent.button) {
3847 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3852 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3857 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3861 ClickPending.Pending = false;
3863 ClickPending.Pending = true;
3864 ClickPending.Hwnd = msg.hwnd;
3865 ClickPending.Message = msg.message;
3866 ClickPending.wParam = msg.wParam;
3867 ClickPending.lParam = msg.lParam;
3868 ClickPending.Time = (long)xevent.ButtonEvent.time;
3871 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3872 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3878 case XEventName.ButtonRelease: {
3879 switch(xevent.ButtonEvent.button) {
3882 msg.message = Msg.WM_LBUTTONUP;
3884 msg.message = Msg.WM_NCLBUTTONUP;
3885 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3886 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3888 MouseState &= ~MouseButtons.Left;
3889 msg.wParam = GetMousewParam (0);
3895 msg.message = Msg.WM_MBUTTONUP;
3897 msg.message = Msg.WM_NCMBUTTONUP;
3898 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3899 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3901 MouseState &= ~MouseButtons.Middle;
3902 msg.wParam = GetMousewParam (0);
3908 msg.message = Msg.WM_RBUTTONUP;
3910 msg.message = Msg.WM_NCRBUTTONUP;
3911 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3912 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3914 MouseState &= ~MouseButtons.Right;
3915 msg.wParam = GetMousewParam (0);
3920 goto ProcessNextMessage;
3924 goto ProcessNextMessage;
3928 if (!hwnd.Enabled) {
3931 msg.hwnd = hwnd.EnabledHwnd;
3932 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);
3933 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3936 if (Grab.Hwnd != IntPtr.Zero) {
3937 msg.hwnd = Grab.Hwnd;
3940 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3941 mouse_position.X = xevent.ButtonEvent.x;
3942 mouse_position.Y = xevent.ButtonEvent.y;
3944 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3945 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3946 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3947 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3948 XEvent motionEvent = new XEvent ();
3949 motionEvent.type = XEventName.MotionNotify;
3950 motionEvent.MotionEvent.display = DisplayHandle;
3951 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3952 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3953 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3954 hwnd.Queue.EnqueueLocked (motionEvent);
3959 case XEventName.MotionNotify: {
3961 #if DriverDebugExtra
3962 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);
3965 if (Grab.Hwnd != IntPtr.Zero) {
3966 msg.hwnd = Grab.Hwnd;
3969 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3973 if (xevent.MotionEvent.is_hint != 0)
3977 XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3978 out root, out child,
3979 out xevent.MotionEvent.x_root,
3980 out xevent.MotionEvent.y_root,
3981 out xevent.MotionEvent.x,
3982 out xevent.MotionEvent.y, out mask);
3985 msg.message = Msg.WM_MOUSEMOVE;
3986 msg.wParam = GetMousewParam(0);
3987 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3989 if (!hwnd.Enabled) {
3992 msg.hwnd = hwnd.EnabledHwnd;
3993 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);
3994 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3997 mouse_position.X = xevent.MotionEvent.x;
3998 mouse_position.Y = xevent.MotionEvent.y;
4000 if ((HoverState.Timer.Enabled) &&
4001 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
4002 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
4003 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
4004 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
4005 HoverState.Timer.Stop();
4006 HoverState.Timer.Start();
4007 HoverState.X = mouse_position.X;
4008 HoverState.Y = mouse_position.Y;
4016 #if DriverDebugExtra
4017 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);
4019 msg.message = Msg.WM_NCMOUSEMOVE;
4021 if (!hwnd.Enabled) {
4022 msg.hwnd = hwnd.EnabledHwnd;
4023 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);
4024 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
4027 ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
4028 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
4030 mouse_position.X = xevent.MotionEvent.x;
4031 mouse_position.Y = xevent.MotionEvent.y;
4037 case XEventName.EnterNotify: {
4038 if (!hwnd.Enabled) {
4039 goto ProcessNextMessage;
4041 if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || xevent.AnyEvent.window != hwnd.client_window) {
4042 goto ProcessNextMessage;
4044 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) { // Pseudo motion caused by grabbing
4045 if (LastPointerWindow == xevent.AnyEvent.window)
4046 goto ProcessNextMessage;
4048 if (LastPointerWindow != IntPtr.Zero) {
4049 Point enter_loc = new Point (xevent.ButtonEvent.x, xevent.ButtonEvent.y);
4051 // We need this due to EnterNotify being fired on all the parent controls
4052 // of the Control being grabbed, and obviously in that scenario we are not
4053 // actuallty entering them
4054 Control ctrl = Control.FromHandle (hwnd.client_window);
4055 foreach (Control child_control in ctrl.Controls.GetAllControls ())
4056 if (child_control.Bounds.Contains (enter_loc))
4057 goto ProcessNextMessage;
4059 // A MouseLeave/LeaveNotify event is sent to the previous window
4060 // until the mouse is ungrabbed, not when actually leaving its bounds
4061 int x = xevent.CrossingEvent.x_root;
4062 int y = xevent.CrossingEvent.y_root;
4063 ScreenToClient (LastPointerWindow, ref x, ref y);
4065 XEvent leaveEvent = new XEvent ();
4066 leaveEvent.type = XEventName.LeaveNotify;
4067 leaveEvent.CrossingEvent.display = DisplayHandle;
4068 leaveEvent.CrossingEvent.window = LastPointerWindow;
4069 leaveEvent.CrossingEvent.x = x;
4070 leaveEvent.CrossingEvent.y = y;
4071 leaveEvent.CrossingEvent.mode = NotifyMode.NotifyNormal;
4072 Hwnd last_pointer_hwnd = Hwnd.ObjectFromHandle (LastPointerWindow);
4073 last_pointer_hwnd.Queue.EnqueueLocked (leaveEvent);
4077 LastPointerWindow = xevent.AnyEvent.window;
4079 msg.message = Msg.WM_MOUSE_ENTER;
4080 HoverState.X = xevent.CrossingEvent.x;
4081 HoverState.Y = xevent.CrossingEvent.y;
4082 HoverState.Timer.Enabled = true;
4083 HoverState.Window = xevent.CrossingEvent.window;
4085 // Win32 sends a WM_MOUSEMOVE after mouse enter
4086 XEvent motionEvent = new XEvent ();
4087 motionEvent.type = XEventName.MotionNotify;
4088 motionEvent.MotionEvent.display = DisplayHandle;
4089 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
4090 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
4091 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
4092 hwnd.Queue.EnqueueLocked (motionEvent);
4096 case XEventName.LeaveNotify: {
4097 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
4098 WindowUngrabbed (hwnd.Handle);
4099 goto ProcessNextMessage;
4101 if (!hwnd.Enabled) {
4102 goto ProcessNextMessage;
4104 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
4105 goto ProcessNextMessage;
4107 // If a grab is taking place, ignore it - we handle it in EnterNotify
4108 if (Grab.Hwnd != IntPtr.Zero)
4109 goto ProcessNextMessage;
4111 // Reset the cursor explicitly on X11.
4112 // X11 remembers the last set cursor for the window and in cases where
4113 // the control won't get a WM_SETCURSOR X11 will restore the last
4114 // known cursor, which we don't want.
4116 SetCursor (hwnd.client_window, IntPtr.Zero);
4118 msg.message=Msg.WM_MOUSELEAVE;
4119 HoverState.Timer.Enabled = false;
4120 HoverState.Window = IntPtr.Zero;
4125 case XEventName.CreateNotify: {
4126 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
4127 msg.message = WM_CREATE;
4128 // Set up CreateStruct
4130 goto ProcessNextMessage;
4137 case XEventName.ReparentNotify: {
4138 if (hwnd.parent == null) { // Toplevel
4139 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
4140 hwnd.Reparented = true;
4142 // The location given by the event is not reliable between different wm's,
4143 // so use an alternative way of getting it.
4144 Point location = GetTopLevelWindowLocation (hwnd);
4145 hwnd.X = location.X;
4146 hwnd.Y = location.Y;
4148 if (hwnd.opacity != 0xffffffff) {
4151 opacity = (IntPtr)(Int32)hwnd.opacity;
4152 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4154 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4155 goto ProcessNextMessage;
4157 hwnd.Reparented = false;
4158 goto ProcessNextMessage;
4161 goto ProcessNextMessage;
4164 case XEventName.ConfigureNotify: {
4165 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4166 #if DriverDebugExtra
4167 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);
4170 lock (hwnd.configure_lock) {
4171 Form form = Control.FromHandle (hwnd.client_window) as Form;
4172 if (form != null && !hwnd.resizing_or_moving) {
4173 if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
4174 SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
4175 hwnd.resizing_or_moving = true;
4176 } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
4177 SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
4178 hwnd.resizing_or_moving = true;
4180 if (hwnd.resizing_or_moving)
4181 SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
4184 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4185 hwnd.configure_pending = false;
4187 // We need to adjust our client window to track the resize of whole_window
4188 if (hwnd.whole_window != hwnd.client_window)
4189 PerformNCCalc(hwnd);
4192 goto ProcessNextMessage;
4195 case XEventName.FocusIn: {
4196 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4197 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4198 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4199 // about it having focus again
4200 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4201 goto ProcessNextMessage;
4204 if (FocusWindow == IntPtr.Zero) {
4205 Control c = Control.FromHandle (hwnd.client_window);
4207 goto ProcessNextMessage;
4208 Form form = c.FindForm ();
4210 goto ProcessNextMessage;
4211 if (ActiveWindow != form.Handle) {
4212 ActiveWindow = form.Handle;
4213 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4215 goto ProcessNextMessage;
4217 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4218 Keyboard.FocusIn (FocusWindow);
4219 goto ProcessNextMessage;
4222 case XEventName.FocusOut: {
4223 // Se the comment for our FocusIn handler
4224 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4225 goto ProcessNextMessage;
4228 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4229 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4232 Keyboard.FocusOut(hwnd.client_window);
4233 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4234 goto ProcessNextMessage;
4237 case XEventName.MapNotify: {
4238 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4240 msg.message = Msg.WM_SHOWWINDOW;
4241 msg.wParam = (IntPtr) 1;
4242 // XXX we're missing the lParam..
4245 goto ProcessNextMessage;
4248 case XEventName.UnmapNotify: {
4249 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4250 hwnd.mapped = false;
4251 msg.message = Msg.WM_SHOWWINDOW;
4252 msg.wParam = (IntPtr) 0;
4253 // XXX we're missing the lParam..
4256 goto ProcessNextMessage;
4259 case XEventName.Expose: {
4262 hwnd.expose_pending = false;
4264 hwnd.nc_expose_pending = false;
4266 goto ProcessNextMessage;
4270 if (!hwnd.expose_pending) {
4271 goto ProcessNextMessage;
4274 if (!hwnd.nc_expose_pending) {
4275 goto ProcessNextMessage;
4278 switch (hwnd.border_style) {
4279 case FormBorderStyle.Fixed3D: {
4282 g = Graphics.FromHwnd(hwnd.whole_window);
4283 if (hwnd.border_static)
4284 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4286 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4291 case FormBorderStyle.FixedSingle: {
4294 g = Graphics.FromHwnd(hwnd.whole_window);
4295 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4300 #if DriverDebugExtra
4301 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);
4304 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4305 Region region = new Region (rect);
4306 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4307 msg.message = Msg.WM_NCPAINT;
4308 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4309 msg.refobject = region;
4312 #if DriverDebugExtra
4313 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);
4315 if (Caret.Visible == true) {
4316 Caret.Paused = true;
4320 if (Caret.Visible == true) {
4322 Caret.Paused = false;
4324 msg.message = Msg.WM_PAINT;
4328 case XEventName.DestroyNotify: {
4330 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4331 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4333 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4334 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4335 CleanupCachedWindows (hwnd);
4337 #if DriverDebugDestroy
4338 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4341 msg.hwnd = hwnd.client_window;
4342 msg.message=Msg.WM_DESTROY;
4345 goto ProcessNextMessage;
4351 case XEventName.ClientMessage: {
4352 if (Dnd.HandleClientMessage (ref xevent)) {
4353 goto ProcessNextMessage;
4356 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4357 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4358 goto ProcessNextMessage;
4361 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4362 msg.message = Msg.WM_MOUSEHOVER;
4363 msg.wParam = GetMousewParam(0);
4364 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4368 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4369 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4370 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4371 msg.wParam = xevent.ClientMessageEvent.ptr3;
4372 msg.lParam = xevent.ClientMessageEvent.ptr4;
4373 if (msg.message == (Msg)Msg.WM_QUIT)
4379 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4380 #if DriverDebugXEmbed
4381 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4384 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4385 XSizeHints hints = new XSizeHints();
4388 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4390 hwnd.width = hints.max_width;
4391 hwnd.height = hints.max_height;
4392 hwnd.ClientRect = Rectangle.Empty;
4393 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4397 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4398 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4399 SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
4400 msg.message = Msg.WM_CLOSE;
4404 // We should not get this, but I'll leave the code in case we need it in the future
4405 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4406 goto ProcessNextMessage;
4409 goto ProcessNextMessage;
4413 goto ProcessNextMessage;
4420 private HitTest NCHitTest (Hwnd hwnd, int x, int y)
4422 // The hit test is sent in screen coordinates
4424 int screen_x, screen_y;
4425 XTranslateCoordinates (DisplayHandle, hwnd.WholeWindow, RootWindow, x, y, out screen_x, out screen_y, out dummy);
4426 return (HitTest) NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero,
4427 (IntPtr) (screen_y << 16 | screen_x & 0xFFFF));
4430 internal override bool GetText(IntPtr handle, out string text) {
4437 IntPtr prop = IntPtr.Zero;
4439 XGetWindowProperty(DisplayHandle, handle,
4440 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4441 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4443 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4444 text = Marshal.PtrToStringUni (prop, (int)nitems);
4449 // fallback on the non-_NET property
4452 textptr = IntPtr.Zero;
4454 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4455 if (textptr != IntPtr.Zero) {
4456 text = Marshal.PtrToStringAnsi(textptr);
4467 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) {
4470 hwnd = Hwnd.ObjectFromHandle(handle);
4476 height = hwnd.height;
4478 PerformNCCalc(hwnd);
4480 client_width = hwnd.ClientRect.Width;
4481 client_height = hwnd.ClientRect.Height;
4486 // Should we throw an exception or fail silently?
4487 // throw new ArgumentException("Called with an invalid window handle", "handle");
4497 internal override FormWindowState GetWindowState(IntPtr handle) {
4500 hwnd = Hwnd.ObjectFromHandle(handle);
4502 if (hwnd.cached_window_state == (FormWindowState)(-1))
4503 hwnd.cached_window_state = UpdateWindowState (handle);
4505 return hwnd.cached_window_state;
4508 private FormWindowState UpdateWindowState (IntPtr handle) {
4513 IntPtr prop = IntPtr.Zero;
4517 XWindowAttributes attributes;
4520 hwnd = Hwnd.ObjectFromHandle(handle);
4524 XGetWindowProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4525 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4526 for (int i = 0; i < (long)nitems; i++) {
4527 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4528 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4530 } else if (atom == _NET_WM_STATE_HIDDEN) {
4538 return FormWindowState.Minimized;
4539 } else if (maximized == 2) {
4540 return FormWindowState.Maximized;
4543 attributes = new XWindowAttributes();
4544 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4545 if (attributes.map_state == MapState.IsUnmapped) {
4546 return (FormWindowState)(-1);
4550 return FormWindowState.Normal;
4553 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4555 GrabConfined = Grab.Confined;
4556 GrabArea = Grab.Area;
4559 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4561 IntPtr confine_to_window;
4563 confine_to_window = IntPtr.Zero;
4565 if (confine_to_handle != IntPtr.Zero) {
4566 XWindowAttributes attributes = new XWindowAttributes();
4568 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4571 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4573 Grab.Area.X = attributes.x;
4574 Grab.Area.Y = attributes.y;
4575 Grab.Area.Width = attributes.width;
4576 Grab.Area.Height = attributes.height;
4577 Grab.Confined = true;
4578 confine_to_window = hwnd.client_window;
4583 hwnd = Hwnd.ObjectFromHandle(handle);
4586 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4587 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4588 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4589 EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4590 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4594 internal override void UngrabWindow(IntPtr hwnd) {
4596 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4597 XFlush(DisplayHandle);
4599 WindowUngrabbed (hwnd);
4602 private void WindowUngrabbed (IntPtr hwnd) {
4603 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4605 Grab.Hwnd = IntPtr.Zero;
4606 Grab.Confined = false;
4609 // lparam should be the handle to the window gaining the mouse capture,
4610 // but X doesn't seem to give us that information.
4611 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4612 // X will send a NotifyUngrab, but since it comes late sometimes we're
4613 // calling WindowUngrabbed directly from UngrabWindow in order to send
4614 // this WM right away.
4615 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4619 internal override void HandleException(Exception e) {
4620 StackTrace st = new StackTrace(e, true);
4621 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4622 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4625 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4628 hwnd = Hwnd.ObjectFromHandle(handle);
4631 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4633 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4637 internal override void InvalidateNC (IntPtr handle) {
4640 hwnd = Hwnd.ObjectFromHandle(handle);
4642 AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
4645 internal override bool IsEnabled(IntPtr handle) {
4646 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4647 return (hwnd != null && hwnd.Enabled);
4650 internal override bool IsVisible(IntPtr handle) {
4651 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4652 return (hwnd != null && hwnd.visible);
4655 internal override void KillTimer(Timer timer) {
4656 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4658 if (queue == null) {
4659 // This isn't really an error, MS doesn't start the timer if
4660 // it has no assosciated queue. In this case, remove the timer
4661 // from the list of unattached timers (if it was enabled).
4662 lock (unattached_timer_list) {
4663 if (unattached_timer_list.Contains (timer))
4664 unattached_timer_list.Remove (timer);
4668 queue.timer_list.Remove (timer);
4671 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4677 hwnd = Hwnd.ObjectFromHandle(handle);
4680 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4687 internal override void OverrideCursor(IntPtr cursor)
4689 if (Grab.Hwnd != IntPtr.Zero) {
4690 XChangeActivePointerGrab (DisplayHandle,
4691 EventMask.ButtonMotionMask |
4692 EventMask.PointerMotionMask |
4693 EventMask.PointerMotionHintMask |
4694 EventMask.ButtonPressMask |
4695 EventMask.ButtonReleaseMask,
4696 cursor, IntPtr.Zero);
4700 OverrideCursorHandle = cursor;
4703 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4704 PaintEventArgs paint_event;
4709 // handle (and paint_hwnd) refers to the window that is should be painted.
4710 // msg.HWnd (and hwnd) refers to the window that got the paint message.
4713 hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4714 if (msg.HWnd == handle) {
4717 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4720 if (Caret.Visible == true) {
4721 Caret.Paused = true;
4728 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4730 Region clip_region = new Region ();
4731 clip_region.MakeEmpty();
4733 foreach (Rectangle r in hwnd.ClipRectangles) {
4734 clip_region.Union (r);
4737 if (hwnd.UserClip != null) {
4738 clip_region.Intersect(hwnd.UserClip);
4741 dc.Clip = clip_region;
4742 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4743 hwnd.expose_pending = false;
4745 hwnd.ClearInvalidArea();
4747 hwnd.drawing_stack.Push (paint_event);
4748 hwnd.drawing_stack.Push (dc);
4752 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4754 if (!hwnd.nc_invalid.IsEmpty) {
4755 dc.SetClip (hwnd.nc_invalid);
4756 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4758 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4760 hwnd.nc_expose_pending = false;
4762 hwnd.ClearNcInvalidArea ();
4764 hwnd.drawing_stack.Push (paint_event);
4765 hwnd.drawing_stack.Push (dc);
4771 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4774 hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4776 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4780 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4781 pe.SetGraphics (null);
4784 if (Caret.Visible == true) {
4786 Caret.Paused = false;
4790 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4791 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4792 XEventQueue queue = (XEventQueue) queue_id;
4795 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4796 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4800 if (queue.Count > 0) {
4803 // Only call UpdateMessageQueue if real events are pending
4804 // otherwise we go to sleep on the socket
4805 if (XPending(DisplayHandle) != 0) {
4806 UpdateMessageQueue((XEventQueue)queue_id);
4808 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4813 CheckTimers(queue.timer_list, DateTime.UtcNow);
4818 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4821 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4822 XEvent xevent = new XEvent ();
4823 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4825 xevent.type = XEventName.ClientMessage;
4826 xevent.ClientMessageEvent.display = DisplayHandle;
4829 xevent.ClientMessageEvent.window = hwnd.whole_window;
4831 xevent.ClientMessageEvent.window = IntPtr.Zero;
4834 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4835 xevent.ClientMessageEvent.format = 32;
4836 xevent.ClientMessageEvent.ptr1 = handle;
4837 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4838 xevent.ClientMessageEvent.ptr3 = wparam;
4839 xevent.ClientMessageEvent.ptr4 = lparam;
4842 hwnd.Queue.EnqueueLocked (xevent);
4844 ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
4849 internal override void PostQuitMessage(int exitCode) {
4850 ApplicationContext ctx = Application.MWFThread.Current.Context;
4851 Form f = ctx != null ? ctx.MainForm : null;
4853 PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4855 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4856 XFlush(DisplayHandle);
4859 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4864 internal override void RequestNCRecalc(IntPtr handle) {
4867 hwnd = Hwnd.ObjectFromHandle(handle);
4873 PerformNCCalc(hwnd);
4874 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4875 InvalidateNC(handle);
4878 internal override void ResetMouseHover(IntPtr handle) {
4881 hwnd = Hwnd.ObjectFromHandle(handle);
4886 HoverState.Timer.Enabled = true;
4887 HoverState.X = mouse_position.X;
4888 HoverState.Y = mouse_position.Y;
4889 HoverState.Window = handle;
4893 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4899 hwnd = Hwnd.ObjectFromHandle(handle);
4902 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4909 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4915 hwnd = Hwnd.ObjectFromHandle(handle);
4918 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4921 Form form = Control.FromHandle (handle) as Form;
4922 if (form != null && form.window_manager != null) {
4923 dest_y_return -= form.window_manager.TitleBarHeight;
4930 bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
4932 return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) &&
4933 arg == xevent.GraphicsExposeEvent.drawable;
4936 delegate bool EventPredicate (IntPtr display, ref XEvent xevent, IntPtr arg);
4938 void ProcessGraphicsExpose (Hwnd hwnd)
4940 XEvent xevent = new XEvent ();
4941 IntPtr handle = Hwnd.HandleFromObject (hwnd);
4942 EventPredicate predicate = GraphicsExposePredicate;
4945 XIfEvent (Display, ref xevent, predicate, handle);
4946 if (xevent.type != XEventName.GraphicsExpose)
4949 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
4950 xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);
4952 if (xevent.GraphicsExposeEvent.count == 0)
4957 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4960 XGCValues gc_values;
4962 hwnd = Hwnd.ObjectFromHandle(handle);
4964 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4966 /* We have an invalid area in the window we're scrolling.
4967 Adjust our stored invalid rectangle to to match the scrolled amount */
4982 if (area.Contains (hwnd.Invalid))
4983 hwnd.ClearInvalidArea ();
4984 hwnd.AddInvalidArea(r);
4987 gc_values = new XGCValues();
4989 if (with_children) {
4990 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4993 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4995 Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
4996 visible_rect.Intersect (area);
4998 Rectangle dest_rect = visible_rect;
4999 dest_rect.Y += YAmount;
5000 dest_rect.X += XAmount;
5001 dest_rect.Intersect (area);
5003 Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
5004 XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y,
5005 dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
5007 Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
5008 AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
5010 ProcessGraphicsExpose (hwnd);
5012 XFreeGC(DisplayHandle, gc);
5015 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
5019 hwnd = Hwnd.GetObjectFromWindow(handle);
5021 rect = hwnd.ClientRect;
5024 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
5027 Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
5029 Rectangle dirty_area = total_area;
5032 dirty_area.Height -= valid_area.Height;
5033 else if (YAmount < 0) {
5034 dirty_area.Height -= valid_area.Height;
5035 dirty_area.Y += valid_area.Height;
5039 dirty_area.Width -= valid_area.Width;
5040 else if (XAmount < 0) {
5041 dirty_area.Width -= valid_area.Width;
5042 dirty_area.X += valid_area.Width;
5048 Rectangle GetTotalVisibleArea (IntPtr handle)
5050 Control c = Control.FromHandle (handle);
5052 Rectangle visible_area = c.ClientRectangle;
5053 visible_area.Location = c.PointToScreen (Point.Empty);
5055 for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
5056 if (!parent.IsHandleCreated || !parent.Visible)
5057 return visible_area; // Non visible, not need to finish computations
5059 Rectangle r = parent.ClientRectangle;
5060 r.Location = parent.PointToScreen (Point.Empty);
5062 visible_area.Intersect (r);
5065 visible_area.Location = c.PointToClient (visible_area.Location);
5066 return visible_area;
5069 internal override void SendAsyncMethod (AsyncMethodData method) {
5071 XEvent xevent = new XEvent ();
5073 hwnd = Hwnd.ObjectFromHandle(method.Handle);
5075 xevent.type = XEventName.ClientMessage;
5076 xevent.ClientMessageEvent.display = DisplayHandle;
5077 xevent.ClientMessageEvent.window = method.Handle;
5078 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
5079 xevent.ClientMessageEvent.format = 32;
5080 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
5082 hwnd.Queue.EnqueueLocked (xevent);
5087 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
5089 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
5092 h = Hwnd.ObjectFromHandle(hwnd);
5094 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
5095 AsyncMethodResult result;
5096 AsyncMethodData data;
5098 result = new AsyncMethodResult ();
5099 data = new AsyncMethodData ();
5102 data.Method = new WndProcDelegate (NativeWindow.WndProc);
5103 data.Args = new object[] { hwnd, message, wParam, lParam };
5104 data.Result = result;
5106 SendAsyncMethod (data);
5107 #if DriverDebug || DriverDebugThreads
5108 Console.WriteLine ("Sending {0} message across.", message);
5113 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
5116 internal override int SendInput(IntPtr handle, Queue keys) {
5117 if (handle == IntPtr.Zero)
5120 int count = keys.Count;
5121 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5123 while (keys.Count > 0) {
5125 MSG msg = (MSG)keys.Dequeue();
5127 XEvent xevent = new XEvent ();
5129 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
5130 xevent.KeyEvent.display = DisplayHandle;
5133 xevent.KeyEvent.window = hwnd.whole_window;
5135 xevent.KeyEvent.window = IntPtr.Zero;
5138 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
5140 hwnd.Queue.EnqueueLocked (xevent);
5145 internal override void SetAllowDrop (IntPtr handle, bool value)
5147 // We allow drop on all windows
5150 internal override DragDropEffects StartDrag (IntPtr handle, object data,
5151 DragDropEffects allowed_effects)
5153 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5156 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
5158 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
5161 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
5162 Form form = Control.FromHandle (handle) as Form;
5163 if (form != null && form.window_manager == null) {
5164 CreateParams cp = form.GetCreateParams ();
5165 if (border_style == FormBorderStyle.FixedToolWindow ||
5166 border_style == FormBorderStyle.SizableToolWindow ||
5167 cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
5168 form.window_manager = new ToolWindowManager (form);
5172 RequestNCRecalc(handle);
5175 internal override void SetCaretPos(IntPtr handle, int x, int y) {
5176 if (Caret.Hwnd == handle) {
5183 Keyboard.SetCaretPos (Caret, handle, x, y);
5185 if (Caret.Visible == true) {
5187 Caret.Timer.Start();
5192 internal override void SetClipRegion(IntPtr handle, Region region) {
5195 hwnd = Hwnd.ObjectFromHandle(handle);
5200 hwnd.UserClip = region;
5203 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
5206 if (OverrideCursorHandle == IntPtr.Zero) {
5207 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
5211 LastCursorHandle = cursor;
5212 LastCursorWindow = handle;
5214 hwnd = Hwnd.ObjectFromHandle(handle);
5216 if (cursor != IntPtr.Zero) {
5217 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
5219 XUndefineCursor(DisplayHandle, hwnd.whole_window);
5221 XFlush(DisplayHandle);
5226 hwnd = Hwnd.ObjectFromHandle(handle);
5228 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
5232 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
5233 out int root_x, out int root_y, out int child_x, out int child_y,
5236 /* this code was written with the help of
5237 glance at gdk. I never would have realized we
5238 needed a loop in order to traverse down in the
5239 hierarchy. I would have assumed you'd get the
5240 most deeply nested child and have to do
5241 XQueryTree to move back up the hierarchy..
5242 stupid me, of course. */
5245 XGrabServer (display);
5247 XQueryPointer(display, w, out root, out c,
5248 out root_x, out root_y, out child_x, out child_y,
5254 IntPtr child_last = IntPtr.Zero;
5255 while (c != IntPtr.Zero) {
5257 XQueryPointer(display, c, out root, out c,
5258 out root_x, out root_y, out child_x, out child_y,
5261 XUngrabServer (display);
5267 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5268 if (handle == IntPtr.Zero) {
5271 int root_x, root_y, child_x, child_y, mask;
5274 * QueryPointer before warping
5275 * because if the warp is on
5276 * the RootWindow, the x/y are
5277 * relative to the current
5280 QueryPointer (DisplayHandle, RootWindow,
5283 out root_x, out root_y,
5284 out child_x, out child_y,
5287 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5289 XFlush (DisplayHandle);
5291 /* then we need to a
5292 * QueryPointer after warping
5293 * to manually generate a
5294 * motion event for the window
5297 QueryPointer (DisplayHandle, RootWindow,
5300 out root_x, out root_y,
5301 out child_x, out child_y,
5304 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5305 if (child_hwnd == null) {
5309 XEvent xevent = new XEvent ();
5311 xevent.type = XEventName.MotionNotify;
5312 xevent.MotionEvent.display = DisplayHandle;
5313 xevent.MotionEvent.window = child_hwnd.client_window;
5314 xevent.MotionEvent.root = RootWindow;
5315 xevent.MotionEvent.x = child_x;
5316 xevent.MotionEvent.y = child_y;
5317 xevent.MotionEvent.x_root = root_x;
5318 xevent.MotionEvent.y_root = root_y;
5319 xevent.MotionEvent.state = mask;
5321 child_hwnd.Queue.EnqueueLocked (xevent);
5326 hwnd = Hwnd.ObjectFromHandle(handle);
5328 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5333 internal override void SetFocus(IntPtr handle) {
5335 IntPtr prev_focus_window;
5337 hwnd = Hwnd.ObjectFromHandle(handle);
5339 if (hwnd.client_window == FocusWindow) {
5343 // Win32 doesn't do anything if disabled
5347 prev_focus_window = FocusWindow;
5348 FocusWindow = hwnd.client_window;
5350 if (prev_focus_window != IntPtr.Zero) {
5351 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5353 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5354 Keyboard.FocusIn (FocusWindow);
5356 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5359 internal override void SetIcon(IntPtr handle, Icon icon) {
5362 hwnd = Hwnd.ObjectFromHandle(handle);
5364 SetIcon(hwnd, icon);
5368 internal override void SetMenu(IntPtr handle, Menu menu) {
5371 hwnd = Hwnd.ObjectFromHandle(handle);
5374 RequestNCRecalc(handle);
5377 internal override void SetModal(IntPtr handle, bool Modal) {
5379 ModalWindows.Push(handle);
5381 if (ModalWindows.Contains(handle)) {
5384 if (ModalWindows.Count > 0) {
5385 Activate((IntPtr)ModalWindows.Peek());
5389 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5390 Control ctrl = Control.FromHandle (handle);
5391 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5394 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5397 hwnd = Hwnd.ObjectFromHandle(handle);
5398 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5401 #if DriverDebug || DriverDebugParent
5402 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5404 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5410 internal override void SetTimer (Timer timer) {
5411 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5413 if (queue == null) {
5414 // This isn't really an error, MS doesn't start the timer if
5415 // it has no assosciated queue at this stage (it will be
5416 // enabled when a window is activated).
5417 unattached_timer_list.Add (timer);
5420 queue.timer_list.Add (timer);
5424 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5426 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5431 SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_ADD, _NET_WM_STATE_ABOVE, IntPtr.Zero);
5433 int[] atoms = new int[8];
5434 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5435 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5441 SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_REMOVE, _NET_WM_STATE_ABOVE, IntPtr.Zero);
5443 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5449 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5453 hwnd = Hwnd.ObjectFromHandle(handle);
5455 if (handle_owner != IntPtr.Zero) {
5456 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5462 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5463 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5465 if (hwnd_owner != null) {
5466 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5468 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5473 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5479 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5483 hwnd = Hwnd.ObjectFromHandle(handle);
5484 hwnd.visible = visible;
5488 MapWindow(hwnd, WindowType.Both);
5490 if (Control.FromHandle(handle) is Form) {
5493 s = ((Form)Control.FromHandle(handle)).WindowState;
5496 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5497 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5501 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5504 UnmapWindow(hwnd, WindowType.Both);
5510 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5511 Control ctrl = Control.FromHandle (handle);
5512 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5515 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5521 hwnd = Hwnd.ObjectFromHandle(handle);
5526 min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
5527 min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
5529 hints = new XSizeHints();
5531 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5532 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5534 min = TranslateWindowSizeToXWindowSize (cp, min);
5535 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5536 hints.min_width = min.Width;
5537 hints.min_height = min.Height;
5540 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5542 max = TranslateWindowSizeToXWindowSize (cp, max);
5543 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5544 hints.max_width = max.Width;
5545 hints.max_height = max.Height;
5548 if (hints.flags != IntPtr.Zero) {
5549 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5550 // they will maximize the window to fill the screen/parent no matter what.
5551 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5552 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5555 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5557 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5558 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5559 hints.x = maximized.X;
5560 hints.y = maximized.Y;
5561 hints.width = maximized.Width;
5562 hints.height = maximized.Height;
5564 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5565 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5570 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5573 hwnd = Hwnd.ObjectFromHandle(handle);
5579 // Win32 automatically changes negative width/height to 0.
5585 // X requires a sanity check for width & height; otherwise it dies
5586 if (hwnd.zero_sized && width > 0 && height > 0) {
5588 MapWindow(hwnd, WindowType.Whole);
5590 hwnd.zero_sized = false;
5593 if ((width < 1) || (height < 1)) {
5594 hwnd.zero_sized = true;
5595 UnmapWindow(hwnd, WindowType.Whole);
5598 // Save a server roundtrip (and prevent a feedback loop)
5599 if ((hwnd.x == x) && (hwnd.y == y) &&
5600 (hwnd.width == width) && (hwnd.height == height)) {
5604 if (!hwnd.zero_sized) {
5609 hwnd.height = height;
5610 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5612 if (hwnd.fixed_size) {
5613 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5617 Control ctrl = Control.FromHandle (handle);
5618 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5619 MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5620 PerformNCCalc(hwnd);
5624 // Update our position/size immediately, so
5625 // that future calls to SetWindowPos aren't
5626 // kept from calling XMoveResizeWindow (by the
5627 // "Save a server roundtrip" block above).
5631 hwnd.height = height;
5632 hwnd.ClientRect = Rectangle.Empty;
5635 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5636 FormWindowState current_state;
5639 hwnd = Hwnd.ObjectFromHandle(handle);
5641 current_state = GetWindowState(handle);
5643 if (current_state == state) {
5648 case FormWindowState.Normal: {
5650 if (current_state == FormWindowState.Minimized) {
5651 MapWindow(hwnd, WindowType.Both);
5652 } else if (current_state == FormWindowState.Maximized) {
5653 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5660 case FormWindowState.Minimized: {
5662 if (current_state == FormWindowState.Maximized) {
5663 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5665 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5670 case FormWindowState.Maximized: {
5672 if (current_state == FormWindowState.Minimized) {
5673 MapWindow(hwnd, WindowType.Both);
5676 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5684 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5687 hwnd = Hwnd.ObjectFromHandle(handle);
5688 SetHwndStyles(hwnd, cp);
5689 SetWMStyles(hwnd, cp);
5692 internal override double GetWindowTransparency(IntPtr handle)
5697 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5701 hwnd = Hwnd.ObjectFromHandle(handle);
5707 hwnd.opacity = (uint)(0xffffffff * transparency);
5708 opacity = (IntPtr)((int)hwnd.opacity);
5710 IntPtr w = hwnd.whole_window;
5711 if (hwnd.reparented)
5712 w = XGetParent (hwnd.whole_window);
5713 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5716 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5717 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5725 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5728 } else if (!bottom) {
5729 Hwnd after_hwnd = null;
5731 if (after_handle != IntPtr.Zero) {
5732 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5735 XWindowChanges values = new XWindowChanges();
5737 if (after_hwnd == null) {
5738 // Work around metacity 'issues'
5742 atoms[0] = unixtime();
5743 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5745 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5746 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5748 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5751 values.sibling = after_hwnd.whole_window;
5752 values.stack_mode = StackMode.Below;
5755 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5760 XLowerWindow(DisplayHandle, hwnd.whole_window);
5767 internal override void ShowCursor(bool show) {
5768 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5771 internal override object StartLoop(Thread thread) {
5772 XEventQueue q = ThreadQueue(thread);
5776 internal override TransparencySupport SupportsTransparency() {
5777 // We need to check if the x compositing manager is running
5778 return TransparencySupport.Set;
5781 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5782 GetSystrayManagerWindow();
5784 if (SystrayMgrWindow != IntPtr.Zero) {
5785 XSizeHints size_hints;
5788 hwnd = Hwnd.ObjectFromHandle(handle);
5790 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5794 if (hwnd.client_window != hwnd.whole_window) {
5795 Keyboard.DestroyICForWindow (hwnd.client_window);
5796 XDestroyWindow(DisplayHandle, hwnd.client_window);
5797 hwnd.client_window = hwnd.whole_window;
5800 /* by virtue of the way the tests are ordered when determining if it's PAINT
5801 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5802 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5803 there's a pending expose). */
5804 if (hwnd.nc_expose_pending) {
5805 hwnd.nc_expose_pending = false;
5806 if (!hwnd.expose_pending)
5807 hwnd.Queue.Paint.Remove (hwnd);
5810 size_hints = new XSizeHints();
5812 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5814 size_hints.min_width = 24;
5815 size_hints.min_height = 24;
5816 size_hints.max_width = 24;
5817 size_hints.max_height = 24;
5818 size_hints.base_width = 24;
5819 size_hints.base_height = 24;
5821 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5823 int[] atoms = new int[2];
5824 atoms [0] = 1; // Version 1
5825 atoms [1] = 1; // we want to be mapped
5827 // This line cost me 3 days...
5828 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5830 // Need to pick some reasonable defaults
5832 tt.AutomaticDelay = 350;
5833 tt.InitialDelay = 250;
5834 tt.ReshowDelay = 250;
5835 tt.ShowAlways = true;
5837 if ((tip != null) && (tip != string.Empty)) {
5838 tt.SetToolTip(Control.FromHandle(handle), tip);
5844 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5852 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5855 control = Control.FromHandle(handle);
5856 if (control != null && tt != null) {
5857 tt.SetToolTip(control, tip);
5859 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5866 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5868 SetVisible (handle, false, false);
5870 // The caller can now re-dock it later...
5878 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5880 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5881 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5885 internal override bool Text(IntPtr handle, string text) {
5888 hwnd = Hwnd.ObjectFromHandle(handle);
5891 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5892 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5894 // XXX this has problems with UTF8.
5895 // we need to either use the actual
5896 // text if it's latin-1, or convert it
5897 // to compound text if it's in a
5898 // different charset.
5899 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5904 internal override bool TranslateMessage(ref MSG msg) {
5905 return Keyboard.TranslateMessage (ref msg);
5908 internal override void UpdateWindow(IntPtr handle) {
5911 hwnd = Hwnd.ObjectFromHandle(handle);
5913 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5917 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5918 hwnd.Queue.Paint.Remove(hwnd);
5921 internal override void CreateOffscreenDrawable (IntPtr handle,
5922 int width, int height,
5923 out object offscreen_drawable)
5926 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5928 XGetGeometry (DisplayHandle, handle,
5930 out x_out, out y_out,
5931 out width_out, out height_out,
5932 out border_width_out, out depth_out);
5934 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5936 offscreen_drawable = pixmap;
5940 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5942 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5945 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5947 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5950 internal override void BlitFromOffscreen (IntPtr dest_handle,
5952 object offscreen_drawable,
5953 Graphics offscreen_dc,
5956 XGCValues gc_values;
5959 gc_values = new XGCValues();
5961 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5963 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5964 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5966 XFreeGC (DisplayHandle, gc);
5969 #endregion // Public Static Methods
5972 internal override event EventHandler Idle;
5973 #endregion // Events
5975 #region Xcursor imports
5976 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5977 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5979 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5980 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5982 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5983 internal extern static void XcursorImagesDestroy (IntPtr images);
5985 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5986 internal extern static int XcursorGetDefaultSize (IntPtr display);
5988 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5989 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5991 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5992 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5995 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5996 internal extern static IntPtr XOpenDisplay(IntPtr display);
5997 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5998 internal extern static int XCloseDisplay(IntPtr display);
5999 [DllImport ("libX11", EntryPoint="XSynchronize")]
6000 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
6002 [DllImport ("libX11", EntryPoint="XCreateWindow")]
6003 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, UIntPtr valuemask, ref XSetWindowAttributes attributes);
6004 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
6005 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
6006 [DllImport ("libX11", EntryPoint="XMapWindow")]
6007 internal extern static int XMapWindow(IntPtr display, IntPtr window);
6008 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
6009 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
6010 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
6011 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
6012 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
6013 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
6014 [DllImport ("libX11", EntryPoint="XRootWindow")]
6015 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
6016 [DllImport ("libX11", EntryPoint="XNextEvent")]
6017 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
6018 [DllImport ("libX11")]
6019 internal extern static int XConnectionNumber (IntPtr diplay);
6020 [DllImport ("libX11")]
6021 internal extern static int XPending (IntPtr diplay);
6022 [DllImport ("libX11", EntryPoint="XSelectInput")]
6023 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
6025 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
6026 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
6028 [DllImport ("libX11", EntryPoint="XReparentWindow")]
6029 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
6030 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
6031 private extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
6033 internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
6035 int ret = XMoveResizeWindow (display, window, x, y, width, height);
6036 Keyboard.MoveCurrentCaretPos ();
6040 [DllImport ("libX11", EntryPoint="XResizeWindow")]
6041 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
6043 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
6044 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
6046 [DllImport ("libX11", EntryPoint="XFlush")]
6047 internal extern static int XFlush(IntPtr display);
6049 [DllImport ("libX11", EntryPoint="XSetWMName")]
6050 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
6052 [DllImport ("libX11", EntryPoint="XStoreName")]
6053 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
6055 [DllImport ("libX11", EntryPoint="XFetchName")]
6056 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
6058 [DllImport ("libX11", EntryPoint="XSendEvent")]
6059 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
6061 [DllImport ("libX11", EntryPoint="XQueryTree")]
6062 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);
6064 [DllImport ("libX11", EntryPoint="XFree")]
6065 internal extern static int XFree(IntPtr data);
6067 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
6068 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
6070 [DllImport ("libX11", EntryPoint="XLowerWindow")]
6071 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
6073 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
6074 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
6076 [DllImport ("libX11", EntryPoint="XInternAtom")]
6077 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
6079 [DllImport ("libX11", EntryPoint="XInternAtoms")]
6080 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
6082 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
6083 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
6085 [DllImport ("libX11", EntryPoint="XGrabPointer")]
6086 internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
6088 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
6089 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
6091 [DllImport ("libX11", EntryPoint="XQueryPointer")]
6092 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);
6094 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
6095 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);
6097 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6098 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);
6100 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6101 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);
6103 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6104 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);
6106 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6107 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);
6109 [DllImport ("libX11", EntryPoint="XWarpPointer")]
6110 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);
6112 [DllImport ("libX11", EntryPoint="XClearWindow")]
6113 internal extern static int XClearWindow(IntPtr display, IntPtr window);
6115 [DllImport ("libX11", EntryPoint="XClearArea")]
6116 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
6119 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
6120 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
6122 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
6123 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
6125 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
6126 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
6128 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
6129 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
6131 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
6132 internal extern static int XDefaultScreen(IntPtr display);
6134 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
6135 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
6137 [DllImport ("libX11", EntryPoint="XLookupColor")]
6138 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
6140 [DllImport ("libX11", EntryPoint="XAllocColor")]
6141 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
6143 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
6144 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
6146 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6147 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
6149 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6150 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
6152 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6153 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
6155 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6156 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
6158 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6159 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
6161 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6162 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
6164 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6165 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
6167 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
6168 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
6170 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
6171 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
6174 [DllImport ("libX11", EntryPoint="XCreateGC")]
6175 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
6177 [DllImport ("libX11", EntryPoint="XFreeGC")]
6178 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
6180 [DllImport ("libX11", EntryPoint="XSetFunction")]
6181 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
6183 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
6184 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
6186 [DllImport ("libX11", EntryPoint="XDrawLine")]
6187 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
6189 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
6190 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6192 [DllImport ("libX11", EntryPoint="XFillRectangle")]
6193 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6195 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
6196 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
6198 [DllImport ("libX11", EntryPoint="XCopyArea")]
6199 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);
6201 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
6202 internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
6204 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
6205 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
6207 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
6208 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
6210 [DllImport ("libX11", EntryPoint="XDefineCursor")]
6211 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
6213 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
6214 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
6216 [DllImport ("libX11", EntryPoint="XFreeCursor")]
6217 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
6219 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
6220 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
6222 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
6223 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);
6225 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
6226 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
6228 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
6229 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
6231 [DllImport ("libX11", EntryPoint="XFreePixmap")]
6232 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
6234 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
6235 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
6237 [DllImport ("libX11", EntryPoint="XQueryExtension")]
6238 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
6240 [DllImport ("libX11", EntryPoint="XWhitePixel")]
6241 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
6243 [DllImport ("libX11", EntryPoint="XBlackPixel")]
6244 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
6246 [DllImport ("libX11", EntryPoint="XGrabServer")]
6247 internal extern static void XGrabServer(IntPtr display);
6249 [DllImport ("libX11", EntryPoint="XUngrabServer")]
6250 internal extern static void XUngrabServer(IntPtr display);
6252 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
6253 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
6255 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
6256 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6258 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
6259 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6261 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6262 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6264 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6265 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6267 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6268 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6270 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6271 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6273 [DllImport ("libX11", EntryPoint="XInitThreads")]
6274 internal extern static int XInitThreads();
6276 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6277 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6279 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6280 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6282 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6283 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6285 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6286 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6288 [DllImport ("libX11", EntryPoint="XSetForeground")]
6289 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6291 [DllImport ("libX11", EntryPoint="XSetBackground")]
6292 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6294 [DllImport ("libX11", EntryPoint="XBell")]
6295 internal extern static int XBell(IntPtr display, int percent);
6297 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6298 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6300 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6301 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6303 [DllImport ("libX11")]
6304 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6306 [DllImport ("libX11")]
6307 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
6309 [DllImport ("libX11")]
6310 internal extern static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);