1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
90 private int render_major_opcode;
91 private int render_first_event;
92 private int render_first_error;
95 private static IntPtr ClipMagic;
96 private static ClipboardStruct Clipboard; // Our clipboard
99 private static IntPtr PostAtom; // PostMessage atom
100 private static IntPtr AsyncAtom; // Support for async messages
103 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
105 private static Pollfd[] pollfds; // For watching the X11 socket
106 private static bool wake_waiting;
107 private static object wake_waiting_lock = new object ();
109 private static X11Keyboard Keyboard; //
110 private static X11Dnd Dnd;
111 private static Socket listen; //
112 private static Socket wake; //
113 private static Socket wake_receive; //
114 private static byte[] network_buffer; //
115 private static bool detectable_key_auto_repeat;
118 private static IntPtr ActiveWindow; // Handle of the active window
119 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
122 private static Stack ModalWindows; // Stack of our modal windows
125 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
128 private static IntPtr LastCursorWindow; // The last window we set the cursor on
129 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
130 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
133 private static CaretStruct Caret; //
136 private static IntPtr WM_PROTOCOLS;
137 private static IntPtr WM_DELETE_WINDOW;
138 private static IntPtr WM_TAKE_FOCUS;
139 //private static IntPtr _NET_SUPPORTED;
140 //private static IntPtr _NET_CLIENT_LIST;
141 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
142 private static IntPtr _NET_DESKTOP_GEOMETRY;
143 //private static IntPtr _NET_DESKTOP_VIEWPORT;
144 private static IntPtr _NET_CURRENT_DESKTOP;
145 //private static IntPtr _NET_DESKTOP_NAMES;
146 private static IntPtr _NET_ACTIVE_WINDOW;
147 private static IntPtr _NET_WORKAREA;
148 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
149 //private static IntPtr _NET_VIRTUAL_ROOTS;
150 //private static IntPtr _NET_DESKTOP_LAYOUT;
151 //private static IntPtr _NET_SHOWING_DESKTOP;
152 //private static IntPtr _NET_CLOSE_WINDOW;
153 //private static IntPtr _NET_MOVERESIZE_WINDOW;
154 //private static IntPtr _NET_WM_MOVERESIZE;
155 //private static IntPtr _NET_RESTACK_WINDOW;
156 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
157 private static IntPtr _NET_WM_NAME;
158 //private static IntPtr _NET_WM_VISIBLE_NAME;
159 //private static IntPtr _NET_WM_ICON_NAME;
160 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
161 //private static IntPtr _NET_WM_DESKTOP;
162 private static IntPtr _NET_WM_WINDOW_TYPE;
163 private static IntPtr _NET_WM_STATE;
164 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
165 //private static IntPtr _NET_WM_STRUT;
166 //private static IntPtr _NET_WM_STRUT_PARTIAL;
167 //private static IntPtr _NET_WM_ICON_GEOMETRY;
168 private static IntPtr _NET_WM_ICON;
169 //private static IntPtr _NET_WM_PID;
170 //private static IntPtr _NET_WM_HANDLED_ICONS;
171 private static IntPtr _NET_WM_USER_TIME;
172 private static IntPtr _NET_FRAME_EXTENTS;
173 //private static IntPtr _NET_WM_PING;
174 //private static IntPtr _NET_WM_SYNC_REQUEST;
175 private static IntPtr _NET_SYSTEM_TRAY_S;
176 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
177 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
178 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
179 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
180 private static IntPtr _XEMBED;
181 private static IntPtr _XEMBED_INFO;
182 private static IntPtr _MOTIF_WM_HINTS;
183 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
184 private static IntPtr _NET_WM_STATE_ABOVE;
185 //private static IntPtr _NET_WM_STATE_MODAL;
186 private static IntPtr _NET_WM_STATE_HIDDEN;
187 private static IntPtr _NET_WM_CONTEXT_HELP;
188 private static IntPtr _NET_WM_WINDOW_OPACITY;
189 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
190 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
193 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
194 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
195 //private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
196 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
197 private static IntPtr CLIPBOARD;
198 private static IntPtr PRIMARY;
199 //private static IntPtr DIB;
200 private static IntPtr OEMTEXT;
201 private static IntPtr UNICODETEXT;
202 private static IntPtr TARGETS;
204 // mouse hover message generation
205 private static HoverStruct HoverState; //
207 // double click message generation
208 private static ClickStruct ClickPending; //
210 // Support for mouse grab
211 private static GrabStruct Grab; //
214 Point mouse_position; // Last position of mouse, in screen coords
215 internal static MouseButtons MouseState; // Last state of mouse buttons
218 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
220 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
221 EventMask.ButtonReleaseMask |
222 EventMask.KeyPressMask |
223 EventMask.KeyReleaseMask |
224 EventMask.EnterWindowMask |
225 EventMask.LeaveWindowMask |
226 EventMask.ExposureMask |
227 EventMask.FocusChangeMask |
228 EventMask.PointerMotionMask |
229 EventMask.SubstructureNotifyMask);
231 static readonly object lockobj = new object ();
233 #endregion // Local Variables
235 private XplatUIX11() {
236 // Handle singleton stuff first
239 // Now regular initialization
240 XlibLock = new object ();
241 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
244 ErrorExceptions = false;
246 // X11 Initialization
247 SetDisplay(XOpenDisplay(IntPtr.Zero));
248 X11DesktopColors.Initialize();
251 // Disable keyboard autorepeat
253 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
254 detectable_key_auto_repeat = true;
256 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
257 detectable_key_auto_repeat = false;
260 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
261 ErrorHandler = new XErrorHandler(HandleError);
262 XSetErrorHandler(ErrorHandler);
266 // Remove our display handle from S.D
267 Graphics.FromHdcInternal (IntPtr.Zero);
270 #endregion // Constructors
272 #region Singleton Specific Code
273 public static XplatUIX11 GetInstance() {
275 if (Instance == null) {
276 Instance=new XplatUIX11();
283 public int Reference {
290 #region Internal Properties
291 internal static IntPtr Display {
293 return DisplayHandle;
297 XplatUIX11.GetInstance().SetDisplay(value);
301 internal static int Screen {
311 internal static IntPtr RootWindowHandle {
321 internal static IntPtr Visual {
327 CustomVisual = value;
331 internal static IntPtr ColorMap {
333 return CustomColormap;
337 CustomColormap = value;
342 #region XExceptionClass
343 internal class XException : ApplicationException {
347 XRequest RequestCode;
351 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
352 this.Display = Display;
353 this.ResourceID = ResourceID;
354 this.Serial = Serial;
355 this.RequestCode = RequestCode;
356 this.ErrorCode = ErrorCode;
357 this.MinorCode = MinorCode;
360 public override string Message {
362 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
366 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
375 sb = new StringBuilder(160);
376 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
377 x_error_text = sb.ToString();
378 hwnd = Hwnd.ObjectFromHandle(ResourceID);
380 hwnd_text = hwnd.ToString();
381 c = Control.FromHandle(hwnd.Handle);
383 control_text = c.ToString();
385 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
388 hwnd_text = "<null>";
389 control_text = "<null>";
393 error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
397 #endregion // XExceptionClass
399 #region Internal Methods
400 internal void SetDisplay(IntPtr display_handle) {
401 if (display_handle != IntPtr.Zero) {
404 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
405 hwnd = Hwnd.ObjectFromHandle(FosterParent);
406 XDestroyWindow(DisplayHandle, FosterParent);
410 if (DisplayHandle != IntPtr.Zero) {
411 XCloseDisplay(DisplayHandle);
414 DisplayHandle=display_handle;
416 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
417 // been hacked to do this for us.
418 Graphics.FromHdcInternal (DisplayHandle);
420 // query for the render extension so
421 // we can ignore the spurious
422 // BadPicture errors that are
423 // generated by cairo/render.
424 XQueryExtension (DisplayHandle, "RENDER",
425 ref render_major_opcode, ref render_first_event, ref render_first_error);
428 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
429 XSynchronize(DisplayHandle, true);
432 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
433 ErrorExceptions = true;
437 ScreenNo = XDefaultScreen(DisplayHandle);
438 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
439 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
441 // Create the foster parent
442 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
443 if (FosterParent==IntPtr.Zero) {
444 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
448 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
449 hwnd.WholeWindow = FosterParent;
450 hwnd.ClientWindow = FosterParent;
452 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
454 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
455 hwnd.whole_window = RootWindow;
456 hwnd.ClientWindow = RootWindow;
458 // For sleeping on the X11 socket
459 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
460 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
464 // To wake up when a timer is ready
465 network_buffer = new byte[10];
467 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
468 wake.Connect(listen.LocalEndPoint);
469 wake_receive = listen.Accept();
472 pollfds = new Pollfd [2];
473 pollfds [0] = new Pollfd ();
474 pollfds [0].fd = XConnectionNumber (DisplayHandle);
475 pollfds [0].events = PollEvents.POLLIN;
477 pollfds [1] = new Pollfd ();
478 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
479 pollfds [1].events = PollEvents.POLLIN;
482 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
483 Dnd = new X11Dnd (DisplayHandle, Keyboard);
485 DoubleClickInterval = 500;
487 HoverState.Interval = 500;
488 HoverState.Timer = new Timer();
489 HoverState.Timer.Enabled = false;
490 HoverState.Timer.Interval = HoverState.Interval;
491 HoverState.Timer.Tick += new EventHandler(MouseHover);
492 HoverState.Size = new Size(4, 4);
496 ActiveWindow = IntPtr.Zero;
497 FocusWindow = IntPtr.Zero;
498 ModalWindows = new Stack(3);
500 MouseState = MouseButtons.None;
501 mouse_position = new Point(0, 0);
503 Caret.Timer = new Timer();
504 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
505 Caret.Timer.Tick += new EventHandler(CaretCallback);
509 // Grab atom changes off the root window to catch certain WM events
510 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
512 // Handle any upcoming errors
513 ErrorHandler = new XErrorHandler(HandleError);
514 XSetErrorHandler(ErrorHandler);
516 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
519 #endregion // Internal Methods
521 #region Private Methods
522 private int unixtime() {
523 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
525 return (int) t.TotalSeconds;
528 private static void SetupAtoms() {
529 // make sure this array stays in sync with the statements below
530 string [] atom_names = new string[] {
535 //"_NET_CLIENT_LIST",
536 //"_NET_NUMBER_OF_DESKTOPS",
537 "_NET_DESKTOP_GEOMETRY",
538 //"_NET_DESKTOP_VIEWPORT",
539 "_NET_CURRENT_DESKTOP",
540 //"_NET_DESKTOP_NAMES",
541 "_NET_ACTIVE_WINDOW",
543 //"_NET_SUPPORTING_WM_CHECK",
544 //"_NET_VIRTUAL_ROOTS",
545 //"_NET_DESKTOP_LAYOUT",
546 //"_NET_SHOWING_DESKTOP",
547 //"_NET_CLOSE_WINDOW",
548 //"_NET_MOVERESIZE_WINDOW",
549 //"_NET_WM_MOVERESIZE",
550 //"_NET_RESTACK_WINDOW",
551 //"_NET_REQUEST_FRAME_EXTENTS",
553 //"_NET_WM_VISIBLE_NAME",
554 //"_NET_WM_ICON_NAME",
555 //"_NET_WM_VISIBLE_ICON_NAME",
557 "_NET_WM_WINDOW_TYPE",
559 //"_NET_WM_ALLOWED_ACTIONS",
561 //"_NET_WM_STRUT_PARTIAL",
562 //"_NET_WM_ICON_GEOMETRY",
565 //"_NET_WM_HANDLED_ICONS",
567 "_NET_FRAME_EXTENTS",
569 //"_NET_WM_SYNC_REQUEST",
570 "_NET_SYSTEM_TRAY_OPCODE",
571 //"_NET_SYSTEM_TRAY_ORIENTATION",
572 "_NET_WM_STATE_MAXIMIZED_HORZ",
573 "_NET_WM_STATE_MAXIMIZED_VERT",
574 "_NET_WM_STATE_HIDDEN",
578 "_NET_WM_STATE_SKIP_TASKBAR",
579 "_NET_WM_STATE_ABOVE",
580 //"_NET_WM_STATE_MODAL",
581 "_NET_WM_CONTEXT_HELP",
582 "_NET_WM_WINDOW_OPACITY",
583 //"_NET_WM_WINDOW_TYPE_DESKTOP",
584 //"_NET_WM_WINDOW_TYPE_DOCK",
585 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
586 //"_NET_WM_WINDOW_TYPE_MENU",
587 "_NET_WM_WINDOW_TYPE_UTILITY",
588 //"_NET_WM_WINDOW_TYPE_DIALOG",
589 //"_NET_WM_WINDOW_TYPE_SPLASH",
590 "_NET_WM_WINDOW_TYPE_NORMAL",
597 "_SWF_PostMessageAtom",
600 IntPtr[] atoms = new IntPtr [atom_names.Length];;
602 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
605 WM_PROTOCOLS = atoms [off++];
606 WM_DELETE_WINDOW = atoms [off++];
607 WM_TAKE_FOCUS = atoms [off++];
608 //_NET_SUPPORTED = atoms [off++];
609 //_NET_CLIENT_LIST = atoms [off++];
610 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
611 _NET_DESKTOP_GEOMETRY = atoms [off++];
612 //_NET_DESKTOP_VIEWPORT = atoms [off++];
613 _NET_CURRENT_DESKTOP = atoms [off++];
614 //_NET_DESKTOP_NAMES = atoms [off++];
615 _NET_ACTIVE_WINDOW = atoms [off++];
616 _NET_WORKAREA = atoms [off++];
617 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
618 //_NET_VIRTUAL_ROOTS = atoms [off++];
619 //_NET_DESKTOP_LAYOUT = atoms [off++];
620 //_NET_SHOWING_DESKTOP = atoms [off++];
621 //_NET_CLOSE_WINDOW = atoms [off++];
622 //_NET_MOVERESIZE_WINDOW = atoms [off++];
623 //_NET_WM_MOVERESIZE = atoms [off++];
624 //_NET_RESTACK_WINDOW = atoms [off++];
625 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
626 _NET_WM_NAME = atoms [off++];
627 //_NET_WM_VISIBLE_NAME = atoms [off++];
628 //_NET_WM_ICON_NAME = atoms [off++];
629 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
630 //_NET_WM_DESKTOP = atoms [off++];
631 _NET_WM_WINDOW_TYPE = atoms [off++];
632 _NET_WM_STATE = atoms [off++];
633 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
634 //_NET_WM_STRUT = atoms [off++];
635 //_NET_WM_STRUT_PARTIAL = atoms [off++];
636 //_NET_WM_ICON_GEOMETRY = atoms [off++];
637 _NET_WM_ICON = atoms [off++];
638 //_NET_WM_PID = atoms [off++];
639 //_NET_WM_HANDLED_ICONS = atoms [off++];
640 _NET_WM_USER_TIME = atoms [off++];
641 _NET_FRAME_EXTENTS = atoms [off++];
642 //_NET_WM_PING = atoms [off++];
643 //_NET_WM_SYNC_REQUEST = atoms [off++];
644 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
645 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
646 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
647 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
648 _NET_WM_STATE_HIDDEN = atoms [off++];
649 _XEMBED = atoms [off++];
650 _XEMBED_INFO = atoms [off++];
651 _MOTIF_WM_HINTS = atoms [off++];
652 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
653 _NET_WM_STATE_ABOVE = atoms [off++];
654 //_NET_WM_STATE_MODAL = atoms [off++];
655 _NET_WM_CONTEXT_HELP = atoms [off++];
656 _NET_WM_WINDOW_OPACITY = atoms [off++];
657 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
658 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
659 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
660 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
661 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
662 //_NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
663 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
664 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
665 CLIPBOARD = atoms [off++];
666 PRIMARY = atoms [off++];
667 OEMTEXT = atoms [off++];
668 UNICODETEXT = atoms [off++];
669 TARGETS = atoms [off++];
670 AsyncAtom = atoms [off++];
671 PostAtom = atoms [off++];
672 HoverState.Atom = atoms [off++];
674 //DIB = (IntPtr)Atom.XA_PIXMAP;
675 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
678 private void GetSystrayManagerWindow() {
679 XGrabServer(DisplayHandle);
680 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
681 XUngrabServer(DisplayHandle);
682 XFlush(DisplayHandle);
685 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
689 xev.ClientMessageEvent.type = XEventName.ClientMessage;
690 xev.ClientMessageEvent.send_event = true;
691 xev.ClientMessageEvent.window = window;
692 xev.ClientMessageEvent.message_type = message_type;
693 xev.ClientMessageEvent.format = 32;
694 xev.ClientMessageEvent.ptr1 = l0;
695 xev.ClientMessageEvent.ptr2 = l1;
696 xev.ClientMessageEvent.ptr3 = l2;
697 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
700 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
704 xev.ClientMessageEvent.type = XEventName.ClientMessage;
705 xev.ClientMessageEvent.send_event = true;
706 xev.ClientMessageEvent.window = window;
707 xev.ClientMessageEvent.message_type = message_type;
708 xev.ClientMessageEvent.format = 32;
709 xev.ClientMessageEvent.ptr1 = l0;
710 xev.ClientMessageEvent.ptr2 = l1;
711 xev.ClientMessageEvent.ptr3 = l2;
712 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
715 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
716 // WM_CREATE and WM_DESTROY causes
717 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
721 if (child == IntPtr.Zero) {
725 hwnd = Hwnd.GetObjectFromWindow (child);
731 if (hwnd.Handle == IntPtr.Zero) {
735 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
739 if (hwnd.Parent == null) {
743 if (hwnd.Parent.Handle == IntPtr.Zero) {
747 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
748 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
750 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
753 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
756 bool StyleSet (int s, WindowStyles ws)
758 return (s & (int)ws) == (int)ws;
761 bool ExStyleSet (int ex, WindowExStyles exws)
763 return (ex & (int)exws) == (int)exws;
766 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) {
769 tool_caption_height = 19;
770 border_static = false;
772 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
773 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
774 border_style = FormBorderStyle.Fixed3D;
775 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
776 border_style = FormBorderStyle.Fixed3D;
777 border_static = true;
778 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
779 border_style = FormBorderStyle.None;
781 border_style = FormBorderStyle.FixedSingle;
783 title_style = TitleStyle.None;
785 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
787 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
788 title_style = TitleStyle.Tool;
790 title_style = TitleStyle.Normal;
794 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
797 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
798 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
799 border_style = (FormBorderStyle) 0xFFFF;
801 border_style = FormBorderStyle.None;
806 title_style = TitleStyle.None;
807 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
808 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
809 title_style = TitleStyle.Tool;
811 title_style = TitleStyle.Normal;
815 border_style = FormBorderStyle.None;
817 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
818 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
819 border_style = FormBorderStyle.SizableToolWindow;
821 border_style = FormBorderStyle.Sizable;
824 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
825 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
826 border_style = FormBorderStyle.Fixed3D;
827 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
828 border_style = FormBorderStyle.Fixed3D;
829 border_static = true;
830 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
831 border_style = FormBorderStyle.FixedDialog;
832 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
833 border_style = FormBorderStyle.FixedToolWindow;
834 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
835 border_style = FormBorderStyle.FixedSingle;
838 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
839 border_style = FormBorderStyle.FixedSingle;
846 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
847 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);
850 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
851 MotifWmHints mwmHints;
852 MotifFunctions functions;
853 MotifDecorations decorations;
856 Rectangle client_rect;
858 // Windows we manage ourselves don't need WM window styles.
859 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
864 mwmHints = new MotifWmHints();
868 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
869 mwmHints.functions = (IntPtr)0;
870 mwmHints.decorations = (IntPtr)0;
872 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
873 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
874 /* tool windows get no window manager
875 decorations, and neither do windows
876 which lack CAPTION/BORDER/DLGFRAME
880 /* just because the window doesn't get any decorations doesn't
881 mean we should disable the functions. for instance, without
882 MotifFunctions.Maximize, changing the windowstate to Maximized
883 is ignored by metacity. */
884 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
887 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
888 functions |= MotifFunctions.Move;
889 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
892 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
893 functions |= MotifFunctions.Move | MotifFunctions.Resize;
894 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
897 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
898 functions |= MotifFunctions.Minimize;
899 decorations |= MotifDecorations.Minimize;
902 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
903 functions |= MotifFunctions.Maximize;
904 decorations |= MotifDecorations.Maximize;
907 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
908 functions |= MotifFunctions.Resize;
909 decorations |= MotifDecorations.ResizeH;
912 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
913 decorations |= MotifDecorations.Border;
916 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
917 decorations |= MotifDecorations.Border;
920 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
921 decorations |= MotifDecorations.Border;
924 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
925 functions |= MotifFunctions.Close;
928 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
929 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
930 if (cp.Caption == "") {
931 functions &= ~MotifFunctions.Move;
932 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
937 if ((functions & MotifFunctions.Resize) == 0) {
938 hwnd.fixed_size = true;
939 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));
941 hwnd.fixed_size = false;
944 mwmHints.functions = (IntPtr)functions;
945 mwmHints.decorations = (IntPtr)decorations;
947 FormWindowState current_state = GetWindowState (hwnd.Handle);
948 if (current_state == (FormWindowState)(-1))
949 current_state = FormWindowState.Normal;
951 client_rect = hwnd.ClientRect;
955 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
956 // and get those windows in front of their parents
957 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
958 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
959 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
960 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
962 Form f = Control.FromHandle(hwnd.Handle) as Form;
963 if (f != null && !hwnd.reparented) {
964 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
965 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
966 if (owner_hwnd != null)
967 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
968 owner_hwnd.whole_window);
973 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
974 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
975 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
976 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
978 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
979 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
980 /* this line keeps the window from showing up in gnome's taskbar */
981 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
983 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
984 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
986 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
989 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
990 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
992 /* we need to add these atoms in the
993 * event we're maximized, since we're
994 * replacing the existing
995 * _NET_WM_STATE here. If we don't
996 * add them, future calls to
997 * GetWindowState will return Normal
998 * for a window which is maximized. */
999 if (current_state == FormWindowState.Maximized) {
1000 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1001 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1003 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1006 IntPtr[] atom_ptrs = new IntPtr[2];
1007 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1008 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1009 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1012 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1016 private void SetIcon(Hwnd hwnd, Icon icon)
1021 // This really needs to do whatever it
1022 // takes to remove the window manager
1023 // menu, not just delete the ICON
1024 // property. This will cause metacity
1025 // to use the "no icon set" icon, and
1026 // we'll still have an icon.
1027 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1035 bitmap = icon.ToBitmap();
1037 size = bitmap.Width * bitmap.Height + 2;
1038 data = new IntPtr[size];
1040 data[index++] = (IntPtr)bitmap.Width;
1041 data[index++] = (IntPtr)bitmap.Height;
1043 for (int y = 0; y < bitmap.Height; y++) {
1044 for (int x = 0; x < bitmap.Width; x++) {
1045 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1049 XChangeProperty (DisplayHandle, hwnd.whole_window,
1050 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1051 PropertyMode.Replace, data, size);
1055 private void WakeupMain () {
1056 wake.Send (new byte [] { 0xFF });
1059 private XEventQueue ThreadQueue(Thread thread) {
1062 queue = (XEventQueue)MessageQueues[thread];
1063 if (queue == null) {
1064 queue = new XEventQueue(thread);
1065 MessageQueues[thread] = queue;
1071 private void TranslatePropertyToClipboard(IntPtr property) {
1076 IntPtr prop = IntPtr.Zero;
1078 Clipboard.Item = null;
1080 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);
1082 if ((long)nitems > 0) {
1083 if (property == (IntPtr)Atom.XA_STRING) {
1084 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1085 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1086 // FIXME - convert bitmap to image
1087 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1088 // FIXME - convert pixmap to image
1089 } else if (property == OEMTEXT) {
1090 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1091 } else if (property == UNICODETEXT) {
1092 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1099 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1101 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1105 // Keep the invalid area as small as needed
1106 if ((x + width) > hwnd.width) {
1107 width = hwnd.width - x;
1110 if ((y + height) > hwnd.height) {
1111 height = hwnd.height - y;
1115 hwnd.AddInvalidArea(x, y, width, height);
1116 if (!hwnd.expose_pending) {
1117 if (!hwnd.nc_expose_pending) {
1118 hwnd.Queue.Paint.Enqueue(hwnd);
1120 hwnd.expose_pending = true;
1123 hwnd.AddNcInvalidArea (x, y, width, height);
1125 if (!hwnd.nc_expose_pending) {
1126 if (!hwnd.expose_pending) {
1127 hwnd.Queue.Paint.Enqueue(hwnd);
1129 hwnd.nc_expose_pending = true;
1134 private void FrameExtents(IntPtr window, out int left, out int top) {
1139 IntPtr prop = IntPtr.Zero;
1141 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);
1142 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1143 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1144 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1145 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1146 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1152 if (prop != IntPtr.Zero) {
1158 private void AddConfigureNotify (XEvent xevent) {
1161 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1168 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1169 if (!hwnd.reparented) {
1170 hwnd.x = xevent.ConfigureEvent.x;
1171 hwnd.y = xevent.ConfigureEvent.y;
1173 // This sucks ass, part 1
1174 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1175 // no standard way of getting our adjustment.
1176 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1177 // Several other WMs do their decorations different yet again and we fail to deal
1178 // with that, since I couldn't find any frigging commonality between them.
1179 // The only sane WM seems to be KDE
1181 if (!xevent.ConfigureEvent.send_event) {
1184 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1186 // This is a synthetic event, coordinates are in root space
1187 hwnd.x = xevent.ConfigureEvent.x;
1188 hwnd.y = xevent.ConfigureEvent.y;
1189 if (hwnd.whacky_wm) {
1193 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1194 hwnd.x -= frame_left;
1195 hwnd.y -= frame_top;
1200 // XXX this sucks. this isn't thread safe
1201 hwnd.width = xevent.ConfigureEvent.width;
1202 hwnd.height = xevent.ConfigureEvent.height;
1203 hwnd.ClientRect = Rectangle.Empty;
1205 lock (hwnd.configure_lock) {
1206 if (!hwnd.configure_pending) {
1207 hwnd.Queue.EnqueueLocked (xevent);
1208 hwnd.configure_pending = true;
1212 // We drop configure events for Client windows
1215 private void ShowCaret() {
1216 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1222 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1226 private void HideCaret() {
1227 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1233 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1237 private int NextTimeout (ArrayList timers, DateTime now) {
1238 int timeout = Int32.MaxValue;
1240 foreach (Timer timer in timers) {
1241 int next = (int) (timer.Expires - now).TotalMilliseconds;
1243 return 0; // Have a timer that has already expired
1246 if (next < timeout) {
1250 if (timeout < Timer.Minimum) {
1251 timeout = Timer.Minimum;
1259 private void CheckTimers (ArrayList timers, DateTime now) {
1262 count = timers.Count;
1267 for (int i = 0; i < timers.Count; i++) {
1270 timer = (Timer) timers [i];
1272 if (timer.Enabled && timer.Expires <= now) {
1279 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1280 MSG msg = new MSG ();
1283 queue = ThreadQueue(Thread.CurrentThread);
1285 queue.DispatchIdle = false;
1289 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1290 if ((Msg)msg.message == Msg.WM_QUIT) {
1291 PostQuitMessage (0);
1295 if (msg.hwnd == hwnd.Handle) {
1296 if ((Msg)msg.message == message)
1298 else if ((Msg)msg.message == Msg.WM_DESTROY)
1302 TranslateMessage (ref msg);
1303 DispatchMessage (ref msg);
1308 queue.DispatchIdle = true;
1312 private void MapWindow(Hwnd hwnd, WindowType windows) {
1314 if (Control.FromHandle(hwnd.Handle) is Form)
1315 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1317 // it's possible that our Hwnd is no
1318 // longer valid after making that
1319 // SendMessage call, so check here.
1323 bool need_to_wait = false;
1325 if ((windows & WindowType.Whole) != 0) {
1326 XMapWindow(DisplayHandle, hwnd.whole_window);
1328 if ((windows & WindowType.Client) != 0) {
1329 XMapWindow(DisplayHandle, hwnd.client_window);
1331 need_to_wait = true;
1336 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1337 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1341 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1343 if (Control.FromHandle(hwnd.Handle) is Form)
1344 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1346 // it's possible that our Hwnd is no
1347 // longer valid after making that
1348 // SendMessage call, so check here.
1352 bool need_to_wait = false;
1354 if ((windows & WindowType.Client) != 0) {
1355 XUnmapWindow(DisplayHandle, hwnd.client_window);
1357 need_to_wait = true;
1359 if ((windows & WindowType.Whole) != 0) {
1360 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1363 hwnd.mapped = false;
1365 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1366 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1370 private void UpdateMessageQueue (XEventQueue queue) {
1375 now = DateTime.UtcNow;
1378 pending = XPending (DisplayHandle);
1382 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1383 Idle (this, EventArgs.Empty);
1387 pending = XPending (DisplayHandle);
1394 if (queue != null) {
1395 if (queue.Paint.Count > 0)
1398 timeout = NextTimeout (queue.timer_list, now);
1403 int length = pollfds.Length - 1;
1404 lock (wake_waiting_lock) {
1405 if (wake_waiting == false) {
1407 wake_waiting = true;
1411 Syscall.poll (pollfds, (uint)length, timeout);
1412 // Clean out buffer, so we're not busy-looping on the same data
1413 if (length == pollfds.Length) {
1414 if (pollfds[1].revents != 0)
1415 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1416 lock (wake_waiting_lock) {
1417 wake_waiting = false;
1422 pending = XPending (DisplayHandle);
1428 CheckTimers (queue.timer_list, now);
1431 XEvent xevent = new XEvent ();
1434 if (XPending (DisplayHandle) == 0)
1437 XNextEvent (DisplayHandle, ref xevent);
1439 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1440 if (XFilterEvent(ref xevent, FosterParent)) {
1446 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1450 switch (xevent.type) {
1451 case XEventName.Expose:
1452 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1455 case XEventName.SelectionClear: {
1456 // Should we do something?
1460 case XEventName.SelectionRequest: {
1461 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1465 sel_event = new XEvent();
1466 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1467 sel_event.SelectionEvent.send_event = true;
1468 sel_event.SelectionEvent.display = DisplayHandle;
1469 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1470 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1471 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1472 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1473 sel_event.SelectionEvent.property = IntPtr.Zero;
1475 // Seems that some apps support asking for supported types
1476 if (xevent.SelectionEvent.target == TARGETS) {
1483 if (Clipboard.Item is String) {
1484 atoms[atom_count++] = (int)Atom.XA_STRING;
1485 atoms[atom_count++] = (int)OEMTEXT;
1486 atoms[atom_count++] = (int)UNICODETEXT;
1487 } else if (Clipboard.Item is Image) {
1488 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1489 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1491 // FIXME - handle other types
1494 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1495 } else if (Clipboard.Item is string) {
1501 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1504 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1505 buffer = Marshal.AllocHGlobal(bytes.Length);
1506 buflen = bytes.Length;
1508 for (int i = 0; i < buflen; i++) {
1509 Marshal.WriteByte(buffer, i, bytes[i]);
1511 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1512 // FIXME - this should encode into ISO2022
1513 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1514 while (Marshal.ReadByte(buffer, buflen) != 0) {
1517 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1518 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1519 while (Marshal.ReadByte(buffer, buflen) != 0) {
1523 buffer = IntPtr.Zero;
1526 if (buffer != IntPtr.Zero) {
1527 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1528 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1529 Marshal.FreeHGlobal(buffer);
1531 } else if (Clipboard.Item is Image) {
1532 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1533 // FIXME - convert image and store as property
1534 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1535 // FIXME - convert image and store as property
1539 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1543 case XEventName.SelectionNotify: {
1544 if (Clipboard.Enumerating) {
1545 Clipboard.Enumerating = false;
1546 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1547 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1548 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1549 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1550 #if DriverDebugExtra
1551 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1555 } else if (Clipboard.Retrieving) {
1556 Clipboard.Retrieving = false;
1557 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1558 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1560 Clipboard.Item = null;
1563 Dnd.HandleSelectionNotifyEvent (ref xevent);
1568 case XEventName.KeyRelease:
1569 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1570 XEvent nextevent = new XEvent ();
1572 XPeekEvent (DisplayHandle, ref nextevent);
1574 if (nextevent.type == XEventName.KeyPress &&
1575 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1576 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1580 goto case XEventName.KeyPress;
1582 case XEventName.MotionNotify: {
1585 /* we can't do motion compression across threads, so just punt if we don't match up */
1586 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1587 peek = hwnd.Queue.Peek();
1588 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1592 goto case XEventName.KeyPress;
1595 case XEventName.KeyPress:
1596 case XEventName.ButtonPress:
1597 case XEventName.ButtonRelease:
1598 case XEventName.EnterNotify:
1599 case XEventName.LeaveNotify:
1600 case XEventName.CreateNotify:
1601 case XEventName.DestroyNotify:
1602 case XEventName.FocusIn:
1603 case XEventName.FocusOut:
1604 case XEventName.ClientMessage:
1605 case XEventName.ReparentNotify:
1606 case XEventName.MapNotify:
1607 case XEventName.UnmapNotify:
1608 hwnd.Queue.EnqueueLocked (xevent);
1611 case XEventName.ConfigureNotify:
1612 AddConfigureNotify(xevent);
1615 case XEventName.PropertyNotify:
1616 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1621 IntPtr prop = IntPtr.Zero;
1624 prev_active = ActiveWindow;
1625 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);
1626 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1627 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1630 if (prev_active != ActiveWindow) {
1631 if (prev_active != IntPtr.Zero) {
1632 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1634 if (ActiveWindow != IntPtr.Zero) {
1635 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1638 if (ModalWindows.Count == 0) {
1641 // Modality handling, if we are modal and the new active window is one
1642 // of ours but not the modal one, switch back to the modal window
1644 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1645 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1646 Activate((IntPtr)ModalWindows.Peek());
1653 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1654 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1655 hwnd.cached_window_state = (FormWindowState)(-1);
1663 private IntPtr GetMousewParam(int Delta) {
1666 if ((MouseState & MouseButtons.Left) != 0) {
1667 result |= (int)MsgButtons.MK_LBUTTON;
1670 if ((MouseState & MouseButtons.Middle) != 0) {
1671 result |= (int)MsgButtons.MK_MBUTTON;
1674 if ((MouseState & MouseButtons.Right) != 0) {
1675 result |= (int)MsgButtons.MK_RBUTTON;
1678 Keys mods = ModifierKeys;
1679 if ((mods & Keys.Control) != 0) {
1680 result |= (int)MsgButtons.MK_CONTROL;
1683 if ((mods & Keys.Shift) != 0) {
1684 result |= (int)MsgButtons.MK_SHIFT;
1687 result |= Delta << 16;
1689 return (IntPtr)result;
1691 private IntPtr XGetParent(IntPtr handle) {
1698 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1701 if (Children!=IntPtr.Zero) {
1709 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1711 // we need to workaround a problem with the
1712 // ordering of destruction of Drawables and
1713 // Pictures that exists between cairo and
1714 // RENDER on the server.
1715 if (error_event.request_code == (XRequest)render_major_opcode
1716 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1717 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1721 if (ErrorExceptions) {
1722 XUngrabPointer (display, IntPtr.Zero);
1723 throw new XException (error_event.display, error_event.resourceid,
1724 error_event.serial, error_event.error_code,
1725 error_event.request_code, error_event.minor_code);
1727 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1728 XException.GetMessage (error_event.display, error_event.resourceid,
1729 error_event.serial, error_event.error_code,
1730 error_event.request_code, error_event.minor_code),
1731 Environment.StackTrace);
1736 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1739 Control[] controls = c.Controls.GetAllControls ();
1741 if (c.IsHandleCreated && !c.IsDisposed) {
1742 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1744 #if DriverDebug || DriverDebugDestroy
1745 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1746 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1750 CleanupCachedWindows (hwnd);
1753 for (int i = 0; i < controls.Length; i ++) {
1754 AccumulateDestroyedHandles (controls[i], list);
1760 void CleanupCachedWindows (Hwnd hwnd)
1762 if (ActiveWindow == hwnd.Handle) {
1763 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1764 ActiveWindow = IntPtr.Zero;
1767 if (FocusWindow == hwnd.Handle) {
1768 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1769 FocusWindow = IntPtr.Zero;
1772 if (Grab.Hwnd == hwnd.Handle) {
1773 Grab.Hwnd = IntPtr.Zero;
1774 Grab.Confined = false;
1777 DestroyCaret (hwnd.Handle);
1780 private void PerformNCCalc(Hwnd hwnd) {
1781 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1785 rect = hwnd.DefaultClientRect;
1787 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1788 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1790 ncp.rgrc1.left = rect.Left;
1791 ncp.rgrc1.top = rect.Top;
1792 ncp.rgrc1.right = rect.Right;
1793 ncp.rgrc1.bottom = rect.Bottom;
1795 Marshal.StructureToPtr(ncp, ptr, true);
1796 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1797 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1798 Marshal.FreeHGlobal(ptr);
1800 // FIXME - debug this with Menus
1802 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1803 hwnd.ClientRect = rect;
1806 if ((rect.Width < 1) || (rect.Height < 1)) {
1807 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1809 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1813 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1815 #endregion // Private Methods
1818 private void MouseHover(object sender, EventArgs e) {
1822 HoverState.Timer.Enabled = false;
1824 if (HoverState.Window != IntPtr.Zero) {
1825 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1827 xevent = new XEvent ();
1829 xevent.type = XEventName.ClientMessage;
1830 xevent.ClientMessageEvent.display = DisplayHandle;
1831 xevent.ClientMessageEvent.window = HoverState.Window;
1832 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1833 xevent.ClientMessageEvent.format = 32;
1834 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1836 hwnd.Queue.EnqueueLocked (xevent);
1843 private void CaretCallback(object sender, EventArgs e) {
1847 Caret.On = !Caret.On;
1849 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1851 #endregion // Callbacks
1853 #region Public Properties
1855 internal override int Caption {
1861 internal override Size CursorSize {
1866 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1867 return new Size(x, y);
1869 return new Size(16, 16);
1874 internal override bool DragFullWindows {
1880 internal override Size DragSize {
1882 return new Size(4, 4);
1886 internal override Size FrameBorderSize {
1888 return new Size (4, 4);
1892 internal override Size IconSize {
1898 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1902 current = (long)list;
1905 size = new XIconSize();
1907 for (int i = 0; i < count; i++) {
1908 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1909 current += Marshal.SizeOf(size);
1911 // Look for our preferred size
1912 if (size.min_width == 32) {
1914 return new Size(32, 32);
1917 if (size.max_width == 32) {
1919 return new Size(32, 32);
1922 if (size.min_width < 32 && size.max_width > 32) {
1925 // check if we can fit one
1927 while (x < size.max_width) {
1928 x += size.width_inc;
1931 return new Size(32, 32);
1936 if (largest < size.max_width) {
1937 largest = size.max_width;
1941 // We didn't find a match or we wouldn't be here
1942 return new Size(largest, largest);
1945 return new Size(32, 32);
1950 internal override int KeyboardSpeed {
1953 // A lot harder: need to do:
1954 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1955 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1956 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1958 // And from that we can tell the repetition rate
1960 // Notice, the values must map to:
1961 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1967 internal override int KeyboardDelay {
1970 // Return values must range from 0 to 4, 0 meaning 250ms,
1971 // and 4 meaning 1000 ms.
1973 return 1; // ie, 500 ms
1977 internal override Size MaxWindowTrackSize {
1979 return new Size (WorkingArea.Width, WorkingArea.Height);
1983 internal override Size MinimizedWindowSize {
1985 return new Size(1, 1);
1989 internal override Size MinimizedWindowSpacingSize {
1991 return new Size(1, 1);
1995 internal override Size MinimumWindowSize {
1997 return new Size(1, 1);
2001 internal override Size MinWindowTrackSize {
2003 return new Size(1, 1);
2007 internal override Keys ModifierKeys {
2009 return Keyboard.ModifierKeys;
2013 internal override Size SmallIconSize {
2019 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2023 current = (long)list;
2026 size = new XIconSize();
2028 for (int i = 0; i < count; i++) {
2029 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2030 current += Marshal.SizeOf(size);
2032 // Look for our preferred size
2033 if (size.min_width == 16) {
2035 return new Size(16, 16);
2038 if (size.max_width == 16) {
2040 return new Size(16, 16);
2043 if (size.min_width < 16 && size.max_width > 16) {
2046 // check if we can fit one
2048 while (x < size.max_width) {
2049 x += size.width_inc;
2052 return new Size(16, 16);
2057 if (smallest == 0 || smallest > size.min_width) {
2058 smallest = size.min_width;
2062 // We didn't find a match or we wouldn't be here
2063 return new Size(smallest, smallest);
2066 return new Size(16, 16);
2071 internal override int MouseButtonCount {
2077 internal override bool MouseButtonsSwapped {
2079 return false; // FIXME - how to detect?
2083 internal override Point MousePosition {
2085 return mouse_position;
2089 internal override Size MouseHoverSize {
2091 return new Size (1, 1);
2095 internal override int MouseHoverTime {
2097 return HoverState.Interval;
2103 internal override bool MouseWheelPresent {
2105 return true; // FIXME - how to detect?
2109 internal override Rectangle VirtualScreen {
2115 IntPtr prop = IntPtr.Zero;
2119 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);
2120 if ((long)nitems < 2)
2123 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2124 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2128 return new Rectangle(0, 0, width, height);
2131 XWindowAttributes attributes=new XWindowAttributes();
2134 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2137 return new Rectangle(0, 0, attributes.width, attributes.height);
2141 internal override Rectangle WorkingArea {
2147 IntPtr prop = IntPtr.Zero;
2150 int current_desktop;
2154 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);
2155 if ((long)nitems < 1) {
2159 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2162 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);
2163 if ((long)nitems < 4 * current_desktop) {
2167 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2168 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2169 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2170 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2173 return new Rectangle(x, y, width, height);
2176 XWindowAttributes attributes=new XWindowAttributes();
2179 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2182 return new Rectangle(0, 0, attributes.width, attributes.height);
2186 internal override bool ThemesEnabled {
2188 return XplatUIX11.themes_enabled;
2193 #endregion // Public properties
2195 #region Public Static Methods
2196 internal override IntPtr InitializeDriver() {
2198 if (DisplayHandle==IntPtr.Zero) {
2199 SetDisplay(XOpenDisplay(IntPtr.Zero));
2205 internal override void ShutdownDriver(IntPtr token) {
2207 if (DisplayHandle!=IntPtr.Zero) {
2208 XCloseDisplay(DisplayHandle);
2209 DisplayHandle=IntPtr.Zero;
2214 internal override void EnableThemes() {
2215 themes_enabled = true;
2219 internal override void Activate(IntPtr handle) {
2222 hwnd = Hwnd.ObjectFromHandle(handle);
2226 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2227 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2230 // XRaiseWindow(DisplayHandle, handle);
2236 internal override void AudibleAlert() {
2237 XBell(DisplayHandle, 0);
2242 internal override void CaretVisible(IntPtr handle, bool visible) {
2243 if (Caret.Hwnd == handle) {
2245 if (!Caret.Visible) {
2246 Caret.Visible = true;
2248 Caret.Timer.Start();
2251 Caret.Visible = false;
2258 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2259 FormBorderStyle border_style;
2260 TitleStyle title_style;
2263 int tool_caption_height;
2265 DeriveStyles(Style, ExStyle, out border_style, out border_static, out title_style,
2266 out caption_height, out tool_caption_height);
2268 WindowRect = Hwnd.GetWindowRectangle(border_style, border_static, menu, title_style,
2269 caption_height, tool_caption_height,
2274 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2280 hwnd = Hwnd.ObjectFromHandle(handle);
2283 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2290 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2291 DataFormats.Format f;
2294 f = DataFormats.Format.List;
2296 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2300 Clipboard.Formats = new ArrayList();
2303 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2305 Clipboard.Enumerating = true;
2306 while (Clipboard.Enumerating) {
2307 UpdateMessageQueue(null);
2312 result = new int[Clipboard.Formats.Count];
2314 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2315 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2318 Clipboard.Formats = null;
2322 internal override void ClipboardClose(IntPtr handle) {
2323 if (handle != ClipMagic) {
2324 throw new ArgumentException("handle is not a valid clipboard handle");
2329 internal override int ClipboardGetID(IntPtr handle, string format) {
2330 if (handle != ClipMagic) {
2331 throw new ArgumentException("handle is not a valid clipboard handle");
2334 if (format == "Text" ) return (int)Atom.XA_STRING;
2335 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2336 //else if (format == "MetaFilePict" ) return 3;
2337 //else if (format == "SymbolicLink" ) return 4;
2338 //else if (format == "DataInterchangeFormat" ) return 5;
2339 //else if (format == "Tiff" ) return 6;
2340 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2341 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2342 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2343 //else if (format == "PenData" ) return 10;
2344 //else if (format == "RiffAudio" ) return 11;
2345 //else if (format == "WaveAudio" ) return 12;
2346 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2347 //else if (format == "EnhancedMetafile" ) return 14;
2348 //else if (format == "FileDrop" ) return 15;
2349 //else if (format == "Locale" ) return 16;
2351 return XInternAtom(DisplayHandle, format, false).ToInt32();
2354 internal override IntPtr ClipboardOpen(bool primary_selection) {
2355 if (!primary_selection)
2356 ClipMagic = CLIPBOARD;
2358 ClipMagic = PRIMARY;
2362 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2363 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2365 Clipboard.Retrieving = true;
2366 while (Clipboard.Retrieving) {
2367 UpdateMessageQueue(null);
2370 return Clipboard.Item;
2373 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2374 Clipboard.Item = obj;
2375 Clipboard.Type = type;
2376 Clipboard.Converter = converter;
2379 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2381 // Clearing the selection
2382 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2386 internal override void CreateCaret (IntPtr handle, int width, int height)
2388 XGCValues gc_values;
2391 hwnd = Hwnd.ObjectFromHandle(handle);
2393 if (Caret.Hwnd != IntPtr.Zero) {
2394 DestroyCaret(Caret.Hwnd);
2397 Caret.Hwnd = handle;
2398 Caret.Window = hwnd.client_window;
2399 Caret.Width = width;
2400 Caret.Height = height;
2401 Caret.Visible = false;
2404 gc_values = new XGCValues();
2405 gc_values.line_width = width;
2407 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2408 if (Caret.gc == IntPtr.Zero) {
2409 Caret.Hwnd = IntPtr.Zero;
2413 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2416 internal override IntPtr CreateWindow (CreateParams cp)
2418 XSetWindowAttributes Attributes;
2420 Hwnd parent_hwnd = null;
2425 IntPtr ParentHandle;
2427 IntPtr ClientWindow;
2428 Rectangle ClientRect;
2429 SetWindowValuemask ValueMask;
2434 Attributes = new XSetWindowAttributes();
2440 if (Width<1) Width=1;
2441 if (Height<1) Height=1;
2443 if (cp.Parent != IntPtr.Zero) {
2444 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2445 ParentHandle = parent_hwnd.client_window;
2447 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2448 // We need to use our foster parent window until this poor child gets it's parent assigned
2449 ParentHandle=FosterParent;
2450 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2451 ParentHandle=RootWindow;
2453 // Default position on screen, if window manager doesn't place us somewhere else
2456 ParentHandle=RootWindow;
2460 // Set the default location location for forms.
2461 Point previous, next;
2463 if (cp.control is Form) {
2464 if (parent_hwnd != null) {
2465 previous = parent_hwnd.previous_child_startup_location;
2466 within = parent_hwnd.client_rectangle;
2468 previous = Hwnd.previous_main_startup_location;
2469 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
2472 if (previous.X == int.MinValue || previous.Y == int.MaxValue) {
2475 next = new Point (previous.X + 22, previous.Y + 22);
2478 if (!within.Contains (next.X * 3, next.Y * 3)) {
2482 if (parent_hwnd != null) {
2483 parent_hwnd.previous_child_startup_location = next;
2485 Hwnd.previous_main_startup_location = next;
2488 if (X == int.MinValue && Y == int.MinValue) {
2493 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2495 Attributes.bit_gravity = Gravity.NorthWestGravity;
2496 Attributes.win_gravity = Gravity.NorthWestGravity;
2498 // Save what's under the toolwindow
2499 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2500 Attributes.save_under = true;
2501 ValueMask |= SetWindowValuemask.SaveUnder;
2505 // If we're a popup without caption we override the WM
2506 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2507 Attributes.override_redirect = true;
2508 ValueMask |= SetWindowValuemask.OverrideRedirect;
2514 hwnd.height = Height;
2515 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2516 hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
2518 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2519 hwnd.enabled = false;
2522 ClientRect = hwnd.ClientRect;
2523 ClientWindow = IntPtr.Zero;
2526 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2527 if (WholeWindow != IntPtr.Zero) {
2528 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2530 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2531 ValueMask = SetWindowValuemask.ColorMap;
2532 Attributes.colormap = CustomColormap;
2534 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);
2538 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2539 throw new Exception("Could not create X11 windows");
2542 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2543 hwnd.WholeWindow = WholeWindow;
2544 hwnd.ClientWindow = ClientWindow;
2546 #if DriverDebug || DriverDebugCreate
2547 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);
2550 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2551 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2554 hints = new XSizeHints();
2557 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2558 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2563 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2564 if (hwnd.whole_window != hwnd.client_window)
2565 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2568 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2570 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2571 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2573 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2576 SetWMStyles(hwnd, cp);
2578 // set the group leader
2579 XWMHints wm_hints = new XWMHints ();
2581 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2582 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2583 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2585 if (ParentHandle != RootWindow) {
2586 wm_hints.window_group = hwnd.whole_window;
2588 wm_hints.window_group = ParentHandle;
2592 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2595 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2596 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2597 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2598 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2601 // for now make all windows dnd enabled
2602 Dnd.SetAllowDrop (hwnd, true);
2604 // Set caption/window title
2605 Text(hwnd.Handle, cp.Caption);
2607 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2608 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2610 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2611 hwnd.visible = true;
2612 MapWindow(hwnd, WindowType.Both);
2613 if (!(Control.FromHandle(hwnd.Handle) is Form))
2614 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2620 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2621 CreateParams create_params = new CreateParams();
2623 create_params.Caption = "";
2624 create_params.X = X;
2625 create_params.Y = Y;
2626 create_params.Width = Width;
2627 create_params.Height = Height;
2629 create_params.ClassName=XplatUI.DefaultClassName;
2630 create_params.ClassStyle = 0;
2631 create_params.ExStyle=0;
2632 create_params.Parent=IntPtr.Zero;
2633 create_params.Param=0;
2635 return CreateWindow(create_params);
2638 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2640 Bitmap cursor_bitmap;
2648 IntPtr cursor_pixmap;
2655 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2659 // Win32 only allows creation cursors of a certain size
2660 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2661 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2662 cursor_mask = new Bitmap(mask, new Size(width, height));
2664 cursor_bitmap = bitmap;
2668 width = cursor_bitmap.Width;
2669 height = cursor_bitmap.Height;
2671 cursor_bits = new Byte[(width / 8) * height];
2672 mask_bits = new Byte[(width / 8) * height];
2674 for (int y = 0; y < height; y++) {
2675 for (int x = 0; x < width; x++) {
2676 c_pixel = cursor_bitmap.GetPixel(x, y);
2677 m_pixel = cursor_mask.GetPixel(x, y);
2679 and = c_pixel == cursor_pixel;
2680 xor = m_pixel == mask_pixel;
2684 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2685 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2686 } else if (and && !xor) {
2688 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2689 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2691 } else if (and && !xor) {
2693 } else if (and && xor) {
2696 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2697 // we want both to be 0 so nothing to be done
2698 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2699 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2705 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2706 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2710 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2711 fg.red = (ushort)65535;
2712 fg.green = (ushort)65535;
2713 fg.blue = (ushort)65535;
2715 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2717 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2719 XFreePixmap(DisplayHandle, cursor_pixmap);
2720 XFreePixmap(DisplayHandle, mask_pixmap);
2725 internal override IntPtr DefineStdCursor(StdCursor id) {
2726 CursorFontShape shape;
2729 // FIXME - define missing shapes
2732 case StdCursor.AppStarting: {
2733 shape = CursorFontShape.XC_watch;
2737 case StdCursor.Arrow: {
2738 shape = CursorFontShape.XC_top_left_arrow;
2742 case StdCursor.Cross: {
2743 shape = CursorFontShape.XC_crosshair;
2747 case StdCursor.Default: {
2748 shape = CursorFontShape.XC_top_left_arrow;
2752 case StdCursor.Hand: {
2753 shape = CursorFontShape.XC_hand1;
2757 case StdCursor.Help: {
2758 shape = CursorFontShape.XC_question_arrow;
2762 case StdCursor.HSplit: {
2763 shape = CursorFontShape.XC_sb_v_double_arrow;
2767 case StdCursor.IBeam: {
2768 shape = CursorFontShape.XC_xterm;
2772 case StdCursor.No: {
2773 shape = CursorFontShape.XC_circle;
2777 case StdCursor.NoMove2D: {
2778 shape = CursorFontShape.XC_fleur;
2782 case StdCursor.NoMoveHoriz: {
2783 shape = CursorFontShape.XC_fleur;
2787 case StdCursor.NoMoveVert: {
2788 shape = CursorFontShape.XC_fleur;
2792 case StdCursor.PanEast: {
2793 shape = CursorFontShape.XC_fleur;
2797 case StdCursor.PanNE: {
2798 shape = CursorFontShape.XC_fleur;
2802 case StdCursor.PanNorth: {
2803 shape = CursorFontShape.XC_fleur;
2807 case StdCursor.PanNW: {
2808 shape = CursorFontShape.XC_fleur;
2812 case StdCursor.PanSE: {
2813 shape = CursorFontShape.XC_fleur;
2817 case StdCursor.PanSouth: {
2818 shape = CursorFontShape.XC_fleur;
2822 case StdCursor.PanSW: {
2823 shape = CursorFontShape.XC_fleur;
2827 case StdCursor.PanWest: {
2828 shape = CursorFontShape.XC_sizing;
2832 case StdCursor.SizeAll: {
2833 shape = CursorFontShape.XC_fleur;
2837 case StdCursor.SizeNESW: {
2838 shape = CursorFontShape.XC_top_right_corner;
2842 case StdCursor.SizeNS: {
2843 shape = CursorFontShape.XC_sb_v_double_arrow;
2847 case StdCursor.SizeNWSE: {
2848 shape = CursorFontShape.XC_top_left_corner;
2852 case StdCursor.SizeWE: {
2853 shape = CursorFontShape.XC_sb_h_double_arrow;
2857 case StdCursor.UpArrow: {
2858 shape = CursorFontShape.XC_center_ptr;
2862 case StdCursor.VSplit: {
2863 shape = CursorFontShape.XC_sb_h_double_arrow;
2867 case StdCursor.WaitCursor: {
2868 shape = CursorFontShape.XC_watch;
2878 cursor = XCreateFontCursor(DisplayHandle, shape);
2883 internal override IntPtr DefWndProc(ref Message msg) {
2884 switch ((Msg)msg.Msg) {
2885 case Msg.WM_PAINT: {
2888 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2890 hwnd.expose_pending = false;
2896 case Msg.WM_NCPAINT: {
2899 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2901 hwnd.nc_expose_pending = false;
2907 case Msg.WM_CONTEXTMENU: {
2910 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2912 if ((hwnd != null) && (hwnd.parent != null)) {
2913 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2918 case Msg.WM_MOUSEWHEEL: {
2921 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2923 if ((hwnd != null) && (hwnd.parent != null)) {
2924 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2925 if (msg.Result == IntPtr.Zero) {
2932 case Msg.WM_SETCURSOR: {
2935 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2937 break; // not sure how this happens, but it does
2939 // Pass to parent window first
2940 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2942 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2945 if (msg.Result == IntPtr.Zero) {
2948 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2949 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2950 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2951 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2952 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2953 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2956 handle = Cursors.Default.handle;
2959 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2960 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2961 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2962 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2963 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2964 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2967 case HitTest.HTGROWBOX:
2968 case HitTest.HTSIZE:
2969 case HitTest.HTZOOM:
2970 case HitTest.HTVSCROLL:
2971 case HitTest.HTSYSMENU:
2972 case HitTest.HTREDUCE:
2973 case HitTest.HTNOWHERE:
2974 case HitTest.HTMAXBUTTON:
2975 case HitTest.HTMINBUTTON:
2976 case HitTest.HTMENU:
2977 case HitTest.HSCROLL:
2978 case HitTest.HTBOTTOM:
2979 case HitTest.HTCAPTION:
2980 case HitTest.HTCLIENT:
2981 case HitTest.HTCLOSE:
2983 default: handle = Cursors.Default.handle; break;
2985 SetCursor(msg.HWnd, handle);
2993 internal override void DestroyCaret(IntPtr handle) {
2994 if (Caret.Hwnd == handle) {
2995 if (Caret.Visible) {
2999 if (Caret.gc != IntPtr.Zero) {
3000 XFreeGC(DisplayHandle, Caret.gc);
3001 Caret.gc = IntPtr.Zero;
3003 Caret.Hwnd = IntPtr.Zero;
3004 Caret.Visible = false;
3009 internal override void DestroyCursor(IntPtr cursor) {
3011 XFreeCursor(DisplayHandle, cursor);
3015 internal override void DestroyWindow(IntPtr handle) {
3018 hwnd = Hwnd.ObjectFromHandle(handle);
3021 #if DriverDebug || DriverDebugDestroy
3022 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3027 #if DriverDebug || DriverDebugDestroy
3028 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3031 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3033 CleanupCachedWindows (hwnd);
3035 ArrayList windows = new ArrayList ();
3037 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3040 foreach (Hwnd h in windows) {
3041 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3046 if (hwnd.whole_window != IntPtr.Zero) {
3047 #if DriverDebug || DriverDebugDestroy
3048 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3050 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3052 else if (hwnd.client_window != IntPtr.Zero) {
3053 #if DriverDebug || DriverDebugDestroy
3054 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3056 XDestroyWindow(DisplayHandle, hwnd.client_window);
3062 internal override IntPtr DispatchMessage(ref MSG msg) {
3063 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3066 IntPtr GetReversibleScreenGC (Color backColor)
3068 XGCValues gc_values;
3072 XColor xcolor = new XColor();
3073 xcolor.red = (ushort)(backColor.R * 257);
3074 xcolor.green = (ushort)(backColor.G * 257);
3075 xcolor.blue = (ushort)(backColor.B * 257);
3076 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3077 pixel = (uint)xcolor.pixel.ToInt32();
3080 gc_values = new XGCValues();
3082 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3083 gc_values.foreground = (IntPtr)pixel;
3085 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3086 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3087 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3092 IntPtr GetReversibleControlGC (Control control, int line_width)
3094 XGCValues gc_values;
3097 gc_values = new XGCValues();
3099 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3100 gc_values.line_width = line_width;
3101 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3103 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3104 //mask = foreground ^ background;
3105 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3106 //XSetBackground(DisplayHandle, gc, background);
3107 //XSetFunction(DisplayHandle, gc, GXxor);
3108 //XSetPlaneMask(DisplayHandle, gc, mask);
3111 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3115 XColor xcolor = new XColor();
3117 xcolor.red = (ushort)(control.ForeColor.R * 257);
3118 xcolor.green = (ushort)(control.ForeColor.G * 257);
3119 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3120 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3121 foreground = (uint)xcolor.pixel.ToInt32();
3123 xcolor.red = (ushort)(control.BackColor.R * 257);
3124 xcolor.green = (ushort)(control.BackColor.G * 257);
3125 xcolor.blue = (ushort)(control.BackColor.B * 257);
3126 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3127 background = (uint)xcolor.pixel.ToInt32();
3129 uint mask = foreground ^ background;
3131 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3132 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3133 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3134 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3139 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3141 IntPtr gc = GetReversibleScreenGC (backColor);
3143 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3145 XFreeGC(DisplayHandle, gc);
3148 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3150 IntPtr gc = GetReversibleScreenGC (backColor);
3152 if (rectangle.Width < 0) {
3153 rectangle.X += rectangle.Width;
3154 rectangle.Width = -rectangle.Width;
3156 if (rectangle.Height < 0) {
3157 rectangle.Y += rectangle.Height;
3158 rectangle.Height = -rectangle.Height;
3162 GCLineStyle line_style = GCLineStyle.LineSolid;
3163 GCCapStyle cap_style = GCCapStyle.CapButt;
3164 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3167 case FrameStyle.Dashed:
3168 line_style = GCLineStyle.LineOnOffDash;
3170 case FrameStyle.Thick:
3175 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3177 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3179 XFreeGC(DisplayHandle, gc);
3182 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3184 IntPtr gc = GetReversibleScreenGC (backColor);
3186 if (rectangle.Width < 0) {
3187 rectangle.X += rectangle.Width;
3188 rectangle.Width = -rectangle.Width;
3190 if (rectangle.Height < 0) {
3191 rectangle.Y += rectangle.Height;
3192 rectangle.Height = -rectangle.Height;
3194 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3196 XFreeGC(DisplayHandle, gc);
3199 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3201 Control control = Control.FromHandle(handle);
3203 gc = GetReversibleControlGC (control, line_width);
3205 if ((rect.Width > 0) && (rect.Height > 0)) {
3206 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3208 if (rect.Width > 0) {
3209 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3211 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3214 XFreeGC(DisplayHandle, gc);
3217 internal override void DoEvents() {
3218 MSG msg = new MSG ();
3221 if (OverrideCursorHandle != IntPtr.Zero) {
3222 OverrideCursorHandle = IntPtr.Zero;
3225 queue = ThreadQueue(Thread.CurrentThread);
3227 queue.DispatchIdle = false;
3229 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3230 TranslateMessage (ref msg);
3231 DispatchMessage (ref msg);
3234 queue.DispatchIdle = true;
3237 internal override void EnableWindow(IntPtr handle, bool Enable) {
3240 hwnd = Hwnd.ObjectFromHandle(handle);
3242 hwnd.Enabled = Enable;
3246 internal override void EndLoop(Thread thread) {
3247 // This is where we one day will shut down the loop for the thread
3250 internal override IntPtr GetActive() {
3255 IntPtr prop = IntPtr.Zero;
3256 IntPtr active = IntPtr.Zero;
3258 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);
3259 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3260 active = (IntPtr)Marshal.ReadInt32(prop);
3264 if (active != IntPtr.Zero) {
3267 hwnd = Hwnd.GetObjectFromWindow(active);
3269 active = hwnd.Handle;
3271 active = IntPtr.Zero;
3277 internal override Region GetClipRegion(IntPtr handle) {
3280 hwnd = Hwnd.ObjectFromHandle(handle);
3282 return hwnd.UserClip;
3288 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3295 internal override void GetDisplaySize(out Size size) {
3296 XWindowAttributes attributes=new XWindowAttributes();
3299 // FIXME - use _NET_WM messages instead?
3300 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3303 size = new Size(attributes.width, attributes.height);
3306 internal override SizeF GetAutoScaleSize(Font font) {
3309 string magic_string = "The quick brown fox jumped over the lazy dog.";
3310 double magic_number = 44.549996948242189;
3312 g = Graphics.FromHwnd(FosterParent);
3314 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3315 return new SizeF(width, font.Height);
3318 internal override IntPtr GetParent(IntPtr handle) {
3321 hwnd = Hwnd.ObjectFromHandle(handle);
3322 if (hwnd != null && hwnd.parent != null) {
3323 return hwnd.parent.Handle;
3328 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3338 if (handle != IntPtr.Zero) {
3339 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3341 use_handle = RootWindow;
3345 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3348 if (handle != IntPtr.Zero) {
3357 internal override IntPtr GetFocus() {
3362 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3363 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3366 internal override Point GetMenuOrigin(IntPtr handle) {
3369 hwnd = Hwnd.ObjectFromHandle(handle);
3372 return hwnd.MenuOrigin;
3377 [MonoTODO("Implement filtering")]
3378 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3385 if (((XEventQueue)queue_id).Count > 0) {
3386 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3388 UpdateMessageQueue ((XEventQueue)queue_id);
3390 if (((XEventQueue)queue_id).Count > 0) {
3391 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3392 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3393 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3395 msg.hwnd= IntPtr.Zero;
3396 msg.message = Msg.WM_ENTERIDLE;
3401 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3403 // Handle messages for windows that are already or are about to be destroyed.
3405 // we need a special block for this because unless we remove the hwnd from the paint
3406 // queue it will always stay there (since we don't handle the expose), and we'll
3407 // effectively loop infinitely trying to repaint a non-existant window.
3408 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3409 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3410 hwnd.Queue.Paint.Remove (hwnd);
3411 goto ProcessNextMessage;
3414 // We need to make sure we only allow DestroyNotify events through for zombie
3415 // hwnds, since much of the event handling code makes requests using the hwnd's
3416 // client_window, and that'll result in BadWindow errors if there's some lag
3417 // between the XDestroyWindow call and the DestroyNotify event.
3418 if (hwnd == null || hwnd.zombie) {
3419 #if DriverDebug || DriverDebugDestroy
3420 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3422 goto ProcessNextMessage;
3425 if (hwnd.client_window == xevent.AnyEvent.window) {
3427 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3430 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3433 msg.hwnd = hwnd.Handle;
3436 // If you add a new event to this switch make sure to add it in
3437 // UpdateMessage also unless it is not coming through the X event system.
3439 switch(xevent.type) {
3440 case XEventName.KeyPress: {
3442 Dnd.HandleKeyPress (ref xevent);
3443 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3447 case XEventName.KeyRelease: {
3448 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3452 case XEventName.ButtonPress: {
3453 switch(xevent.ButtonEvent.button) {
3455 MouseState |= MouseButtons.Left;
3457 msg.message = Msg.WM_LBUTTONDOWN;
3459 msg.message = Msg.WM_NCLBUTTONDOWN;
3460 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3462 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3463 msg.wParam=GetMousewParam(0);
3468 MouseState |= MouseButtons.Middle;
3470 msg.message = Msg.WM_MBUTTONDOWN;
3472 msg.message = Msg.WM_NCMBUTTONDOWN;
3473 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3475 msg.wParam=GetMousewParam(0);
3480 MouseState |= MouseButtons.Right;
3482 msg.message = Msg.WM_RBUTTONDOWN;
3484 msg.message = Msg.WM_NCRBUTTONDOWN;
3485 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3487 msg.wParam=GetMousewParam(0);
3492 msg.hwnd = FocusWindow;
3493 msg.message=Msg.WM_MOUSEWHEEL;
3494 msg.wParam=GetMousewParam(120);
3499 msg.hwnd = FocusWindow;
3500 msg.message=Msg.WM_MOUSEWHEEL;
3501 msg.wParam=GetMousewParam(-120);
3507 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3508 mouse_position.X = xevent.ButtonEvent.x;
3509 mouse_position.Y = xevent.ButtonEvent.y;
3511 if (!hwnd.Enabled) {
3514 msg.hwnd = hwnd.EnabledHwnd;
3515 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);
3516 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3519 if (Grab.Hwnd != IntPtr.Zero) {
3520 msg.hwnd = Grab.Hwnd;
3523 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3524 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3525 switch(xevent.ButtonEvent.button) {
3527 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3532 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3537 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3541 ClickPending.Pending = false;
3543 ClickPending.Pending = true;
3544 ClickPending.Hwnd = msg.hwnd;
3545 ClickPending.Message = msg.message;
3546 ClickPending.wParam = msg.wParam;
3547 ClickPending.lParam = msg.lParam;
3548 ClickPending.Time = (long)xevent.ButtonEvent.time;
3551 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3552 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3554 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3555 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3556 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3557 XEvent motionEvent = new XEvent ();
3558 motionEvent.type = XEventName.MotionNotify;
3559 motionEvent.MotionEvent.display = DisplayHandle;
3560 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3561 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3562 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3563 hwnd.Queue.EnqueueLocked (motionEvent);
3569 case XEventName.ButtonRelease: {
3571 if (Dnd.HandleButtonRelease (ref xevent)) {
3574 // Allow the LBUTTONUP message to get through
3577 switch(xevent.ButtonEvent.button) {
3580 msg.message = Msg.WM_LBUTTONUP;
3582 msg.message = Msg.WM_NCLBUTTONUP;
3583 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3585 MouseState &= ~MouseButtons.Left;
3586 msg.wParam=GetMousewParam(0);
3592 msg.message = Msg.WM_MBUTTONUP;
3594 msg.message = Msg.WM_NCMBUTTONUP;
3595 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3597 MouseState &= ~MouseButtons.Middle;
3598 msg.wParam=GetMousewParam(0);
3604 msg.message = Msg.WM_RBUTTONUP;
3606 msg.message = Msg.WM_NCRBUTTONUP;
3607 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3609 MouseState &= ~MouseButtons.Right;
3610 msg.wParam=GetMousewParam(0);
3615 goto ProcessNextMessage;
3619 goto ProcessNextMessage;
3623 if (!hwnd.Enabled) {
3626 msg.hwnd = hwnd.EnabledHwnd;
3627 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);
3628 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3631 if (Grab.Hwnd != IntPtr.Zero) {
3632 msg.hwnd = Grab.Hwnd;
3635 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3636 mouse_position.X = xevent.ButtonEvent.x;
3637 mouse_position.Y = xevent.ButtonEvent.y;
3639 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3640 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3641 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3642 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3643 XEvent motionEvent = new XEvent ();
3644 motionEvent.type = XEventName.MotionNotify;
3645 motionEvent.MotionEvent.display = DisplayHandle;
3646 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3647 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3648 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3649 hwnd.Queue.EnqueueLocked (motionEvent);
3654 case XEventName.MotionNotify: {
3656 #if DriverDebugExtra
3657 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);
3660 if (Dnd.HandleMotionNotify (ref xevent))
3661 goto ProcessNextMessage;
3662 if (Grab.Hwnd != IntPtr.Zero) {
3663 msg.hwnd = Grab.Hwnd;
3665 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3668 msg.message = Msg.WM_MOUSEMOVE;
3669 msg.wParam = GetMousewParam(0);
3670 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3672 if (!hwnd.Enabled) {
3675 msg.hwnd = hwnd.EnabledHwnd;
3676 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);
3677 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3680 mouse_position.X = xevent.MotionEvent.x;
3681 mouse_position.Y = xevent.MotionEvent.y;
3683 if ((HoverState.Timer.Enabled) &&
3684 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3685 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3686 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3687 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3688 HoverState.Timer.Stop();
3689 HoverState.Timer.Start();
3690 HoverState.X = mouse_position.X;
3691 HoverState.Y = mouse_position.Y;
3701 #if DriverDebugExtra
3702 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);
3704 msg.message = Msg.WM_NCMOUSEMOVE;
3706 if (!hwnd.Enabled) {
3707 msg.hwnd = hwnd.EnabledHwnd;
3708 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);
3709 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3712 // The hit test is sent in screen coordinates
3713 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3714 xevent.MotionEvent.x, xevent.MotionEvent.y,
3715 out screen_x, out screen_y, out dummy);
3717 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3718 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3719 IntPtr.Zero, msg.lParam).ToInt32 ();
3720 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3722 mouse_position.X = xevent.MotionEvent.x;
3723 mouse_position.Y = xevent.MotionEvent.y;
3729 case XEventName.EnterNotify: {
3730 if (!hwnd.Enabled) {
3731 goto ProcessNextMessage;
3733 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3734 goto ProcessNextMessage;
3736 msg.message = Msg.WM_MOUSE_ENTER;
3737 HoverState.X = xevent.CrossingEvent.x;
3738 HoverState.Y = xevent.CrossingEvent.y;
3739 HoverState.Timer.Enabled = true;
3740 HoverState.Window = xevent.CrossingEvent.window;
3744 case XEventName.LeaveNotify: {
3745 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3746 WindowUngrabbed (hwnd.Handle);
3747 goto ProcessNextMessage;
3749 if (!hwnd.Enabled) {
3750 goto ProcessNextMessage;
3752 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3753 goto ProcessNextMessage;
3755 msg.message=Msg.WM_MOUSELEAVE;
3756 HoverState.Timer.Enabled = false;
3757 HoverState.Window = IntPtr.Zero;
3762 case XEventName.CreateNotify: {
3763 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3764 msg.message = WM_CREATE;
3765 // Set up CreateStruct
3767 goto ProcessNextMessage;
3774 case XEventName.ReparentNotify: {
3775 if (hwnd.parent == null) { // Toplevel
3776 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3777 // We need to adjust x/y
3778 // This sucks ass, part 2
3779 // Every WM does the reparenting of toplevel windows different, so there's
3780 // no standard way of getting our adjustment considering frames/decorations
3781 // The code below is needed for metacity. KDE doesn't works just fine without this
3789 hwnd.Reparented = true;
3791 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);
3792 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3793 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3796 hwnd.whacky_wm = true;
3799 if (hwnd.opacity != 0xffffffff) {
3802 opacity = (IntPtr)(Int32)hwnd.opacity;
3803 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3805 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3806 goto ProcessNextMessage;
3808 hwnd.Reparented = false;
3809 goto ProcessNextMessage;
3812 goto ProcessNextMessage;
3815 case XEventName.ConfigureNotify: {
3816 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3817 #if DriverDebugExtra
3818 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);
3820 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3821 lock (hwnd.configure_lock) {
3822 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3823 hwnd.configure_pending = false;
3826 // We need to adjust our client window to track the resize of whole_window
3827 if (hwnd.whole_window != hwnd.client_window)
3828 PerformNCCalc(hwnd);
3831 goto ProcessNextMessage;
3834 case XEventName.FocusIn: {
3835 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3836 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3837 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3838 // about it having focus again
3839 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3840 goto ProcessNextMessage;
3843 if (FocusWindow == IntPtr.Zero) {
3844 Control c = Control.FromHandle (hwnd.client_window);
3846 goto ProcessNextMessage;
3847 Form form = c.FindForm ();
3849 goto ProcessNextMessage;
3850 if (ActiveWindow != form.Handle) {
3851 ActiveWindow = form.Handle;
3852 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3854 goto ProcessNextMessage;
3856 Keyboard.FocusIn(FocusWindow);
3857 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3858 goto ProcessNextMessage;
3861 case XEventName.FocusOut: {
3862 // Se the comment for our FocusIn handler
3863 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3864 goto ProcessNextMessage;
3866 Keyboard.FocusOut(FocusWindow);
3868 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3869 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3872 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3873 goto ProcessNextMessage;
3876 case XEventName.MapNotify: {
3877 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3879 msg.message = Msg.WM_SHOWWINDOW;
3880 msg.wParam = (IntPtr) 1;
3881 // XXX we're missing the lParam..
3884 goto ProcessNextMessage;
3887 case XEventName.UnmapNotify: {
3888 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3889 hwnd.mapped = false;
3890 msg.message = Msg.WM_SHOWWINDOW;
3891 msg.wParam = (IntPtr) 0;
3892 // XXX we're missing the lParam..
3895 goto ProcessNextMessage;
3898 case XEventName.Expose: {
3901 hwnd.expose_pending = false;
3903 hwnd.nc_expose_pending = false;
3905 goto ProcessNextMessage;
3909 if (!hwnd.expose_pending) {
3910 goto ProcessNextMessage;
3913 if (!hwnd.nc_expose_pending) {
3914 goto ProcessNextMessage;
3917 switch (hwnd.border_style) {
3918 case FormBorderStyle.Fixed3D: {
3921 g = Graphics.FromHwnd(hwnd.whole_window);
3922 if (hwnd.border_static)
3923 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
3925 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3930 case FormBorderStyle.FixedSingle: {
3933 g = Graphics.FromHwnd(hwnd.whole_window);
3934 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3939 #if DriverDebugExtra
3940 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);
3943 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3944 Region region = new Region (rect);
3945 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3946 msg.message = Msg.WM_NCPAINT;
3947 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3948 msg.refobject = region;
3951 #if DriverDebugExtra
3952 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);
3954 if (Caret.Visible == true) {
3955 Caret.Paused = true;
3959 if (Caret.Visible == true) {
3961 Caret.Paused = false;
3963 msg.message = Msg.WM_PAINT;
3967 case XEventName.DestroyNotify: {
3969 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3970 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3972 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3973 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3974 CleanupCachedWindows (hwnd);
3976 #if DriverDebugDestroy
3977 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3980 msg.hwnd = hwnd.client_window;
3981 msg.message=Msg.WM_DESTROY;
3984 goto ProcessNextMessage;
3990 case XEventName.ClientMessage: {
3991 if (Dnd.HandleClientMessage (ref xevent)) {
3992 goto ProcessNextMessage;
3995 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3996 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3997 goto ProcessNextMessage;
4000 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4001 msg.message = Msg.WM_MOUSEHOVER;
4002 msg.wParam = GetMousewParam(0);
4003 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4007 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4008 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4009 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4010 msg.wParam = xevent.ClientMessageEvent.ptr3;
4011 msg.lParam = xevent.ClientMessageEvent.ptr4;
4012 if (msg.message == (Msg)Msg.WM_QUIT)
4018 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4019 #if DriverDebugXEmbed
4020 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4023 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4024 XSizeHints hints = new XSizeHints();
4027 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4029 hwnd.width = hints.max_width;
4030 hwnd.height = hints.max_height;
4031 hwnd.ClientRect = Rectangle.Empty;
4032 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4036 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4037 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4038 msg.message = Msg.WM_CLOSE;
4042 // We should not get this, but I'll leave the code in case we need it in the future
4043 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4044 goto ProcessNextMessage;
4047 goto ProcessNextMessage;
4051 goto ProcessNextMessage;
4058 internal override bool GetText(IntPtr handle, out string text) {
4065 IntPtr prop = IntPtr.Zero;
4067 XGetWindowProperty(DisplayHandle, handle,
4068 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4069 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4071 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4072 text = Marshal.PtrToStringUni (prop, (int)nitems);
4077 // fallback on the non-_NET property
4080 textptr = IntPtr.Zero;
4082 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4083 if (textptr != IntPtr.Zero) {
4084 text = Marshal.PtrToStringAnsi(textptr);
4095 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) {
4098 hwnd = Hwnd.ObjectFromHandle(handle);
4104 height = hwnd.height;
4106 PerformNCCalc(hwnd);
4108 client_width = hwnd.ClientRect.Width;
4109 client_height = hwnd.ClientRect.Height;
4114 // Should we throw an exception or fail silently?
4115 // throw new ArgumentException("Called with an invalid window handle", "handle");
4125 internal override FormWindowState GetWindowState(IntPtr handle) {
4128 hwnd = Hwnd.ObjectFromHandle(handle);
4130 if (hwnd.cached_window_state == (FormWindowState)(-1))
4131 hwnd.cached_window_state = UpdateWindowState (handle);
4133 return hwnd.cached_window_state;
4136 private FormWindowState UpdateWindowState (IntPtr handle) {
4141 IntPtr prop = IntPtr.Zero;
4145 XWindowAttributes attributes;
4148 hwnd = Hwnd.ObjectFromHandle(handle);
4152 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);
4153 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4154 for (int i = 0; i < (long)nitems; i++) {
4155 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4156 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4158 } else if (atom == _NET_WM_STATE_HIDDEN) {
4166 return FormWindowState.Minimized;
4167 } else if (maximized == 2) {
4168 return FormWindowState.Maximized;
4171 attributes = new XWindowAttributes();
4172 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4173 if (attributes.map_state == MapState.IsUnmapped) {
4174 return (FormWindowState)(-1);
4178 return FormWindowState.Normal;
4181 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4183 GrabConfined = Grab.Confined;
4184 GrabArea = Grab.Area;
4187 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4189 IntPtr confine_to_window;
4191 confine_to_window = IntPtr.Zero;
4193 if (confine_to_handle != IntPtr.Zero) {
4194 XWindowAttributes attributes = new XWindowAttributes();
4196 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4199 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4201 Grab.Area.X = attributes.x;
4202 Grab.Area.Y = attributes.y;
4203 Grab.Area.Width = attributes.width;
4204 Grab.Area.Height = attributes.height;
4205 Grab.Confined = true;
4206 confine_to_window = hwnd.client_window;
4211 hwnd = Hwnd.ObjectFromHandle(handle);
4214 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4215 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4216 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4217 EventMask.LeaveWindowMask,
4218 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4222 internal override void UngrabWindow(IntPtr hwnd) {
4224 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4225 XFlush(DisplayHandle);
4227 WindowUngrabbed (hwnd);
4230 private void WindowUngrabbed (IntPtr hwnd) {
4231 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4233 Grab.Hwnd = IntPtr.Zero;
4234 Grab.Confined = false;
4237 // lparam should be the handle to the window gaining the mouse capture,
4238 // but X doesn't seem to give us that information.
4239 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4240 // X will send a NotifyUngrab, but since it comes late sometimes we're
4241 // calling WindowUngrabbed directly from UngrabWindow in order to send
4242 // this WM right away.
4243 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4247 internal override void HandleException(Exception e) {
4248 StackTrace st = new StackTrace(e, true);
4249 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4250 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4253 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4256 hwnd = Hwnd.ObjectFromHandle(handle);
4259 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4261 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4265 internal override void InvalidateNC (IntPtr handle) {
4268 hwnd = Hwnd.ObjectFromHandle(handle);
4270 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4273 internal override bool IsEnabled(IntPtr handle) {
4274 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4275 return (hwnd != null && hwnd.Enabled);
4278 internal override bool IsVisible(IntPtr handle) {
4279 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4280 return (hwnd != null && hwnd.visible);
4283 internal override void KillTimer(Timer timer) {
4284 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4286 if (queue == null) {
4287 // This isn't really an error, MS doesn't start the timer if
4288 // it has no assosciated queue
4291 queue.timer_list.Remove (timer);
4294 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4300 hwnd = Hwnd.ObjectFromHandle(handle);
4303 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4310 internal override void OverrideCursor(IntPtr cursor)
4312 if (Grab.Hwnd != IntPtr.Zero) {
4313 XChangeActivePointerGrab (DisplayHandle,
4314 EventMask.ButtonMotionMask |
4315 EventMask.PointerMotionMask |
4316 EventMask.ButtonPressMask |
4317 EventMask.ButtonReleaseMask,
4318 cursor, IntPtr.Zero);
4322 OverrideCursorHandle = cursor;
4325 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4326 PaintEventArgs paint_event;
4329 hwnd = Hwnd.ObjectFromHandle(handle);
4331 if (Caret.Visible == true) {
4332 Caret.Paused = true;
4339 dc = Graphics.FromHwnd (hwnd.client_window);
4341 Region clip_region = new Region ();
4342 clip_region.MakeEmpty();
4344 foreach (Rectangle r in hwnd.ClipRectangles) {
4345 clip_region.Union (r);
4348 if (hwnd.UserClip != null) {
4349 clip_region.Intersect(hwnd.UserClip);
4352 dc.Clip = clip_region;
4353 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4354 hwnd.expose_pending = false;
4356 hwnd.ClearInvalidArea();
4358 hwnd.drawing_stack.Push (paint_event);
4359 hwnd.drawing_stack.Push (dc);
4363 dc = Graphics.FromHwnd (hwnd.whole_window);
4365 if (!hwnd.nc_invalid.IsEmpty) {
4366 dc.SetClip (hwnd.nc_invalid);
4367 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4369 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4371 hwnd.nc_expose_pending = false;
4373 hwnd.ClearNcInvalidArea ();
4375 hwnd.drawing_stack.Push (paint_event);
4376 hwnd.drawing_stack.Push (dc);
4382 internal override void PaintEventEnd(IntPtr handle, bool client) {
4385 hwnd = Hwnd.ObjectFromHandle(handle);
4387 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4391 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4392 pe.SetGraphics (null);
4395 if (Caret.Visible == true) {
4397 Caret.Paused = false;
4401 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4402 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4403 XEventQueue queue = (XEventQueue) queue_id;
4406 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4407 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4411 if (queue.Count > 0) {
4414 // Only call UpdateMessageQueue if real events are pending
4415 // otherwise we go to sleep on the socket
4416 if (XPending(DisplayHandle) != 0) {
4417 UpdateMessageQueue((XEventQueue)queue_id);
4419 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4424 CheckTimers(queue.timer_list, DateTime.UtcNow);
4429 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4432 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4433 XEvent xevent = new XEvent ();
4434 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4436 xevent.type = XEventName.ClientMessage;
4437 xevent.ClientMessageEvent.display = DisplayHandle;
4440 xevent.ClientMessageEvent.window = hwnd.whole_window;
4442 xevent.ClientMessageEvent.window = IntPtr.Zero;
4445 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4446 xevent.ClientMessageEvent.format = 32;
4447 xevent.ClientMessageEvent.ptr1 = handle;
4448 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4449 xevent.ClientMessageEvent.ptr3 = wparam;
4450 xevent.ClientMessageEvent.ptr4 = lparam;
4452 hwnd.Queue.EnqueueLocked (xevent);
4457 internal override void PostQuitMessage(int exitCode) {
4458 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4459 XFlush(DisplayHandle);
4462 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4467 internal override void RequestNCRecalc(IntPtr handle) {
4470 hwnd = Hwnd.ObjectFromHandle(handle);
4476 PerformNCCalc(hwnd);
4477 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4478 InvalidateNC(handle);
4481 internal override void ResetMouseHover(IntPtr handle) {
4484 hwnd = Hwnd.ObjectFromHandle(handle);
4489 HoverState.Timer.Enabled = true;
4490 HoverState.X = mouse_position.X;
4491 HoverState.Y = mouse_position.Y;
4492 HoverState.Window = handle;
4496 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4502 hwnd = Hwnd.ObjectFromHandle(handle);
4505 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4512 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4518 hwnd = Hwnd.ObjectFromHandle(handle);
4521 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4528 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4531 XGCValues gc_values;
4533 hwnd = Hwnd.ObjectFromHandle(handle);
4535 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4537 /* We have an invalid area in the window we're scrolling.
4538 Adjust our stored invalid rectangle to to match the scrolled amount */
4553 if (area.Contains (hwnd.Invalid))
4554 hwnd.ClearInvalidArea ();
4555 hwnd.AddInvalidArea(r);
4558 gc_values = new XGCValues();
4560 if (with_children) {
4561 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4564 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4572 height = area.Height - YAmount;
4573 dest_y = area.Y + YAmount;
4576 src_y = area.Y - YAmount;
4577 height = area.Height + YAmount;
4583 width = area.Width - XAmount;
4584 dest_x = area.X + XAmount;
4587 src_x = area.X - XAmount;
4588 width = area.Width + XAmount;
4592 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4594 // Generate an expose for the area exposed by the horizontal scroll
4595 // We don't use AddExpose since we're
4597 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4598 } else if (XAmount < 0) {
4599 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4602 // Generate an expose for the area exposed by the vertical scroll
4604 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4605 } else if (YAmount < 0) {
4606 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4608 XFreeGC(DisplayHandle, gc);
4611 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4615 hwnd = Hwnd.GetObjectFromWindow(handle);
4617 rect = hwnd.ClientRect;
4620 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4623 internal override void SendAsyncMethod (AsyncMethodData method) {
4625 XEvent xevent = new XEvent ();
4627 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4629 xevent.type = XEventName.ClientMessage;
4630 xevent.ClientMessageEvent.display = DisplayHandle;
4631 xevent.ClientMessageEvent.window = method.Handle;
4632 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4633 xevent.ClientMessageEvent.format = 32;
4634 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4636 hwnd.Queue.EnqueueLocked (xevent);
4641 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4643 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4646 h = Hwnd.ObjectFromHandle(hwnd);
4648 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4649 AsyncMethodResult result;
4650 AsyncMethodData data;
4652 result = new AsyncMethodResult ();
4653 data = new AsyncMethodData ();
4656 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4657 data.Args = new object[] { hwnd, message, wParam, lParam };
4658 data.Result = result;
4660 SendAsyncMethod (data);
4661 #if DriverDebug || DriverDebugThreads
4662 Console.WriteLine ("Sending {0} message across.", message);
4667 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4670 internal override int SendInput(IntPtr handle, Queue keys) {
4671 if (handle == IntPtr.Zero)
4674 int count = keys.Count;
4675 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4677 while (keys.Count > 0) {
4679 MSG msg = (MSG)keys.Dequeue();
4681 XEvent xevent = new XEvent ();
4683 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4684 xevent.KeyEvent.display = DisplayHandle;
4687 xevent.KeyEvent.window = hwnd.whole_window;
4689 xevent.KeyEvent.window = IntPtr.Zero;
4692 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4694 hwnd.Queue.EnqueueLocked (xevent);
4699 internal override void SetAllowDrop (IntPtr handle, bool value)
4701 // We allow drop on all windows
4704 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4705 DragDropEffects allowed_effects)
4707 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4710 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4712 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4715 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4716 Form form = Control.FromHandle (handle) as Form;
4717 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4718 border_style == FormBorderStyle.SizableToolWindow)) {
4719 form.window_manager = new ToolWindowManager (form);
4722 RequestNCRecalc(handle);
4725 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4726 if (Caret.Hwnd == handle) {
4733 if (Caret.Visible == true) {
4735 Caret.Timer.Start();
4740 internal override void SetClipRegion(IntPtr handle, Region region) {
4743 hwnd = Hwnd.ObjectFromHandle(handle);
4748 hwnd.UserClip = region;
4749 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4752 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4755 if (OverrideCursorHandle == IntPtr.Zero) {
4756 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4760 LastCursorHandle = cursor;
4761 LastCursorWindow = handle;
4763 hwnd = Hwnd.ObjectFromHandle(handle);
4765 if (cursor != IntPtr.Zero) {
4766 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4768 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4770 XFlush(DisplayHandle);
4775 hwnd = Hwnd.ObjectFromHandle(handle);
4777 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4781 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4782 out int root_x, out int root_y, out int child_x, out int child_y,
4785 /* this code was written with the help of
4786 glance at gdk. I never would have realized we
4787 needed a loop in order to traverse down in the
4788 hierarchy. I would have assumed you'd get the
4789 most deeply nested child and have to do
4790 XQueryTree to move back up the hierarchy..
4791 stupid me, of course. */
4794 XGrabServer (display);
4796 XQueryPointer(display, w, out root, out c,
4797 out root_x, out root_y, out child_x, out child_y,
4803 IntPtr child_last = IntPtr.Zero;
4804 while (c != IntPtr.Zero) {
4806 XQueryPointer(display, c, out root, out c,
4807 out root_x, out root_y, out child_x, out child_y,
4810 XUngrabServer (display);
4816 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4817 if (handle == IntPtr.Zero) {
4820 int root_x, root_y, child_x, child_y, mask;
4823 * QueryPointer before warping
4824 * because if the warp is on
4825 * the RootWindow, the x/y are
4826 * relative to the current
4829 QueryPointer (DisplayHandle, RootWindow,
4832 out root_x, out root_y,
4833 out child_x, out child_y,
4836 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4838 XFlush (DisplayHandle);
4840 /* then we need to a
4841 * QueryPointer after warping
4842 * to manually generate a
4843 * motion event for the window
4846 QueryPointer (DisplayHandle, RootWindow,
4849 out root_x, out root_y,
4850 out child_x, out child_y,
4853 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4854 if (child_hwnd == null) {
4858 XEvent xevent = new XEvent ();
4860 xevent.type = XEventName.MotionNotify;
4861 xevent.MotionEvent.display = DisplayHandle;
4862 xevent.MotionEvent.window = child_hwnd.client_window;
4863 xevent.MotionEvent.root = RootWindow;
4864 xevent.MotionEvent.x = child_x;
4865 xevent.MotionEvent.y = child_y;
4866 xevent.MotionEvent.x_root = root_x;
4867 xevent.MotionEvent.y_root = root_y;
4868 xevent.MotionEvent.state = mask;
4870 child_hwnd.Queue.EnqueueLocked (xevent);
4875 hwnd = Hwnd.ObjectFromHandle(handle);
4877 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4882 internal override void SetFocus(IntPtr handle) {
4884 IntPtr prev_focus_window;
4886 hwnd = Hwnd.ObjectFromHandle(handle);
4888 if (hwnd.client_window == FocusWindow) {
4892 prev_focus_window = FocusWindow;
4893 FocusWindow = hwnd.client_window;
4895 if (prev_focus_window != IntPtr.Zero) {
4896 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4898 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4900 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4903 internal override void SetIcon(IntPtr handle, Icon icon) {
4906 hwnd = Hwnd.ObjectFromHandle(handle);
4908 SetIcon(hwnd, icon);
4912 internal override void SetMenu(IntPtr handle, Menu menu) {
4915 hwnd = Hwnd.ObjectFromHandle(handle);
4918 RequestNCRecalc(handle);
4921 internal override void SetModal(IntPtr handle, bool Modal) {
4923 ModalWindows.Push(handle);
4925 if (ModalWindows.Contains(handle)) {
4928 if (ModalWindows.Count > 0) {
4929 Activate((IntPtr)ModalWindows.Peek());
4934 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4937 hwnd = Hwnd.ObjectFromHandle(handle);
4938 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4941 #if DriverDebug || DriverDebugParent
4942 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4944 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4950 internal override void SetTimer (Timer timer) {
4951 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4953 if (queue == null) {
4954 // This isn't really an error, MS doesn't start the timer if
4955 // it has no assosciated queue
4958 queue.timer_list.Add (timer);
4962 internal override bool SetTopmost(IntPtr handle, bool enabled) {
4964 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4968 int[] atoms = new int[8];
4969 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
4970 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4974 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
4980 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
4984 hwnd = Hwnd.ObjectFromHandle(handle);
4986 if (handle_owner != IntPtr.Zero) {
4987 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4993 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4994 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4996 if (hwnd_owner != null) {
4997 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4999 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5004 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5010 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5014 hwnd = Hwnd.ObjectFromHandle(handle);
5015 hwnd.visible = visible;
5019 MapWindow(hwnd, WindowType.Both);
5021 if (Control.FromHandle(handle) is Form) {
5024 s = ((Form)Control.FromHandle(handle)).WindowState;
5027 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5028 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5032 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5035 UnmapWindow(hwnd, WindowType.Both);
5041 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5046 hwnd = Hwnd.ObjectFromHandle(handle);
5051 hints = new XSizeHints();
5053 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5054 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5055 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5056 hints.min_width = min.Width;
5057 hints.min_height = min.Height;
5060 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5061 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5062 hints.max_width = max.Width;
5063 hints.max_height = max.Height;
5066 if (hints.flags != IntPtr.Zero) {
5067 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5070 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5071 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5072 hints.x = maximized.X;
5073 hints.y = maximized.Y;
5074 hints.width = maximized.Width;
5075 hints.height = maximized.Height;
5077 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5078 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5083 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5086 hwnd = Hwnd.ObjectFromHandle(handle);
5092 // Win32 automatically changes negative width/height to 0.
5098 // X requires a sanity check for width & height; otherwise it dies
5099 if (hwnd.zero_sized && width > 0 && height > 0) {
5101 MapWindow(hwnd, WindowType.Whole);
5103 hwnd.zero_sized = false;
5106 if ((width < 1) || (height < 1)) {
5107 hwnd.zero_sized = true;
5108 UnmapWindow(hwnd, WindowType.Whole);
5111 // Save a server roundtrip (and prevent a feedback loop)
5112 if ((hwnd.x == x) && (hwnd.y == y) &&
5113 (hwnd.width == width) && (hwnd.height == height)) {
5117 if (!hwnd.zero_sized) {
5122 hwnd.height = height;
5123 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5125 if (hwnd.fixed_size) {
5126 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5130 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
5131 PerformNCCalc(hwnd);
5135 // Update our position/size immediately, so
5136 // that future calls to SetWindowPos aren't
5137 // kept from calling XMoveResizeWindow (by the
5138 // "Save a server roundtrip" block above).
5142 hwnd.height = height;
5143 hwnd.ClientRect = Rectangle.Empty;
5146 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5147 FormWindowState current_state;
5150 hwnd = Hwnd.ObjectFromHandle(handle);
5152 current_state = GetWindowState(handle);
5154 if (current_state == state) {
5159 case FormWindowState.Normal: {
5161 if (current_state == FormWindowState.Minimized) {
5162 MapWindow(hwnd, WindowType.Both);
5163 } else if (current_state == FormWindowState.Maximized) {
5164 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5171 case FormWindowState.Minimized: {
5173 if (current_state == FormWindowState.Maximized) {
5174 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5176 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5181 case FormWindowState.Maximized: {
5183 if (current_state == FormWindowState.Minimized) {
5184 MapWindow(hwnd, WindowType.Both);
5187 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5195 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5198 hwnd = Hwnd.ObjectFromHandle(handle);
5199 SetHwndStyles(hwnd, cp);
5200 SetWMStyles(hwnd, cp);
5203 internal override double GetWindowTransparency(IntPtr handle)
5208 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5212 hwnd = Hwnd.ObjectFromHandle(handle);
5218 hwnd.opacity = (uint)(0xffffffff * transparency);
5219 opacity = (IntPtr)((int)hwnd.opacity);
5221 IntPtr w = hwnd.whole_window;
5222 if (hwnd.reparented)
5223 w = XGetParent (hwnd.whole_window);
5224 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5227 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5228 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5236 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5239 } else if (!bottom) {
5240 Hwnd after_hwnd = null;
5242 if (after_handle != IntPtr.Zero) {
5243 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5246 XWindowChanges values = new XWindowChanges();
5248 if (after_hwnd == null) {
5249 // Work around metacity 'issues'
5253 atoms[0] = unixtime();
5254 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5256 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5257 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5259 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5262 values.sibling = after_hwnd.whole_window;
5263 values.stack_mode = StackMode.Below;
5266 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5271 XLowerWindow(DisplayHandle, hwnd.whole_window);
5278 internal override void ShowCursor(bool show) {
5279 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5282 internal override object StartLoop(Thread thread) {
5283 XEventQueue q = ThreadQueue(thread);
5287 internal override TransparencySupport SupportsTransparency() {
5288 // We need to check if the x compositing manager is running
5289 return TransparencySupport.Set;
5292 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5293 GetSystrayManagerWindow();
5295 if (SystrayMgrWindow != IntPtr.Zero) {
5296 XSizeHints size_hints;
5299 hwnd = Hwnd.ObjectFromHandle(handle);
5301 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5305 if (hwnd.client_window != hwnd.whole_window) {
5306 XDestroyWindow(DisplayHandle, hwnd.client_window);
5307 hwnd.client_window = hwnd.whole_window;
5309 /* by virtue of the way the tests are ordered when determining if it's PAINT
5310 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5311 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5312 there's a pending expose). */
5313 if (hwnd.nc_expose_pending) {
5314 hwnd.nc_expose_pending = false;
5315 if (!hwnd.expose_pending)
5316 hwnd.Queue.Paint.Remove (hwnd);
5320 size_hints = new XSizeHints();
5322 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5324 size_hints.min_width = 24;
5325 size_hints.min_height = 24;
5326 size_hints.max_width = 24;
5327 size_hints.max_height = 24;
5328 size_hints.base_width = 24;
5329 size_hints.base_height = 24;
5331 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5333 int[] atoms = new int[2];
5334 atoms [0] = 1; // Version 1
5335 atoms [1] = 1; // we want to be mapped
5337 // This line cost me 3 days...
5338 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5340 // Need to pick some reasonable defaults
5342 tt.AutomaticDelay = 100;
5343 tt.InitialDelay = 250;
5344 tt.ReshowDelay = 250;
5345 tt.ShowAlways = true;
5347 if ((tip != null) && (tip != string.Empty)) {
5348 tt.SetToolTip(Control.FromHandle(handle), tip);
5354 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5362 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5365 control = Control.FromHandle(handle);
5366 if (control != null && tt != null) {
5367 tt.SetToolTip(control, tip);
5375 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5377 #if GTKSOCKET_SUPPORTS_REPARENTING
5380 hwnd = Hwnd.ObjectFromHandle(handle);
5382 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5383 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5384 * 2. The client can reparent its window out of the embedder window.
5385 * 3. The client can destroy its window.
5387 * this call to SetParent is case 2, but in
5388 * the spec it also mentions that gtk doesn't
5389 * support this at present. Looking at HEAD
5390 * gtksocket-x11.c jives with this statement.
5392 * so we can't reparent. we have to destroy.
5394 SetParent(hwnd.whole_window, FosterParent);
5396 Control control = Control.FromHandle(handle);
5397 if (control is NotifyIcon.NotifyIconWindow)
5398 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5401 // The caller can now re-dock it later...
5408 internal override bool Text(IntPtr handle, string text) {
5411 hwnd = Hwnd.ObjectFromHandle(handle);
5414 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5415 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5417 // XXX this has problems with UTF8.
5418 // we need to either use the actual
5419 // text if it's latin-1, or convert it
5420 // to compound text if it's in a
5421 // different charset.
5422 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5427 internal override bool TranslateMessage(ref MSG msg) {
5428 return Keyboard.TranslateMessage (ref msg);
5431 internal override void UpdateWindow(IntPtr handle) {
5434 hwnd = Hwnd.ObjectFromHandle(handle);
5436 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5440 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5441 hwnd.Queue.Paint.Remove(hwnd);
5444 internal override void CreateOffscreenDrawable (IntPtr handle,
5445 int width, int height,
5446 out object offscreen_drawable)
5449 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5451 XGetGeometry (DisplayHandle, handle,
5453 out x_out, out y_out,
5454 out width_out, out height_out,
5455 out border_width_out, out depth_out);
5457 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5459 offscreen_drawable = pixmap;
5463 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5465 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5468 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5470 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5473 internal override void BlitFromOffscreen (IntPtr dest_handle,
5475 object offscreen_drawable,
5476 Graphics offscreen_dc,
5479 XGCValues gc_values;
5482 gc_values = new XGCValues();
5484 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5486 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5487 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5489 XFreeGC (DisplayHandle, gc);
5492 #endregion // Public Static Methods
5495 internal override event EventHandler Idle;
5496 #endregion // Events
5499 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5500 internal extern static IntPtr XOpenDisplay(IntPtr display);
5501 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5502 internal extern static int XCloseDisplay(IntPtr display);
5503 [DllImport ("libX11", EntryPoint="XSynchronize")]
5504 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5506 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5507 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);
5508 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5509 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5510 [DllImport ("libX11", EntryPoint="XMapWindow")]
5511 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5512 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5513 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5514 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5515 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5516 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5517 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5518 [DllImport ("libX11", EntryPoint="XRootWindow")]
5519 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5520 [DllImport ("libX11", EntryPoint="XNextEvent")]
5521 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5522 [DllImport ("libX11")]
5523 internal extern static int XConnectionNumber (IntPtr diplay);
5524 [DllImport ("libX11")]
5525 internal extern static int XPending (IntPtr diplay);
5526 [DllImport ("libX11", EntryPoint="XSelectInput")]
5527 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5529 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5530 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5532 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5533 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5534 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5535 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5537 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5538 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5540 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5541 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5543 [DllImport ("libX11", EntryPoint="XFlush")]
5544 internal extern static int XFlush(IntPtr display);
5546 [DllImport ("libX11", EntryPoint="XSetWMName")]
5547 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5549 [DllImport ("libX11", EntryPoint="XStoreName")]
5550 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5552 [DllImport ("libX11", EntryPoint="XFetchName")]
5553 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5555 [DllImport ("libX11", EntryPoint="XSendEvent")]
5556 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5558 [DllImport ("libX11", EntryPoint="XQueryTree")]
5559 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);
5561 [DllImport ("libX11", EntryPoint="XFree")]
5562 internal extern static int XFree(IntPtr data);
5564 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5565 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5567 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5568 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5570 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5571 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5573 [DllImport ("libX11", EntryPoint="XInternAtom")]
5574 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5576 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5577 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5579 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5580 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5582 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5583 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);
5585 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5586 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5588 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5589 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);
5591 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5592 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);
5594 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5595 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);
5597 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5598 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);
5600 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5601 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);
5603 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5604 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);
5606 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5607 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);
5609 [DllImport ("libX11", EntryPoint="XClearWindow")]
5610 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5612 [DllImport ("libX11", EntryPoint="XClearArea")]
5613 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5616 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5617 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5619 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5620 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5622 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5623 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5625 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5626 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5628 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5629 internal extern static int XDefaultScreen(IntPtr display);
5631 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5632 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5634 [DllImport ("libX11", EntryPoint="XLookupColor")]
5635 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5637 [DllImport ("libX11", EntryPoint="XAllocColor")]
5638 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5640 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5641 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5643 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5644 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5646 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5647 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5649 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5650 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5652 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5653 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5655 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5656 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5658 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5659 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5661 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5662 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5664 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5665 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5667 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5668 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5670 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5671 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5674 [DllImport ("libX11", EntryPoint="XCreateGC")]
5675 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5677 [DllImport ("libX11", EntryPoint="XFreeGC")]
5678 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5680 [DllImport ("libX11", EntryPoint="XSetFunction")]
5681 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5683 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5684 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5686 [DllImport ("libX11", EntryPoint="XDrawLine")]
5687 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5689 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5690 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5692 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5693 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5695 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5696 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5698 [DllImport ("libX11", EntryPoint="XCopyArea")]
5699 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);
5701 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5702 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);
5704 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5705 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5707 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5708 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5710 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5711 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5713 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5714 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5716 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5717 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5719 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5720 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5722 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5723 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);
5725 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5726 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5728 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5729 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5731 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5732 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5734 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5735 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5737 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5738 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5740 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5741 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5743 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5744 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5746 [DllImport ("libX11", EntryPoint="XGrabServer")]
5747 internal extern static void XGrabServer(IntPtr display);
5749 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5750 internal extern static void XUngrabServer(IntPtr display);
5752 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5753 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5755 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5756 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5758 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5759 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5761 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5762 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5764 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5765 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5767 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5768 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5770 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5771 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5773 [DllImport ("libX11", EntryPoint="XInitThreads")]
5774 internal extern static int XInitThreads();
5776 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5777 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5779 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5780 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5782 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5783 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5785 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5786 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5788 [DllImport ("libX11", EntryPoint="XSetForeground")]
5789 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5791 [DllImport ("libX11", EntryPoint="XSetBackground")]
5792 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5794 [DllImport ("libX11", EntryPoint="XBell")]
5795 internal extern static int XBell(IntPtr display, int percent);
5797 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5798 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5800 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5801 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5803 [DllImport ("libX11")]
5804 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5806 [DllImport ("libX11")]
5807 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);