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.PointerMotionHintMask |
230 EventMask.SubstructureNotifyMask);
232 static readonly object lockobj = new object ();
234 #endregion // Local Variables
236 private XplatUIX11() {
237 // Handle singleton stuff first
240 // Now regular initialization
241 XlibLock = new object ();
242 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
245 ErrorExceptions = false;
247 // X11 Initialization
248 SetDisplay(XOpenDisplay(IntPtr.Zero));
249 X11DesktopColors.Initialize();
252 // Disable keyboard autorepeat
254 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
255 detectable_key_auto_repeat = true;
257 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
258 detectable_key_auto_repeat = false;
261 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
262 ErrorHandler = new XErrorHandler(HandleError);
263 XSetErrorHandler(ErrorHandler);
267 // Remove our display handle from S.D
268 Graphics.FromHdcInternal (IntPtr.Zero);
271 #endregion // Constructors
273 #region Singleton Specific Code
274 public static XplatUIX11 GetInstance() {
276 if (Instance == null) {
277 Instance=new XplatUIX11();
284 public int Reference {
291 #region Internal Properties
292 internal static IntPtr Display {
294 return DisplayHandle;
298 XplatUIX11.GetInstance().SetDisplay(value);
302 internal static int Screen {
312 internal static IntPtr RootWindowHandle {
322 internal static IntPtr Visual {
328 CustomVisual = value;
332 internal static IntPtr ColorMap {
334 return CustomColormap;
338 CustomColormap = value;
343 #region XExceptionClass
344 internal class XException : ApplicationException {
348 XRequest RequestCode;
352 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
353 this.Display = Display;
354 this.ResourceID = ResourceID;
355 this.Serial = Serial;
356 this.RequestCode = RequestCode;
357 this.ErrorCode = ErrorCode;
358 this.MinorCode = MinorCode;
361 public override string Message {
363 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
367 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
376 sb = new StringBuilder(160);
377 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
378 x_error_text = sb.ToString();
379 hwnd = Hwnd.ObjectFromHandle(ResourceID);
381 hwnd_text = hwnd.ToString();
382 c = Control.FromHandle(hwnd.Handle);
384 control_text = c.ToString();
386 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
389 hwnd_text = "<null>";
390 control_text = "<null>";
394 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);
398 #endregion // XExceptionClass
400 #region Internal Methods
401 internal void SetDisplay(IntPtr display_handle) {
402 if (display_handle != IntPtr.Zero) {
405 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
406 hwnd = Hwnd.ObjectFromHandle(FosterParent);
407 XDestroyWindow(DisplayHandle, FosterParent);
411 if (DisplayHandle != IntPtr.Zero) {
412 XCloseDisplay(DisplayHandle);
415 DisplayHandle=display_handle;
417 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
418 // been hacked to do this for us.
419 Graphics.FromHdcInternal (DisplayHandle);
421 // query for the render extension so
422 // we can ignore the spurious
423 // BadPicture errors that are
424 // generated by cairo/render.
425 XQueryExtension (DisplayHandle, "RENDER",
426 ref render_major_opcode, ref render_first_event, ref render_first_error);
429 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
430 XSynchronize(DisplayHandle, true);
433 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
434 ErrorExceptions = true;
438 ScreenNo = XDefaultScreen(DisplayHandle);
439 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
440 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
442 // Create the foster parent
443 // it is important that border_width is kept in synch with the other XCreateWindow calls
444 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
445 if (FosterParent==IntPtr.Zero) {
446 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
450 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
451 hwnd.WholeWindow = FosterParent;
452 hwnd.ClientWindow = FosterParent;
454 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
456 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
457 hwnd.whole_window = RootWindow;
458 hwnd.ClientWindow = RootWindow;
460 // For sleeping on the X11 socket
461 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
462 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
466 // To wake up when a timer is ready
467 network_buffer = new byte[10];
469 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
470 wake.Connect(listen.LocalEndPoint);
471 wake_receive = listen.Accept();
474 pollfds = new Pollfd [2];
475 pollfds [0] = new Pollfd ();
476 pollfds [0].fd = XConnectionNumber (DisplayHandle);
477 pollfds [0].events = PollEvents.POLLIN;
479 pollfds [1] = new Pollfd ();
480 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
481 pollfds [1].events = PollEvents.POLLIN;
484 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
485 Dnd = new X11Dnd (DisplayHandle, Keyboard);
487 DoubleClickInterval = 500;
489 HoverState.Interval = 500;
490 HoverState.Timer = new Timer();
491 HoverState.Timer.Enabled = false;
492 HoverState.Timer.Interval = HoverState.Interval;
493 HoverState.Timer.Tick += new EventHandler(MouseHover);
494 HoverState.Size = new Size(4, 4);
498 ActiveWindow = IntPtr.Zero;
499 FocusWindow = IntPtr.Zero;
500 ModalWindows = new Stack(3);
502 MouseState = MouseButtons.None;
503 mouse_position = new Point(0, 0);
505 Caret.Timer = new Timer();
506 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
507 Caret.Timer.Tick += new EventHandler(CaretCallback);
511 // Grab atom changes off the root window to catch certain WM events
512 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
514 // Handle any upcoming errors
515 ErrorHandler = new XErrorHandler(HandleError);
516 XSetErrorHandler(ErrorHandler);
518 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
521 #endregion // Internal Methods
523 #region Private Methods
524 private int unixtime() {
525 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
527 return (int) t.TotalSeconds;
530 private static void SetupAtoms() {
531 // make sure this array stays in sync with the statements below
532 string [] atom_names = new string[] {
537 //"_NET_CLIENT_LIST",
538 //"_NET_NUMBER_OF_DESKTOPS",
539 "_NET_DESKTOP_GEOMETRY",
540 //"_NET_DESKTOP_VIEWPORT",
541 "_NET_CURRENT_DESKTOP",
542 //"_NET_DESKTOP_NAMES",
543 "_NET_ACTIVE_WINDOW",
545 //"_NET_SUPPORTING_WM_CHECK",
546 //"_NET_VIRTUAL_ROOTS",
547 //"_NET_DESKTOP_LAYOUT",
548 //"_NET_SHOWING_DESKTOP",
549 //"_NET_CLOSE_WINDOW",
550 //"_NET_MOVERESIZE_WINDOW",
551 //"_NET_WM_MOVERESIZE",
552 //"_NET_RESTACK_WINDOW",
553 //"_NET_REQUEST_FRAME_EXTENTS",
555 //"_NET_WM_VISIBLE_NAME",
556 //"_NET_WM_ICON_NAME",
557 //"_NET_WM_VISIBLE_ICON_NAME",
559 "_NET_WM_WINDOW_TYPE",
561 //"_NET_WM_ALLOWED_ACTIONS",
563 //"_NET_WM_STRUT_PARTIAL",
564 //"_NET_WM_ICON_GEOMETRY",
567 //"_NET_WM_HANDLED_ICONS",
569 "_NET_FRAME_EXTENTS",
571 //"_NET_WM_SYNC_REQUEST",
572 "_NET_SYSTEM_TRAY_OPCODE",
573 //"_NET_SYSTEM_TRAY_ORIENTATION",
574 "_NET_WM_STATE_MAXIMIZED_HORZ",
575 "_NET_WM_STATE_MAXIMIZED_VERT",
576 "_NET_WM_STATE_HIDDEN",
580 "_NET_WM_STATE_SKIP_TASKBAR",
581 "_NET_WM_STATE_ABOVE",
582 "_NET_WM_STATE_MODAL",
583 "_NET_WM_CONTEXT_HELP",
584 "_NET_WM_WINDOW_OPACITY",
585 //"_NET_WM_WINDOW_TYPE_DESKTOP",
586 //"_NET_WM_WINDOW_TYPE_DOCK",
587 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
588 //"_NET_WM_WINDOW_TYPE_MENU",
589 "_NET_WM_WINDOW_TYPE_UTILITY",
590 "_NET_WM_WINDOW_TYPE_DIALOG",
591 //"_NET_WM_WINDOW_TYPE_SPLASH",
592 "_NET_WM_WINDOW_TYPE_NORMAL",
599 "_SWF_PostMessageAtom",
602 IntPtr[] atoms = new IntPtr [atom_names.Length];;
604 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
607 WM_PROTOCOLS = atoms [off++];
608 WM_DELETE_WINDOW = atoms [off++];
609 WM_TAKE_FOCUS = atoms [off++];
610 //_NET_SUPPORTED = atoms [off++];
611 //_NET_CLIENT_LIST = atoms [off++];
612 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
613 _NET_DESKTOP_GEOMETRY = atoms [off++];
614 //_NET_DESKTOP_VIEWPORT = atoms [off++];
615 _NET_CURRENT_DESKTOP = atoms [off++];
616 //_NET_DESKTOP_NAMES = atoms [off++];
617 _NET_ACTIVE_WINDOW = atoms [off++];
618 _NET_WORKAREA = atoms [off++];
619 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
620 //_NET_VIRTUAL_ROOTS = atoms [off++];
621 //_NET_DESKTOP_LAYOUT = atoms [off++];
622 //_NET_SHOWING_DESKTOP = atoms [off++];
623 //_NET_CLOSE_WINDOW = atoms [off++];
624 //_NET_MOVERESIZE_WINDOW = atoms [off++];
625 //_NET_WM_MOVERESIZE = atoms [off++];
626 //_NET_RESTACK_WINDOW = atoms [off++];
627 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
628 _NET_WM_NAME = atoms [off++];
629 //_NET_WM_VISIBLE_NAME = atoms [off++];
630 //_NET_WM_ICON_NAME = atoms [off++];
631 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
632 //_NET_WM_DESKTOP = atoms [off++];
633 _NET_WM_WINDOW_TYPE = atoms [off++];
634 _NET_WM_STATE = atoms [off++];
635 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
636 //_NET_WM_STRUT = atoms [off++];
637 //_NET_WM_STRUT_PARTIAL = atoms [off++];
638 //_NET_WM_ICON_GEOMETRY = atoms [off++];
639 _NET_WM_ICON = atoms [off++];
640 //_NET_WM_PID = atoms [off++];
641 //_NET_WM_HANDLED_ICONS = atoms [off++];
642 _NET_WM_USER_TIME = atoms [off++];
643 _NET_FRAME_EXTENTS = atoms [off++];
644 //_NET_WM_PING = atoms [off++];
645 //_NET_WM_SYNC_REQUEST = atoms [off++];
646 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
647 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
648 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
649 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
650 _NET_WM_STATE_HIDDEN = atoms [off++];
651 _XEMBED = atoms [off++];
652 _XEMBED_INFO = atoms [off++];
653 _MOTIF_WM_HINTS = atoms [off++];
654 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
655 _NET_WM_STATE_ABOVE = atoms [off++];
656 _NET_WM_STATE_MODAL = atoms [off++];
657 _NET_WM_CONTEXT_HELP = atoms [off++];
658 _NET_WM_WINDOW_OPACITY = atoms [off++];
659 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
660 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
661 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
662 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
663 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
664 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
665 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
666 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
667 CLIPBOARD = atoms [off++];
668 PRIMARY = atoms [off++];
669 OEMTEXT = atoms [off++];
670 UNICODETEXT = atoms [off++];
671 TARGETS = atoms [off++];
672 AsyncAtom = atoms [off++];
673 PostAtom = atoms [off++];
674 HoverState.Atom = atoms [off++];
676 //DIB = (IntPtr)Atom.XA_PIXMAP;
677 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
680 private void GetSystrayManagerWindow() {
681 XGrabServer(DisplayHandle);
682 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
683 XUngrabServer(DisplayHandle);
684 XFlush(DisplayHandle);
687 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
691 xev.ClientMessageEvent.type = XEventName.ClientMessage;
692 xev.ClientMessageEvent.send_event = true;
693 xev.ClientMessageEvent.window = window;
694 xev.ClientMessageEvent.message_type = message_type;
695 xev.ClientMessageEvent.format = 32;
696 xev.ClientMessageEvent.ptr1 = l0;
697 xev.ClientMessageEvent.ptr2 = l1;
698 xev.ClientMessageEvent.ptr3 = l2;
699 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
702 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
706 xev.ClientMessageEvent.type = XEventName.ClientMessage;
707 xev.ClientMessageEvent.send_event = true;
708 xev.ClientMessageEvent.window = window;
709 xev.ClientMessageEvent.message_type = message_type;
710 xev.ClientMessageEvent.format = 32;
711 xev.ClientMessageEvent.ptr1 = l0;
712 xev.ClientMessageEvent.ptr2 = l1;
713 xev.ClientMessageEvent.ptr3 = l2;
714 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
717 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
718 // WM_CREATE and WM_DESTROY causes
719 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
723 if (child == IntPtr.Zero) {
727 hwnd = Hwnd.GetObjectFromWindow (child);
733 if (hwnd.Handle == IntPtr.Zero) {
737 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
741 if (hwnd.Parent == null) {
745 if (hwnd.Parent.Handle == IntPtr.Zero) {
749 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
750 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
752 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
755 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
758 bool StyleSet (int s, WindowStyles ws)
760 return (s & (int)ws) == (int)ws;
763 bool ExStyleSet (int ex, WindowExStyles exws)
765 return (ex & (int)exws) == (int)exws;
768 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
770 return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
773 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
776 * If this is a form with no window manager, X is handling all the border and caption painting
777 * so remove that from the area (since the area we set of the window here is the part of the window
778 * we're painting in only)
780 Rectangle rect = hwnd.ClientRect;
781 Form form = ctrl as Form;
782 CreateParams cp = null;
785 cp = form.GetCreateParams ();
787 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
788 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
789 Rectangle xrect = rect;
791 xrect.Y -= borders.top;
792 xrect.X -= borders.left;
793 xrect.Width += borders.left + borders.right;
794 xrect.Height += borders.top + borders.bottom;
799 if (rect.Width < 1 || rect.Height < 1) {
809 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
811 return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
814 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
817 * If this is a form with no window manager, X is handling all the border and caption painting
818 * so remove that from the area (since the area we set of the window here is the part of the window
819 * we're painting in only)
821 Form form = cp.control as Form;
822 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
823 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
826 xrect.Width -= borders.left + borders.right;
827 xrect.Height -= borders.top + borders.bottom;
831 if (size.Height == 0)
838 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
841 * If this is a form with no window manager, X is handling all the border and caption painting
842 * so remove that from the area (since the area we set of the window here is the part of the window
843 * we're painting in only)
845 Size rect = new Size (xWidth, xHeight);
846 Form form = cp.control as Form;
847 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
848 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
851 xrect.Width += borders.left + borders.right;
852 xrect.Height += borders.top + borders.bottom;
859 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
865 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
866 frame = FrameExtents (hwnd.whole_window);
871 return new Point (x, y);
874 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) {
877 tool_caption_height = 19;
878 border_static = false;
880 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
881 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
882 border_style = FormBorderStyle.Fixed3D;
883 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
884 border_style = FormBorderStyle.Fixed3D;
885 border_static = true;
886 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
887 border_style = FormBorderStyle.None;
889 border_style = FormBorderStyle.FixedSingle;
891 title_style = TitleStyle.None;
893 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
895 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
896 title_style = TitleStyle.Tool;
898 title_style = TitleStyle.Normal;
902 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
905 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
906 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
907 border_style = (FormBorderStyle) 0xFFFF;
909 border_style = FormBorderStyle.None;
914 title_style = TitleStyle.None;
915 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
916 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
917 title_style = TitleStyle.Tool;
919 title_style = TitleStyle.Normal;
923 border_style = FormBorderStyle.None;
925 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
926 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
927 border_style = FormBorderStyle.SizableToolWindow;
929 border_style = FormBorderStyle.Sizable;
932 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
933 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
934 border_style = FormBorderStyle.Fixed3D;
935 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
936 border_style = FormBorderStyle.Fixed3D;
937 border_static = true;
938 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
939 border_style = FormBorderStyle.FixedDialog;
940 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
941 border_style = FormBorderStyle.FixedToolWindow;
942 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
943 border_style = FormBorderStyle.FixedSingle;
946 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
947 border_style = FormBorderStyle.FixedSingle;
954 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
955 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);
958 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
959 MotifWmHints mwmHints;
960 MotifFunctions functions;
961 MotifDecorations decorations;
964 Rectangle client_rect;
967 bool hide_from_taskbar;
968 IntPtr transient_for_parent;
970 // Windows we manage ourselves don't need WM window styles.
971 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
976 mwmHints = new MotifWmHints();
979 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
980 transient_for_parent = IntPtr.Zero;
982 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
983 mwmHints.functions = (IntPtr)0;
984 mwmHints.decorations = (IntPtr)0;
986 form = cp.control as Form;
988 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
989 /* tool windows get no window manager
993 /* just because the window doesn't get any decorations doesn't
994 mean we should disable the functions. for instance, without
995 MotifFunctions.Maximize, changing the windowstate to Maximized
996 is ignored by metacity. */
997 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
998 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
999 // No functions nor decorations whatsoever.
1001 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
1002 functions |= MotifFunctions.Move;
1003 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1006 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1007 functions |= MotifFunctions.Move | MotifFunctions.Resize;
1008 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1011 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1012 functions |= MotifFunctions.Minimize;
1013 decorations |= MotifDecorations.Minimize;
1016 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1017 functions |= MotifFunctions.Maximize;
1018 decorations |= MotifDecorations.Maximize;
1021 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1022 functions |= MotifFunctions.Resize;
1023 decorations |= MotifDecorations.ResizeH;
1026 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1027 decorations |= MotifDecorations.Border;
1030 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1031 decorations |= MotifDecorations.Border;
1034 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1035 decorations |= MotifDecorations.Border;
1038 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1039 functions |= MotifFunctions.Close;
1042 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1043 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1044 if (cp.Caption == "") {
1045 functions &= ~MotifFunctions.Move;
1046 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1051 if ((functions & MotifFunctions.Resize) == 0) {
1052 hwnd.fixed_size = true;
1053 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1054 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1056 hwnd.fixed_size = false;
1059 mwmHints.functions = (IntPtr)functions;
1060 mwmHints.decorations = (IntPtr)decorations;
1063 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1066 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1067 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1068 // and get those windows in front of their parents
1069 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1070 } else if (form != null && form.Modal) {
1071 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1073 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1076 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1077 hide_from_taskbar = true;
1078 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1079 hide_from_taskbar = true;
1081 hide_from_taskbar = false;
1084 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1085 if (form != null && !hwnd.reparented) {
1086 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1087 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1088 if (owner_hwnd != null)
1089 transient_for_parent = owner_hwnd.whole_window;
1093 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1094 transient_for_parent = hwnd.parent.whole_window;
1097 FormWindowState current_state = GetWindowState (hwnd.Handle);
1098 if (current_state == (FormWindowState)(-1))
1099 current_state = FormWindowState.Normal;
1101 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1106 atoms [0] = window_type.ToInt32 ();
1107 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1109 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1111 if (transient_for_parent != IntPtr.Zero) {
1112 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1115 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1117 if (hide_from_taskbar) {
1118 /* this line keeps the window from showing up in gnome's taskbar */
1119 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1121 /* we need to add these atoms in the
1122 * event we're maximized, since we're
1123 * replacing the existing
1124 * _NET_WM_STATE here. If we don't
1125 * add them, future calls to
1126 * GetWindowState will return Normal
1127 * for a window which is maximized. */
1128 if (current_state == FormWindowState.Maximized) {
1129 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1130 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1133 if (form != null && form.Modal) {
1134 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1137 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1140 IntPtr[] atom_ptrs = new IntPtr[2];
1141 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1142 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1143 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1146 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1150 private void SetIcon(Hwnd hwnd, Icon icon)
1155 // This really needs to do whatever it
1156 // takes to remove the window manager
1157 // menu, not just delete the ICON
1158 // property. This will cause metacity
1159 // to use the "no icon set" icon, and
1160 // we'll still have an icon.
1161 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1169 bitmap = icon.ToBitmap();
1171 size = bitmap.Width * bitmap.Height + 2;
1172 data = new IntPtr[size];
1174 data[index++] = (IntPtr)bitmap.Width;
1175 data[index++] = (IntPtr)bitmap.Height;
1177 for (int y = 0; y < bitmap.Height; y++) {
1178 for (int x = 0; x < bitmap.Width; x++) {
1179 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1183 XChangeProperty (DisplayHandle, hwnd.whole_window,
1184 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1185 PropertyMode.Replace, data, size);
1189 private void WakeupMain () {
1190 wake.Send (new byte [] { 0xFF });
1193 private XEventQueue ThreadQueue(Thread thread) {
1196 queue = (XEventQueue)MessageQueues[thread];
1197 if (queue == null) {
1198 queue = new XEventQueue(thread);
1199 MessageQueues[thread] = queue;
1205 private void TranslatePropertyToClipboard(IntPtr property) {
1210 IntPtr prop = IntPtr.Zero;
1212 Clipboard.Item = null;
1214 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);
1216 if ((long)nitems > 0) {
1217 if (property == (IntPtr)Atom.XA_STRING) {
1218 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1219 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1220 // FIXME - convert bitmap to image
1221 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1222 // FIXME - convert pixmap to image
1223 } else if (property == OEMTEXT) {
1224 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1225 } else if (property == UNICODETEXT) {
1226 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1233 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1235 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1239 // Keep the invalid area as small as needed
1240 if ((x + width) > hwnd.width) {
1241 width = hwnd.width - x;
1244 if ((y + height) > hwnd.height) {
1245 height = hwnd.height - y;
1249 hwnd.AddInvalidArea(x, y, width, height);
1250 if (!hwnd.expose_pending) {
1251 if (!hwnd.nc_expose_pending) {
1252 hwnd.Queue.Paint.Enqueue(hwnd);
1254 hwnd.expose_pending = true;
1257 hwnd.AddNcInvalidArea (x, y, width, height);
1259 if (!hwnd.nc_expose_pending) {
1260 if (!hwnd.expose_pending) {
1261 hwnd.Queue.Paint.Enqueue(hwnd);
1263 hwnd.nc_expose_pending = true;
1268 private static Hwnd.Borders FrameExtents (IntPtr window)
1274 IntPtr prop = IntPtr.Zero;
1275 Hwnd.Borders rect = new Hwnd.Borders ();
1277 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);
1278 if (prop != IntPtr.Zero) {
1279 if (nitems.ToInt32 () == 4) {
1280 rect.left = Marshal.ReadInt32 (prop, 0);
1281 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1282 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1283 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1291 private void AddConfigureNotify (XEvent xevent) {
1294 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1297 if (hwnd == null || hwnd.zombie) {
1300 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1301 if (hwnd.parent == null) {
1302 // The location given by the event is not reliable between different wm's,
1303 // so use an alternative way of getting it.
1304 Point location = GetTopLevelWindowLocation (hwnd);
1305 hwnd.x = location.X;
1306 hwnd.y = location.Y;
1309 // XXX this sucks. this isn't thread safe
1310 Control ctrl = Control.FromHandle (hwnd.Handle);
1311 Size TranslatedSize;
1313 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1315 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1317 hwnd.width = TranslatedSize.Width;
1318 hwnd.height = TranslatedSize.Height;
1319 hwnd.ClientRect = Rectangle.Empty;
1322 Console.WriteLine ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})", new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle, new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
1324 lock (hwnd.configure_lock) {
1325 if (!hwnd.configure_pending) {
1326 hwnd.Queue.EnqueueLocked (xevent);
1327 hwnd.configure_pending = true;
1331 // We drop configure events for Client windows
1334 private void ShowCaret() {
1335 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1341 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1345 private void HideCaret() {
1346 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1352 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1356 private int NextTimeout (ArrayList timers, DateTime now) {
1357 int timeout = Int32.MaxValue;
1359 foreach (Timer timer in timers) {
1360 int next = (int) (timer.Expires - now).TotalMilliseconds;
1362 return 0; // Have a timer that has already expired
1365 if (next < timeout) {
1369 if (timeout < Timer.Minimum) {
1370 timeout = Timer.Minimum;
1378 private void CheckTimers (ArrayList timers, DateTime now) {
1381 count = timers.Count;
1386 for (int i = 0; i < timers.Count; i++) {
1389 timer = (Timer) timers [i];
1391 if (timer.Enabled && timer.Expires <= now) {
1398 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1399 MSG msg = new MSG ();
1402 queue = ThreadQueue(Thread.CurrentThread);
1404 queue.DispatchIdle = false;
1408 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1409 if ((Msg)msg.message == Msg.WM_QUIT) {
1410 PostQuitMessage (0);
1414 if (msg.hwnd == hwnd.Handle) {
1415 if ((Msg)msg.message == message)
1417 else if ((Msg)msg.message == Msg.WM_DESTROY)
1421 TranslateMessage (ref msg);
1422 DispatchMessage (ref msg);
1427 queue.DispatchIdle = true;
1431 private void MapWindow(Hwnd hwnd, WindowType windows) {
1433 if (Control.FromHandle(hwnd.Handle) is Form) {
1434 Form f = Control.FromHandle(hwnd.Handle) as Form;
1435 if (f.WindowState == FormWindowState.Normal)
1436 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1439 // it's possible that our Hwnd is no
1440 // longer valid after making that
1441 // SendMessage call, so check here.
1445 bool need_to_wait = false;
1447 if ((windows & WindowType.Whole) != 0) {
1448 XMapWindow(DisplayHandle, hwnd.whole_window);
1450 if ((windows & WindowType.Client) != 0) {
1451 XMapWindow(DisplayHandle, hwnd.client_window);
1453 need_to_wait = true;
1458 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1459 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1463 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1465 if (Control.FromHandle(hwnd.Handle) is Form) {
1466 Form f = Control.FromHandle(hwnd.Handle) as Form;
1467 if (f.WindowState == FormWindowState.Normal)
1468 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1471 // it's possible that our Hwnd is no
1472 // longer valid after making that
1473 // SendMessage call, so check here.
1477 bool need_to_wait = false;
1479 if ((windows & WindowType.Client) != 0) {
1480 XUnmapWindow(DisplayHandle, hwnd.client_window);
1482 need_to_wait = true;
1484 if ((windows & WindowType.Whole) != 0) {
1485 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1488 hwnd.mapped = false;
1490 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1491 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1495 private void UpdateMessageQueue (XEventQueue queue) {
1500 now = DateTime.UtcNow;
1503 pending = XPending (DisplayHandle);
1507 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1508 Idle (this, EventArgs.Empty);
1512 pending = XPending (DisplayHandle);
1519 if (queue != null) {
1520 if (queue.Paint.Count > 0)
1523 timeout = NextTimeout (queue.timer_list, now);
1528 int length = pollfds.Length - 1;
1529 lock (wake_waiting_lock) {
1530 if (wake_waiting == false) {
1532 wake_waiting = true;
1536 Syscall.poll (pollfds, (uint)length, timeout);
1537 // Clean out buffer, so we're not busy-looping on the same data
1538 if (length == pollfds.Length) {
1539 if (pollfds[1].revents != 0)
1540 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1541 lock (wake_waiting_lock) {
1542 wake_waiting = false;
1547 pending = XPending (DisplayHandle);
1553 CheckTimers (queue.timer_list, now);
1556 XEvent xevent = new XEvent ();
1559 if (XPending (DisplayHandle) == 0)
1562 XNextEvent (DisplayHandle, ref xevent);
1564 if (xevent.AnyEvent.type == XEventName.KeyPress ||
1565 xevent.AnyEvent.type == XEventName.KeyRelease) {
1566 if (XFilterEvent(ref xevent, FosterParent)) {
1567 // probably here we could raise WM_IME_KEYDOWN and
1568 // WM_IME_KEYUP, but I'm not sure it is worthy.
1573 else if (XFilterEvent (ref xevent, IntPtr.Zero))
1577 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1582 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1584 switch (xevent.type) {
1585 case XEventName.Expose:
1586 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1589 case XEventName.SelectionClear: {
1590 // Should we do something?
1594 case XEventName.SelectionRequest: {
1595 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1599 sel_event = new XEvent();
1600 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1601 sel_event.SelectionEvent.send_event = true;
1602 sel_event.SelectionEvent.display = DisplayHandle;
1603 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1604 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1605 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1606 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1607 sel_event.SelectionEvent.property = IntPtr.Zero;
1609 // Seems that some apps support asking for supported types
1610 if (xevent.SelectionEvent.target == TARGETS) {
1617 if (Clipboard.Item is String) {
1618 atoms[atom_count++] = (int)Atom.XA_STRING;
1619 atoms[atom_count++] = (int)OEMTEXT;
1620 atoms[atom_count++] = (int)UNICODETEXT;
1621 } else if (Clipboard.Item is Image) {
1622 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1623 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1625 // FIXME - handle other types
1628 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1629 } else if (Clipboard.Item is string) {
1635 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1638 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1639 buffer = Marshal.AllocHGlobal(bytes.Length);
1640 buflen = bytes.Length;
1642 for (int i = 0; i < buflen; i++) {
1643 Marshal.WriteByte(buffer, i, bytes[i]);
1645 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1646 // FIXME - this should encode into ISO2022
1647 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1648 while (Marshal.ReadByte(buffer, buflen) != 0) {
1651 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1652 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1653 while (Marshal.ReadByte(buffer, buflen) != 0) {
1657 buffer = IntPtr.Zero;
1660 if (buffer != IntPtr.Zero) {
1661 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1662 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1663 Marshal.FreeHGlobal(buffer);
1665 } else if (Clipboard.Item is Image) {
1666 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1667 // FIXME - convert image and store as property
1668 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1669 // FIXME - convert image and store as property
1673 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1677 case XEventName.SelectionNotify: {
1678 if (Clipboard.Enumerating) {
1679 Clipboard.Enumerating = false;
1680 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1681 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1682 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1683 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1684 #if DriverDebugExtra
1685 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1689 } else if (Clipboard.Retrieving) {
1690 Clipboard.Retrieving = false;
1691 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1692 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1694 Clipboard.Item = null;
1697 Dnd.HandleSelectionNotifyEvent (ref xevent);
1702 case XEventName.KeyRelease:
1703 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1704 XEvent nextevent = new XEvent ();
1706 XPeekEvent (DisplayHandle, ref nextevent);
1708 if (nextevent.type == XEventName.KeyPress &&
1709 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1710 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1714 goto case XEventName.KeyPress;
1716 case XEventName.MotionNotify: {
1719 /* we can't do motion compression across threads, so just punt if we don't match up */
1720 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1721 peek = hwnd.Queue.Peek();
1722 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1726 goto case XEventName.KeyPress;
1729 case XEventName.KeyPress:
1730 case XEventName.ButtonPress:
1731 case XEventName.ButtonRelease:
1732 case XEventName.EnterNotify:
1733 case XEventName.LeaveNotify:
1734 case XEventName.CreateNotify:
1735 case XEventName.DestroyNotify:
1736 case XEventName.FocusIn:
1737 case XEventName.FocusOut:
1738 case XEventName.ClientMessage:
1739 case XEventName.ReparentNotify:
1740 case XEventName.MapNotify:
1741 case XEventName.UnmapNotify:
1742 hwnd.Queue.EnqueueLocked (xevent);
1745 case XEventName.ConfigureNotify:
1746 AddConfigureNotify(xevent);
1749 case XEventName.PropertyNotify:
1751 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1753 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1758 IntPtr prop = IntPtr.Zero;
1761 prev_active = ActiveWindow;
1762 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);
1763 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1764 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1767 if (prev_active != ActiveWindow) {
1768 if (prev_active != IntPtr.Zero) {
1769 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1771 if (ActiveWindow != IntPtr.Zero) {
1772 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1775 if (ModalWindows.Count == 0) {
1778 // Modality handling, if we are modal and the new active window is one
1779 // of ours but not the modal one, switch back to the modal window
1781 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1782 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1783 Activate((IntPtr)ModalWindows.Peek());
1790 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1791 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1792 hwnd.cached_window_state = (FormWindowState)(-1);
1800 private IntPtr GetMousewParam(int Delta) {
1803 if ((MouseState & MouseButtons.Left) != 0) {
1804 result |= (int)MsgButtons.MK_LBUTTON;
1807 if ((MouseState & MouseButtons.Middle) != 0) {
1808 result |= (int)MsgButtons.MK_MBUTTON;
1811 if ((MouseState & MouseButtons.Right) != 0) {
1812 result |= (int)MsgButtons.MK_RBUTTON;
1815 Keys mods = ModifierKeys;
1816 if ((mods & Keys.Control) != 0) {
1817 result |= (int)MsgButtons.MK_CONTROL;
1820 if ((mods & Keys.Shift) != 0) {
1821 result |= (int)MsgButtons.MK_SHIFT;
1824 result |= Delta << 16;
1826 return (IntPtr)result;
1828 private IntPtr XGetParent(IntPtr handle) {
1835 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1838 if (Children!=IntPtr.Zero) {
1846 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1848 // we need to workaround a problem with the
1849 // ordering of destruction of Drawables and
1850 // Pictures that exists between cairo and
1851 // RENDER on the server.
1852 if (error_event.request_code == (XRequest)render_major_opcode
1853 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1854 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1858 if (ErrorExceptions) {
1859 XUngrabPointer (display, IntPtr.Zero);
1860 throw new XException (error_event.display, error_event.resourceid,
1861 error_event.serial, error_event.error_code,
1862 error_event.request_code, error_event.minor_code);
1864 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1865 XException.GetMessage (error_event.display, error_event.resourceid,
1866 error_event.serial, error_event.error_code,
1867 error_event.request_code, error_event.minor_code),
1868 Environment.StackTrace);
1873 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1876 Control[] controls = c.Controls.GetAllControls ();
1878 if (c.IsHandleCreated && !c.IsDisposed) {
1879 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1881 #if DriverDebug || DriverDebugDestroy
1882 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1883 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1887 CleanupCachedWindows (hwnd);
1890 for (int i = 0; i < controls.Length; i ++) {
1891 AccumulateDestroyedHandles (controls[i], list);
1897 void CleanupCachedWindows (Hwnd hwnd)
1899 if (ActiveWindow == hwnd.Handle) {
1900 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1901 ActiveWindow = IntPtr.Zero;
1904 if (FocusWindow == hwnd.Handle) {
1905 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1906 FocusWindow = IntPtr.Zero;
1909 if (Grab.Hwnd == hwnd.Handle) {
1910 Grab.Hwnd = IntPtr.Zero;
1911 Grab.Confined = false;
1914 DestroyCaret (hwnd.Handle);
1917 private void PerformNCCalc(Hwnd hwnd) {
1918 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1922 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1924 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1925 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1927 ncp.rgrc1.left = rect.Left;
1928 ncp.rgrc1.top = rect.Top;
1929 ncp.rgrc1.right = rect.Right;
1930 ncp.rgrc1.bottom = rect.Bottom;
1932 Marshal.StructureToPtr(ncp, ptr, true);
1933 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1934 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1935 Marshal.FreeHGlobal(ptr);
1938 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1939 hwnd.ClientRect = rect;
1941 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1944 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1947 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1949 #endregion // Private Methods
1952 private void MouseHover(object sender, EventArgs e) {
1956 HoverState.Timer.Enabled = false;
1958 if (HoverState.Window != IntPtr.Zero) {
1959 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1961 xevent = new XEvent ();
1963 xevent.type = XEventName.ClientMessage;
1964 xevent.ClientMessageEvent.display = DisplayHandle;
1965 xevent.ClientMessageEvent.window = HoverState.Window;
1966 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1967 xevent.ClientMessageEvent.format = 32;
1968 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1970 hwnd.Queue.EnqueueLocked (xevent);
1977 private void CaretCallback(object sender, EventArgs e) {
1981 Caret.On = !Caret.On;
1983 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1985 #endregion // Callbacks
1987 #region Public Properties
1989 internal override int CaptionHeight {
1995 internal override Size CursorSize {
2000 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
2001 return new Size(x, y);
2003 return new Size(16, 16);
2008 internal override bool DragFullWindows {
2014 internal override Size DragSize {
2016 return new Size(4, 4);
2020 internal override Size FrameBorderSize {
2022 return new Size (4, 4);
2026 internal override Size IconSize {
2032 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2036 current = (long)list;
2039 size = new XIconSize();
2041 for (int i = 0; i < count; i++) {
2042 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2043 current += Marshal.SizeOf(size);
2045 // Look for our preferred size
2046 if (size.min_width == 32) {
2048 return new Size(32, 32);
2051 if (size.max_width == 32) {
2053 return new Size(32, 32);
2056 if (size.min_width < 32 && size.max_width > 32) {
2059 // check if we can fit one
2061 while (x < size.max_width) {
2062 x += size.width_inc;
2065 return new Size(32, 32);
2070 if (largest < size.max_width) {
2071 largest = size.max_width;
2075 // We didn't find a match or we wouldn't be here
2076 return new Size(largest, largest);
2079 return new Size(32, 32);
2084 internal override int KeyboardSpeed {
2087 // A lot harder: need to do:
2088 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2089 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2090 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2092 // And from that we can tell the repetition rate
2094 // Notice, the values must map to:
2095 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2101 internal override int KeyboardDelay {
2104 // Return values must range from 0 to 4, 0 meaning 250ms,
2105 // and 4 meaning 1000 ms.
2107 return 1; // ie, 500 ms
2111 internal override Size MaxWindowTrackSize {
2113 return new Size (WorkingArea.Width, WorkingArea.Height);
2117 internal override bool MenuAccessKeysUnderlined {
2123 internal override Size MinimizedWindowSize {
2125 return new Size(1, 1);
2129 internal override Size MinimizedWindowSpacingSize {
2131 return new Size(1, 1);
2135 internal override Size MinimumWindowSize {
2137 return new Size(110, 22);
2141 internal override Size MinimumFixedToolWindowSize {
2142 get { return new Size (27, 22); }
2145 internal override Size MinimumSizeableToolWindowSize {
2146 get { return new Size (37, 22); }
2149 internal override Size MinimumNoBorderWindowSize {
2150 get { return new Size (2, 2); }
2153 internal override Size MinWindowTrackSize {
2155 return new Size(1, 1);
2159 internal override Keys ModifierKeys {
2161 return Keyboard.ModifierKeys;
2165 internal override Size SmallIconSize {
2171 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2175 current = (long)list;
2178 size = new XIconSize();
2180 for (int i = 0; i < count; i++) {
2181 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2182 current += Marshal.SizeOf(size);
2184 // Look for our preferred size
2185 if (size.min_width == 16) {
2187 return new Size(16, 16);
2190 if (size.max_width == 16) {
2192 return new Size(16, 16);
2195 if (size.min_width < 16 && size.max_width > 16) {
2198 // check if we can fit one
2200 while (x < size.max_width) {
2201 x += size.width_inc;
2204 return new Size(16, 16);
2209 if (smallest == 0 || smallest > size.min_width) {
2210 smallest = size.min_width;
2214 // We didn't find a match or we wouldn't be here
2215 return new Size(smallest, smallest);
2218 return new Size(16, 16);
2223 internal override int MouseButtonCount {
2229 internal override bool MouseButtonsSwapped {
2231 return false; // FIXME - how to detect?
2235 internal override Point MousePosition {
2237 return mouse_position;
2241 internal override Size MouseHoverSize {
2243 return new Size (1, 1);
2247 internal override int MouseHoverTime {
2249 return HoverState.Interval;
2255 internal override bool MouseWheelPresent {
2257 return true; // FIXME - how to detect?
2261 internal override Rectangle VirtualScreen {
2267 IntPtr prop = IntPtr.Zero;
2271 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);
2272 if ((long)nitems < 2)
2275 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2276 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2280 return new Rectangle(0, 0, width, height);
2283 XWindowAttributes attributes=new XWindowAttributes();
2286 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2289 return new Rectangle(0, 0, attributes.width, attributes.height);
2293 internal override Rectangle WorkingArea {
2299 IntPtr prop = IntPtr.Zero;
2302 int current_desktop;
2306 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);
2307 if ((long)nitems < 1) {
2311 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2314 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);
2315 if ((long)nitems < 4 * current_desktop) {
2319 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2320 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2321 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2322 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2325 return new Rectangle(x, y, width, height);
2328 XWindowAttributes attributes=new XWindowAttributes();
2331 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2334 return new Rectangle(0, 0, attributes.width, attributes.height);
2338 internal override bool ThemesEnabled {
2340 return XplatUIX11.themes_enabled;
2345 #endregion // Public properties
2347 #region Public Static Methods
2348 internal override void RaiseIdle (EventArgs e)
2354 internal override IntPtr InitializeDriver() {
2356 if (DisplayHandle==IntPtr.Zero) {
2357 SetDisplay(XOpenDisplay(IntPtr.Zero));
2363 internal override void ShutdownDriver(IntPtr token) {
2365 if (DisplayHandle!=IntPtr.Zero) {
2366 XCloseDisplay(DisplayHandle);
2367 DisplayHandle=IntPtr.Zero;
2372 internal override void EnableThemes() {
2373 themes_enabled = true;
2377 internal override void Activate(IntPtr handle) {
2380 hwnd = Hwnd.ObjectFromHandle(handle);
2384 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2385 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2388 // XRaiseWindow(DisplayHandle, handle);
2394 internal override void AudibleAlert() {
2395 XBell(DisplayHandle, 0);
2400 internal override void CaretVisible(IntPtr handle, bool visible) {
2401 if (Caret.Hwnd == handle) {
2403 if (!Caret.Visible) {
2404 Caret.Visible = true;
2406 Caret.Timer.Start();
2409 Caret.Visible = false;
2416 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2417 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2421 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2427 hwnd = Hwnd.ObjectFromHandle(handle);
2430 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2437 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2438 DataFormats.Format f;
2441 f = DataFormats.Format.List;
2443 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2447 Clipboard.Formats = new ArrayList();
2450 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2452 Clipboard.Enumerating = true;
2453 while (Clipboard.Enumerating) {
2454 UpdateMessageQueue(null);
2459 result = new int[Clipboard.Formats.Count];
2461 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2462 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2465 Clipboard.Formats = null;
2469 internal override void ClipboardClose(IntPtr handle) {
2470 if (handle != ClipMagic) {
2471 throw new ArgumentException("handle is not a valid clipboard handle");
2476 internal override int ClipboardGetID(IntPtr handle, string format) {
2477 if (handle != ClipMagic) {
2478 throw new ArgumentException("handle is not a valid clipboard handle");
2481 if (format == "Text" ) return (int)Atom.XA_STRING;
2482 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2483 //else if (format == "MetaFilePict" ) return 3;
2484 //else if (format == "SymbolicLink" ) return 4;
2485 //else if (format == "DataInterchangeFormat" ) return 5;
2486 //else if (format == "Tiff" ) return 6;
2487 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2488 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2489 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2490 //else if (format == "PenData" ) return 10;
2491 //else if (format == "RiffAudio" ) return 11;
2492 //else if (format == "WaveAudio" ) return 12;
2493 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2494 //else if (format == "EnhancedMetafile" ) return 14;
2495 //else if (format == "FileDrop" ) return 15;
2496 //else if (format == "Locale" ) return 16;
2498 return XInternAtom(DisplayHandle, format, false).ToInt32();
2501 internal override IntPtr ClipboardOpen(bool primary_selection) {
2502 if (!primary_selection)
2503 ClipMagic = CLIPBOARD;
2505 ClipMagic = PRIMARY;
2509 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2510 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2512 Clipboard.Retrieving = true;
2513 while (Clipboard.Retrieving) {
2514 UpdateMessageQueue(null);
2517 return Clipboard.Item;
2520 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2521 Clipboard.Item = obj;
2522 Clipboard.Type = type;
2523 Clipboard.Converter = converter;
2526 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2528 // Clearing the selection
2529 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2533 internal override void CreateCaret (IntPtr handle, int width, int height)
2535 XGCValues gc_values;
2538 hwnd = Hwnd.ObjectFromHandle(handle);
2540 if (Caret.Hwnd != IntPtr.Zero) {
2541 DestroyCaret(Caret.Hwnd);
2544 Caret.Hwnd = handle;
2545 Caret.Window = hwnd.client_window;
2546 Caret.Width = width;
2547 Caret.Height = height;
2548 Caret.Visible = false;
2551 gc_values = new XGCValues();
2552 gc_values.line_width = width;
2554 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2555 if (Caret.gc == IntPtr.Zero) {
2556 Caret.Hwnd = IntPtr.Zero;
2560 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2563 internal override IntPtr CreateWindow (CreateParams cp)
2565 XSetWindowAttributes Attributes;
2567 Hwnd parent_hwnd = null;
2572 IntPtr ParentHandle;
2574 IntPtr ClientWindow;
2575 SetWindowValuemask ValueMask;
2580 Attributes = new XSetWindowAttributes();
2586 if (Width<1) Width=1;
2587 if (Height<1) Height=1;
2589 if (cp.Parent != IntPtr.Zero) {
2590 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2591 ParentHandle = parent_hwnd.client_window;
2593 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2594 // We need to use our foster parent window until this poor child gets it's parent assigned
2595 ParentHandle=FosterParent;
2597 ParentHandle=RootWindow;
2601 // Set the default location location for forms.
2603 if (cp.control is Form) {
2604 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2608 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2610 Attributes.bit_gravity = Gravity.NorthWestGravity;
2611 Attributes.win_gravity = Gravity.NorthWestGravity;
2613 // Save what's under the toolwindow
2614 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2615 Attributes.save_under = true;
2616 ValueMask |= SetWindowValuemask.SaveUnder;
2620 // If we're a popup without caption we override the WM
2621 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2622 Attributes.override_redirect = true;
2623 ValueMask |= SetWindowValuemask.OverrideRedirect;
2629 hwnd.height = Height;
2630 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2631 hwnd.initial_style = cp.WindowStyle;
2632 hwnd.initial_ex_style = cp.WindowExStyle;
2634 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2635 hwnd.enabled = false;
2638 ClientWindow = IntPtr.Zero;
2640 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2641 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2644 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2645 if (WholeWindow != IntPtr.Zero) {
2646 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2648 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2649 ValueMask = SetWindowValuemask.ColorMap;
2650 Attributes.colormap = CustomColormap;
2652 ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
2656 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2657 throw new Exception("Could not create X11 windows");
2660 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2661 hwnd.WholeWindow = WholeWindow;
2662 hwnd.ClientWindow = ClientWindow;
2664 #if DriverDebug || DriverDebugCreate
2665 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);
2668 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2669 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2672 hints = new XSizeHints();
2675 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2676 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2681 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
2682 if (hwnd.whole_window != hwnd.client_window)
2683 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
2686 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2688 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2689 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2691 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2694 SetWMStyles(hwnd, cp);
2696 // set the group leader
2697 XWMHints wm_hints = new XWMHints ();
2699 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2700 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2701 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2703 if (ParentHandle != RootWindow) {
2704 wm_hints.window_group = hwnd.whole_window;
2706 wm_hints.window_group = ParentHandle;
2710 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2713 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2714 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2715 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2716 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2719 // for now make all windows dnd enabled
2720 Dnd.SetAllowDrop (hwnd, true);
2722 // Set caption/window title
2723 Text(hwnd.Handle, cp.Caption);
2725 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2726 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2728 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2729 hwnd.visible = true;
2730 MapWindow(hwnd, WindowType.Both);
2731 if (!(Control.FromHandle(hwnd.Handle) is Form))
2732 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2738 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2739 CreateParams create_params = new CreateParams();
2741 create_params.Caption = "";
2742 create_params.X = X;
2743 create_params.Y = Y;
2744 create_params.Width = Width;
2745 create_params.Height = Height;
2747 create_params.ClassName=XplatUI.DefaultClassName;
2748 create_params.ClassStyle = 0;
2749 create_params.ExStyle=0;
2750 create_params.Parent=IntPtr.Zero;
2751 create_params.Param=0;
2753 return CreateWindow(create_params);
2756 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2758 Bitmap cursor_bitmap;
2766 IntPtr cursor_pixmap;
2773 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2777 // Win32 only allows creation cursors of a certain size
2778 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2779 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2780 cursor_mask = new Bitmap(mask, new Size(width, height));
2782 cursor_bitmap = bitmap;
2786 width = cursor_bitmap.Width;
2787 height = cursor_bitmap.Height;
2789 cursor_bits = new Byte[(width / 8) * height];
2790 mask_bits = new Byte[(width / 8) * height];
2792 for (int y = 0; y < height; y++) {
2793 for (int x = 0; x < width; x++) {
2794 c_pixel = cursor_bitmap.GetPixel(x, y);
2795 m_pixel = cursor_mask.GetPixel(x, y);
2797 and = c_pixel == cursor_pixel;
2798 xor = m_pixel == mask_pixel;
2802 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2803 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2804 } else if (and && !xor) {
2806 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2807 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2809 } else if (and && !xor) {
2811 } else if (and && xor) {
2814 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2815 // we want both to be 0 so nothing to be done
2816 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2817 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2823 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2824 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2828 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2829 fg.red = (ushort)65535;
2830 fg.green = (ushort)65535;
2831 fg.blue = (ushort)65535;
2833 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2835 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2837 XFreePixmap(DisplayHandle, cursor_pixmap);
2838 XFreePixmap(DisplayHandle, mask_pixmap);
2843 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2844 CursorFontShape shape;
2851 shape = StdCursorToFontShape (id);
2852 name = shape.ToString ().Replace ("XC_", string.Empty);
2853 size = XcursorGetDefaultSize (DisplayHandle);
2854 theme = XcursorGetTheme (DisplayHandle);
2855 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2857 Console.WriteLine ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
2860 if (images_ptr == IntPtr.Zero) {
2864 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2866 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2869 if (images.nimage > 0) {
2870 // We only care about the first image.
2871 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2874 Console.WriteLine ("DefineStdCursorBitmap, loaded image <size={0}, height={1}, width={2}, xhot={3}, yhot={4}, pixels={5}", image.size, image.height, image.width, image.xhot, image.yhot, image.pixels);
2877 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2878 int [] pixels = new int [image.width * image.height];
2879 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2880 bmp = new Bitmap (image.width, image.height);
2881 for (int w = 0; w < image.width; w++) {
2882 for (int h = 0; h < image.height; h++) {
2883 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2889 XcursorImagesDestroy (images_ptr);
2891 } catch (DllNotFoundException ex) {
2892 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2900 internal override IntPtr DefineStdCursor(StdCursor id) {
2901 CursorFontShape shape;
2904 shape = StdCursorToFontShape (id);
2907 cursor = XCreateFontCursor(DisplayHandle, shape);
2912 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2913 CursorFontShape shape;
2914 // FIXME - define missing shapes
2917 case StdCursor.AppStarting: {
2918 shape = CursorFontShape.XC_watch;
2922 case StdCursor.Arrow: {
2923 shape = CursorFontShape.XC_top_left_arrow;
2927 case StdCursor.Cross: {
2928 shape = CursorFontShape.XC_crosshair;
2932 case StdCursor.Default: {
2933 shape = CursorFontShape.XC_top_left_arrow;
2937 case StdCursor.Hand: {
2938 shape = CursorFontShape.XC_hand1;
2942 case StdCursor.Help: {
2943 shape = CursorFontShape.XC_question_arrow;
2947 case StdCursor.HSplit: {
2948 shape = CursorFontShape.XC_sb_v_double_arrow;
2952 case StdCursor.IBeam: {
2953 shape = CursorFontShape.XC_xterm;
2957 case StdCursor.No: {
2958 shape = CursorFontShape.XC_circle;
2962 case StdCursor.NoMove2D: {
2963 shape = CursorFontShape.XC_fleur;
2967 case StdCursor.NoMoveHoriz: {
2968 shape = CursorFontShape.XC_fleur;
2972 case StdCursor.NoMoveVert: {
2973 shape = CursorFontShape.XC_fleur;
2977 case StdCursor.PanEast: {
2978 shape = CursorFontShape.XC_fleur;
2982 case StdCursor.PanNE: {
2983 shape = CursorFontShape.XC_fleur;
2987 case StdCursor.PanNorth: {
2988 shape = CursorFontShape.XC_fleur;
2992 case StdCursor.PanNW: {
2993 shape = CursorFontShape.XC_fleur;
2997 case StdCursor.PanSE: {
2998 shape = CursorFontShape.XC_fleur;
3002 case StdCursor.PanSouth: {
3003 shape = CursorFontShape.XC_fleur;
3007 case StdCursor.PanSW: {
3008 shape = CursorFontShape.XC_fleur;
3012 case StdCursor.PanWest: {
3013 shape = CursorFontShape.XC_sizing;
3017 case StdCursor.SizeAll: {
3018 shape = CursorFontShape.XC_fleur;
3022 case StdCursor.SizeNESW: {
3023 shape = CursorFontShape.XC_top_right_corner;
3027 case StdCursor.SizeNS: {
3028 shape = CursorFontShape.XC_sb_v_double_arrow;
3032 case StdCursor.SizeNWSE: {
3033 shape = CursorFontShape.XC_top_left_corner;
3037 case StdCursor.SizeWE: {
3038 shape = CursorFontShape.XC_sb_h_double_arrow;
3042 case StdCursor.UpArrow: {
3043 shape = CursorFontShape.XC_center_ptr;
3047 case StdCursor.VSplit: {
3048 shape = CursorFontShape.XC_sb_h_double_arrow;
3052 case StdCursor.WaitCursor: {
3053 shape = CursorFontShape.XC_watch;
3058 shape = (CursorFontShape) 0;
3066 internal override IntPtr DefWndProc(ref Message msg) {
3067 switch ((Msg)msg.Msg) {
3069 case Msg.WM_IME_COMPOSITION:
3070 string s = Keyboard.GetCompositionString ();
3071 foreach (char c in s)
3072 SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
3075 case Msg.WM_IME_CHAR:
3076 int c = (int) msg.WParam;
3077 // On Windows API it sends two WM_CHAR messages for each byte, but
3078 // I wonder if it is worthy to emulate it (also no idea how to
3079 // reconstruct those bytes into chars).
3080 SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
3083 case Msg.WM_PAINT: {
3086 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3088 hwnd.expose_pending = false;
3094 case Msg.WM_NCPAINT: {
3097 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3099 hwnd.nc_expose_pending = false;
3105 case Msg.WM_NCCALCSIZE: {
3108 if (msg.WParam == (IntPtr)1) {
3109 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3111 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3112 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3114 // Add all the stuff X is supposed to draw.
3115 Control ctrl = Control.FromHandle (hwnd.Handle);
3118 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3120 ncp.rgrc1.top += rect.top;
3121 ncp.rgrc1.bottom -= rect.bottom;
3122 ncp.rgrc1.left += rect.left;
3123 ncp.rgrc1.right -= rect.right;
3125 Marshal.StructureToPtr (ncp, msg.LParam, true);
3132 case Msg.WM_CONTEXTMENU: {
3135 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3137 if ((hwnd != null) && (hwnd.parent != null)) {
3138 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3143 case Msg.WM_MOUSEWHEEL: {
3146 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3148 if ((hwnd != null) && (hwnd.parent != null)) {
3149 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3150 if (msg.Result == IntPtr.Zero) {
3157 case Msg.WM_SETCURSOR: {
3160 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3162 break; // not sure how this happens, but it does
3164 // Pass to parent window first
3165 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3167 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3170 if (msg.Result == IntPtr.Zero) {
3173 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3174 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3175 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3176 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3177 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3178 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3181 handle = Cursors.Default.handle;
3184 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3185 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3186 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3187 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3188 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3189 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3192 case HitTest.HTGROWBOX:
3193 case HitTest.HTSIZE:
3194 case HitTest.HTZOOM:
3195 case HitTest.HTVSCROLL:
3196 case HitTest.HTSYSMENU:
3197 case HitTest.HTREDUCE:
3198 case HitTest.HTNOWHERE:
3199 case HitTest.HTMAXBUTTON:
3200 case HitTest.HTMINBUTTON:
3201 case HitTest.HTMENU:
3202 case HitTest.HSCROLL:
3203 case HitTest.HTBOTTOM:
3204 case HitTest.HTCAPTION:
3205 case HitTest.HTCLIENT:
3206 case HitTest.HTCLOSE:
3208 default: handle = Cursors.Default.handle; break;
3210 SetCursor(msg.HWnd, handle);
3218 internal override void DestroyCaret(IntPtr handle) {
3219 if (Caret.Hwnd == handle) {
3220 if (Caret.Visible) {
3224 if (Caret.gc != IntPtr.Zero) {
3225 XFreeGC(DisplayHandle, Caret.gc);
3226 Caret.gc = IntPtr.Zero;
3228 Caret.Hwnd = IntPtr.Zero;
3229 Caret.Visible = false;
3234 internal override void DestroyCursor(IntPtr cursor) {
3236 XFreeCursor(DisplayHandle, cursor);
3240 internal override void DestroyWindow(IntPtr handle) {
3243 hwnd = Hwnd.ObjectFromHandle(handle);
3246 #if DriverDebug || DriverDebugDestroy
3247 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3252 #if DriverDebug || DriverDebugDestroy
3253 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3256 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3258 CleanupCachedWindows (hwnd);
3260 ArrayList windows = new ArrayList ();
3262 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3265 foreach (Hwnd h in windows) {
3266 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3271 if (hwnd.whole_window != IntPtr.Zero) {
3272 #if DriverDebug || DriverDebugDestroy
3273 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3275 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3277 else if (hwnd.client_window != IntPtr.Zero) {
3278 #if DriverDebug || DriverDebugDestroy
3279 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3281 XDestroyWindow(DisplayHandle, hwnd.client_window);
3287 internal override IntPtr DispatchMessage(ref MSG msg) {
3288 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3291 IntPtr GetReversibleScreenGC (Color backColor)
3293 XGCValues gc_values;
3297 XColor xcolor = new XColor();
3298 xcolor.red = (ushort)(backColor.R * 257);
3299 xcolor.green = (ushort)(backColor.G * 257);
3300 xcolor.blue = (ushort)(backColor.B * 257);
3301 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3302 pixel = (uint)xcolor.pixel.ToInt32();
3305 gc_values = new XGCValues();
3307 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3308 gc_values.foreground = (IntPtr)pixel;
3310 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3311 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3312 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3317 IntPtr GetReversibleControlGC (Control control, int line_width)
3319 XGCValues gc_values;
3322 gc_values = new XGCValues();
3324 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3325 gc_values.line_width = line_width;
3326 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3328 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3329 //mask = foreground ^ background;
3330 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3331 //XSetBackground(DisplayHandle, gc, background);
3332 //XSetFunction(DisplayHandle, gc, GXxor);
3333 //XSetPlaneMask(DisplayHandle, gc, mask);
3336 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3340 XColor xcolor = new XColor();
3342 xcolor.red = (ushort)(control.ForeColor.R * 257);
3343 xcolor.green = (ushort)(control.ForeColor.G * 257);
3344 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3345 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3346 foreground = (uint)xcolor.pixel.ToInt32();
3348 xcolor.red = (ushort)(control.BackColor.R * 257);
3349 xcolor.green = (ushort)(control.BackColor.G * 257);
3350 xcolor.blue = (ushort)(control.BackColor.B * 257);
3351 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3352 background = (uint)xcolor.pixel.ToInt32();
3354 uint mask = foreground ^ background;
3356 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3357 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3358 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3359 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3364 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3366 if (backColor.GetBrightness() < 0.5)
3367 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3369 IntPtr gc = GetReversibleScreenGC (backColor);
3371 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3373 XFreeGC(DisplayHandle, gc);
3376 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3378 if (backColor.GetBrightness() < 0.5)
3379 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3381 IntPtr gc = GetReversibleScreenGC (backColor);
3383 if (rectangle.Width < 0) {
3384 rectangle.X += rectangle.Width;
3385 rectangle.Width = -rectangle.Width;
3387 if (rectangle.Height < 0) {
3388 rectangle.Y += rectangle.Height;
3389 rectangle.Height = -rectangle.Height;
3393 GCLineStyle line_style = GCLineStyle.LineSolid;
3394 GCCapStyle cap_style = GCCapStyle.CapButt;
3395 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3398 case FrameStyle.Dashed:
3399 line_style = GCLineStyle.LineOnOffDash;
3401 case FrameStyle.Thick:
3406 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3408 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3410 XFreeGC(DisplayHandle, gc);
3413 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3415 if (backColor.GetBrightness() < 0.5)
3416 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3418 IntPtr gc = GetReversibleScreenGC (backColor);
3420 if (rectangle.Width < 0) {
3421 rectangle.X += rectangle.Width;
3422 rectangle.Width = -rectangle.Width;
3424 if (rectangle.Height < 0) {
3425 rectangle.Y += rectangle.Height;
3426 rectangle.Height = -rectangle.Height;
3428 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3430 XFreeGC(DisplayHandle, gc);
3433 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3436 Control control = Control.FromHandle(handle);
3438 gc = GetReversibleControlGC (control, line_width);
3440 if ((rect.Width > 0) && (rect.Height > 0)) {
3441 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3443 if (rect.Width > 0) {
3444 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3446 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3449 XFreeGC(DisplayHandle, gc);
3452 internal override void DoEvents() {
3453 MSG msg = new MSG ();
3456 if (OverrideCursorHandle != IntPtr.Zero) {
3457 OverrideCursorHandle = IntPtr.Zero;
3460 queue = ThreadQueue(Thread.CurrentThread);
3462 queue.DispatchIdle = false;
3464 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3465 TranslateMessage (ref msg);
3466 DispatchMessage (ref msg);
3469 queue.DispatchIdle = true;
3472 internal override void EnableWindow(IntPtr handle, bool Enable) {
3475 hwnd = Hwnd.ObjectFromHandle(handle);
3477 hwnd.Enabled = Enable;
3481 internal override void EndLoop(Thread thread) {
3482 // This is where we one day will shut down the loop for the thread
3485 internal override IntPtr GetActive() {
3490 IntPtr prop = IntPtr.Zero;
3491 IntPtr active = IntPtr.Zero;
3493 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);
3494 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3495 active = (IntPtr)Marshal.ReadInt32(prop);
3499 if (active != IntPtr.Zero) {
3502 hwnd = Hwnd.GetObjectFromWindow(active);
3504 active = hwnd.Handle;
3506 active = IntPtr.Zero;
3512 internal override Region GetClipRegion(IntPtr handle) {
3515 hwnd = Hwnd.ObjectFromHandle(handle);
3517 return hwnd.UserClip;
3523 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3530 internal override void GetDisplaySize(out Size size) {
3531 XWindowAttributes attributes=new XWindowAttributes();
3534 // FIXME - use _NET_WM messages instead?
3535 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3538 size = new Size(attributes.width, attributes.height);
3541 internal override SizeF GetAutoScaleSize(Font font) {
3544 string magic_string = "The quick brown fox jumped over the lazy dog.";
3545 double magic_number = 44.549996948242189;
3547 g = Graphics.FromHwnd(FosterParent);
3549 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3550 return new SizeF(width, font.Height);
3553 internal override IntPtr GetParent(IntPtr handle) {
3556 hwnd = Hwnd.ObjectFromHandle(handle);
3557 if (hwnd != null && hwnd.parent != null) {
3558 return hwnd.parent.Handle;
3563 // This is a nop on win32 and x11
3564 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3568 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3578 if (handle != IntPtr.Zero) {
3579 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3581 use_handle = RootWindow;
3585 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3588 if (handle != IntPtr.Zero) {
3597 internal override IntPtr GetFocus() {
3602 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3603 FontFamily ff = font.FontFamily;
3604 ascent = ff.GetCellAscent (font.Style);
3605 descent = ff.GetCellDescent (font.Style);
3609 internal override Point GetMenuOrigin(IntPtr handle) {
3612 hwnd = Hwnd.ObjectFromHandle(handle);
3615 return hwnd.MenuOrigin;
3620 [MonoTODO("Implement filtering")]
3621 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3628 if (((XEventQueue)queue_id).Count > 0) {
3629 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3631 UpdateMessageQueue ((XEventQueue)queue_id);
3633 if (((XEventQueue)queue_id).Count > 0) {
3634 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3635 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3636 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3638 msg.hwnd= IntPtr.Zero;
3639 msg.message = Msg.WM_ENTERIDLE;
3644 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3646 // Handle messages for windows that are already or are about to be destroyed.
3648 // we need a special block for this because unless we remove the hwnd from the paint
3649 // queue it will always stay there (since we don't handle the expose), and we'll
3650 // effectively loop infinitely trying to repaint a non-existant window.
3651 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3652 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3653 hwnd.Queue.Paint.Remove (hwnd);
3654 goto ProcessNextMessage;
3657 // We need to make sure we only allow DestroyNotify events through for zombie
3658 // hwnds, since much of the event handling code makes requests using the hwnd's
3659 // client_window, and that'll result in BadWindow errors if there's some lag
3660 // between the XDestroyWindow call and the DestroyNotify event.
3661 if (hwnd == null || hwnd.zombie) {
3662 #if DriverDebug || DriverDebugDestroy
3663 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3665 goto ProcessNextMessage;
3668 if (hwnd.client_window == xevent.AnyEvent.window) {
3670 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3673 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3676 msg.hwnd = hwnd.Handle;
3679 // If you add a new event to this switch make sure to add it in
3680 // UpdateMessage also unless it is not coming through the X event system.
3682 switch(xevent.type) {
3683 case XEventName.KeyPress: {
3684 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3688 case XEventName.KeyRelease: {
3689 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3693 case XEventName.ButtonPress: {
3694 switch(xevent.ButtonEvent.button) {
3696 MouseState |= MouseButtons.Left;
3698 msg.message = Msg.WM_LBUTTONDOWN;
3700 msg.message = Msg.WM_NCLBUTTONDOWN;
3701 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3703 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3704 msg.wParam=GetMousewParam(0);
3709 MouseState |= MouseButtons.Middle;
3711 msg.message = Msg.WM_MBUTTONDOWN;
3713 msg.message = Msg.WM_NCMBUTTONDOWN;
3714 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3716 msg.wParam=GetMousewParam(0);
3721 MouseState |= MouseButtons.Right;
3723 msg.message = Msg.WM_RBUTTONDOWN;
3725 msg.message = Msg.WM_NCRBUTTONDOWN;
3726 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3728 msg.wParam=GetMousewParam(0);
3733 msg.hwnd = FocusWindow;
3734 msg.message=Msg.WM_MOUSEWHEEL;
3735 msg.wParam=GetMousewParam(120);
3740 msg.hwnd = FocusWindow;
3741 msg.message=Msg.WM_MOUSEWHEEL;
3742 msg.wParam=GetMousewParam(-120);
3748 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3749 mouse_position.X = xevent.ButtonEvent.x;
3750 mouse_position.Y = xevent.ButtonEvent.y;
3752 if (!hwnd.Enabled) {
3755 msg.hwnd = hwnd.EnabledHwnd;
3756 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);
3757 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3760 if (Grab.Hwnd != IntPtr.Zero) {
3761 msg.hwnd = Grab.Hwnd;
3764 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3765 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3766 switch(xevent.ButtonEvent.button) {
3768 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3773 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3778 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3782 ClickPending.Pending = false;
3784 ClickPending.Pending = true;
3785 ClickPending.Hwnd = msg.hwnd;
3786 ClickPending.Message = msg.message;
3787 ClickPending.wParam = msg.wParam;
3788 ClickPending.lParam = msg.lParam;
3789 ClickPending.Time = (long)xevent.ButtonEvent.time;
3792 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3793 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3795 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3796 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3797 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3798 XEvent motionEvent = new XEvent ();
3799 motionEvent.type = XEventName.MotionNotify;
3800 motionEvent.MotionEvent.display = DisplayHandle;
3801 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3802 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3803 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3804 hwnd.Queue.EnqueueLocked (motionEvent);
3810 case XEventName.ButtonRelease: {
3812 switch(xevent.ButtonEvent.button) {
3815 msg.message = Msg.WM_LBUTTONUP;
3817 msg.message = Msg.WM_NCLBUTTONUP;
3818 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3820 MouseState &= ~MouseButtons.Left;
3821 msg.wParam=GetMousewParam(0);
3827 msg.message = Msg.WM_MBUTTONUP;
3829 msg.message = Msg.WM_NCMBUTTONUP;
3830 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3832 MouseState &= ~MouseButtons.Middle;
3833 msg.wParam=GetMousewParam(0);
3839 msg.message = Msg.WM_RBUTTONUP;
3841 msg.message = Msg.WM_NCRBUTTONUP;
3842 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3844 MouseState &= ~MouseButtons.Right;
3845 msg.wParam=GetMousewParam(0);
3850 goto ProcessNextMessage;
3854 goto ProcessNextMessage;
3858 if (!hwnd.Enabled) {
3861 msg.hwnd = hwnd.EnabledHwnd;
3862 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);
3863 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3866 if (Grab.Hwnd != IntPtr.Zero) {
3867 msg.hwnd = Grab.Hwnd;
3870 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3871 mouse_position.X = xevent.ButtonEvent.x;
3872 mouse_position.Y = xevent.ButtonEvent.y;
3874 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3875 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3876 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3877 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3878 XEvent motionEvent = new XEvent ();
3879 motionEvent.type = XEventName.MotionNotify;
3880 motionEvent.MotionEvent.display = DisplayHandle;
3881 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3882 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3883 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3884 hwnd.Queue.EnqueueLocked (motionEvent);
3889 case XEventName.MotionNotify: {
3891 #if DriverDebugExtra
3892 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);
3895 if (Grab.Hwnd != IntPtr.Zero) {
3896 msg.hwnd = Grab.Hwnd;
3899 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3903 if (xevent.MotionEvent.is_hint != 0)
3907 XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3908 out root, out child,
3909 out xevent.MotionEvent.x_root,
3910 out xevent.MotionEvent.y_root,
3911 out xevent.MotionEvent.x,
3912 out xevent.MotionEvent.y, out mask);
3915 msg.message = Msg.WM_MOUSEMOVE;
3916 msg.wParam = GetMousewParam(0);
3917 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3919 if (!hwnd.Enabled) {
3922 msg.hwnd = hwnd.EnabledHwnd;
3923 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);
3924 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3927 mouse_position.X = xevent.MotionEvent.x;
3928 mouse_position.Y = xevent.MotionEvent.y;
3930 if ((HoverState.Timer.Enabled) &&
3931 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3932 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3933 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3934 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3935 HoverState.Timer.Stop();
3936 HoverState.Timer.Start();
3937 HoverState.X = mouse_position.X;
3938 HoverState.Y = mouse_position.Y;
3948 #if DriverDebugExtra
3949 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);
3951 msg.message = Msg.WM_NCMOUSEMOVE;
3953 if (!hwnd.Enabled) {
3954 msg.hwnd = hwnd.EnabledHwnd;
3955 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);
3956 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3959 // The hit test is sent in screen coordinates
3960 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3961 xevent.MotionEvent.x, xevent.MotionEvent.y,
3962 out screen_x, out screen_y, out dummy);
3964 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3965 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3966 IntPtr.Zero, msg.lParam).ToInt32 ();
3967 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3969 mouse_position.X = xevent.MotionEvent.x;
3970 mouse_position.Y = xevent.MotionEvent.y;
3976 case XEventName.EnterNotify: {
3977 if (!hwnd.Enabled) {
3978 goto ProcessNextMessage;
3980 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3981 goto ProcessNextMessage;
3983 msg.message = Msg.WM_MOUSE_ENTER;
3984 HoverState.X = xevent.CrossingEvent.x;
3985 HoverState.Y = xevent.CrossingEvent.y;
3986 HoverState.Timer.Enabled = true;
3987 HoverState.Window = xevent.CrossingEvent.window;
3991 case XEventName.LeaveNotify: {
3992 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3993 WindowUngrabbed (hwnd.Handle);
3994 goto ProcessNextMessage;
3996 if (!hwnd.Enabled) {
3997 goto ProcessNextMessage;
3999 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
4000 goto ProcessNextMessage;
4002 msg.message=Msg.WM_MOUSELEAVE;
4003 HoverState.Timer.Enabled = false;
4004 HoverState.Window = IntPtr.Zero;
4009 case XEventName.CreateNotify: {
4010 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
4011 msg.message = WM_CREATE;
4012 // Set up CreateStruct
4014 goto ProcessNextMessage;
4021 case XEventName.ReparentNotify: {
4022 if (hwnd.parent == null) { // Toplevel
4023 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
4024 hwnd.Reparented = true;
4026 // The location given by the event is not reliable between different wm's,
4027 // so use an alternative way of getting it.
4028 Point location = GetTopLevelWindowLocation (hwnd);
4029 hwnd.X = location.X;
4030 hwnd.Y = location.Y;
4032 if (hwnd.opacity != 0xffffffff) {
4035 opacity = (IntPtr)(Int32)hwnd.opacity;
4036 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4038 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4039 goto ProcessNextMessage;
4041 hwnd.Reparented = false;
4042 goto ProcessNextMessage;
4045 goto ProcessNextMessage;
4048 case XEventName.ConfigureNotify: {
4049 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4050 #if DriverDebugExtra
4051 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);
4053 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
4054 lock (hwnd.configure_lock) {
4055 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4056 hwnd.configure_pending = false;
4059 // We need to adjust our client window to track the resize of whole_window
4060 if (hwnd.whole_window != hwnd.client_window)
4061 PerformNCCalc(hwnd);
4064 goto ProcessNextMessage;
4067 case XEventName.FocusIn: {
4068 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4069 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4070 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4071 // about it having focus again
4072 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4073 goto ProcessNextMessage;
4076 if (FocusWindow == IntPtr.Zero) {
4077 Control c = Control.FromHandle (hwnd.client_window);
4079 goto ProcessNextMessage;
4080 Form form = c.FindForm ();
4082 goto ProcessNextMessage;
4083 if (ActiveWindow != form.Handle) {
4084 ActiveWindow = form.Handle;
4085 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4087 goto ProcessNextMessage;
4089 Keyboard.FocusIn(FocusWindow);
4090 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4091 goto ProcessNextMessage;
4094 case XEventName.FocusOut: {
4095 // Se the comment for our FocusIn handler
4096 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4097 goto ProcessNextMessage;
4099 Keyboard.FocusOut(FocusWindow);
4101 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4102 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4105 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4106 goto ProcessNextMessage;
4109 case XEventName.MapNotify: {
4110 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4112 msg.message = Msg.WM_SHOWWINDOW;
4113 msg.wParam = (IntPtr) 1;
4114 // XXX we're missing the lParam..
4117 goto ProcessNextMessage;
4120 case XEventName.UnmapNotify: {
4121 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4122 hwnd.mapped = false;
4123 msg.message = Msg.WM_SHOWWINDOW;
4124 msg.wParam = (IntPtr) 0;
4125 // XXX we're missing the lParam..
4128 goto ProcessNextMessage;
4131 case XEventName.Expose: {
4134 hwnd.expose_pending = false;
4136 hwnd.nc_expose_pending = false;
4138 goto ProcessNextMessage;
4142 if (!hwnd.expose_pending) {
4143 goto ProcessNextMessage;
4146 if (!hwnd.nc_expose_pending) {
4147 goto ProcessNextMessage;
4150 switch (hwnd.border_style) {
4151 case FormBorderStyle.Fixed3D: {
4154 g = Graphics.FromHwnd(hwnd.whole_window);
4155 if (hwnd.border_static)
4156 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4158 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4163 case FormBorderStyle.FixedSingle: {
4166 g = Graphics.FromHwnd(hwnd.whole_window);
4167 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4172 #if DriverDebugExtra
4173 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);
4176 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4177 Region region = new Region (rect);
4178 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4179 msg.message = Msg.WM_NCPAINT;
4180 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4181 msg.refobject = region;
4184 #if DriverDebugExtra
4185 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);
4187 if (Caret.Visible == true) {
4188 Caret.Paused = true;
4192 if (Caret.Visible == true) {
4194 Caret.Paused = false;
4196 msg.message = Msg.WM_PAINT;
4200 case XEventName.DestroyNotify: {
4202 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4203 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4205 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4206 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4207 CleanupCachedWindows (hwnd);
4209 #if DriverDebugDestroy
4210 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4213 msg.hwnd = hwnd.client_window;
4214 msg.message=Msg.WM_DESTROY;
4217 goto ProcessNextMessage;
4223 case XEventName.ClientMessage: {
4224 if (Dnd.HandleClientMessage (ref xevent)) {
4225 goto ProcessNextMessage;
4228 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4229 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4230 goto ProcessNextMessage;
4233 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4234 msg.message = Msg.WM_MOUSEHOVER;
4235 msg.wParam = GetMousewParam(0);
4236 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4240 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4241 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4242 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4243 msg.wParam = xevent.ClientMessageEvent.ptr3;
4244 msg.lParam = xevent.ClientMessageEvent.ptr4;
4245 if (msg.message == (Msg)Msg.WM_QUIT)
4251 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4252 #if DriverDebugXEmbed
4253 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4256 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4257 XSizeHints hints = new XSizeHints();
4260 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4262 hwnd.width = hints.max_width;
4263 hwnd.height = hints.max_height;
4264 hwnd.ClientRect = Rectangle.Empty;
4265 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4269 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4270 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4271 msg.message = Msg.WM_CLOSE;
4275 // We should not get this, but I'll leave the code in case we need it in the future
4276 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4277 goto ProcessNextMessage;
4280 goto ProcessNextMessage;
4284 goto ProcessNextMessage;
4291 internal override bool GetText(IntPtr handle, out string text) {
4298 IntPtr prop = IntPtr.Zero;
4300 XGetWindowProperty(DisplayHandle, handle,
4301 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4302 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4304 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4305 text = Marshal.PtrToStringUni (prop, (int)nitems);
4310 // fallback on the non-_NET property
4313 textptr = IntPtr.Zero;
4315 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4316 if (textptr != IntPtr.Zero) {
4317 text = Marshal.PtrToStringAnsi(textptr);
4328 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) {
4331 hwnd = Hwnd.ObjectFromHandle(handle);
4337 height = hwnd.height;
4339 PerformNCCalc(hwnd);
4341 client_width = hwnd.ClientRect.Width;
4342 client_height = hwnd.ClientRect.Height;
4347 // Should we throw an exception or fail silently?
4348 // throw new ArgumentException("Called with an invalid window handle", "handle");
4358 internal override FormWindowState GetWindowState(IntPtr handle) {
4361 hwnd = Hwnd.ObjectFromHandle(handle);
4363 if (hwnd.cached_window_state == (FormWindowState)(-1))
4364 hwnd.cached_window_state = UpdateWindowState (handle);
4366 return hwnd.cached_window_state;
4369 private FormWindowState UpdateWindowState (IntPtr handle) {
4374 IntPtr prop = IntPtr.Zero;
4378 XWindowAttributes attributes;
4381 hwnd = Hwnd.ObjectFromHandle(handle);
4385 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);
4386 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4387 for (int i = 0; i < (long)nitems; i++) {
4388 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4389 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4391 } else if (atom == _NET_WM_STATE_HIDDEN) {
4399 return FormWindowState.Minimized;
4400 } else if (maximized == 2) {
4401 return FormWindowState.Maximized;
4404 attributes = new XWindowAttributes();
4405 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4406 if (attributes.map_state == MapState.IsUnmapped) {
4407 return (FormWindowState)(-1);
4411 return FormWindowState.Normal;
4414 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4416 GrabConfined = Grab.Confined;
4417 GrabArea = Grab.Area;
4420 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4422 IntPtr confine_to_window;
4424 confine_to_window = IntPtr.Zero;
4426 if (confine_to_handle != IntPtr.Zero) {
4427 XWindowAttributes attributes = new XWindowAttributes();
4429 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4432 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4434 Grab.Area.X = attributes.x;
4435 Grab.Area.Y = attributes.y;
4436 Grab.Area.Width = attributes.width;
4437 Grab.Area.Height = attributes.height;
4438 Grab.Confined = true;
4439 confine_to_window = hwnd.client_window;
4444 hwnd = Hwnd.ObjectFromHandle(handle);
4447 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4448 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4449 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4450 EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4451 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4455 internal override void UngrabWindow(IntPtr hwnd) {
4457 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4458 XFlush(DisplayHandle);
4460 WindowUngrabbed (hwnd);
4463 private void WindowUngrabbed (IntPtr hwnd) {
4464 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4466 Grab.Hwnd = IntPtr.Zero;
4467 Grab.Confined = false;
4470 // lparam should be the handle to the window gaining the mouse capture,
4471 // but X doesn't seem to give us that information.
4472 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4473 // X will send a NotifyUngrab, but since it comes late sometimes we're
4474 // calling WindowUngrabbed directly from UngrabWindow in order to send
4475 // this WM right away.
4476 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4480 internal override void HandleException(Exception e) {
4481 StackTrace st = new StackTrace(e, true);
4482 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4483 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4486 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4489 hwnd = Hwnd.ObjectFromHandle(handle);
4492 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4494 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4498 internal override void InvalidateNC (IntPtr handle) {
4501 hwnd = Hwnd.ObjectFromHandle(handle);
4503 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4506 internal override bool IsEnabled(IntPtr handle) {
4507 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4508 return (hwnd != null && hwnd.Enabled);
4511 internal override bool IsVisible(IntPtr handle) {
4512 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4513 return (hwnd != null && hwnd.visible);
4516 internal override void KillTimer(Timer timer) {
4517 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4519 if (queue == null) {
4520 // This isn't really an error, MS doesn't start the timer if
4521 // it has no assosciated queue
4524 queue.timer_list.Remove (timer);
4527 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4533 hwnd = Hwnd.ObjectFromHandle(handle);
4536 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4543 internal override void OverrideCursor(IntPtr cursor)
4545 if (Grab.Hwnd != IntPtr.Zero) {
4546 XChangeActivePointerGrab (DisplayHandle,
4547 EventMask.ButtonMotionMask |
4548 EventMask.PointerMotionMask |
4549 EventMask.PointerMotionHintMask |
4550 EventMask.ButtonPressMask |
4551 EventMask.ButtonReleaseMask,
4552 cursor, IntPtr.Zero);
4556 OverrideCursorHandle = cursor;
4559 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4560 PaintEventArgs paint_event;
4565 // handle (and paint_hwnd) refers to the window that is should be painted.
4566 // msg.HWnd (and hwnd) refers to the window that got the paint message.
4569 hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4570 if (msg.HWnd == handle) {
4573 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4576 if (Caret.Visible == true) {
4577 Caret.Paused = true;
4584 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4586 Region clip_region = new Region ();
4587 clip_region.MakeEmpty();
4589 foreach (Rectangle r in hwnd.ClipRectangles) {
4590 clip_region.Union (r);
4593 if (hwnd.UserClip != null) {
4594 clip_region.Intersect(hwnd.UserClip);
4597 dc.Clip = clip_region;
4598 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4599 hwnd.expose_pending = false;
4601 hwnd.ClearInvalidArea();
4603 hwnd.drawing_stack.Push (paint_event);
4604 hwnd.drawing_stack.Push (dc);
4608 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4610 if (!hwnd.nc_invalid.IsEmpty) {
4611 dc.SetClip (hwnd.nc_invalid);
4612 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4614 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4616 hwnd.nc_expose_pending = false;
4618 hwnd.ClearNcInvalidArea ();
4620 hwnd.drawing_stack.Push (paint_event);
4621 hwnd.drawing_stack.Push (dc);
4627 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4630 hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4632 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4636 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4637 pe.SetGraphics (null);
4640 if (Caret.Visible == true) {
4642 Caret.Paused = false;
4646 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4647 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4648 XEventQueue queue = (XEventQueue) queue_id;
4651 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4652 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4656 if (queue.Count > 0) {
4659 // Only call UpdateMessageQueue if real events are pending
4660 // otherwise we go to sleep on the socket
4661 if (XPending(DisplayHandle) != 0) {
4662 UpdateMessageQueue((XEventQueue)queue_id);
4664 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4669 CheckTimers(queue.timer_list, DateTime.UtcNow);
4674 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4677 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4678 XEvent xevent = new XEvent ();
4679 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4681 xevent.type = XEventName.ClientMessage;
4682 xevent.ClientMessageEvent.display = DisplayHandle;
4685 xevent.ClientMessageEvent.window = hwnd.whole_window;
4687 xevent.ClientMessageEvent.window = IntPtr.Zero;
4690 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4691 xevent.ClientMessageEvent.format = 32;
4692 xevent.ClientMessageEvent.ptr1 = handle;
4693 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4694 xevent.ClientMessageEvent.ptr3 = wparam;
4695 xevent.ClientMessageEvent.ptr4 = lparam;
4698 hwnd.Queue.EnqueueLocked (xevent);
4700 ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
4705 internal override void PostQuitMessage(int exitCode) {
4706 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4707 XFlush(DisplayHandle);
4710 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4715 internal override void RequestNCRecalc(IntPtr handle) {
4718 hwnd = Hwnd.ObjectFromHandle(handle);
4724 PerformNCCalc(hwnd);
4725 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4726 InvalidateNC(handle);
4729 internal override void ResetMouseHover(IntPtr handle) {
4732 hwnd = Hwnd.ObjectFromHandle(handle);
4737 HoverState.Timer.Enabled = true;
4738 HoverState.X = mouse_position.X;
4739 HoverState.Y = mouse_position.Y;
4740 HoverState.Window = handle;
4744 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4750 hwnd = Hwnd.ObjectFromHandle(handle);
4753 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4760 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4766 hwnd = Hwnd.ObjectFromHandle(handle);
4769 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4772 Form form = Control.FromHandle (handle) as Form;
4773 if (form != null && form.window_manager != null) {
4774 dest_y_return -= form.window_manager.TitleBarHeight;
4781 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4784 XGCValues gc_values;
4786 hwnd = Hwnd.ObjectFromHandle(handle);
4788 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4790 /* We have an invalid area in the window we're scrolling.
4791 Adjust our stored invalid rectangle to to match the scrolled amount */
4806 if (area.Contains (hwnd.Invalid))
4807 hwnd.ClearInvalidArea ();
4808 hwnd.AddInvalidArea(r);
4811 gc_values = new XGCValues();
4813 if (with_children) {
4814 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4817 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4825 height = area.Height - YAmount;
4826 dest_y = area.Y + YAmount;
4829 src_y = area.Y - YAmount;
4830 height = area.Height + YAmount;
4836 width = area.Width - XAmount;
4837 dest_x = area.X + XAmount;
4840 src_x = area.X - XAmount;
4841 width = area.Width + XAmount;
4845 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4847 // Generate an expose for the area exposed by the horizontal scroll
4848 // We don't use AddExpose since we're
4850 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4851 } else if (XAmount < 0) {
4852 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4855 // Generate an expose for the area exposed by the vertical scroll
4857 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4858 } else if (YAmount < 0) {
4859 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4861 XFreeGC(DisplayHandle, gc);
4864 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4868 hwnd = Hwnd.GetObjectFromWindow(handle);
4870 rect = hwnd.ClientRect;
4873 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4876 internal override void SendAsyncMethod (AsyncMethodData method) {
4878 XEvent xevent = new XEvent ();
4880 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4882 xevent.type = XEventName.ClientMessage;
4883 xevent.ClientMessageEvent.display = DisplayHandle;
4884 xevent.ClientMessageEvent.window = method.Handle;
4885 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4886 xevent.ClientMessageEvent.format = 32;
4887 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4889 hwnd.Queue.EnqueueLocked (xevent);
4894 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4896 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4899 h = Hwnd.ObjectFromHandle(hwnd);
4901 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4902 AsyncMethodResult result;
4903 AsyncMethodData data;
4905 result = new AsyncMethodResult ();
4906 data = new AsyncMethodData ();
4909 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4910 data.Args = new object[] { hwnd, message, wParam, lParam };
4911 data.Result = result;
4913 SendAsyncMethod (data);
4914 #if DriverDebug || DriverDebugThreads
4915 Console.WriteLine ("Sending {0} message across.", message);
4920 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4923 internal override int SendInput(IntPtr handle, Queue keys) {
4924 if (handle == IntPtr.Zero)
4927 int count = keys.Count;
4928 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4930 while (keys.Count > 0) {
4932 MSG msg = (MSG)keys.Dequeue();
4934 XEvent xevent = new XEvent ();
4936 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4937 xevent.KeyEvent.display = DisplayHandle;
4940 xevent.KeyEvent.window = hwnd.whole_window;
4942 xevent.KeyEvent.window = IntPtr.Zero;
4945 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4947 hwnd.Queue.EnqueueLocked (xevent);
4952 internal override void SetAllowDrop (IntPtr handle, bool value)
4954 // We allow drop on all windows
4957 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4958 DragDropEffects allowed_effects)
4960 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4963 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4965 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4968 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4969 Form form = Control.FromHandle (handle) as Form;
4970 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4971 border_style == FormBorderStyle.SizableToolWindow)) {
4972 form.window_manager = new ToolWindowManager (form);
4975 RequestNCRecalc(handle);
4978 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4979 if (Caret.Hwnd == handle) {
4986 if (Caret.Visible == true) {
4988 Caret.Timer.Start();
4993 internal override void SetClipRegion(IntPtr handle, Region region) {
4996 hwnd = Hwnd.ObjectFromHandle(handle);
5001 hwnd.UserClip = region;
5004 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
5007 if (OverrideCursorHandle == IntPtr.Zero) {
5008 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
5012 LastCursorHandle = cursor;
5013 LastCursorWindow = handle;
5015 hwnd = Hwnd.ObjectFromHandle(handle);
5017 if (cursor != IntPtr.Zero) {
5018 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
5020 XUndefineCursor(DisplayHandle, hwnd.whole_window);
5022 XFlush(DisplayHandle);
5027 hwnd = Hwnd.ObjectFromHandle(handle);
5029 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
5033 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
5034 out int root_x, out int root_y, out int child_x, out int child_y,
5037 /* this code was written with the help of
5038 glance at gdk. I never would have realized we
5039 needed a loop in order to traverse down in the
5040 hierarchy. I would have assumed you'd get the
5041 most deeply nested child and have to do
5042 XQueryTree to move back up the hierarchy..
5043 stupid me, of course. */
5046 XGrabServer (display);
5048 XQueryPointer(display, w, out root, out c,
5049 out root_x, out root_y, out child_x, out child_y,
5055 IntPtr child_last = IntPtr.Zero;
5056 while (c != IntPtr.Zero) {
5058 XQueryPointer(display, c, out root, out c,
5059 out root_x, out root_y, out child_x, out child_y,
5062 XUngrabServer (display);
5068 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5069 if (handle == IntPtr.Zero) {
5072 int root_x, root_y, child_x, child_y, mask;
5075 * QueryPointer before warping
5076 * because if the warp is on
5077 * the RootWindow, the x/y are
5078 * relative to the current
5081 QueryPointer (DisplayHandle, RootWindow,
5084 out root_x, out root_y,
5085 out child_x, out child_y,
5088 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5090 XFlush (DisplayHandle);
5092 /* then we need to a
5093 * QueryPointer after warping
5094 * to manually generate a
5095 * motion event for the window
5098 QueryPointer (DisplayHandle, RootWindow,
5101 out root_x, out root_y,
5102 out child_x, out child_y,
5105 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5106 if (child_hwnd == null) {
5110 XEvent xevent = new XEvent ();
5112 xevent.type = XEventName.MotionNotify;
5113 xevent.MotionEvent.display = DisplayHandle;
5114 xevent.MotionEvent.window = child_hwnd.client_window;
5115 xevent.MotionEvent.root = RootWindow;
5116 xevent.MotionEvent.x = child_x;
5117 xevent.MotionEvent.y = child_y;
5118 xevent.MotionEvent.x_root = root_x;
5119 xevent.MotionEvent.y_root = root_y;
5120 xevent.MotionEvent.state = mask;
5122 child_hwnd.Queue.EnqueueLocked (xevent);
5127 hwnd = Hwnd.ObjectFromHandle(handle);
5129 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5134 internal override void SetFocus(IntPtr handle) {
5136 IntPtr prev_focus_window;
5138 hwnd = Hwnd.ObjectFromHandle(handle);
5140 if (hwnd.client_window == FocusWindow) {
5144 prev_focus_window = FocusWindow;
5145 FocusWindow = hwnd.client_window;
5146 Keyboard.FocusIn (FocusWindow);
5148 if (prev_focus_window != IntPtr.Zero) {
5149 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5151 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5153 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5156 internal override void SetIcon(IntPtr handle, Icon icon) {
5159 hwnd = Hwnd.ObjectFromHandle(handle);
5161 SetIcon(hwnd, icon);
5165 internal override void SetMenu(IntPtr handle, Menu menu) {
5168 hwnd = Hwnd.ObjectFromHandle(handle);
5171 RequestNCRecalc(handle);
5174 internal override void SetModal(IntPtr handle, bool Modal) {
5176 ModalWindows.Push(handle);
5178 if (ModalWindows.Contains(handle)) {
5181 if (ModalWindows.Count > 0) {
5182 Activate((IntPtr)ModalWindows.Peek());
5186 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5187 Control ctrl = Control.FromHandle (handle);
5188 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5191 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5194 hwnd = Hwnd.ObjectFromHandle(handle);
5195 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5198 #if DriverDebug || DriverDebugParent
5199 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5201 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5207 internal override void SetTimer (Timer timer) {
5208 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5210 if (queue == null) {
5211 // This isn't really an error, MS doesn't start the timer if
5212 // it has no assosciated queue
5215 queue.timer_list.Add (timer);
5219 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5221 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5225 int[] atoms = new int[8];
5226 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5227 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5231 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5237 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5241 hwnd = Hwnd.ObjectFromHandle(handle);
5243 if (handle_owner != IntPtr.Zero) {
5244 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5250 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5251 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5253 if (hwnd_owner != null) {
5254 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5256 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5261 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5267 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5271 hwnd = Hwnd.ObjectFromHandle(handle);
5272 hwnd.visible = visible;
5276 MapWindow(hwnd, WindowType.Both);
5278 if (Control.FromHandle(handle) is Form) {
5281 s = ((Form)Control.FromHandle(handle)).WindowState;
5284 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5285 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5289 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5292 UnmapWindow(hwnd, WindowType.Both);
5298 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5299 Control ctrl = Control.FromHandle (handle);
5300 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5303 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5309 hwnd = Hwnd.ObjectFromHandle(handle);
5314 min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
5315 min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
5317 hints = new XSizeHints();
5319 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5320 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5322 min = TranslateWindowSizeToXWindowSize (cp, min);
5323 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5324 hints.min_width = min.Width;
5325 hints.min_height = min.Height;
5328 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5330 max = TranslateWindowSizeToXWindowSize (cp, max);
5331 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5332 hints.max_width = max.Width;
5333 hints.max_height = max.Height;
5336 if (hints.flags != IntPtr.Zero) {
5337 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5338 // they will maximize the window to fill the screen/parent no matter what.
5339 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5340 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5343 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5345 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5346 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5347 hints.x = maximized.X;
5348 hints.y = maximized.Y;
5349 hints.width = maximized.Width;
5350 hints.height = maximized.Height;
5352 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5353 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5358 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5361 hwnd = Hwnd.ObjectFromHandle(handle);
5367 // Win32 automatically changes negative width/height to 0.
5373 // X requires a sanity check for width & height; otherwise it dies
5374 if (hwnd.zero_sized && width > 0 && height > 0) {
5376 MapWindow(hwnd, WindowType.Whole);
5378 hwnd.zero_sized = false;
5381 if ((width < 1) || (height < 1)) {
5382 hwnd.zero_sized = true;
5383 UnmapWindow(hwnd, WindowType.Whole);
5386 // Save a server roundtrip (and prevent a feedback loop)
5387 if ((hwnd.x == x) && (hwnd.y == y) &&
5388 (hwnd.width == width) && (hwnd.height == height)) {
5392 if (!hwnd.zero_sized) {
5397 hwnd.height = height;
5398 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5400 if (hwnd.fixed_size) {
5401 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5405 Control ctrl = Control.FromHandle (handle);
5406 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5407 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5408 PerformNCCalc(hwnd);
5412 // Update our position/size immediately, so
5413 // that future calls to SetWindowPos aren't
5414 // kept from calling XMoveResizeWindow (by the
5415 // "Save a server roundtrip" block above).
5419 hwnd.height = height;
5420 hwnd.ClientRect = Rectangle.Empty;
5423 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5424 FormWindowState current_state;
5427 hwnd = Hwnd.ObjectFromHandle(handle);
5429 current_state = GetWindowState(handle);
5431 if (current_state == state) {
5436 case FormWindowState.Normal: {
5438 if (current_state == FormWindowState.Minimized) {
5439 MapWindow(hwnd, WindowType.Both);
5440 } else if (current_state == FormWindowState.Maximized) {
5441 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5448 case FormWindowState.Minimized: {
5450 if (current_state == FormWindowState.Maximized) {
5451 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5453 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5458 case FormWindowState.Maximized: {
5460 if (current_state == FormWindowState.Minimized) {
5461 MapWindow(hwnd, WindowType.Both);
5464 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5472 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5475 hwnd = Hwnd.ObjectFromHandle(handle);
5476 SetHwndStyles(hwnd, cp);
5477 SetWMStyles(hwnd, cp);
5480 internal override double GetWindowTransparency(IntPtr handle)
5485 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5489 hwnd = Hwnd.ObjectFromHandle(handle);
5495 hwnd.opacity = (uint)(0xffffffff * transparency);
5496 opacity = (IntPtr)((int)hwnd.opacity);
5498 IntPtr w = hwnd.whole_window;
5499 if (hwnd.reparented)
5500 w = XGetParent (hwnd.whole_window);
5501 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5504 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5505 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5513 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5516 } else if (!bottom) {
5517 Hwnd after_hwnd = null;
5519 if (after_handle != IntPtr.Zero) {
5520 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5523 XWindowChanges values = new XWindowChanges();
5525 if (after_hwnd == null) {
5526 // Work around metacity 'issues'
5530 atoms[0] = unixtime();
5531 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5533 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5534 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5536 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5539 values.sibling = after_hwnd.whole_window;
5540 values.stack_mode = StackMode.Below;
5543 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5548 XLowerWindow(DisplayHandle, hwnd.whole_window);
5555 internal override void ShowCursor(bool show) {
5556 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5559 internal override object StartLoop(Thread thread) {
5560 XEventQueue q = ThreadQueue(thread);
5564 internal override TransparencySupport SupportsTransparency() {
5565 // We need to check if the x compositing manager is running
5566 return TransparencySupport.Set;
5569 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5570 GetSystrayManagerWindow();
5572 if (SystrayMgrWindow != IntPtr.Zero) {
5573 XSizeHints size_hints;
5576 hwnd = Hwnd.ObjectFromHandle(handle);
5578 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5582 if (hwnd.client_window != hwnd.whole_window) {
5583 XDestroyWindow(DisplayHandle, hwnd.client_window);
5584 hwnd.client_window = hwnd.whole_window;
5587 /* by virtue of the way the tests are ordered when determining if it's PAINT
5588 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5589 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5590 there's a pending expose). */
5591 if (hwnd.nc_expose_pending) {
5592 hwnd.nc_expose_pending = false;
5593 if (!hwnd.expose_pending)
5594 hwnd.Queue.Paint.Remove (hwnd);
5597 size_hints = new XSizeHints();
5599 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5601 size_hints.min_width = 24;
5602 size_hints.min_height = 24;
5603 size_hints.max_width = 24;
5604 size_hints.max_height = 24;
5605 size_hints.base_width = 24;
5606 size_hints.base_height = 24;
5608 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5610 int[] atoms = new int[2];
5611 atoms [0] = 1; // Version 1
5612 atoms [1] = 1; // we want to be mapped
5614 // This line cost me 3 days...
5615 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5617 // Need to pick some reasonable defaults
5619 tt.AutomaticDelay = 350;
5620 tt.InitialDelay = 250;
5621 tt.ReshowDelay = 250;
5622 tt.ShowAlways = true;
5624 if ((tip != null) && (tip != string.Empty)) {
5625 tt.SetToolTip(Control.FromHandle(handle), tip);
5631 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5639 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5642 control = Control.FromHandle(handle);
5643 if (control != null && tt != null) {
5644 tt.SetToolTip(control, tip);
5646 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5653 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5655 SetVisible (handle, false, false);
5657 // The caller can now re-dock it later...
5665 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5667 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5668 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5672 internal override bool Text(IntPtr handle, string text) {
5675 hwnd = Hwnd.ObjectFromHandle(handle);
5678 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5679 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5681 // XXX this has problems with UTF8.
5682 // we need to either use the actual
5683 // text if it's latin-1, or convert it
5684 // to compound text if it's in a
5685 // different charset.
5686 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5691 internal override bool TranslateMessage(ref MSG msg) {
5692 return Keyboard.TranslateMessage (ref msg);
5695 internal override void UpdateWindow(IntPtr handle) {
5698 hwnd = Hwnd.ObjectFromHandle(handle);
5700 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5704 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5705 hwnd.Queue.Paint.Remove(hwnd);
5708 internal override void CreateOffscreenDrawable (IntPtr handle,
5709 int width, int height,
5710 out object offscreen_drawable)
5713 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5715 XGetGeometry (DisplayHandle, handle,
5717 out x_out, out y_out,
5718 out width_out, out height_out,
5719 out border_width_out, out depth_out);
5721 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5723 offscreen_drawable = pixmap;
5727 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5729 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5732 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5734 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5737 internal override void BlitFromOffscreen (IntPtr dest_handle,
5739 object offscreen_drawable,
5740 Graphics offscreen_dc,
5743 XGCValues gc_values;
5746 gc_values = new XGCValues();
5748 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5750 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5751 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5753 XFreeGC (DisplayHandle, gc);
5756 #endregion // Public Static Methods
5759 internal override event EventHandler Idle;
5760 #endregion // Events
5762 #region Xcursor imports
5763 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5764 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5766 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5767 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5769 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5770 internal extern static void XcursorImagesDestroy (IntPtr images);
5772 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5773 internal extern static int XcursorGetDefaultSize (IntPtr display);
5775 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5776 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5778 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5779 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5782 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5783 internal extern static IntPtr XOpenDisplay(IntPtr display);
5784 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5785 internal extern static int XCloseDisplay(IntPtr display);
5786 [DllImport ("libX11", EntryPoint="XSynchronize")]
5787 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5789 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5790 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);
5791 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5792 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5793 [DllImport ("libX11", EntryPoint="XMapWindow")]
5794 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5795 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5796 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5797 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5798 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5799 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5800 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5801 [DllImport ("libX11", EntryPoint="XRootWindow")]
5802 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5803 [DllImport ("libX11", EntryPoint="XNextEvent")]
5804 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5805 [DllImport ("libX11")]
5806 internal extern static int XConnectionNumber (IntPtr diplay);
5807 [DllImport ("libX11")]
5808 internal extern static int XPending (IntPtr diplay);
5809 [DllImport ("libX11", EntryPoint="XSelectInput")]
5810 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5812 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5813 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5815 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5816 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5817 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5818 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5820 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5821 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5823 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5824 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5826 [DllImport ("libX11", EntryPoint="XFlush")]
5827 internal extern static int XFlush(IntPtr display);
5829 [DllImport ("libX11", EntryPoint="XSetWMName")]
5830 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5832 [DllImport ("libX11", EntryPoint="XStoreName")]
5833 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5835 [DllImport ("libX11", EntryPoint="XFetchName")]
5836 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5838 [DllImport ("libX11", EntryPoint="XSendEvent")]
5839 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5841 [DllImport ("libX11", EntryPoint="XQueryTree")]
5842 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);
5844 [DllImport ("libX11", EntryPoint="XFree")]
5845 internal extern static int XFree(IntPtr data);
5847 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5848 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5850 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5851 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5853 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5854 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5856 [DllImport ("libX11", EntryPoint="XInternAtom")]
5857 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5859 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5860 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5862 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5863 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5865 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5866 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);
5868 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5869 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5871 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5872 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);
5874 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5875 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);
5877 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5878 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);
5880 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5881 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);
5883 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5884 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);
5886 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5887 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);
5889 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5890 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);
5892 [DllImport ("libX11", EntryPoint="XClearWindow")]
5893 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5895 [DllImport ("libX11", EntryPoint="XClearArea")]
5896 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5899 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5900 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5902 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5903 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5905 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5906 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5908 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5909 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5911 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5912 internal extern static int XDefaultScreen(IntPtr display);
5914 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5915 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5917 [DllImport ("libX11", EntryPoint="XLookupColor")]
5918 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5920 [DllImport ("libX11", EntryPoint="XAllocColor")]
5921 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5923 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5924 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5926 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5927 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5929 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5930 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5932 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5933 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5935 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5936 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5938 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5939 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5941 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5942 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5944 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5945 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5947 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5948 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5950 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5951 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5954 [DllImport ("libX11", EntryPoint="XCreateGC")]
5955 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5957 [DllImport ("libX11", EntryPoint="XFreeGC")]
5958 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5960 [DllImport ("libX11", EntryPoint="XSetFunction")]
5961 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5963 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5964 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5966 [DllImport ("libX11", EntryPoint="XDrawLine")]
5967 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5969 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5970 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5972 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5973 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5975 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5976 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5978 [DllImport ("libX11", EntryPoint="XCopyArea")]
5979 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);
5981 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5982 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);
5984 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5985 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5987 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5988 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5990 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5991 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5993 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5994 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5996 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5997 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5999 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
6000 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
6002 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
6003 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);
6005 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
6006 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
6008 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
6009 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
6011 [DllImport ("libX11", EntryPoint="XFreePixmap")]
6012 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
6014 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
6015 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
6017 [DllImport ("libX11", EntryPoint="XQueryExtension")]
6018 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
6020 [DllImport ("libX11", EntryPoint="XWhitePixel")]
6021 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
6023 [DllImport ("libX11", EntryPoint="XBlackPixel")]
6024 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
6026 [DllImport ("libX11", EntryPoint="XGrabServer")]
6027 internal extern static void XGrabServer(IntPtr display);
6029 [DllImport ("libX11", EntryPoint="XUngrabServer")]
6030 internal extern static void XUngrabServer(IntPtr display);
6032 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
6033 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
6035 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
6036 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6038 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
6039 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6041 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6042 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6044 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6045 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6047 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6048 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6050 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6051 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6053 [DllImport ("libX11", EntryPoint="XInitThreads")]
6054 internal extern static int XInitThreads();
6056 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6057 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6059 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6060 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6062 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6063 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6065 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6066 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6068 [DllImport ("libX11", EntryPoint="XSetForeground")]
6069 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6071 [DllImport ("libX11", EntryPoint="XSetBackground")]
6072 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6074 [DllImport ("libX11", EntryPoint="XBell")]
6075 internal extern static int XBell(IntPtr display, int percent);
6077 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6078 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6080 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6081 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6083 [DllImport ("libX11")]
6084 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6086 [DllImport ("libX11")]
6087 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);