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
92 private static IntPtr ClipMagic;
93 private static ClipboardStruct Clipboard; // Our clipboard
96 private static IntPtr PostAtom; // PostMessage atom
97 private static IntPtr AsyncAtom; // Support for async messages
100 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
102 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static bool wake_waiting;
104 private static object wake_waiting_lock = new object ();
106 private static X11Keyboard Keyboard; //
107 private static X11Dnd Dnd;
108 private static Socket listen; //
109 private static Socket wake; //
110 private static Socket wake_receive; //
111 private static byte[] network_buffer; //
112 private static bool detectable_key_auto_repeat;
115 private static IntPtr ActiveWindow; // Handle of the active window
116 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
119 private static Stack ModalWindows; // Stack of our modal windows
122 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
125 private static IntPtr LastCursorWindow; // The last window we set the cursor on
126 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
127 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
130 private static CaretStruct Caret; //
133 private static IntPtr WM_PROTOCOLS;
134 private static IntPtr WM_DELETE_WINDOW;
135 private static IntPtr WM_TAKE_FOCUS;
136 //private static IntPtr _NET_SUPPORTED;
137 //private static IntPtr _NET_CLIENT_LIST;
138 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
139 private static IntPtr _NET_DESKTOP_GEOMETRY;
140 //private static IntPtr _NET_DESKTOP_VIEWPORT;
141 private static IntPtr _NET_CURRENT_DESKTOP;
142 //private static IntPtr _NET_DESKTOP_NAMES;
143 private static IntPtr _NET_ACTIVE_WINDOW;
144 private static IntPtr _NET_WORKAREA;
145 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
146 //private static IntPtr _NET_VIRTUAL_ROOTS;
147 //private static IntPtr _NET_DESKTOP_LAYOUT;
148 //private static IntPtr _NET_SHOWING_DESKTOP;
149 //private static IntPtr _NET_CLOSE_WINDOW;
150 //private static IntPtr _NET_MOVERESIZE_WINDOW;
151 //private static IntPtr _NET_WM_MOVERESIZE;
152 //private static IntPtr _NET_RESTACK_WINDOW;
153 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
154 private static IntPtr _NET_WM_NAME;
155 //private static IntPtr _NET_WM_VISIBLE_NAME;
156 //private static IntPtr _NET_WM_ICON_NAME;
157 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
158 //private static IntPtr _NET_WM_DESKTOP;
159 private static IntPtr _NET_WM_WINDOW_TYPE;
160 private static IntPtr _NET_WM_STATE;
161 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
162 //private static IntPtr _NET_WM_STRUT;
163 //private static IntPtr _NET_WM_STRUT_PARTIAL;
164 //private static IntPtr _NET_WM_ICON_GEOMETRY;
165 private static IntPtr _NET_WM_ICON;
166 //private static IntPtr _NET_WM_PID;
167 //private static IntPtr _NET_WM_HANDLED_ICONS;
168 private static IntPtr _NET_WM_USER_TIME;
169 private static IntPtr _NET_FRAME_EXTENTS;
170 //private static IntPtr _NET_WM_PING;
171 //private static IntPtr _NET_WM_SYNC_REQUEST;
172 private static IntPtr _NET_SYSTEM_TRAY_S;
173 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
174 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
175 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
176 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
177 private static IntPtr _XEMBED;
178 private static IntPtr _XEMBED_INFO;
179 private static IntPtr _MOTIF_WM_HINTS;
180 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
181 private static IntPtr _NET_WM_STATE_ABOVE;
182 //private static IntPtr _NET_WM_STATE_MODAL;
183 private static IntPtr _NET_WM_STATE_HIDDEN;
184 private static IntPtr _NET_WM_CONTEXT_HELP;
185 private static IntPtr _NET_WM_WINDOW_OPACITY;
186 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
187 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
188 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
189 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
190 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
193 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
194 private static IntPtr CLIPBOARD;
195 private static IntPtr PRIMARY;
196 //private static IntPtr DIB;
197 private static IntPtr OEMTEXT;
198 private static IntPtr UNICODETEXT;
199 private static IntPtr TARGETS;
201 // mouse hover message generation
202 private static HoverStruct HoverState; //
204 // double click message generation
205 private static ClickStruct ClickPending; //
207 // Support for mouse grab
208 private static GrabStruct Grab; //
211 Point mouse_position; // Last position of mouse, in screen coords
212 internal static MouseButtons MouseState; // Last state of mouse buttons
215 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
217 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
218 EventMask.ButtonReleaseMask |
219 EventMask.KeyPressMask |
220 EventMask.KeyReleaseMask |
221 EventMask.EnterWindowMask |
222 EventMask.LeaveWindowMask |
223 EventMask.ExposureMask |
224 EventMask.FocusChangeMask |
225 EventMask.PointerMotionMask |
226 EventMask.SubstructureNotifyMask);
228 static readonly object lockobj = new object ();
230 #endregion // Local Variables
232 private XplatUIX11() {
233 // Handle singleton stuff first
236 // Now regular initialization
237 XlibLock = new object ();
238 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
241 ErrorExceptions = false;
243 // X11 Initialization
244 SetDisplay(XOpenDisplay(IntPtr.Zero));
245 X11DesktopColors.Initialize();
248 // Disable keyboard autorepeat
250 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
251 detectable_key_auto_repeat = true;
253 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
254 detectable_key_auto_repeat = false;
257 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
258 ErrorHandler = new XErrorHandler(HandleError);
259 XSetErrorHandler(ErrorHandler);
263 // Remove our display handle from S.D
264 Graphics.FromHdcInternal (IntPtr.Zero);
267 #endregion // Constructors
269 #region Singleton Specific Code
270 public static XplatUIX11 GetInstance() {
272 if (Instance == null) {
273 Instance=new XplatUIX11();
280 public int Reference {
287 #region Internal Properties
288 internal static IntPtr Display {
290 return DisplayHandle;
294 XplatUIX11.GetInstance().SetDisplay(value);
298 internal static int Screen {
308 internal static IntPtr RootWindowHandle {
318 internal static IntPtr Visual {
324 CustomVisual = value;
328 internal static IntPtr ColorMap {
330 return CustomColormap;
334 CustomColormap = value;
339 #region XExceptionClass
340 internal class XException : ApplicationException {
344 XRequest RequestCode;
348 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
349 this.Display = Display;
350 this.ResourceID = ResourceID;
351 this.Serial = Serial;
352 this.RequestCode = RequestCode;
353 this.ErrorCode = ErrorCode;
354 this.MinorCode = MinorCode;
357 public override string Message {
359 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
363 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
372 sb = new StringBuilder(160);
373 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
374 x_error_text = sb.ToString();
375 hwnd = Hwnd.ObjectFromHandle(ResourceID);
377 hwnd_text = hwnd.ToString();
378 c = Control.FromHandle(hwnd.Handle);
380 control_text = c.ToString();
382 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
385 hwnd_text = "<null>";
386 control_text = "<null>";
390 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, RequestCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
394 #endregion // XExceptionClass
396 #region Internal Methods
397 internal void SetDisplay(IntPtr display_handle) {
398 if (display_handle != IntPtr.Zero) {
401 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
402 hwnd = Hwnd.ObjectFromHandle(FosterParent);
403 XDestroyWindow(DisplayHandle, FosterParent);
407 if (DisplayHandle != IntPtr.Zero) {
408 XCloseDisplay(DisplayHandle);
411 DisplayHandle=display_handle;
413 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
414 // been hacked to do this for us.
415 Graphics.FromHdcInternal (DisplayHandle);
418 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
419 XSynchronize(DisplayHandle, true);
422 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
423 ErrorExceptions = true;
427 ScreenNo = XDefaultScreen(DisplayHandle);
428 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
429 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
431 // Create the foster parent
432 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
433 if (FosterParent==IntPtr.Zero) {
434 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
438 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
439 hwnd.WholeWindow = FosterParent;
440 hwnd.ClientWindow = FosterParent;
442 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
444 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
445 hwnd.whole_window = RootWindow;
446 hwnd.ClientWindow = RootWindow;
448 // For sleeping on the X11 socket
449 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
450 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
454 // To wake up when a timer is ready
455 network_buffer = new byte[10];
457 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
458 wake.Connect(listen.LocalEndPoint);
459 wake_receive = listen.Accept();
462 pollfds = new Pollfd [2];
463 pollfds [0] = new Pollfd ();
464 pollfds [0].fd = XConnectionNumber (DisplayHandle);
465 pollfds [0].events = PollEvents.POLLIN;
467 pollfds [1] = new Pollfd ();
468 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
469 pollfds [1].events = PollEvents.POLLIN;
472 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
473 Dnd = new X11Dnd (DisplayHandle, Keyboard);
475 DoubleClickInterval = 500;
477 HoverState.Interval = 500;
478 HoverState.Timer = new Timer();
479 HoverState.Timer.Enabled = false;
480 HoverState.Timer.Interval = HoverState.Interval;
481 HoverState.Timer.Tick += new EventHandler(MouseHover);
482 HoverState.Size = new Size(4, 4);
486 ActiveWindow = IntPtr.Zero;
487 FocusWindow = IntPtr.Zero;
488 ModalWindows = new Stack(3);
490 MouseState = MouseButtons.None;
491 mouse_position = new Point(0, 0);
493 Caret.Timer = new Timer();
494 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
495 Caret.Timer.Tick += new EventHandler(CaretCallback);
499 // Grab atom changes off the root window to catch certain WM events
500 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
502 // Handle any upcoming errors
503 ErrorHandler = new XErrorHandler(HandleError);
504 XSetErrorHandler(ErrorHandler);
506 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
509 #endregion // Internal Methods
511 #region Private Methods
512 private int unixtime() {
513 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
515 return (int) t.TotalSeconds;
518 private static void SetupAtoms() {
519 // make sure this array stays in sync with the statements below
520 string [] atom_names = new string[] {
525 //"_NET_CLIENT_LIST",
526 //"_NET_NUMBER_OF_DESKTOPS",
527 "_NET_DESKTOP_GEOMETRY",
528 //"_NET_DESKTOP_VIEWPORT",
529 "_NET_CURRENT_DESKTOP",
530 //"_NET_DESKTOP_NAMES",
531 "_NET_ACTIVE_WINDOW",
533 //"_NET_SUPPORTING_WM_CHECK",
534 //"_NET_VIRTUAL_ROOTS",
535 //"_NET_DESKTOP_LAYOUT",
536 //"_NET_SHOWING_DESKTOP",
537 //"_NET_CLOSE_WINDOW",
538 //"_NET_MOVERESIZE_WINDOW",
539 //"_NET_WM_MOVERESIZE",
540 //"_NET_RESTACK_WINDOW",
541 //"_NET_REQUEST_FRAME_EXTENTS",
543 //"_NET_WM_VISIBLE_NAME",
544 //"_NET_WM_ICON_NAME",
545 //"_NET_WM_VISIBLE_ICON_NAME",
547 "_NET_WM_WINDOW_TYPE",
549 //"_NET_WM_ALLOWED_ACTIONS",
551 //"_NET_WM_STRUT_PARTIAL",
552 //"_NET_WM_ICON_GEOMETRY",
555 //"_NET_WM_HANDLED_ICONS",
557 "_NET_FRAME_EXTENTS",
559 //"_NET_WM_SYNC_REQUEST",
560 "_NET_SYSTEM_TRAY_OPCODE",
561 //"_NET_SYSTEM_TRAY_ORIENTATION",
562 "_NET_WM_STATE_MAXIMIZED_HORZ",
563 "_NET_WM_STATE_MAXIMIZED_VERT",
564 "_NET_WM_STATE_HIDDEN",
568 "_NET_WM_STATE_SKIP_TASKBAR",
569 "_NET_WM_STATE_ABOVE",
570 //"_NET_WM_STATE_MODAL",
571 "_NET_WM_CONTEXT_HELP",
572 "_NET_WM_WINDOW_OPACITY",
573 //"_NET_WM_WINDOW_TYPE_DESKTOP",
574 //"_NET_WM_WINDOW_TYPE_DOCK",
575 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
576 //"_NET_WM_WINDOW_TYPE_MENU",
577 "_NET_WM_WINDOW_TYPE_UTILITY",
578 //"_NET_WM_WINDOW_TYPE_DIALOG",
579 //"_NET_WM_WINDOW_TYPE_SPLASH",
580 "_NET_WM_WINDOW_TYPE_NORMAL",
587 "_SWF_PostMessageAtom",
590 IntPtr[] atoms = new IntPtr [atom_names.Length];;
592 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
595 WM_PROTOCOLS = atoms [off++];
596 WM_DELETE_WINDOW = atoms [off++];
597 WM_TAKE_FOCUS = atoms [off++];
598 //_NET_SUPPORTED = atoms [off++];
599 //_NET_CLIENT_LIST = atoms [off++];
600 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
601 _NET_DESKTOP_GEOMETRY = atoms [off++];
602 //_NET_DESKTOP_VIEWPORT = atoms [off++];
603 _NET_CURRENT_DESKTOP = atoms [off++];
604 //_NET_DESKTOP_NAMES = atoms [off++];
605 _NET_ACTIVE_WINDOW = atoms [off++];
606 _NET_WORKAREA = atoms [off++];
607 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
608 //_NET_VIRTUAL_ROOTS = atoms [off++];
609 //_NET_DESKTOP_LAYOUT = atoms [off++];
610 //_NET_SHOWING_DESKTOP = atoms [off++];
611 //_NET_CLOSE_WINDOW = atoms [off++];
612 //_NET_MOVERESIZE_WINDOW = atoms [off++];
613 //_NET_WM_MOVERESIZE = atoms [off++];
614 //_NET_RESTACK_WINDOW = atoms [off++];
615 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
616 _NET_WM_NAME = atoms [off++];
617 //_NET_WM_VISIBLE_NAME = atoms [off++];
618 //_NET_WM_ICON_NAME = atoms [off++];
619 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
620 //_NET_WM_DESKTOP = atoms [off++];
621 _NET_WM_WINDOW_TYPE = atoms [off++];
622 _NET_WM_STATE = atoms [off++];
623 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
624 //_NET_WM_STRUT = atoms [off++];
625 //_NET_WM_STRUT_PARTIAL = atoms [off++];
626 //_NET_WM_ICON_GEOMETRY = atoms [off++];
627 _NET_WM_ICON = atoms [off++];
628 //_NET_WM_PID = atoms [off++];
629 //_NET_WM_HANDLED_ICONS = atoms [off++];
630 _NET_WM_USER_TIME = atoms [off++];
631 _NET_FRAME_EXTENTS = atoms [off++];
632 //_NET_WM_PING = atoms [off++];
633 //_NET_WM_SYNC_REQUEST = atoms [off++];
634 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
635 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
636 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
637 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
638 _NET_WM_STATE_HIDDEN = atoms [off++];
639 _XEMBED = atoms [off++];
640 _XEMBED_INFO = atoms [off++];
641 _MOTIF_WM_HINTS = atoms [off++];
642 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
643 _NET_WM_STATE_ABOVE = atoms [off++];
644 //_NET_WM_STATE_MODAL = atoms [off++];
645 _NET_WM_CONTEXT_HELP = atoms [off++];
646 _NET_WM_WINDOW_OPACITY = atoms [off++];
647 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
648 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
649 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
650 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
651 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
652 //_NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
653 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
654 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
655 CLIPBOARD = atoms [off++];
656 PRIMARY = atoms [off++];
657 OEMTEXT = atoms [off++];
658 UNICODETEXT = atoms [off++];
659 TARGETS = atoms [off++];
660 AsyncAtom = atoms [off++];
661 PostAtom = atoms [off++];
662 HoverState.Atom = atoms [off++];
664 //DIB = (IntPtr)Atom.XA_PIXMAP;
665 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
668 private void GetSystrayManagerWindow() {
669 XGrabServer(DisplayHandle);
670 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
671 XUngrabServer(DisplayHandle);
672 XFlush(DisplayHandle);
675 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
679 xev.ClientMessageEvent.type = XEventName.ClientMessage;
680 xev.ClientMessageEvent.send_event = true;
681 xev.ClientMessageEvent.window = window;
682 xev.ClientMessageEvent.message_type = message_type;
683 xev.ClientMessageEvent.format = 32;
684 xev.ClientMessageEvent.ptr1 = l0;
685 xev.ClientMessageEvent.ptr2 = l1;
686 xev.ClientMessageEvent.ptr3 = l2;
687 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
690 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
694 xev.ClientMessageEvent.type = XEventName.ClientMessage;
695 xev.ClientMessageEvent.send_event = true;
696 xev.ClientMessageEvent.window = window;
697 xev.ClientMessageEvent.message_type = message_type;
698 xev.ClientMessageEvent.format = 32;
699 xev.ClientMessageEvent.ptr1 = l0;
700 xev.ClientMessageEvent.ptr2 = l1;
701 xev.ClientMessageEvent.ptr3 = l2;
702 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
705 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
706 // WM_CREATE and WM_DESTROY causes
707 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
711 if (child == IntPtr.Zero) {
715 hwnd = Hwnd.GetObjectFromWindow (child);
721 if (hwnd.Handle == IntPtr.Zero) {
725 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
729 if (hwnd.Parent == null) {
733 if (hwnd.Parent.Handle == IntPtr.Zero) {
737 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
738 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
740 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
743 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
746 bool StyleSet (int s, WindowStyles ws)
748 return (s & (int)ws) == (int)ws;
751 bool ExStyleSet (int ex, WindowExStyles exws)
753 return (ex & (int)exws) == (int)exws;
756 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) {
759 tool_caption_height = 19;
760 border_static = false;
762 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
763 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
764 border_style = FormBorderStyle.Fixed3D;
765 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
766 border_style = FormBorderStyle.Fixed3D;
767 border_static = true;
768 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
769 border_style = FormBorderStyle.None;
771 border_style = FormBorderStyle.FixedSingle;
773 title_style = TitleStyle.None;
775 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
777 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
778 title_style = TitleStyle.Tool;
780 title_style = TitleStyle.Normal;
784 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
787 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
788 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
789 border_style = (FormBorderStyle) 0xFFFF;
791 border_style = FormBorderStyle.None;
796 title_style = TitleStyle.None;
797 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
798 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
799 title_style = TitleStyle.Tool;
801 title_style = TitleStyle.Normal;
805 border_style = FormBorderStyle.None;
807 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
808 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
809 border_style = FormBorderStyle.SizableToolWindow;
811 border_style = FormBorderStyle.Sizable;
814 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
815 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
816 border_style = FormBorderStyle.Fixed3D;
817 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
818 border_style = FormBorderStyle.Fixed3D;
819 border_static = true;
820 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
821 border_style = FormBorderStyle.FixedDialog;
822 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
823 border_style = FormBorderStyle.FixedToolWindow;
824 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
825 border_style = FormBorderStyle.FixedSingle;
828 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
829 border_style = FormBorderStyle.FixedSingle;
836 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
837 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);
840 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
841 MotifWmHints mwmHints;
842 MotifFunctions functions;
843 MotifDecorations decorations;
846 Rectangle client_rect;
848 // Windows we manage ourselves don't need WM window styles.
849 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
854 mwmHints = new MotifWmHints();
858 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
859 mwmHints.functions = (IntPtr)0;
860 mwmHints.decorations = (IntPtr)0;
862 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
863 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
864 /* tool windows get no window manager
865 decorations, and neither do windows
866 which lack CAPTION/BORDER/DLGFRAME
870 /* just because the window doesn't get any decorations doesn't
871 mean we should disable the functions. for instance, without
872 MotifFunctions.Maximize, changing the windowstate to Maximized
873 is ignored by metacity. */
874 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
877 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
878 functions |= MotifFunctions.Move;
879 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
882 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
883 functions |= MotifFunctions.Move | MotifFunctions.Resize;
884 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
887 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
888 functions |= MotifFunctions.Minimize;
889 decorations |= MotifDecorations.Minimize;
892 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
893 functions |= MotifFunctions.Maximize;
894 decorations |= MotifDecorations.Maximize;
897 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
898 functions |= MotifFunctions.Resize;
899 decorations |= MotifDecorations.ResizeH;
902 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
903 decorations |= MotifDecorations.Border;
906 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
907 decorations |= MotifDecorations.Border;
910 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
911 decorations |= MotifDecorations.Border;
914 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
915 functions |= MotifFunctions.Close;
918 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
919 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
920 if (cp.Caption == "") {
921 functions &= ~MotifFunctions.Move;
922 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
927 if ((functions & MotifFunctions.Resize) == 0) {
928 hwnd.fixed_size = true;
929 XplatUI.SetWindowMinMax(hwnd.Handle, new Rectangle(cp.X, cp.Y, cp.Width, cp.Height), new Size(cp.Width, cp.Height), new Size(cp.Width, cp.Height));
931 hwnd.fixed_size = false;
934 mwmHints.functions = (IntPtr)functions;
935 mwmHints.decorations = (IntPtr)decorations;
937 FormWindowState current_state = GetWindowState (hwnd.Handle);
938 if (current_state == (FormWindowState)(-1))
939 current_state = FormWindowState.Normal;
941 client_rect = hwnd.ClientRect;
945 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
946 // and get those windows in front of their parents
947 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
948 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
949 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
950 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
952 Form f = Control.FromHandle(hwnd.Handle) as Form;
953 if (f != null && !hwnd.reparented) {
954 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
955 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
956 if (owner_hwnd != null)
957 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
958 owner_hwnd.whole_window);
963 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
964 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
965 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
966 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
968 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
969 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
970 /* this line keeps the window from showing up in gnome's taskbar */
971 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
973 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
974 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
976 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
979 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
980 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
982 /* we need to add these atoms in the
983 * event we're maximized, since we're
984 * replacing the existing
985 * _NET_WM_STATE here. If we don't
986 * add them, future calls to
987 * GetWindowState will return Normal
988 * for a window which is maximized. */
989 if (current_state == FormWindowState.Maximized) {
990 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
991 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
993 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
996 IntPtr[] atom_ptrs = new IntPtr[2];
997 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
998 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
999 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1002 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1006 private void SetIcon(Hwnd hwnd, Icon icon)
1011 // This really needs to do whatever it
1012 // takes to remove the window manager
1013 // menu, not just delete the ICON
1014 // property. This will cause metacity
1015 // to use the "no icon set" icon, and
1016 // we'll still have an icon.
1017 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1025 bitmap = icon.ToBitmap();
1027 size = bitmap.Width * bitmap.Height + 2;
1028 data = new IntPtr[size];
1030 data[index++] = (IntPtr)bitmap.Width;
1031 data[index++] = (IntPtr)bitmap.Height;
1033 for (int y = 0; y < bitmap.Height; y++) {
1034 for (int x = 0; x < bitmap.Width; x++) {
1035 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1039 XChangeProperty (DisplayHandle, hwnd.whole_window,
1040 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1041 PropertyMode.Replace, data, size);
1045 private void WakeupMain () {
1046 wake.Send (new byte [] { 0xFF });
1049 private XEventQueue ThreadQueue(Thread thread) {
1052 queue = (XEventQueue)MessageQueues[thread];
1053 if (queue == null) {
1054 queue = new XEventQueue(thread);
1055 MessageQueues[thread] = queue;
1061 private void TranslatePropertyToClipboard(IntPtr property) {
1066 IntPtr prop = IntPtr.Zero;
1068 Clipboard.Item = null;
1070 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);
1072 if ((long)nitems > 0) {
1073 if (property == (IntPtr)Atom.XA_STRING) {
1074 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1075 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1076 // FIXME - convert bitmap to image
1077 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1078 // FIXME - convert pixmap to image
1079 } else if (property == OEMTEXT) {
1080 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1081 } else if (property == UNICODETEXT) {
1082 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1089 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1091 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1095 // Keep the invalid area as small as needed
1096 if ((x + width) > hwnd.width) {
1097 width = hwnd.width - x;
1100 if ((y + height) > hwnd.height) {
1101 height = hwnd.height - y;
1105 hwnd.AddInvalidArea(x, y, width, height);
1106 if (!hwnd.expose_pending) {
1107 if (!hwnd.nc_expose_pending) {
1108 hwnd.Queue.Paint.Enqueue(hwnd);
1110 hwnd.expose_pending = true;
1113 hwnd.AddNcInvalidArea (x, y, width, height);
1115 if (!hwnd.nc_expose_pending) {
1116 if (!hwnd.expose_pending) {
1117 hwnd.Queue.Paint.Enqueue(hwnd);
1119 hwnd.nc_expose_pending = true;
1124 private void FrameExtents(IntPtr window, out int left, out int top) {
1129 IntPtr prop = IntPtr.Zero;
1131 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);
1132 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1133 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1134 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1135 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1136 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1142 if (prop != IntPtr.Zero) {
1148 private void AddConfigureNotify (XEvent xevent) {
1151 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1158 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1159 if (!hwnd.reparented) {
1160 hwnd.x = xevent.ConfigureEvent.x;
1161 hwnd.y = xevent.ConfigureEvent.y;
1163 // This sucks ass, part 1
1164 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1165 // no standard way of getting our adjustment.
1166 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1167 // Several other WMs do their decorations different yet again and we fail to deal
1168 // with that, since I couldn't find any frigging commonality between them.
1169 // The only sane WM seems to be KDE
1171 if (!xevent.ConfigureEvent.send_event) {
1174 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1176 // This is a synthetic event, coordinates are in root space
1177 hwnd.x = xevent.ConfigureEvent.x;
1178 hwnd.y = xevent.ConfigureEvent.y;
1179 if (hwnd.whacky_wm) {
1183 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1184 hwnd.x -= frame_left;
1185 hwnd.y -= frame_top;
1190 // XXX this sucks. this isn't thread safe
1191 hwnd.width = xevent.ConfigureEvent.width;
1192 hwnd.height = xevent.ConfigureEvent.height;
1193 hwnd.ClientRect = Rectangle.Empty;
1195 lock (hwnd.configure_lock) {
1196 if (!hwnd.configure_pending) {
1197 hwnd.Queue.EnqueueLocked (xevent);
1198 hwnd.configure_pending = true;
1202 // We drop configure events for Client windows
1205 private void ShowCaret() {
1206 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1212 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1216 private void HideCaret() {
1217 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1223 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1227 private int NextTimeout (ArrayList timers, DateTime now) {
1228 int timeout = Int32.MaxValue;
1230 foreach (Timer timer in timers) {
1231 int next = (int) (timer.Expires - now).TotalMilliseconds;
1233 return 0; // Have a timer that has already expired
1236 if (next < timeout) {
1240 if (timeout < Timer.Minimum) {
1241 timeout = Timer.Minimum;
1249 private void CheckTimers (ArrayList timers, DateTime now) {
1252 count = timers.Count;
1257 for (int i = 0; i < timers.Count; i++) {
1260 timer = (Timer) timers [i];
1262 if (timer.Enabled && timer.Expires <= now) {
1269 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1270 MSG msg = new MSG ();
1273 queue = ThreadQueue(Thread.CurrentThread);
1275 queue.DispatchIdle = false;
1279 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1280 if ((Msg)msg.message == Msg.WM_QUIT) {
1281 PostQuitMessage (0);
1285 if (msg.hwnd == hwnd.Handle) {
1286 if ((Msg)msg.message == message)
1288 else if ((Msg)msg.message == Msg.WM_DESTROY)
1292 TranslateMessage (ref msg);
1293 DispatchMessage (ref msg);
1298 queue.DispatchIdle = true;
1302 private void MapWindow(Hwnd hwnd, WindowType windows) {
1304 if (Control.FromHandle(hwnd.Handle) is Form)
1305 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1307 // it's possible that our Hwnd is no
1308 // longer valid after making that
1309 // SendMessage call, so check here.
1313 bool need_to_wait = false;
1315 if ((windows & WindowType.Whole) != 0) {
1316 XMapWindow(DisplayHandle, hwnd.whole_window);
1318 if ((windows & WindowType.Client) != 0) {
1319 XMapWindow(DisplayHandle, hwnd.client_window);
1321 need_to_wait = true;
1326 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1327 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1331 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1333 if (Control.FromHandle(hwnd.Handle) is Form)
1334 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1336 // it's possible that our Hwnd is no
1337 // longer valid after making that
1338 // SendMessage call, so check here.
1342 bool need_to_wait = false;
1344 if ((windows & WindowType.Client) != 0) {
1345 XUnmapWindow(DisplayHandle, hwnd.client_window);
1347 need_to_wait = true;
1349 if ((windows & WindowType.Whole) != 0) {
1350 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1353 hwnd.mapped = false;
1355 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1356 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1360 private void UpdateMessageQueue (XEventQueue queue) {
1365 now = DateTime.UtcNow;
1368 pending = XPending (DisplayHandle);
1372 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1373 Idle (this, EventArgs.Empty);
1377 pending = XPending (DisplayHandle);
1384 if (queue != null) {
1385 if (queue.Paint.Count > 0)
1388 timeout = NextTimeout (queue.timer_list, now);
1393 int length = pollfds.Length - 1;
1394 lock (wake_waiting_lock) {
1395 if (wake_waiting == false) {
1397 wake_waiting = true;
1401 Syscall.poll (pollfds, (uint)length, timeout);
1402 // Clean out buffer, so we're not busy-looping on the same data
1403 if (length == pollfds.Length) {
1404 if (pollfds[1].revents != 0)
1405 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1406 lock (wake_waiting_lock) {
1407 wake_waiting = false;
1412 pending = XPending (DisplayHandle);
1418 CheckTimers (queue.timer_list, now);
1421 XEvent xevent = new XEvent ();
1424 if (XPending (DisplayHandle) == 0)
1427 XNextEvent (DisplayHandle, ref xevent);
1429 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1430 if (XFilterEvent(ref xevent, FosterParent)) {
1436 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1440 switch (xevent.type) {
1441 case XEventName.Expose:
1442 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1445 case XEventName.SelectionClear: {
1446 // Should we do something?
1450 case XEventName.SelectionRequest: {
1451 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1455 sel_event = new XEvent();
1456 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1457 sel_event.SelectionEvent.send_event = true;
1458 sel_event.SelectionEvent.display = DisplayHandle;
1459 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1460 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1461 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1462 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1463 sel_event.SelectionEvent.property = IntPtr.Zero;
1465 // Seems that some apps support asking for supported types
1466 if (xevent.SelectionEvent.target == TARGETS) {
1473 if (Clipboard.Item is String) {
1474 atoms[atom_count++] = (int)Atom.XA_STRING;
1475 atoms[atom_count++] = (int)OEMTEXT;
1476 atoms[atom_count++] = (int)UNICODETEXT;
1477 } else if (Clipboard.Item is Image) {
1478 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1479 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1481 // FIXME - handle other types
1484 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1485 } else if (Clipboard.Item is string) {
1491 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1494 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1495 buffer = Marshal.AllocHGlobal(bytes.Length);
1496 buflen = bytes.Length;
1498 for (int i = 0; i < buflen; i++) {
1499 Marshal.WriteByte(buffer, i, bytes[i]);
1501 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1502 // FIXME - this should encode into ISO2022
1503 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1504 while (Marshal.ReadByte(buffer, buflen) != 0) {
1507 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1508 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1509 while (Marshal.ReadByte(buffer, buflen) != 0) {
1513 buffer = IntPtr.Zero;
1516 if (buffer != IntPtr.Zero) {
1517 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1518 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1519 Marshal.FreeHGlobal(buffer);
1521 } else if (Clipboard.Item is Image) {
1522 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1523 // FIXME - convert image and store as property
1524 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1525 // FIXME - convert image and store as property
1529 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1533 case XEventName.SelectionNotify: {
1534 if (Clipboard.Enumerating) {
1535 Clipboard.Enumerating = false;
1536 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1537 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1538 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1539 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1540 #if DriverDebugExtra
1541 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1545 } else if (Clipboard.Retrieving) {
1546 Clipboard.Retrieving = false;
1547 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1548 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1550 Clipboard.Item = null;
1553 Dnd.HandleSelectionNotifyEvent (ref xevent);
1558 case XEventName.KeyRelease:
1559 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1560 XEvent nextevent = new XEvent ();
1562 XPeekEvent (DisplayHandle, ref nextevent);
1564 if (nextevent.type == XEventName.KeyPress &&
1565 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1566 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1570 goto case XEventName.KeyPress;
1572 case XEventName.MotionNotify: {
1575 /* we can't do motion compression across threads, so just punt if we don't match up */
1576 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1577 peek = hwnd.Queue.Peek();
1578 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1582 goto case XEventName.KeyPress;
1585 case XEventName.KeyPress:
1586 case XEventName.ButtonPress:
1587 case XEventName.ButtonRelease:
1588 case XEventName.EnterNotify:
1589 case XEventName.LeaveNotify:
1590 case XEventName.CreateNotify:
1591 case XEventName.DestroyNotify:
1592 case XEventName.FocusIn:
1593 case XEventName.FocusOut:
1594 case XEventName.ClientMessage:
1595 case XEventName.ReparentNotify:
1596 case XEventName.MapNotify:
1597 case XEventName.UnmapNotify:
1598 hwnd.Queue.EnqueueLocked (xevent);
1601 case XEventName.ConfigureNotify:
1602 AddConfigureNotify(xevent);
1605 case XEventName.PropertyNotify:
1606 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1611 IntPtr prop = IntPtr.Zero;
1614 prev_active = ActiveWindow;
1615 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);
1616 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1617 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1620 if (prev_active != ActiveWindow) {
1621 if (prev_active != IntPtr.Zero) {
1622 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1624 if (ActiveWindow != IntPtr.Zero) {
1625 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1628 if (ModalWindows.Count == 0) {
1631 // Modality handling, if we are modal and the new active window is one
1632 // of ours but not the modal one, switch back to the modal window
1634 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1635 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1636 Activate((IntPtr)ModalWindows.Peek());
1643 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1644 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1645 hwnd.cached_window_state = (FormWindowState)(-1);
1653 private IntPtr GetMousewParam(int Delta) {
1656 if ((MouseState & MouseButtons.Left) != 0) {
1657 result |= (int)MsgButtons.MK_LBUTTON;
1660 if ((MouseState & MouseButtons.Middle) != 0) {
1661 result |= (int)MsgButtons.MK_MBUTTON;
1664 if ((MouseState & MouseButtons.Right) != 0) {
1665 result |= (int)MsgButtons.MK_RBUTTON;
1668 Keys mods = ModifierKeys;
1669 if ((mods & Keys.Control) != 0) {
1670 result |= (int)MsgButtons.MK_CONTROL;
1673 if ((mods & Keys.Shift) != 0) {
1674 result |= (int)MsgButtons.MK_SHIFT;
1677 result |= Delta << 16;
1679 return (IntPtr)result;
1681 private IntPtr XGetParent(IntPtr handle) {
1688 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1691 if (Children!=IntPtr.Zero) {
1699 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1700 if (ErrorExceptions) {
1701 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1703 Console.WriteLine("X11 Error encountered: {0}{1}\n", XException.GetMessage(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), Environment.StackTrace);
1708 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1711 Control[] controls = c.Controls.GetAllControls ();
1713 if (c.IsHandleCreated && !c.IsDisposed) {
1714 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1716 #if DriverDebug || DriverDebugDestroy
1717 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1718 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1722 CleanupCachedWindows (hwnd);
1725 for (int i = 0; i < controls.Length; i ++) {
1726 AccumulateDestroyedHandles (controls[i], list);
1732 void CleanupCachedWindows (Hwnd hwnd)
1734 if (ActiveWindow == hwnd.Handle) {
1735 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1736 ActiveWindow = IntPtr.Zero;
1739 if (FocusWindow == hwnd.Handle) {
1740 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1741 FocusWindow = IntPtr.Zero;
1744 if (Grab.Hwnd == hwnd.Handle) {
1745 Grab.Hwnd = IntPtr.Zero;
1746 Grab.Confined = false;
1749 DestroyCaret (hwnd.Handle);
1752 private void PerformNCCalc(Hwnd hwnd) {
1753 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1757 rect = hwnd.DefaultClientRect;
1759 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1760 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1762 ncp.rgrc1.left = rect.Left;
1763 ncp.rgrc1.top = rect.Top;
1764 ncp.rgrc1.right = rect.Right;
1765 ncp.rgrc1.bottom = rect.Bottom;
1767 Marshal.StructureToPtr(ncp, ptr, true);
1768 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1769 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1770 Marshal.FreeHGlobal(ptr);
1772 // FIXME - debug this with Menus
1774 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1775 hwnd.ClientRect = rect;
1778 if ((rect.Width < 1) || (rect.Height < 1)) {
1779 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1781 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1785 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1787 #endregion // Private Methods
1790 private void MouseHover(object sender, EventArgs e) {
1794 HoverState.Timer.Enabled = false;
1796 if (HoverState.Window != IntPtr.Zero) {
1797 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1799 xevent = new XEvent ();
1801 xevent.type = XEventName.ClientMessage;
1802 xevent.ClientMessageEvent.display = DisplayHandle;
1803 xevent.ClientMessageEvent.window = HoverState.Window;
1804 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1805 xevent.ClientMessageEvent.format = 32;
1806 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1808 hwnd.Queue.EnqueueLocked (xevent);
1815 private void CaretCallback(object sender, EventArgs e) {
1819 Caret.On = !Caret.On;
1821 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1823 #endregion // Callbacks
1825 #region Public Properties
1827 internal override int Caption {
1833 internal override Size CursorSize {
1838 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1839 return new Size(x, y);
1841 return new Size(16, 16);
1846 internal override bool DragFullWindows {
1852 internal override Size DragSize {
1854 return new Size(4, 4);
1858 internal override Size FrameBorderSize {
1860 return new Size (4, 4);
1864 internal override Size IconSize {
1870 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1874 current = (long)list;
1877 size = new XIconSize();
1879 for (int i = 0; i < count; i++) {
1880 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1881 current += Marshal.SizeOf(size);
1883 // Look for our preferred size
1884 if (size.min_width == 32) {
1886 return new Size(32, 32);
1889 if (size.max_width == 32) {
1891 return new Size(32, 32);
1894 if (size.min_width < 32 && size.max_width > 32) {
1897 // check if we can fit one
1899 while (x < size.max_width) {
1900 x += size.width_inc;
1903 return new Size(32, 32);
1908 if (largest < size.max_width) {
1909 largest = size.max_width;
1913 // We didn't find a match or we wouldn't be here
1914 return new Size(largest, largest);
1917 return new Size(32, 32);
1922 internal override int KeyboardSpeed {
1925 // A lot harder: need to do:
1926 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1927 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1928 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1930 // And from that we can tell the repetition rate
1932 // Notice, the values must map to:
1933 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1939 internal override int KeyboardDelay {
1942 // Return values must range from 0 to 4, 0 meaning 250ms,
1943 // and 4 meaning 1000 ms.
1945 return 1; // ie, 500 ms
1949 internal override Size MaxWindowTrackSize {
1951 return new Size (WorkingArea.Width, WorkingArea.Height);
1955 internal override Size MinimizedWindowSize {
1957 return new Size(1, 1);
1961 internal override Size MinimizedWindowSpacingSize {
1963 return new Size(1, 1);
1967 internal override Size MinimumWindowSize {
1969 return new Size(1, 1);
1973 internal override Size MinWindowTrackSize {
1975 return new Size(1, 1);
1979 internal override Keys ModifierKeys {
1981 return Keyboard.ModifierKeys;
1985 internal override Size SmallIconSize {
1991 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1995 current = (long)list;
1998 size = new XIconSize();
2000 for (int i = 0; i < count; i++) {
2001 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2002 current += Marshal.SizeOf(size);
2004 // Look for our preferred size
2005 if (size.min_width == 16) {
2007 return new Size(16, 16);
2010 if (size.max_width == 16) {
2012 return new Size(16, 16);
2015 if (size.min_width < 16 && size.max_width > 16) {
2018 // check if we can fit one
2020 while (x < size.max_width) {
2021 x += size.width_inc;
2024 return new Size(16, 16);
2029 if (smallest == 0 || smallest > size.min_width) {
2030 smallest = size.min_width;
2034 // We didn't find a match or we wouldn't be here
2035 return new Size(smallest, smallest);
2038 return new Size(16, 16);
2043 internal override int MouseButtonCount {
2049 internal override bool MouseButtonsSwapped {
2051 return false; // FIXME - how to detect?
2055 internal override Point MousePosition {
2057 return mouse_position;
2061 internal override Size MouseHoverSize {
2063 return new Size (1, 1);
2067 internal override int MouseHoverTime {
2069 return HoverState.Interval;
2075 internal override bool MouseWheelPresent {
2077 return true; // FIXME - how to detect?
2081 internal override Rectangle VirtualScreen {
2087 IntPtr prop = IntPtr.Zero;
2091 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);
2092 if ((long)nitems < 2)
2095 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2096 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2100 return new Rectangle(0, 0, width, height);
2103 XWindowAttributes attributes=new XWindowAttributes();
2106 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2109 return new Rectangle(0, 0, attributes.width, attributes.height);
2113 internal override Rectangle WorkingArea {
2119 IntPtr prop = IntPtr.Zero;
2122 int current_desktop;
2126 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);
2127 if ((long)nitems < 1) {
2131 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2134 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);
2135 if ((long)nitems < 4 * current_desktop) {
2139 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2140 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2141 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2142 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2145 return new Rectangle(x, y, width, height);
2148 XWindowAttributes attributes=new XWindowAttributes();
2151 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2154 return new Rectangle(0, 0, attributes.width, attributes.height);
2158 internal override bool ThemesEnabled {
2160 return XplatUIX11.themes_enabled;
2165 #endregion // Public properties
2167 #region Public Static Methods
2168 internal override IntPtr InitializeDriver() {
2170 if (DisplayHandle==IntPtr.Zero) {
2171 SetDisplay(XOpenDisplay(IntPtr.Zero));
2177 internal override void ShutdownDriver(IntPtr token) {
2179 if (DisplayHandle!=IntPtr.Zero) {
2180 XCloseDisplay(DisplayHandle);
2181 DisplayHandle=IntPtr.Zero;
2186 internal override void EnableThemes() {
2187 themes_enabled = true;
2191 internal override void Activate(IntPtr handle) {
2194 hwnd = Hwnd.ObjectFromHandle(handle);
2198 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2199 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2202 // XRaiseWindow(DisplayHandle, handle);
2208 internal override void AudibleAlert() {
2209 XBell(DisplayHandle, 0);
2214 internal override void CaretVisible(IntPtr handle, bool visible) {
2215 if (Caret.Hwnd == handle) {
2217 if (!Caret.Visible) {
2218 Caret.Visible = true;
2220 Caret.Timer.Start();
2223 Caret.Visible = false;
2230 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2231 FormBorderStyle border_style;
2232 TitleStyle title_style;
2235 int tool_caption_height;
2237 DeriveStyles(Style, ExStyle, out border_style, out border_static, out title_style,
2238 out caption_height, out tool_caption_height);
2240 WindowRect = Hwnd.GetWindowRectangle(border_style, border_static, menu, title_style,
2241 caption_height, tool_caption_height,
2246 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2252 hwnd = Hwnd.ObjectFromHandle(handle);
2255 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2262 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2263 DataFormats.Format f;
2266 f = DataFormats.Format.List;
2268 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2272 Clipboard.Formats = new ArrayList();
2275 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2277 Clipboard.Enumerating = true;
2278 while (Clipboard.Enumerating) {
2279 UpdateMessageQueue(null);
2284 result = new int[Clipboard.Formats.Count];
2286 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2287 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2290 Clipboard.Formats = null;
2294 internal override void ClipboardClose(IntPtr handle) {
2295 if (handle != ClipMagic) {
2296 throw new ArgumentException("handle is not a valid clipboard handle");
2301 internal override int ClipboardGetID(IntPtr handle, string format) {
2302 if (handle != ClipMagic) {
2303 throw new ArgumentException("handle is not a valid clipboard handle");
2306 if (format == "Text" ) return (int)Atom.XA_STRING;
2307 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2308 //else if (format == "MetaFilePict" ) return 3;
2309 //else if (format == "SymbolicLink" ) return 4;
2310 //else if (format == "DataInterchangeFormat" ) return 5;
2311 //else if (format == "Tiff" ) return 6;
2312 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2313 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2314 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2315 //else if (format == "PenData" ) return 10;
2316 //else if (format == "RiffAudio" ) return 11;
2317 //else if (format == "WaveAudio" ) return 12;
2318 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2319 //else if (format == "EnhancedMetafile" ) return 14;
2320 //else if (format == "FileDrop" ) return 15;
2321 //else if (format == "Locale" ) return 16;
2323 return XInternAtom(DisplayHandle, format, false).ToInt32();
2326 internal override IntPtr ClipboardOpen(bool primary_selection) {
2327 if (!primary_selection)
2328 ClipMagic = CLIPBOARD;
2330 ClipMagic = PRIMARY;
2334 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2335 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2337 Clipboard.Retrieving = true;
2338 while (Clipboard.Retrieving) {
2339 UpdateMessageQueue(null);
2342 return Clipboard.Item;
2345 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2346 Clipboard.Item = obj;
2347 Clipboard.Type = type;
2348 Clipboard.Converter = converter;
2351 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2353 // Clearing the selection
2354 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2358 internal override void CreateCaret (IntPtr handle, int width, int height)
2360 XGCValues gc_values;
2363 hwnd = Hwnd.ObjectFromHandle(handle);
2365 if (Caret.Hwnd != IntPtr.Zero) {
2366 DestroyCaret(Caret.Hwnd);
2369 Caret.Hwnd = handle;
2370 Caret.Window = hwnd.client_window;
2371 Caret.Width = width;
2372 Caret.Height = height;
2373 Caret.Visible = false;
2376 gc_values = new XGCValues();
2377 gc_values.line_width = width;
2379 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2380 if (Caret.gc == IntPtr.Zero) {
2381 Caret.Hwnd = IntPtr.Zero;
2385 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2388 internal override IntPtr CreateWindow (CreateParams cp)
2390 XSetWindowAttributes Attributes;
2396 IntPtr ParentHandle;
2398 IntPtr ClientWindow;
2399 Rectangle ClientRect;
2400 SetWindowValuemask ValueMask;
2405 Attributes = new XSetWindowAttributes();
2411 if (Width<1) Width=1;
2412 if (Height<1) Height=1;
2414 if (cp.Parent != IntPtr.Zero) {
2415 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2417 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2418 // We need to use our foster parent window until this poor child gets it's parent assigned
2419 ParentHandle=FosterParent;
2420 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2421 ParentHandle=RootWindow;
2423 // Default position on screen, if window manager doesn't place us somewhere else
2426 ParentHandle=RootWindow;
2430 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2432 Attributes.bit_gravity = Gravity.NorthWestGravity;
2433 Attributes.win_gravity = Gravity.NorthWestGravity;
2435 // Save what's under the toolwindow
2436 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2437 Attributes.save_under = true;
2438 ValueMask |= SetWindowValuemask.SaveUnder;
2442 // If we're a popup without caption we override the WM
2443 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2444 Attributes.override_redirect = true;
2445 ValueMask |= SetWindowValuemask.OverrideRedirect;
2451 hwnd.height = Height;
2452 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2453 hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
2455 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2456 hwnd.enabled = false;
2459 ClientRect = hwnd.ClientRect;
2460 ClientWindow = IntPtr.Zero;
2463 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2464 if (WholeWindow != IntPtr.Zero) {
2465 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2467 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2468 ValueMask = SetWindowValuemask.ColorMap;
2469 Attributes.colormap = CustomColormap;
2471 ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
2475 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2476 throw new Exception("Could not create X11 windows");
2479 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2480 hwnd.WholeWindow = WholeWindow;
2481 hwnd.ClientWindow = ClientWindow;
2483 #if DriverDebug || DriverDebugCreate
2484 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);
2487 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2488 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2491 hints = new XSizeHints();
2494 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2495 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2500 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2501 if (hwnd.whole_window != hwnd.client_window)
2502 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2505 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2507 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2508 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2510 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2513 SetWMStyles(hwnd, cp);
2515 // set the group leader
2516 XWMHints wm_hints = new XWMHints ();
2518 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2519 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2520 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2522 if (ParentHandle != RootWindow) {
2523 wm_hints.window_group = hwnd.whole_window;
2525 wm_hints.window_group = ParentHandle;
2529 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2532 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2533 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2534 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2535 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2538 // for now make all windows dnd enabled
2539 Dnd.SetAllowDrop (hwnd, true);
2541 // Set caption/window title
2542 Text(hwnd.Handle, cp.Caption);
2544 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2545 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2547 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2548 hwnd.visible = true;
2549 MapWindow(hwnd, WindowType.Both);
2550 if (!(Control.FromHandle(hwnd.Handle) is Form))
2551 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2557 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2558 CreateParams create_params = new CreateParams();
2560 create_params.Caption = "";
2561 create_params.X = X;
2562 create_params.Y = Y;
2563 create_params.Width = Width;
2564 create_params.Height = Height;
2566 create_params.ClassName=XplatUI.DefaultClassName;
2567 create_params.ClassStyle = 0;
2568 create_params.ExStyle=0;
2569 create_params.Parent=IntPtr.Zero;
2570 create_params.Param=0;
2572 return CreateWindow(create_params);
2575 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2577 Bitmap cursor_bitmap;
2585 IntPtr cursor_pixmap;
2592 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2596 // Win32 only allows creation cursors of a certain size
2597 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2598 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2599 cursor_mask = new Bitmap(mask, new Size(width, height));
2601 cursor_bitmap = bitmap;
2605 width = cursor_bitmap.Width;
2606 height = cursor_bitmap.Height;
2608 cursor_bits = new Byte[(width / 8) * height];
2609 mask_bits = new Byte[(width / 8) * height];
2611 for (int y = 0; y < height; y++) {
2612 for (int x = 0; x < width; x++) {
2613 c_pixel = cursor_bitmap.GetPixel(x, y);
2614 m_pixel = cursor_mask.GetPixel(x, y);
2616 and = c_pixel == cursor_pixel;
2617 xor = m_pixel == mask_pixel;
2621 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2622 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2623 } else if (and && !xor) {
2625 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2626 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2628 } else if (and && !xor) {
2630 } else if (and && xor) {
2633 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2634 // we want both to be 0 so nothing to be done
2635 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2636 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2642 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2643 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2647 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2648 fg.red = (ushort)65535;
2649 fg.green = (ushort)65535;
2650 fg.blue = (ushort)65535;
2652 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2654 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2656 XFreePixmap(DisplayHandle, cursor_pixmap);
2657 XFreePixmap(DisplayHandle, mask_pixmap);
2662 internal override IntPtr DefineStdCursor(StdCursor id) {
2663 CursorFontShape shape;
2666 // FIXME - define missing shapes
2669 case StdCursor.AppStarting: {
2670 shape = CursorFontShape.XC_watch;
2674 case StdCursor.Arrow: {
2675 shape = CursorFontShape.XC_top_left_arrow;
2679 case StdCursor.Cross: {
2680 shape = CursorFontShape.XC_crosshair;
2684 case StdCursor.Default: {
2685 shape = CursorFontShape.XC_top_left_arrow;
2689 case StdCursor.Hand: {
2690 shape = CursorFontShape.XC_hand1;
2694 case StdCursor.Help: {
2695 shape = CursorFontShape.XC_question_arrow;
2699 case StdCursor.HSplit: {
2700 shape = CursorFontShape.XC_sb_v_double_arrow;
2704 case StdCursor.IBeam: {
2705 shape = CursorFontShape.XC_xterm;
2709 case StdCursor.No: {
2710 shape = CursorFontShape.XC_circle;
2714 case StdCursor.NoMove2D: {
2715 shape = CursorFontShape.XC_fleur;
2719 case StdCursor.NoMoveHoriz: {
2720 shape = CursorFontShape.XC_fleur;
2724 case StdCursor.NoMoveVert: {
2725 shape = CursorFontShape.XC_fleur;
2729 case StdCursor.PanEast: {
2730 shape = CursorFontShape.XC_fleur;
2734 case StdCursor.PanNE: {
2735 shape = CursorFontShape.XC_fleur;
2739 case StdCursor.PanNorth: {
2740 shape = CursorFontShape.XC_fleur;
2744 case StdCursor.PanNW: {
2745 shape = CursorFontShape.XC_fleur;
2749 case StdCursor.PanSE: {
2750 shape = CursorFontShape.XC_fleur;
2754 case StdCursor.PanSouth: {
2755 shape = CursorFontShape.XC_fleur;
2759 case StdCursor.PanSW: {
2760 shape = CursorFontShape.XC_fleur;
2764 case StdCursor.PanWest: {
2765 shape = CursorFontShape.XC_sizing;
2769 case StdCursor.SizeAll: {
2770 shape = CursorFontShape.XC_fleur;
2774 case StdCursor.SizeNESW: {
2775 shape = CursorFontShape.XC_top_right_corner;
2779 case StdCursor.SizeNS: {
2780 shape = CursorFontShape.XC_sb_v_double_arrow;
2784 case StdCursor.SizeNWSE: {
2785 shape = CursorFontShape.XC_top_left_corner;
2789 case StdCursor.SizeWE: {
2790 shape = CursorFontShape.XC_sb_h_double_arrow;
2794 case StdCursor.UpArrow: {
2795 shape = CursorFontShape.XC_center_ptr;
2799 case StdCursor.VSplit: {
2800 shape = CursorFontShape.XC_sb_h_double_arrow;
2804 case StdCursor.WaitCursor: {
2805 shape = CursorFontShape.XC_watch;
2815 cursor = XCreateFontCursor(DisplayHandle, shape);
2820 internal override IntPtr DefWndProc(ref Message msg) {
2821 switch ((Msg)msg.Msg) {
2822 case Msg.WM_PAINT: {
2825 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2827 hwnd.expose_pending = false;
2833 case Msg.WM_NCPAINT: {
2836 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2838 hwnd.nc_expose_pending = false;
2844 case Msg.WM_CONTEXTMENU: {
2847 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2849 if ((hwnd != null) && (hwnd.parent != null)) {
2850 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2855 case Msg.WM_MOUSEWHEEL: {
2858 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2860 if ((hwnd != null) && (hwnd.parent != null)) {
2861 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2862 if (msg.Result == IntPtr.Zero) {
2869 case Msg.WM_SETCURSOR: {
2872 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2874 break; // not sure how this happens, but it does
2876 // Pass to parent window first
2877 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2879 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2882 if (msg.Result == IntPtr.Zero) {
2885 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2886 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2887 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2888 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2889 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2890 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2893 handle = Cursors.Default.handle;
2896 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2897 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2898 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2899 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2900 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2901 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2904 case HitTest.HTGROWBOX:
2905 case HitTest.HTSIZE:
2906 case HitTest.HTZOOM:
2907 case HitTest.HTVSCROLL:
2908 case HitTest.HTSYSMENU:
2909 case HitTest.HTREDUCE:
2910 case HitTest.HTNOWHERE:
2911 case HitTest.HTMAXBUTTON:
2912 case HitTest.HTMINBUTTON:
2913 case HitTest.HTMENU:
2914 case HitTest.HSCROLL:
2915 case HitTest.HTBOTTOM:
2916 case HitTest.HTCAPTION:
2917 case HitTest.HTCLIENT:
2918 case HitTest.HTCLOSE:
2920 default: handle = Cursors.Default.handle; break;
2922 SetCursor(msg.HWnd, handle);
2930 internal override void DestroyCaret(IntPtr handle) {
2931 if (Caret.Hwnd == handle) {
2932 if (Caret.Visible) {
2936 if (Caret.gc != IntPtr.Zero) {
2937 XFreeGC(DisplayHandle, Caret.gc);
2938 Caret.gc = IntPtr.Zero;
2940 Caret.Hwnd = IntPtr.Zero;
2941 Caret.Visible = false;
2946 internal override void DestroyCursor(IntPtr cursor) {
2948 XFreeCursor(DisplayHandle, cursor);
2952 internal override void DestroyWindow(IntPtr handle) {
2955 hwnd = Hwnd.ObjectFromHandle(handle);
2958 #if DriverDebug || DriverDebugDestroy
2959 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2964 #if DriverDebug || DriverDebugDestroy
2965 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2968 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
2970 CleanupCachedWindows (hwnd);
2972 ArrayList windows = new ArrayList ();
2974 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2977 foreach (Hwnd h in windows) {
2978 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2983 if (hwnd.whole_window != IntPtr.Zero) {
2984 #if DriverDebug || DriverDebugDestroy
2985 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2987 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2989 else if (hwnd.client_window != IntPtr.Zero) {
2990 #if DriverDebug || DriverDebugDestroy
2991 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2993 XDestroyWindow(DisplayHandle, hwnd.client_window);
2999 internal override IntPtr DispatchMessage(ref MSG msg) {
3000 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3003 IntPtr GetReversibleScreenGC (Color backColor)
3005 XGCValues gc_values;
3009 XColor xcolor = new XColor();
3010 xcolor.red = (ushort)(backColor.R * 257);
3011 xcolor.green = (ushort)(backColor.G * 257);
3012 xcolor.blue = (ushort)(backColor.B * 257);
3013 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3014 pixel = (uint)xcolor.pixel.ToInt32();
3017 gc_values = new XGCValues();
3019 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3020 gc_values.foreground = (IntPtr)pixel;
3022 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3023 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3024 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3029 IntPtr GetReversibleControlGC (Control control, int line_width)
3031 XGCValues gc_values;
3034 gc_values = new XGCValues();
3036 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3037 gc_values.line_width = line_width;
3038 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3040 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3041 //mask = foreground ^ background;
3042 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3043 //XSetBackground(DisplayHandle, gc, background);
3044 //XSetFunction(DisplayHandle, gc, GXxor);
3045 //XSetPlaneMask(DisplayHandle, gc, mask);
3048 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3052 XColor xcolor = new XColor();
3054 xcolor.red = (ushort)(control.ForeColor.R * 257);
3055 xcolor.green = (ushort)(control.ForeColor.G * 257);
3056 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3057 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3058 foreground = (uint)xcolor.pixel.ToInt32();
3060 xcolor.red = (ushort)(control.BackColor.R * 257);
3061 xcolor.green = (ushort)(control.BackColor.G * 257);
3062 xcolor.blue = (ushort)(control.BackColor.B * 257);
3063 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3064 background = (uint)xcolor.pixel.ToInt32();
3066 uint mask = foreground ^ background;
3068 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3069 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3070 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3071 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3076 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3078 IntPtr gc = GetReversibleScreenGC (backColor);
3080 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3082 XFreeGC(DisplayHandle, gc);
3085 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3087 IntPtr gc = GetReversibleScreenGC (backColor);
3089 if (rectangle.Width < 0) {
3090 rectangle.X += rectangle.Width;
3091 rectangle.Width = -rectangle.Width;
3093 if (rectangle.Height < 0) {
3094 rectangle.Y += rectangle.Height;
3095 rectangle.Height = -rectangle.Height;
3099 GCLineStyle line_style = GCLineStyle.LineSolid;
3100 GCCapStyle cap_style = GCCapStyle.CapButt;
3101 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3104 case FrameStyle.Dashed:
3105 line_style = GCLineStyle.LineOnOffDash;
3107 case FrameStyle.Thick:
3112 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3114 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3116 XFreeGC(DisplayHandle, gc);
3119 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3121 IntPtr gc = GetReversibleScreenGC (backColor);
3123 if (rectangle.Width < 0) {
3124 rectangle.X += rectangle.Width;
3125 rectangle.Width = -rectangle.Width;
3127 if (rectangle.Height < 0) {
3128 rectangle.Y += rectangle.Height;
3129 rectangle.Height = -rectangle.Height;
3131 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3133 XFreeGC(DisplayHandle, gc);
3136 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3138 Control control = Control.FromHandle(handle);
3140 gc = GetReversibleControlGC (control, line_width);
3142 if ((rect.Width > 0) && (rect.Height > 0)) {
3143 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3145 if (rect.Width > 0) {
3146 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3148 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3151 XFreeGC(DisplayHandle, gc);
3154 internal override void DoEvents() {
3155 MSG msg = new MSG ();
3158 if (OverrideCursorHandle != IntPtr.Zero) {
3159 OverrideCursorHandle = IntPtr.Zero;
3162 queue = ThreadQueue(Thread.CurrentThread);
3164 queue.DispatchIdle = false;
3166 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3167 TranslateMessage (ref msg);
3168 DispatchMessage (ref msg);
3171 queue.DispatchIdle = true;
3174 internal override void EnableWindow(IntPtr handle, bool Enable) {
3177 hwnd = Hwnd.ObjectFromHandle(handle);
3179 hwnd.Enabled = Enable;
3183 internal override void EndLoop(Thread thread) {
3184 // This is where we one day will shut down the loop for the thread
3187 internal override IntPtr GetActive() {
3192 IntPtr prop = IntPtr.Zero;
3193 IntPtr active = IntPtr.Zero;
3195 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);
3196 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3197 active = (IntPtr)Marshal.ReadInt32(prop);
3201 if (active != IntPtr.Zero) {
3204 hwnd = Hwnd.GetObjectFromWindow(active);
3206 active = hwnd.Handle;
3208 active = IntPtr.Zero;
3214 internal override Region GetClipRegion(IntPtr handle) {
3217 hwnd = Hwnd.ObjectFromHandle(handle);
3219 return hwnd.UserClip;
3225 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3232 internal override void GetDisplaySize(out Size size) {
3233 XWindowAttributes attributes=new XWindowAttributes();
3236 // FIXME - use _NET_WM messages instead?
3237 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3240 size = new Size(attributes.width, attributes.height);
3243 internal override SizeF GetAutoScaleSize(Font font) {
3246 string magic_string = "The quick brown fox jumped over the lazy dog.";
3247 double magic_number = 44.549996948242189;
3249 g = Graphics.FromHwnd(FosterParent);
3251 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3252 return new SizeF(width, font.Height);
3255 internal override IntPtr GetParent(IntPtr handle) {
3258 hwnd = Hwnd.ObjectFromHandle(handle);
3259 if (hwnd != null && hwnd.parent != null) {
3260 return hwnd.parent.Handle;
3265 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3275 if (handle != IntPtr.Zero) {
3276 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3278 use_handle = RootWindow;
3282 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3285 if (handle != IntPtr.Zero) {
3294 internal override IntPtr GetFocus() {
3299 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3300 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3303 internal override Point GetMenuOrigin(IntPtr handle) {
3306 hwnd = Hwnd.ObjectFromHandle(handle);
3309 return hwnd.MenuOrigin;
3314 [MonoTODO("Implement filtering")]
3315 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3322 if (((XEventQueue)queue_id).Count > 0) {
3323 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3325 UpdateMessageQueue ((XEventQueue)queue_id);
3327 if (((XEventQueue)queue_id).Count > 0) {
3328 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3329 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3330 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3332 msg.hwnd= IntPtr.Zero;
3333 msg.message = Msg.WM_ENTERIDLE;
3338 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3340 // Handle messages for windows that are already or are about to be destroyed.
3342 // we need a special block for this because unless we remove the hwnd from the paint
3343 // queue it will always stay there (since we don't handle the expose), and we'll
3344 // effectively loop infinitely trying to repaint a non-existant window.
3345 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3346 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3347 hwnd.Queue.Paint.Remove (hwnd);
3348 goto ProcessNextMessage;
3351 // We need to make sure we only allow DestroyNotify events through for zombie
3352 // hwnds, since much of the event handling code makes requests using the hwnd's
3353 // client_window, and that'll result in BadWindow errors if there's some lag
3354 // between the XDestroyWindow call and the DestroyNotify event.
3355 if (hwnd == null || hwnd.zombie) {
3356 #if DriverDebug || DriverDebugDestroy
3357 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3359 goto ProcessNextMessage;
3362 if (hwnd.client_window == xevent.AnyEvent.window) {
3364 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3367 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3370 msg.hwnd = hwnd.Handle;
3373 // If you add a new event to this switch make sure to add it in
3374 // UpdateMessage also unless it is not coming through the X event system.
3376 switch(xevent.type) {
3377 case XEventName.KeyPress: {
3379 Dnd.HandleKeyPress (ref xevent);
3380 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3384 case XEventName.KeyRelease: {
3385 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3389 case XEventName.ButtonPress: {
3390 switch(xevent.ButtonEvent.button) {
3392 MouseState |= MouseButtons.Left;
3394 msg.message = Msg.WM_LBUTTONDOWN;
3396 msg.message = Msg.WM_NCLBUTTONDOWN;
3397 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3399 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3400 msg.wParam=GetMousewParam(0);
3405 MouseState |= MouseButtons.Middle;
3407 msg.message = Msg.WM_MBUTTONDOWN;
3409 msg.message = Msg.WM_NCMBUTTONDOWN;
3410 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3412 msg.wParam=GetMousewParam(0);
3417 MouseState |= MouseButtons.Right;
3419 msg.message = Msg.WM_RBUTTONDOWN;
3421 msg.message = Msg.WM_NCRBUTTONDOWN;
3422 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3424 msg.wParam=GetMousewParam(0);
3429 msg.hwnd = FocusWindow;
3430 msg.message=Msg.WM_MOUSEWHEEL;
3431 msg.wParam=GetMousewParam(120);
3436 msg.hwnd = FocusWindow;
3437 msg.message=Msg.WM_MOUSEWHEEL;
3438 msg.wParam=GetMousewParam(-120);
3444 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3445 mouse_position.X = xevent.ButtonEvent.x;
3446 mouse_position.Y = xevent.ButtonEvent.y;
3448 if (!hwnd.Enabled) {
3451 msg.hwnd = hwnd.EnabledHwnd;
3452 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);
3453 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3456 if (Grab.Hwnd != IntPtr.Zero) {
3457 msg.hwnd = Grab.Hwnd;
3460 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3461 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3462 switch(xevent.ButtonEvent.button) {
3464 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3469 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3474 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3478 ClickPending.Pending = false;
3480 ClickPending.Pending = true;
3481 ClickPending.Hwnd = msg.hwnd;
3482 ClickPending.Message = msg.message;
3483 ClickPending.wParam = msg.wParam;
3484 ClickPending.lParam = msg.lParam;
3485 ClickPending.Time = (long)xevent.ButtonEvent.time;
3488 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3489 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3491 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3492 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3493 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3494 XEvent motionEvent = new XEvent ();
3495 motionEvent.type = XEventName.MotionNotify;
3496 motionEvent.MotionEvent.display = DisplayHandle;
3497 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3498 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3499 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3500 hwnd.Queue.EnqueueLocked (motionEvent);
3506 case XEventName.ButtonRelease: {
3508 if (Dnd.HandleButtonRelease (ref xevent)) {
3511 // Allow the LBUTTONUP message to get through
3514 switch(xevent.ButtonEvent.button) {
3517 msg.message = Msg.WM_LBUTTONUP;
3519 msg.message = Msg.WM_NCLBUTTONUP;
3520 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3522 MouseState &= ~MouseButtons.Left;
3523 msg.wParam=GetMousewParam(0);
3529 msg.message = Msg.WM_MBUTTONUP;
3531 msg.message = Msg.WM_NCMBUTTONUP;
3532 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3534 MouseState &= ~MouseButtons.Middle;
3535 msg.wParam=GetMousewParam(0);
3541 msg.message = Msg.WM_RBUTTONUP;
3543 msg.message = Msg.WM_NCRBUTTONUP;
3544 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3546 MouseState &= ~MouseButtons.Right;
3547 msg.wParam=GetMousewParam(0);
3552 goto ProcessNextMessage;
3556 goto ProcessNextMessage;
3560 if (!hwnd.Enabled) {
3563 msg.hwnd = hwnd.EnabledHwnd;
3564 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);
3565 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3568 if (Grab.Hwnd != IntPtr.Zero) {
3569 msg.hwnd = Grab.Hwnd;
3572 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3573 mouse_position.X = xevent.ButtonEvent.x;
3574 mouse_position.Y = xevent.ButtonEvent.y;
3576 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3577 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3578 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3579 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3580 XEvent motionEvent = new XEvent ();
3581 motionEvent.type = XEventName.MotionNotify;
3582 motionEvent.MotionEvent.display = DisplayHandle;
3583 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3584 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3585 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3586 hwnd.Queue.EnqueueLocked (motionEvent);
3591 case XEventName.MotionNotify: {
3593 #if DriverDebugExtra
3594 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);
3597 if (Dnd.HandleMotionNotify (ref xevent))
3598 goto ProcessNextMessage;
3599 if (Grab.Hwnd != IntPtr.Zero) {
3600 msg.hwnd = Grab.Hwnd;
3602 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3605 msg.message = Msg.WM_MOUSEMOVE;
3606 msg.wParam = GetMousewParam(0);
3607 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3609 if (!hwnd.Enabled) {
3612 msg.hwnd = hwnd.EnabledHwnd;
3613 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);
3614 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3617 mouse_position.X = xevent.MotionEvent.x;
3618 mouse_position.Y = xevent.MotionEvent.y;
3620 if ((HoverState.Timer.Enabled) &&
3621 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3622 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3623 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3624 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3625 HoverState.Timer.Stop();
3626 HoverState.Timer.Start();
3627 HoverState.X = mouse_position.X;
3628 HoverState.Y = mouse_position.Y;
3638 #if DriverDebugExtra
3639 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);
3641 msg.message = Msg.WM_NCMOUSEMOVE;
3643 if (!hwnd.Enabled) {
3644 msg.hwnd = hwnd.EnabledHwnd;
3645 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);
3646 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3649 // The hit test is sent in screen coordinates
3650 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3651 xevent.MotionEvent.x, xevent.MotionEvent.y,
3652 out screen_x, out screen_y, out dummy);
3654 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3655 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3656 IntPtr.Zero, msg.lParam).ToInt32 ();
3657 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3659 mouse_position.X = xevent.MotionEvent.x;
3660 mouse_position.Y = xevent.MotionEvent.y;
3666 case XEventName.EnterNotify: {
3667 if (!hwnd.Enabled) {
3668 goto ProcessNextMessage;
3670 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3671 goto ProcessNextMessage;
3673 msg.message = Msg.WM_MOUSE_ENTER;
3674 HoverState.X = xevent.CrossingEvent.x;
3675 HoverState.Y = xevent.CrossingEvent.y;
3676 HoverState.Timer.Enabled = true;
3677 HoverState.Window = xevent.CrossingEvent.window;
3681 case XEventName.LeaveNotify: {
3682 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3683 WindowUngrabbed (hwnd.Handle);
3684 goto ProcessNextMessage;
3686 if (!hwnd.Enabled) {
3687 goto ProcessNextMessage;
3689 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3690 goto ProcessNextMessage;
3692 msg.message=Msg.WM_MOUSELEAVE;
3693 HoverState.Timer.Enabled = false;
3694 HoverState.Window = IntPtr.Zero;
3699 case XEventName.CreateNotify: {
3700 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3701 msg.message = WM_CREATE;
3702 // Set up CreateStruct
3704 goto ProcessNextMessage;
3711 case XEventName.ReparentNotify: {
3712 if (hwnd.parent == null) { // Toplevel
3713 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3714 // We need to adjust x/y
3715 // This sucks ass, part 2
3716 // Every WM does the reparenting of toplevel windows different, so there's
3717 // no standard way of getting our adjustment considering frames/decorations
3718 // The code below is needed for metacity. KDE doesn't works just fine without this
3726 hwnd.Reparented = true;
3728 XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out new_x, out new_y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
3729 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3730 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3733 hwnd.whacky_wm = true;
3736 if (hwnd.opacity != 0xffffffff) {
3739 opacity = (IntPtr)(Int32)hwnd.opacity;
3740 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3742 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3743 goto ProcessNextMessage;
3745 hwnd.Reparented = false;
3746 goto ProcessNextMessage;
3749 goto ProcessNextMessage;
3752 case XEventName.ConfigureNotify: {
3753 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3754 #if DriverDebugExtra
3755 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);
3757 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3758 lock (hwnd.configure_lock) {
3759 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3760 hwnd.configure_pending = false;
3763 // We need to adjust our client window to track the resize of whole_window
3764 if (hwnd.whole_window != hwnd.client_window)
3765 PerformNCCalc(hwnd);
3768 goto ProcessNextMessage;
3771 case XEventName.FocusIn: {
3772 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3773 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3774 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3775 // about it having focus again
3776 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3777 goto ProcessNextMessage;
3780 if (FocusWindow == IntPtr.Zero) {
3781 Control c = Control.FromHandle (hwnd.client_window);
3783 goto ProcessNextMessage;
3784 Form form = c.FindForm ();
3786 goto ProcessNextMessage;
3787 if (ActiveWindow != form.Handle) {
3788 ActiveWindow = form.Handle;
3789 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3791 goto ProcessNextMessage;
3793 Keyboard.FocusIn(FocusWindow);
3794 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3795 goto ProcessNextMessage;
3798 case XEventName.FocusOut: {
3799 // Se the comment for our FocusIn handler
3800 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3801 goto ProcessNextMessage;
3803 Keyboard.FocusOut(FocusWindow);
3805 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3806 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3809 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3810 goto ProcessNextMessage;
3813 case XEventName.MapNotify: {
3814 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3816 msg.message = Msg.WM_SHOWWINDOW;
3817 msg.wParam = (IntPtr) 1;
3818 // XXX we're missing the lParam..
3821 goto ProcessNextMessage;
3824 case XEventName.UnmapNotify: {
3825 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3826 hwnd.mapped = false;
3827 msg.message = Msg.WM_SHOWWINDOW;
3828 msg.wParam = (IntPtr) 0;
3829 // XXX we're missing the lParam..
3832 goto ProcessNextMessage;
3835 case XEventName.Expose: {
3838 hwnd.expose_pending = false;
3840 hwnd.nc_expose_pending = false;
3842 goto ProcessNextMessage;
3846 if (!hwnd.expose_pending) {
3847 goto ProcessNextMessage;
3850 if (!hwnd.nc_expose_pending) {
3851 goto ProcessNextMessage;
3854 switch (hwnd.border_style) {
3855 case FormBorderStyle.Fixed3D: {
3858 g = Graphics.FromHwnd(hwnd.whole_window);
3859 if (hwnd.border_static)
3860 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
3862 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3867 case FormBorderStyle.FixedSingle: {
3870 g = Graphics.FromHwnd(hwnd.whole_window);
3871 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3876 #if DriverDebugExtra
3877 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);
3880 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3881 Region region = new Region (rect);
3882 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3883 msg.message = Msg.WM_NCPAINT;
3884 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3885 msg.refobject = region;
3888 #if DriverDebugExtra
3889 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);
3891 if (Caret.Visible == true) {
3892 Caret.Paused = true;
3896 if (Caret.Visible == true) {
3898 Caret.Paused = false;
3900 msg.message = Msg.WM_PAINT;
3904 case XEventName.DestroyNotify: {
3906 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3907 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3909 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3910 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3911 CleanupCachedWindows (hwnd);
3913 #if DriverDebugDestroy
3914 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3917 msg.hwnd = hwnd.client_window;
3918 msg.message=Msg.WM_DESTROY;
3921 goto ProcessNextMessage;
3927 case XEventName.ClientMessage: {
3928 if (Dnd.HandleClientMessage (ref xevent)) {
3929 goto ProcessNextMessage;
3932 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3933 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3934 goto ProcessNextMessage;
3937 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3938 msg.message = Msg.WM_MOUSEHOVER;
3939 msg.wParam = GetMousewParam(0);
3940 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3944 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3945 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3946 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3947 msg.wParam = xevent.ClientMessageEvent.ptr3;
3948 msg.lParam = xevent.ClientMessageEvent.ptr4;
3949 if (msg.message == (Msg)Msg.WM_QUIT)
3955 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3956 #if DriverDebugXEmbed
3957 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3960 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3961 XSizeHints hints = new XSizeHints();
3964 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3966 hwnd.width = hints.max_width;
3967 hwnd.height = hints.max_height;
3968 hwnd.ClientRect = Rectangle.Empty;
3969 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3973 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3974 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3975 msg.message = Msg.WM_CLOSE;
3979 // We should not get this, but I'll leave the code in case we need it in the future
3980 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3981 goto ProcessNextMessage;
3984 goto ProcessNextMessage;
3988 goto ProcessNextMessage;
3995 internal override bool GetText(IntPtr handle, out string text) {
4002 IntPtr prop = IntPtr.Zero;
4004 XGetWindowProperty(DisplayHandle, handle,
4005 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4006 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4008 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4009 text = Marshal.PtrToStringUni (prop, (int)nitems);
4014 // fallback on the non-_NET property
4017 textptr = IntPtr.Zero;
4019 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4020 if (textptr != IntPtr.Zero) {
4021 text = Marshal.PtrToStringAnsi(textptr);
4032 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) {
4035 hwnd = Hwnd.ObjectFromHandle(handle);
4041 height = hwnd.height;
4043 PerformNCCalc(hwnd);
4045 client_width = hwnd.ClientRect.Width;
4046 client_height = hwnd.ClientRect.Height;
4051 // Should we throw an exception or fail silently?
4052 // throw new ArgumentException("Called with an invalid window handle", "handle");
4062 internal override FormWindowState GetWindowState(IntPtr handle) {
4065 hwnd = Hwnd.ObjectFromHandle(handle);
4067 if (hwnd.cached_window_state == (FormWindowState)(-1))
4068 hwnd.cached_window_state = UpdateWindowState (handle);
4070 return hwnd.cached_window_state;
4073 private FormWindowState UpdateWindowState (IntPtr handle) {
4078 IntPtr prop = IntPtr.Zero;
4082 XWindowAttributes attributes;
4085 hwnd = Hwnd.ObjectFromHandle(handle);
4089 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);
4090 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4091 for (int i = 0; i < (long)nitems; i++) {
4092 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4093 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4095 } else if (atom == _NET_WM_STATE_HIDDEN) {
4103 return FormWindowState.Minimized;
4104 } else if (maximized == 2) {
4105 return FormWindowState.Maximized;
4108 attributes = new XWindowAttributes();
4109 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4110 if (attributes.map_state == MapState.IsUnmapped) {
4111 return (FormWindowState)(-1);
4115 return FormWindowState.Normal;
4118 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4120 GrabConfined = Grab.Confined;
4121 GrabArea = Grab.Area;
4124 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4126 IntPtr confine_to_window;
4128 confine_to_window = IntPtr.Zero;
4130 if (confine_to_handle != IntPtr.Zero) {
4131 XWindowAttributes attributes = new XWindowAttributes();
4133 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4136 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4138 Grab.Area.X = attributes.x;
4139 Grab.Area.Y = attributes.y;
4140 Grab.Area.Width = attributes.width;
4141 Grab.Area.Height = attributes.height;
4142 Grab.Confined = true;
4143 confine_to_window = hwnd.client_window;
4148 hwnd = Hwnd.ObjectFromHandle(handle);
4151 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4152 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4153 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4154 EventMask.LeaveWindowMask,
4155 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4159 internal override void UngrabWindow(IntPtr hwnd) {
4161 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4162 XFlush(DisplayHandle);
4164 WindowUngrabbed (hwnd);
4167 private void WindowUngrabbed (IntPtr hwnd) {
4168 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4170 Grab.Hwnd = IntPtr.Zero;
4171 Grab.Confined = false;
4174 // lparam should be the handle to the window gaining the mouse capture,
4175 // but X doesn't seem to give us that information.
4176 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4177 // X will send a NotifyUngrab, but since it comes late sometimes we're
4178 // calling WindowUngrabbed directly from UngrabWindow in order to send
4179 // this WM right away.
4180 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4184 internal override void HandleException(Exception e) {
4185 StackTrace st = new StackTrace(e, true);
4186 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4187 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4190 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4193 hwnd = Hwnd.ObjectFromHandle(handle);
4196 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4198 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4202 internal override void InvalidateNC (IntPtr handle) {
4205 hwnd = Hwnd.ObjectFromHandle(handle);
4207 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4210 internal override bool IsEnabled(IntPtr handle) {
4211 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4212 return (hwnd != null && hwnd.Enabled);
4215 internal override bool IsVisible(IntPtr handle) {
4216 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4217 return (hwnd != null && hwnd.visible);
4220 internal override void KillTimer(Timer timer) {
4221 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4223 if (queue == null) {
4224 // This isn't really an error, MS doesn't start the timer if
4225 // it has no assosciated queue
4228 queue.timer_list.Remove (timer);
4231 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4237 hwnd = Hwnd.ObjectFromHandle(handle);
4240 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4247 internal override void OverrideCursor(IntPtr cursor)
4249 if (Grab.Hwnd != IntPtr.Zero) {
4250 XChangeActivePointerGrab (DisplayHandle,
4251 EventMask.ButtonMotionMask |
4252 EventMask.PointerMotionMask |
4253 EventMask.ButtonPressMask |
4254 EventMask.ButtonReleaseMask,
4255 cursor, IntPtr.Zero);
4259 OverrideCursorHandle = cursor;
4262 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4263 PaintEventArgs paint_event;
4266 hwnd = Hwnd.ObjectFromHandle(handle);
4268 if (Caret.Visible == true) {
4269 Caret.Paused = true;
4276 dc = Graphics.FromHwnd (hwnd.client_window);
4278 Region clip_region = new Region ();
4279 clip_region.MakeEmpty();
4281 foreach (Rectangle r in hwnd.ClipRectangles) {
4282 clip_region.Union (r);
4285 if (hwnd.UserClip != null) {
4286 clip_region.Intersect(hwnd.UserClip);
4289 dc.Clip = clip_region;
4290 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4291 hwnd.expose_pending = false;
4293 hwnd.ClearInvalidArea();
4295 hwnd.drawing_stack.Push (paint_event);
4296 hwnd.drawing_stack.Push (dc);
4300 dc = Graphics.FromHwnd (hwnd.whole_window);
4302 if (!hwnd.nc_invalid.IsEmpty) {
4303 dc.SetClip (hwnd.nc_invalid);
4304 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4306 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4308 hwnd.nc_expose_pending = false;
4310 hwnd.ClearNcInvalidArea ();
4312 hwnd.drawing_stack.Push (paint_event);
4313 hwnd.drawing_stack.Push (dc);
4319 internal override void PaintEventEnd(IntPtr handle, bool client) {
4322 hwnd = Hwnd.ObjectFromHandle(handle);
4324 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4328 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4329 pe.SetGraphics (null);
4332 if (Caret.Visible == true) {
4334 Caret.Paused = false;
4338 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4339 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4340 XEventQueue queue = (XEventQueue) queue_id;
4343 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4344 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4348 if (queue.Count > 0) {
4351 // Only call UpdateMessageQueue if real events are pending
4352 // otherwise we go to sleep on the socket
4353 if (XPending(DisplayHandle) != 0) {
4354 UpdateMessageQueue((XEventQueue)queue_id);
4356 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4361 CheckTimers(queue.timer_list, DateTime.UtcNow);
4366 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4369 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4370 XEvent xevent = new XEvent ();
4371 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4373 xevent.type = XEventName.ClientMessage;
4374 xevent.ClientMessageEvent.display = DisplayHandle;
4377 xevent.ClientMessageEvent.window = hwnd.whole_window;
4379 xevent.ClientMessageEvent.window = IntPtr.Zero;
4382 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4383 xevent.ClientMessageEvent.format = 32;
4384 xevent.ClientMessageEvent.ptr1 = handle;
4385 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4386 xevent.ClientMessageEvent.ptr3 = wparam;
4387 xevent.ClientMessageEvent.ptr4 = lparam;
4389 hwnd.Queue.EnqueueLocked (xevent);
4394 internal override void PostQuitMessage(int exitCode) {
4395 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4396 XFlush(DisplayHandle);
4399 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4404 internal override void RequestNCRecalc(IntPtr handle) {
4407 hwnd = Hwnd.ObjectFromHandle(handle);
4413 PerformNCCalc(hwnd);
4414 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4415 InvalidateNC(handle);
4418 internal override void ResetMouseHover(IntPtr handle) {
4421 hwnd = Hwnd.ObjectFromHandle(handle);
4426 HoverState.Timer.Enabled = true;
4427 HoverState.X = mouse_position.X;
4428 HoverState.Y = mouse_position.Y;
4429 HoverState.Window = handle;
4433 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4439 hwnd = Hwnd.ObjectFromHandle(handle);
4442 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4449 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4455 hwnd = Hwnd.ObjectFromHandle(handle);
4458 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4465 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4468 XGCValues gc_values;
4470 hwnd = Hwnd.ObjectFromHandle(handle);
4472 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4474 /* We have an invalid area in the window we're scrolling.
4475 Adjust our stored invalid rectangle to to match the scrolled amount */
4490 if (area.Contains (hwnd.Invalid))
4491 hwnd.ClearInvalidArea ();
4492 hwnd.AddInvalidArea(r);
4495 gc_values = new XGCValues();
4497 if (with_children) {
4498 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4501 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4509 height = area.Height - YAmount;
4510 dest_y = area.Y + YAmount;
4513 src_y = area.Y - YAmount;
4514 height = area.Height + YAmount;
4520 width = area.Width - XAmount;
4521 dest_x = area.X + XAmount;
4524 src_x = area.X - XAmount;
4525 width = area.Width + XAmount;
4529 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4531 // Generate an expose for the area exposed by the horizontal scroll
4532 // We don't use AddExpose since we're
4534 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4535 } else if (XAmount < 0) {
4536 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4539 // Generate an expose for the area exposed by the vertical scroll
4541 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4542 } else if (YAmount < 0) {
4543 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4545 XFreeGC(DisplayHandle, gc);
4548 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4552 hwnd = Hwnd.GetObjectFromWindow(handle);
4554 rect = hwnd.ClientRect;
4557 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4560 internal override void SendAsyncMethod (AsyncMethodData method) {
4562 XEvent xevent = new XEvent ();
4564 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4566 xevent.type = XEventName.ClientMessage;
4567 xevent.ClientMessageEvent.display = DisplayHandle;
4568 xevent.ClientMessageEvent.window = method.Handle;
4569 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4570 xevent.ClientMessageEvent.format = 32;
4571 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4573 hwnd.Queue.EnqueueLocked (xevent);
4578 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4580 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4583 h = Hwnd.ObjectFromHandle(hwnd);
4585 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4586 AsyncMethodResult result;
4587 AsyncMethodData data;
4589 result = new AsyncMethodResult ();
4590 data = new AsyncMethodData ();
4593 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4594 data.Args = new object[] { hwnd, message, wParam, lParam };
4595 data.Result = result;
4597 SendAsyncMethod (data);
4598 #if DriverDebug || DriverDebugThreads
4599 Console.WriteLine ("Sending {0} message across.", message);
4604 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4607 internal override int SendInput(IntPtr handle, Queue keys) {
4608 if (handle == IntPtr.Zero)
4611 int count = keys.Count;
4612 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4614 while (keys.Count > 0) {
4616 MSG msg = (MSG)keys.Dequeue();
4618 XEvent xevent = new XEvent ();
4620 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4621 xevent.KeyEvent.display = DisplayHandle;
4624 xevent.KeyEvent.window = hwnd.whole_window;
4626 xevent.KeyEvent.window = IntPtr.Zero;
4629 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4631 hwnd.Queue.EnqueueLocked (xevent);
4636 internal override void SetAllowDrop (IntPtr handle, bool value)
4638 // We allow drop on all windows
4641 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4642 DragDropEffects allowed_effects)
4644 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4647 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4649 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4652 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4653 Form form = Control.FromHandle (handle) as Form;
4654 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4655 border_style == FormBorderStyle.SizableToolWindow)) {
4656 form.window_manager = new ToolWindowManager (form);
4659 RequestNCRecalc(handle);
4662 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4663 if (Caret.Hwnd == handle) {
4670 if (Caret.Visible == true) {
4672 Caret.Timer.Start();
4677 internal override void SetClipRegion(IntPtr handle, Region region) {
4680 hwnd = Hwnd.ObjectFromHandle(handle);
4685 hwnd.UserClip = region;
4686 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4689 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4692 if (OverrideCursorHandle == IntPtr.Zero) {
4693 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4697 LastCursorHandle = cursor;
4698 LastCursorWindow = handle;
4700 hwnd = Hwnd.ObjectFromHandle(handle);
4702 if (cursor != IntPtr.Zero) {
4703 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4705 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4707 XFlush(DisplayHandle);
4712 hwnd = Hwnd.ObjectFromHandle(handle);
4714 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4718 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4719 out int root_x, out int root_y, out int child_x, out int child_y,
4722 /* this code was written with the help of
4723 glance at gdk. I never would have realized we
4724 needed a loop in order to traverse down in the
4725 hierarchy. I would have assumed you'd get the
4726 most deeply nested child and have to do
4727 XQueryTree to move back up the hierarchy..
4728 stupid me, of course. */
4731 XGrabServer (display);
4733 XQueryPointer(display, w, out root, out c,
4734 out root_x, out root_y, out child_x, out child_y,
4740 IntPtr child_last = IntPtr.Zero;
4741 while (c != IntPtr.Zero) {
4743 XQueryPointer(display, c, out root, out c,
4744 out root_x, out root_y, out child_x, out child_y,
4747 XUngrabServer (display);
4753 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4754 if (handle == IntPtr.Zero) {
4757 int root_x, root_y, child_x, child_y, mask;
4760 * QueryPointer before warping
4761 * because if the warp is on
4762 * the RootWindow, the x/y are
4763 * relative to the current
4766 QueryPointer (DisplayHandle, RootWindow,
4769 out root_x, out root_y,
4770 out child_x, out child_y,
4773 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4775 XFlush (DisplayHandle);
4777 /* then we need to a
4778 * QueryPointer after warping
4779 * to manually generate a
4780 * motion event for the window
4783 QueryPointer (DisplayHandle, RootWindow,
4786 out root_x, out root_y,
4787 out child_x, out child_y,
4790 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4791 if (child_hwnd == null) {
4795 XEvent xevent = new XEvent ();
4797 xevent.type = XEventName.MotionNotify;
4798 xevent.MotionEvent.display = DisplayHandle;
4799 xevent.MotionEvent.window = child_hwnd.client_window;
4800 xevent.MotionEvent.root = RootWindow;
4801 xevent.MotionEvent.x = child_x;
4802 xevent.MotionEvent.y = child_y;
4803 xevent.MotionEvent.x_root = root_x;
4804 xevent.MotionEvent.y_root = root_y;
4805 xevent.MotionEvent.state = mask;
4807 child_hwnd.Queue.EnqueueLocked (xevent);
4812 hwnd = Hwnd.ObjectFromHandle(handle);
4814 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4819 internal override void SetFocus(IntPtr handle) {
4821 IntPtr prev_focus_window;
4823 hwnd = Hwnd.ObjectFromHandle(handle);
4825 if (hwnd.client_window == FocusWindow) {
4829 prev_focus_window = FocusWindow;
4830 FocusWindow = hwnd.client_window;
4832 if (prev_focus_window != IntPtr.Zero) {
4833 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4835 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4837 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4840 internal override void SetIcon(IntPtr handle, Icon icon) {
4843 hwnd = Hwnd.ObjectFromHandle(handle);
4845 SetIcon(hwnd, icon);
4849 internal override void SetMenu(IntPtr handle, Menu menu) {
4852 hwnd = Hwnd.ObjectFromHandle(handle);
4855 RequestNCRecalc(handle);
4858 internal override void SetModal(IntPtr handle, bool Modal) {
4860 ModalWindows.Push(handle);
4862 if (ModalWindows.Contains(handle)) {
4865 if (ModalWindows.Count > 0) {
4866 Activate((IntPtr)ModalWindows.Peek());
4871 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4874 hwnd = Hwnd.ObjectFromHandle(handle);
4875 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4878 #if DriverDebug || DriverDebugParent
4879 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4881 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4887 internal override void SetTimer (Timer timer) {
4888 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4890 if (queue == null) {
4891 // This isn't really an error, MS doesn't start the timer if
4892 // it has no assosciated queue
4895 queue.timer_list.Add (timer);
4899 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4901 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4905 int[] atoms = new int[8];
4906 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
4907 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4911 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
4917 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
4921 hwnd = Hwnd.ObjectFromHandle(handle);
4923 if (handle_owner != IntPtr.Zero) {
4924 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4930 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4931 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4933 if (hwnd_owner != null) {
4934 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4936 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4941 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4947 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
4951 hwnd = Hwnd.ObjectFromHandle(handle);
4952 hwnd.visible = visible;
4956 MapWindow(hwnd, WindowType.Both);
4958 if (Control.FromHandle(handle) is Form) {
4961 s = ((Form)Control.FromHandle(handle)).WindowState;
4964 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4965 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4969 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4972 UnmapWindow(hwnd, WindowType.Both);
4978 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4983 hwnd = Hwnd.ObjectFromHandle(handle);
4988 hints = new XSizeHints();
4990 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4991 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4992 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4993 hints.min_width = min.Width;
4994 hints.min_height = min.Height;
4997 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4998 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4999 hints.max_width = max.Width;
5000 hints.max_height = max.Height;
5003 if (hints.flags != IntPtr.Zero) {
5004 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5007 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5008 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5009 hints.x = maximized.X;
5010 hints.y = maximized.Y;
5011 hints.width = maximized.Width;
5012 hints.height = maximized.Height;
5014 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5015 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5020 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5023 hwnd = Hwnd.ObjectFromHandle(handle);
5029 // Win32 automatically changes negative width/height to 0.
5035 // X requires a sanity check for width & height; otherwise it dies
5036 if (hwnd.zero_sized && width > 0 && height > 0) {
5038 MapWindow(hwnd, WindowType.Whole);
5040 hwnd.zero_sized = false;
5043 if ((width < 1) || (height < 1)) {
5044 hwnd.zero_sized = true;
5045 UnmapWindow(hwnd, WindowType.Whole);
5048 // Save a server roundtrip (and prevent a feedback loop)
5049 if ((hwnd.x == x) && (hwnd.y == y) &&
5050 (hwnd.width == width) && (hwnd.height == height)) {
5054 if (!hwnd.zero_sized) {
5059 hwnd.height = height;
5060 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5062 if (hwnd.fixed_size) {
5063 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5067 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
5068 PerformNCCalc(hwnd);
5072 // Update our position/size immediately, so
5073 // that future calls to SetWindowPos aren't
5074 // kept from calling XMoveResizeWindow (by the
5075 // "Save a server roundtrip" block above).
5079 hwnd.height = height;
5080 hwnd.ClientRect = Rectangle.Empty;
5083 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5084 FormWindowState current_state;
5087 hwnd = Hwnd.ObjectFromHandle(handle);
5089 current_state = GetWindowState(handle);
5091 if (current_state == state) {
5096 case FormWindowState.Normal: {
5098 if (current_state == FormWindowState.Minimized) {
5099 MapWindow(hwnd, WindowType.Both);
5100 } else if (current_state == FormWindowState.Maximized) {
5101 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5108 case FormWindowState.Minimized: {
5110 if (current_state == FormWindowState.Maximized) {
5111 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5113 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5118 case FormWindowState.Maximized: {
5120 if (current_state == FormWindowState.Minimized) {
5121 MapWindow(hwnd, WindowType.Both);
5124 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5132 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5135 hwnd = Hwnd.ObjectFromHandle(handle);
5136 SetHwndStyles(hwnd, cp);
5137 SetWMStyles(hwnd, cp);
5140 internal override double GetWindowTransparency(IntPtr handle)
5145 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5149 hwnd = Hwnd.ObjectFromHandle(handle);
5155 hwnd.opacity = (uint)(0xffffffff * transparency);
5156 opacity = (IntPtr)((int)hwnd.opacity);
5158 IntPtr w = hwnd.whole_window;
5159 if (hwnd.reparented)
5160 w = XGetParent (hwnd.whole_window);
5161 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5164 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5165 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5173 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5176 } else if (!bottom) {
5177 Hwnd after_hwnd = null;
5179 if (after_handle != IntPtr.Zero) {
5180 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5183 XWindowChanges values = new XWindowChanges();
5185 if (after_hwnd == null) {
5186 // Work around metacity 'issues'
5190 atoms[0] = unixtime();
5191 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5193 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5194 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5196 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5199 values.sibling = after_hwnd.whole_window;
5200 values.stack_mode = StackMode.Below;
5203 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5208 XLowerWindow(DisplayHandle, hwnd.whole_window);
5215 internal override void ShowCursor(bool show) {
5216 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5219 internal override object StartLoop(Thread thread) {
5220 XEventQueue q = ThreadQueue(thread);
5224 internal override TransparencySupport SupportsTransparency() {
5225 // We need to check if the x compositing manager is running
5226 return TransparencySupport.Set;
5229 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5230 GetSystrayManagerWindow();
5232 if (SystrayMgrWindow != IntPtr.Zero) {
5233 XSizeHints size_hints;
5236 hwnd = Hwnd.ObjectFromHandle(handle);
5238 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5242 if (hwnd.client_window != hwnd.whole_window) {
5243 XDestroyWindow(DisplayHandle, hwnd.client_window);
5244 hwnd.client_window = hwnd.whole_window;
5246 /* by virtue of the way the tests are ordered when determining if it's PAINT
5247 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5248 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5249 there's a pending expose). */
5250 if (hwnd.nc_expose_pending) {
5251 hwnd.nc_expose_pending = false;
5252 if (!hwnd.expose_pending)
5253 hwnd.Queue.Paint.Remove (hwnd);
5257 size_hints = new XSizeHints();
5259 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5261 size_hints.min_width = 24;
5262 size_hints.min_height = 24;
5263 size_hints.max_width = 24;
5264 size_hints.max_height = 24;
5265 size_hints.base_width = 24;
5266 size_hints.base_height = 24;
5268 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5270 int[] atoms = new int[2];
5271 atoms [0] = 1; // Version 1
5272 atoms [1] = 1; // we want to be mapped
5274 // This line cost me 3 days...
5275 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5277 // Need to pick some reasonable defaults
5279 tt.AutomaticDelay = 100;
5280 tt.InitialDelay = 250;
5281 tt.ReshowDelay = 250;
5282 tt.ShowAlways = true;
5284 if ((tip != null) && (tip != string.Empty)) {
5285 tt.SetToolTip(Control.FromHandle(handle), tip);
5291 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5299 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5302 control = Control.FromHandle(handle);
5303 if (control != null && tt != null) {
5304 tt.SetToolTip(control, tip);
5312 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5314 #if GTKSOCKET_SUPPORTS_REPARENTING
5317 hwnd = Hwnd.ObjectFromHandle(handle);
5319 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5320 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5321 * 2. The client can reparent its window out of the embedder window.
5322 * 3. The client can destroy its window.
5324 * this call to SetParent is case 2, but in
5325 * the spec it also mentions that gtk doesn't
5326 * support this at present. Looking at HEAD
5327 * gtksocket-x11.c jives with this statement.
5329 * so we can't reparent. we have to destroy.
5331 SetParent(hwnd.whole_window, FosterParent);
5333 Control control = Control.FromHandle(handle);
5334 if (control is NotifyIcon.NotifyIconWindow)
5335 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5338 // The caller can now re-dock it later...
5345 internal override bool Text(IntPtr handle, string text) {
5348 hwnd = Hwnd.ObjectFromHandle(handle);
5351 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5352 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5354 // XXX this has problems with UTF8.
5355 // we need to either use the actual
5356 // text if it's latin-1, or convert it
5357 // to compound text if it's in a
5358 // different charset.
5359 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5364 internal override bool TranslateMessage(ref MSG msg) {
5365 return Keyboard.TranslateMessage (ref msg);
5368 internal override void UpdateWindow(IntPtr handle) {
5371 hwnd = Hwnd.ObjectFromHandle(handle);
5373 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5377 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5378 hwnd.Queue.Paint.Remove(hwnd);
5381 internal override void CreateOffscreenDrawable (IntPtr handle,
5382 int width, int height,
5383 out object offscreen_drawable)
5386 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5388 XGetGeometry (DisplayHandle, handle,
5390 out x_out, out y_out,
5391 out width_out, out height_out,
5392 out border_width_out, out depth_out);
5394 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5396 offscreen_drawable = pixmap;
5400 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5402 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5405 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5407 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5410 internal override void BlitFromOffscreen (IntPtr dest_handle,
5412 object offscreen_drawable,
5413 Graphics offscreen_dc,
5416 XGCValues gc_values;
5419 gc_values = new XGCValues();
5421 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5423 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5424 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5426 XFreeGC (DisplayHandle, gc);
5429 #endregion // Public Static Methods
5432 internal override event EventHandler Idle;
5433 #endregion // Events
5436 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5437 internal extern static IntPtr XOpenDisplay(IntPtr display);
5438 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5439 internal extern static int XCloseDisplay(IntPtr display);
5440 [DllImport ("libX11", EntryPoint="XSynchronize")]
5441 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5443 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5444 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);
5445 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5446 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5447 [DllImport ("libX11", EntryPoint="XMapWindow")]
5448 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5449 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5450 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5451 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5452 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5453 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5454 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5455 [DllImport ("libX11", EntryPoint="XRootWindow")]
5456 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5457 [DllImport ("libX11", EntryPoint="XNextEvent")]
5458 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5459 [DllImport ("libX11")]
5460 internal extern static int XConnectionNumber (IntPtr diplay);
5461 [DllImport ("libX11")]
5462 internal extern static int XPending (IntPtr diplay);
5463 [DllImport ("libX11", EntryPoint="XSelectInput")]
5464 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5466 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5467 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5469 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5470 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5471 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5472 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5474 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5475 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5477 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5478 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5480 [DllImport ("libX11", EntryPoint="XFlush")]
5481 internal extern static int XFlush(IntPtr display);
5483 [DllImport ("libX11", EntryPoint="XSetWMName")]
5484 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5486 [DllImport ("libX11", EntryPoint="XStoreName")]
5487 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5489 [DllImport ("libX11", EntryPoint="XFetchName")]
5490 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5492 [DllImport ("libX11", EntryPoint="XSendEvent")]
5493 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5495 [DllImport ("libX11", EntryPoint="XQueryTree")]
5496 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);
5498 [DllImport ("libX11", EntryPoint="XFree")]
5499 internal extern static int XFree(IntPtr data);
5501 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5502 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5504 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5505 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5507 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5508 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5510 [DllImport ("libX11", EntryPoint="XInternAtom")]
5511 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5513 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5514 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5516 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5517 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5519 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5520 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);
5522 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5523 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5525 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5526 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);
5528 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5529 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);
5531 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5532 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);
5534 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5535 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);
5537 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5538 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);
5540 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5541 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);
5543 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5544 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);
5546 [DllImport ("libX11", EntryPoint="XClearWindow")]
5547 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5549 [DllImport ("libX11", EntryPoint="XClearArea")]
5550 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5553 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5554 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5556 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5557 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5559 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5560 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5562 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5563 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5565 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5566 internal extern static int XDefaultScreen(IntPtr display);
5568 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5569 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5571 [DllImport ("libX11", EntryPoint="XLookupColor")]
5572 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5574 [DllImport ("libX11", EntryPoint="XAllocColor")]
5575 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5577 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5578 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5580 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5581 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5583 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5584 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5586 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5587 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5589 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5590 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5592 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5593 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5595 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5596 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5598 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5599 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5601 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5602 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5604 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5605 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5607 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5608 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5611 [DllImport ("libX11", EntryPoint="XCreateGC")]
5612 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5614 [DllImport ("libX11", EntryPoint="XFreeGC")]
5615 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5617 [DllImport ("libX11", EntryPoint="XSetFunction")]
5618 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5620 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5621 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5623 [DllImport ("libX11", EntryPoint="XDrawLine")]
5624 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5626 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5627 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5629 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5630 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5632 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5633 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5635 [DllImport ("libX11", EntryPoint="XCopyArea")]
5636 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);
5638 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5639 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);
5641 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5642 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5644 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5645 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5647 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5648 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5650 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5651 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5653 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5654 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5656 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5657 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5659 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5660 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);
5662 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5663 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5665 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5666 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5668 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5669 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5671 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5672 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5674 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5675 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5677 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5678 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5680 [DllImport ("libX11", EntryPoint="XGrabServer")]
5681 internal extern static void XGrabServer(IntPtr display);
5683 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5684 internal extern static void XUngrabServer(IntPtr display);
5686 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5687 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5689 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5690 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5692 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5693 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5695 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5696 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5698 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5699 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5701 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5702 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5704 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5705 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5707 [DllImport ("libX11", EntryPoint="XInitThreads")]
5708 internal extern static int XInitThreads();
5710 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5711 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5713 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5714 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5716 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5717 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5719 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5720 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5722 [DllImport ("libX11", EntryPoint="XSetForeground")]
5723 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5725 [DllImport ("libX11", EntryPoint="XSetBackground")]
5726 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5728 [DllImport ("libX11", EntryPoint="XBell")]
5729 internal extern static int XBell(IntPtr display, int percent);
5731 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5732 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5734 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5735 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5737 [DllImport ("libX11")]
5738 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5740 [DllImport ("libX11")]
5741 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);