1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
90 private int render_major_opcode;
91 private int render_first_event;
92 private int render_first_error;
95 private static IntPtr ClipMagic;
96 private static ClipboardStruct Clipboard; // Our clipboard
99 private static IntPtr PostAtom; // PostMessage atom
100 private static IntPtr AsyncAtom; // Support for async messages
103 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
104 private static ArrayList unattached_timer_list; // holds timers that are enabled but not attached to a window.
106 private static Pollfd[] pollfds; // For watching the X11 socket
107 private static bool wake_waiting;
108 private static object wake_waiting_lock = new object ();
110 private static X11Keyboard Keyboard; //
111 private static X11Dnd Dnd;
112 private static Socket listen; //
113 private static Socket wake; //
114 private static Socket wake_receive; //
115 private static byte[] network_buffer; //
116 private static bool detectable_key_auto_repeat;
119 private static IntPtr ActiveWindow; // Handle of the active window
120 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
123 private static Stack ModalWindows; // Stack of our modal windows
126 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
129 private static IntPtr LastCursorWindow; // The last window we set the cursor on
130 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
131 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
134 private static CaretStruct Caret; //
137 private static IntPtr WM_PROTOCOLS;
138 private static IntPtr WM_DELETE_WINDOW;
139 private static IntPtr WM_TAKE_FOCUS;
140 //private static IntPtr _NET_SUPPORTED;
141 //private static IntPtr _NET_CLIENT_LIST;
142 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
143 private static IntPtr _NET_DESKTOP_GEOMETRY;
144 //private static IntPtr _NET_DESKTOP_VIEWPORT;
145 private static IntPtr _NET_CURRENT_DESKTOP;
146 //private static IntPtr _NET_DESKTOP_NAMES;
147 private static IntPtr _NET_ACTIVE_WINDOW;
148 private static IntPtr _NET_WORKAREA;
149 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
150 //private static IntPtr _NET_VIRTUAL_ROOTS;
151 //private static IntPtr _NET_DESKTOP_LAYOUT;
152 //private static IntPtr _NET_SHOWING_DESKTOP;
153 //private static IntPtr _NET_CLOSE_WINDOW;
154 //private static IntPtr _NET_MOVERESIZE_WINDOW;
155 //private static IntPtr _NET_WM_MOVERESIZE;
156 //private static IntPtr _NET_RESTACK_WINDOW;
157 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
158 private static IntPtr _NET_WM_NAME;
159 //private static IntPtr _NET_WM_VISIBLE_NAME;
160 //private static IntPtr _NET_WM_ICON_NAME;
161 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
162 //private static IntPtr _NET_WM_DESKTOP;
163 private static IntPtr _NET_WM_WINDOW_TYPE;
164 private static IntPtr _NET_WM_STATE;
165 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
166 //private static IntPtr _NET_WM_STRUT;
167 //private static IntPtr _NET_WM_STRUT_PARTIAL;
168 //private static IntPtr _NET_WM_ICON_GEOMETRY;
169 private static IntPtr _NET_WM_ICON;
170 //private static IntPtr _NET_WM_PID;
171 //private static IntPtr _NET_WM_HANDLED_ICONS;
172 private static IntPtr _NET_WM_USER_TIME;
173 private static IntPtr _NET_FRAME_EXTENTS;
174 //private static IntPtr _NET_WM_PING;
175 //private static IntPtr _NET_WM_SYNC_REQUEST;
176 private static IntPtr _NET_SYSTEM_TRAY_S;
177 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
178 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
179 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
180 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
181 private static IntPtr _XEMBED;
182 private static IntPtr _XEMBED_INFO;
183 private static IntPtr _MOTIF_WM_HINTS;
184 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
185 private static IntPtr _NET_WM_STATE_ABOVE;
186 private static IntPtr _NET_WM_STATE_MODAL;
187 private static IntPtr _NET_WM_STATE_HIDDEN;
188 private static IntPtr _NET_WM_CONTEXT_HELP;
189 private static IntPtr _NET_WM_WINDOW_OPACITY;
190 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
193 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
194 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
195 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
196 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
197 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
198 private static IntPtr CLIPBOARD;
199 private static IntPtr PRIMARY;
200 //private static IntPtr DIB;
201 private static IntPtr OEMTEXT;
202 private static IntPtr UNICODETEXT;
203 private static IntPtr TARGETS;
205 // mouse hover message generation
206 private static HoverStruct HoverState; //
208 // double click message generation
209 private static ClickStruct ClickPending; //
211 // Support for mouse grab
212 private static GrabStruct Grab; //
215 Point mouse_position; // Last position of mouse, in screen coords
216 internal static MouseButtons MouseState; // Last state of mouse buttons
219 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
221 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
222 EventMask.ButtonReleaseMask |
223 EventMask.KeyPressMask |
224 EventMask.KeyReleaseMask |
225 EventMask.EnterWindowMask |
226 EventMask.LeaveWindowMask |
227 EventMask.ExposureMask |
228 EventMask.FocusChangeMask |
229 EventMask.PointerMotionMask |
230 EventMask.PointerMotionHintMask |
231 EventMask.SubstructureNotifyMask);
233 static readonly object lockobj = new object ();
235 #endregion // Local Variables
237 private XplatUIX11() {
238 // Handle singleton stuff first
241 // Now regular initialization
242 XlibLock = new object ();
243 X11Keyboard.XlibLock = XlibLock;
244 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
245 unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
248 ErrorExceptions = false;
250 // X11 Initialization
251 SetDisplay(XOpenDisplay(IntPtr.Zero));
252 X11DesktopColors.Initialize();
255 // Disable keyboard autorepeat
257 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
258 detectable_key_auto_repeat = true;
260 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
261 detectable_key_auto_repeat = false;
264 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
265 ErrorHandler = new XErrorHandler(HandleError);
266 XSetErrorHandler(ErrorHandler);
270 // Remove our display handle from S.D
271 Graphics.FromHdcInternal (IntPtr.Zero);
274 #endregion // Constructors
276 #region Singleton Specific Code
277 public static XplatUIX11 GetInstance() {
279 if (Instance == null) {
280 Instance=new XplatUIX11();
287 public int Reference {
294 #region Internal Properties
295 internal static IntPtr Display {
297 return DisplayHandle;
301 XplatUIX11.GetInstance().SetDisplay(value);
305 internal static int Screen {
315 internal static IntPtr RootWindowHandle {
325 internal static IntPtr Visual {
331 CustomVisual = value;
335 internal static IntPtr ColorMap {
337 return CustomColormap;
341 CustomColormap = value;
346 #region XExceptionClass
347 internal class XException : ApplicationException {
351 XRequest RequestCode;
355 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
356 this.Display = Display;
357 this.ResourceID = ResourceID;
358 this.Serial = Serial;
359 this.RequestCode = RequestCode;
360 this.ErrorCode = ErrorCode;
361 this.MinorCode = MinorCode;
364 public override string Message {
366 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
370 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
379 sb = new StringBuilder(160);
380 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
381 x_error_text = sb.ToString();
382 hwnd = Hwnd.ObjectFromHandle(ResourceID);
384 hwnd_text = hwnd.ToString();
385 c = Control.FromHandle(hwnd.Handle);
387 control_text = c.ToString();
389 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
392 hwnd_text = "<null>";
393 control_text = "<null>";
397 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);
401 #endregion // XExceptionClass
403 #region Internal Methods
404 internal void SetDisplay(IntPtr display_handle) {
405 if (display_handle != IntPtr.Zero) {
408 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
409 hwnd = Hwnd.ObjectFromHandle(FosterParent);
410 XDestroyWindow(DisplayHandle, FosterParent);
414 if (DisplayHandle != IntPtr.Zero) {
415 XCloseDisplay(DisplayHandle);
418 DisplayHandle=display_handle;
420 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
421 // been hacked to do this for us.
422 Graphics.FromHdcInternal (DisplayHandle);
424 // query for the render extension so
425 // we can ignore the spurious
426 // BadPicture errors that are
427 // generated by cairo/render.
428 XQueryExtension (DisplayHandle, "RENDER",
429 ref render_major_opcode, ref render_first_event, ref render_first_error);
432 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
433 XSynchronize(DisplayHandle, true);
436 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
437 ErrorExceptions = true;
441 ScreenNo = XDefaultScreen(DisplayHandle);
442 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
443 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
445 // Create the foster parent
446 // it is important that border_width is kept in synch with the other XCreateWindow calls
447 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
448 if (FosterParent==IntPtr.Zero) {
449 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
453 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
454 hwnd.WholeWindow = FosterParent;
455 hwnd.ClientWindow = FosterParent;
457 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
459 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
460 hwnd.whole_window = RootWindow;
461 hwnd.ClientWindow = RootWindow;
463 // For sleeping on the X11 socket
464 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
465 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
469 // To wake up when a timer is ready
470 network_buffer = new byte[10];
472 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
473 wake.Connect(listen.LocalEndPoint);
474 wake_receive = listen.Accept();
477 pollfds = new Pollfd [2];
478 pollfds [0] = new Pollfd ();
479 pollfds [0].fd = XConnectionNumber (DisplayHandle);
480 pollfds [0].events = PollEvents.POLLIN;
482 pollfds [1] = new Pollfd ();
483 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
484 pollfds [1].events = PollEvents.POLLIN;
487 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
488 Dnd = new X11Dnd (DisplayHandle, Keyboard);
490 DoubleClickInterval = 500;
492 HoverState.Interval = 500;
493 HoverState.Timer = new Timer();
494 HoverState.Timer.Enabled = false;
495 HoverState.Timer.Interval = HoverState.Interval;
496 HoverState.Timer.Tick += new EventHandler(MouseHover);
497 HoverState.Size = new Size(4, 4);
501 ActiveWindow = IntPtr.Zero;
502 FocusWindow = IntPtr.Zero;
503 ModalWindows = new Stack(3);
505 MouseState = MouseButtons.None;
506 mouse_position = new Point(0, 0);
508 Caret.Timer = new Timer();
509 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
510 Caret.Timer.Tick += new EventHandler(CaretCallback);
514 // Grab atom changes off the root window to catch certain WM events
515 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
517 // Handle any upcoming errors
518 ErrorHandler = new XErrorHandler(HandleError);
519 XSetErrorHandler(ErrorHandler);
521 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
524 #endregion // Internal Methods
526 #region Private Methods
527 private int unixtime() {
528 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
530 return (int) t.TotalSeconds;
533 private static void SetupAtoms() {
534 // make sure this array stays in sync with the statements below
535 string [] atom_names = new string[] {
540 //"_NET_CLIENT_LIST",
541 //"_NET_NUMBER_OF_DESKTOPS",
542 "_NET_DESKTOP_GEOMETRY",
543 //"_NET_DESKTOP_VIEWPORT",
544 "_NET_CURRENT_DESKTOP",
545 //"_NET_DESKTOP_NAMES",
546 "_NET_ACTIVE_WINDOW",
548 //"_NET_SUPPORTING_WM_CHECK",
549 //"_NET_VIRTUAL_ROOTS",
550 //"_NET_DESKTOP_LAYOUT",
551 //"_NET_SHOWING_DESKTOP",
552 //"_NET_CLOSE_WINDOW",
553 //"_NET_MOVERESIZE_WINDOW",
554 //"_NET_WM_MOVERESIZE",
555 //"_NET_RESTACK_WINDOW",
556 //"_NET_REQUEST_FRAME_EXTENTS",
558 //"_NET_WM_VISIBLE_NAME",
559 //"_NET_WM_ICON_NAME",
560 //"_NET_WM_VISIBLE_ICON_NAME",
562 "_NET_WM_WINDOW_TYPE",
564 //"_NET_WM_ALLOWED_ACTIONS",
566 //"_NET_WM_STRUT_PARTIAL",
567 //"_NET_WM_ICON_GEOMETRY",
570 //"_NET_WM_HANDLED_ICONS",
572 "_NET_FRAME_EXTENTS",
574 //"_NET_WM_SYNC_REQUEST",
575 "_NET_SYSTEM_TRAY_OPCODE",
576 //"_NET_SYSTEM_TRAY_ORIENTATION",
577 "_NET_WM_STATE_MAXIMIZED_HORZ",
578 "_NET_WM_STATE_MAXIMIZED_VERT",
579 "_NET_WM_STATE_HIDDEN",
583 "_NET_WM_STATE_SKIP_TASKBAR",
584 "_NET_WM_STATE_ABOVE",
585 "_NET_WM_STATE_MODAL",
586 "_NET_WM_CONTEXT_HELP",
587 "_NET_WM_WINDOW_OPACITY",
588 //"_NET_WM_WINDOW_TYPE_DESKTOP",
589 //"_NET_WM_WINDOW_TYPE_DOCK",
590 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
591 //"_NET_WM_WINDOW_TYPE_MENU",
592 "_NET_WM_WINDOW_TYPE_UTILITY",
593 "_NET_WM_WINDOW_TYPE_DIALOG",
594 //"_NET_WM_WINDOW_TYPE_SPLASH",
595 "_NET_WM_WINDOW_TYPE_NORMAL",
602 "_SWF_PostMessageAtom",
605 IntPtr[] atoms = new IntPtr [atom_names.Length];;
607 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
610 WM_PROTOCOLS = atoms [off++];
611 WM_DELETE_WINDOW = atoms [off++];
612 WM_TAKE_FOCUS = atoms [off++];
613 //_NET_SUPPORTED = atoms [off++];
614 //_NET_CLIENT_LIST = atoms [off++];
615 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
616 _NET_DESKTOP_GEOMETRY = atoms [off++];
617 //_NET_DESKTOP_VIEWPORT = atoms [off++];
618 _NET_CURRENT_DESKTOP = atoms [off++];
619 //_NET_DESKTOP_NAMES = atoms [off++];
620 _NET_ACTIVE_WINDOW = atoms [off++];
621 _NET_WORKAREA = atoms [off++];
622 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
623 //_NET_VIRTUAL_ROOTS = atoms [off++];
624 //_NET_DESKTOP_LAYOUT = atoms [off++];
625 //_NET_SHOWING_DESKTOP = atoms [off++];
626 //_NET_CLOSE_WINDOW = atoms [off++];
627 //_NET_MOVERESIZE_WINDOW = atoms [off++];
628 //_NET_WM_MOVERESIZE = atoms [off++];
629 //_NET_RESTACK_WINDOW = atoms [off++];
630 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
631 _NET_WM_NAME = atoms [off++];
632 //_NET_WM_VISIBLE_NAME = atoms [off++];
633 //_NET_WM_ICON_NAME = atoms [off++];
634 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
635 //_NET_WM_DESKTOP = atoms [off++];
636 _NET_WM_WINDOW_TYPE = atoms [off++];
637 _NET_WM_STATE = atoms [off++];
638 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
639 //_NET_WM_STRUT = atoms [off++];
640 //_NET_WM_STRUT_PARTIAL = atoms [off++];
641 //_NET_WM_ICON_GEOMETRY = atoms [off++];
642 _NET_WM_ICON = atoms [off++];
643 //_NET_WM_PID = atoms [off++];
644 //_NET_WM_HANDLED_ICONS = atoms [off++];
645 _NET_WM_USER_TIME = atoms [off++];
646 _NET_FRAME_EXTENTS = atoms [off++];
647 //_NET_WM_PING = atoms [off++];
648 //_NET_WM_SYNC_REQUEST = atoms [off++];
649 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
650 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
651 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
652 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
653 _NET_WM_STATE_HIDDEN = atoms [off++];
654 _XEMBED = atoms [off++];
655 _XEMBED_INFO = atoms [off++];
656 _MOTIF_WM_HINTS = atoms [off++];
657 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
658 _NET_WM_STATE_ABOVE = atoms [off++];
659 _NET_WM_STATE_MODAL = atoms [off++];
660 _NET_WM_CONTEXT_HELP = atoms [off++];
661 _NET_WM_WINDOW_OPACITY = atoms [off++];
662 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
663 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
664 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
665 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
666 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
667 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
668 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
669 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
670 CLIPBOARD = atoms [off++];
671 PRIMARY = atoms [off++];
672 OEMTEXT = atoms [off++];
673 UNICODETEXT = atoms [off++];
674 TARGETS = atoms [off++];
675 AsyncAtom = atoms [off++];
676 PostAtom = atoms [off++];
677 HoverState.Atom = atoms [off++];
679 //DIB = (IntPtr)Atom.XA_PIXMAP;
680 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
683 private void GetSystrayManagerWindow() {
684 XGrabServer(DisplayHandle);
685 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
686 XUngrabServer(DisplayHandle);
687 XFlush(DisplayHandle);
690 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
694 xev.ClientMessageEvent.type = XEventName.ClientMessage;
695 xev.ClientMessageEvent.send_event = true;
696 xev.ClientMessageEvent.window = window;
697 xev.ClientMessageEvent.message_type = message_type;
698 xev.ClientMessageEvent.format = 32;
699 xev.ClientMessageEvent.ptr1 = l0;
700 xev.ClientMessageEvent.ptr2 = l1;
701 xev.ClientMessageEvent.ptr3 = l2;
702 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
705 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
709 xev.ClientMessageEvent.type = XEventName.ClientMessage;
710 xev.ClientMessageEvent.send_event = true;
711 xev.ClientMessageEvent.window = window;
712 xev.ClientMessageEvent.message_type = message_type;
713 xev.ClientMessageEvent.format = 32;
714 xev.ClientMessageEvent.ptr1 = l0;
715 xev.ClientMessageEvent.ptr2 = l1;
716 xev.ClientMessageEvent.ptr3 = l2;
717 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
720 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
721 // WM_CREATE and WM_DESTROY causes
722 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
726 if (child == IntPtr.Zero) {
730 hwnd = Hwnd.GetObjectFromWindow (child);
736 if (hwnd.Handle == IntPtr.Zero) {
740 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
744 if (hwnd.Parent == null) {
748 if (hwnd.Parent.Handle == IntPtr.Zero) {
752 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
753 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
755 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
758 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
761 bool StyleSet (int s, WindowStyles ws)
763 return (s & (int)ws) == (int)ws;
766 bool ExStyleSet (int ex, WindowExStyles exws)
768 return (ex & (int)exws) == (int)exws;
771 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
773 return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
776 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
779 * If this is a form with no window manager, X is handling all the border and caption painting
780 * so remove that from the area (since the area we set of the window here is the part of the window
781 * we're painting in only)
783 Rectangle rect = hwnd.ClientRect;
784 Form form = ctrl as Form;
785 CreateParams cp = null;
788 cp = form.GetCreateParams ();
790 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
791 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
792 Rectangle xrect = rect;
794 xrect.Y -= borders.top;
795 xrect.X -= borders.left;
796 xrect.Width += borders.left + borders.right;
797 xrect.Height += borders.top + borders.bottom;
802 if (rect.Width < 1 || rect.Height < 1) {
812 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
814 return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
817 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
820 * If this is a form with no window manager, X is handling all the border and caption painting
821 * so remove that from the area (since the area we set of the window here is the part of the window
822 * we're painting in only)
824 Form form = cp.control as Form;
825 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
826 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
829 xrect.Width -= borders.left + borders.right;
830 xrect.Height -= borders.top + borders.bottom;
834 if (size.Height == 0)
841 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
844 * If this is a form with no window manager, X is handling all the border and caption painting
845 * so remove that from the area (since the area we set of the window here is the part of the window
846 * we're painting in only)
848 Size rect = new Size (xWidth, xHeight);
849 Form form = cp.control as Form;
850 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
851 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
854 xrect.Width += borders.left + borders.right;
855 xrect.Height += borders.top + borders.bottom;
862 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
868 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
869 frame = FrameExtents (hwnd.whole_window);
874 return new Point (x, y);
877 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) {
880 tool_caption_height = 19;
881 border_static = false;
883 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
884 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
885 border_style = FormBorderStyle.Fixed3D;
886 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
887 border_style = FormBorderStyle.Fixed3D;
888 border_static = true;
889 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
890 border_style = FormBorderStyle.None;
892 border_style = FormBorderStyle.FixedSingle;
894 title_style = TitleStyle.None;
896 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
898 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
899 title_style = TitleStyle.Tool;
901 title_style = TitleStyle.Normal;
905 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
908 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
909 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
910 border_style = (FormBorderStyle) 0xFFFF;
912 border_style = FormBorderStyle.None;
917 title_style = TitleStyle.None;
918 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
919 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
920 title_style = TitleStyle.Tool;
922 title_style = TitleStyle.Normal;
926 border_style = FormBorderStyle.None;
928 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
929 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
930 border_style = FormBorderStyle.SizableToolWindow;
932 border_style = FormBorderStyle.Sizable;
935 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
936 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
937 border_style = FormBorderStyle.Fixed3D;
938 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
939 border_style = FormBorderStyle.Fixed3D;
940 border_static = true;
941 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
942 border_style = FormBorderStyle.FixedDialog;
943 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
944 border_style = FormBorderStyle.FixedToolWindow;
945 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
946 border_style = FormBorderStyle.FixedSingle;
949 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
950 border_style = FormBorderStyle.FixedSingle;
957 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
958 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);
961 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
962 MotifWmHints mwmHints;
963 MotifFunctions functions;
964 MotifDecorations decorations;
967 Rectangle client_rect;
970 bool hide_from_taskbar;
971 IntPtr transient_for_parent;
973 // Windows we manage ourselves don't need WM window styles.
974 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
979 mwmHints = new MotifWmHints();
982 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
983 transient_for_parent = IntPtr.Zero;
985 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
986 mwmHints.functions = (IntPtr)0;
987 mwmHints.decorations = (IntPtr)0;
989 form = cp.control as Form;
991 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
992 /* tool windows get no window manager
996 /* just because the window doesn't get any decorations doesn't
997 mean we should disable the functions. for instance, without
998 MotifFunctions.Maximize, changing the windowstate to Maximized
999 is ignored by metacity. */
1000 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
1001 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
1002 functions |= MotifFunctions.All;
1004 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
1005 functions |= MotifFunctions.Move;
1006 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1009 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1010 functions |= MotifFunctions.Move | MotifFunctions.Resize;
1011 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1014 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1015 functions |= MotifFunctions.Minimize;
1016 decorations |= MotifDecorations.Minimize;
1019 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1020 functions |= MotifFunctions.Maximize;
1021 decorations |= MotifDecorations.Maximize;
1024 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1025 functions |= MotifFunctions.Resize;
1026 decorations |= MotifDecorations.ResizeH;
1029 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1030 decorations |= MotifDecorations.Border;
1033 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1034 decorations |= MotifDecorations.Border;
1037 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1038 decorations |= MotifDecorations.Border;
1041 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1042 functions |= MotifFunctions.Close;
1045 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1046 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1047 if (cp.Caption == "") {
1048 functions &= ~MotifFunctions.Move;
1049 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1054 if ((functions & MotifFunctions.Resize) == 0) {
1055 hwnd.fixed_size = true;
1056 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1057 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1059 hwnd.fixed_size = false;
1062 mwmHints.functions = (IntPtr)functions;
1063 mwmHints.decorations = (IntPtr)decorations;
1066 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1069 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1070 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1071 // and get those windows in front of their parents
1072 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1073 } else if (form != null && form.Modal) {
1074 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1076 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1079 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1080 hide_from_taskbar = true;
1081 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1082 hide_from_taskbar = true;
1084 hide_from_taskbar = false;
1087 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1088 if (form != null && !hwnd.reparented) {
1089 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1090 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1091 if (owner_hwnd != null)
1092 transient_for_parent = owner_hwnd.whole_window;
1096 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1097 transient_for_parent = hwnd.parent.whole_window;
1100 FormWindowState current_state = GetWindowState (hwnd.Handle);
1101 if (current_state == (FormWindowState)(-1))
1102 current_state = FormWindowState.Normal;
1104 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1109 atoms [0] = window_type.ToInt32 ();
1110 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1112 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1114 if (transient_for_parent != IntPtr.Zero) {
1115 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1118 MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1120 if (hide_from_taskbar) {
1121 /* this line keeps the window from showing up in gnome's taskbar */
1122 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1124 /* we need to add these atoms in the
1125 * event we're maximized, since we're
1126 * replacing the existing
1127 * _NET_WM_STATE here. If we don't
1128 * add them, future calls to
1129 * GetWindowState will return Normal
1130 * for a window which is maximized. */
1131 if (current_state == FormWindowState.Maximized) {
1132 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1133 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1136 if (form != null && form.Modal) {
1137 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1140 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1143 IntPtr[] atom_ptrs = new IntPtr[2];
1144 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1145 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1146 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1149 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1153 private void SetIcon(Hwnd hwnd, Icon icon)
1158 // This really needs to do whatever it
1159 // takes to remove the window manager
1160 // menu, not just delete the ICON
1161 // property. This will cause metacity
1162 // to use the "no icon set" icon, and
1163 // we'll still have an icon.
1164 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1172 bitmap = icon.ToBitmap();
1174 size = bitmap.Width * bitmap.Height + 2;
1175 data = new IntPtr[size];
1177 data[index++] = (IntPtr)bitmap.Width;
1178 data[index++] = (IntPtr)bitmap.Height;
1180 for (int y = 0; y < bitmap.Height; y++) {
1181 for (int x = 0; x < bitmap.Width; x++) {
1182 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1186 XChangeProperty (DisplayHandle, hwnd.whole_window,
1187 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1188 PropertyMode.Replace, data, size);
1192 private void WakeupMain () {
1193 wake.Send (new byte [] { 0xFF });
1196 private XEventQueue ThreadQueue(Thread thread) {
1199 queue = (XEventQueue)MessageQueues[thread];
1200 if (queue == null) {
1201 queue = new XEventQueue(thread);
1202 MessageQueues[thread] = queue;
1208 private void TranslatePropertyToClipboard(IntPtr property) {
1213 IntPtr prop = IntPtr.Zero;
1215 Clipboard.Item = null;
1217 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);
1219 if ((long)nitems > 0) {
1220 if (property == (IntPtr)Atom.XA_STRING) {
1221 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1222 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1223 // FIXME - convert bitmap to image
1224 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1225 // FIXME - convert pixmap to image
1226 } else if (property == OEMTEXT) {
1227 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1228 } else if (property == UNICODETEXT) {
1229 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1236 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1238 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1242 // Keep the invalid area as small as needed
1243 if ((x + width) > hwnd.width) {
1244 width = hwnd.width - x;
1247 if ((y + height) > hwnd.height) {
1248 height = hwnd.height - y;
1252 hwnd.AddInvalidArea(x, y, width, height);
1253 if (!hwnd.expose_pending) {
1254 if (!hwnd.nc_expose_pending) {
1255 hwnd.Queue.Paint.Enqueue(hwnd);
1257 hwnd.expose_pending = true;
1260 hwnd.AddNcInvalidArea (x, y, width, height);
1262 if (!hwnd.nc_expose_pending) {
1263 if (!hwnd.expose_pending) {
1264 hwnd.Queue.Paint.Enqueue(hwnd);
1266 hwnd.nc_expose_pending = true;
1271 private static Hwnd.Borders FrameExtents (IntPtr window)
1277 IntPtr prop = IntPtr.Zero;
1278 Hwnd.Borders rect = new Hwnd.Borders ();
1280 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);
1281 if (prop != IntPtr.Zero) {
1282 if (nitems.ToInt32 () == 4) {
1283 rect.left = Marshal.ReadInt32 (prop, 0);
1284 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1285 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1286 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1294 private void AddConfigureNotify (XEvent xevent) {
1297 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1300 if (hwnd == null || hwnd.zombie) {
1303 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1304 if (hwnd.parent == null) {
1305 // The location given by the event is not reliable between different wm's,
1306 // so use an alternative way of getting it.
1307 Point location = GetTopLevelWindowLocation (hwnd);
1308 hwnd.x = location.X;
1309 hwnd.y = location.Y;
1312 // XXX this sucks. this isn't thread safe
1313 Control ctrl = Control.FromHandle (hwnd.Handle);
1314 Size TranslatedSize;
1316 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1318 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1320 hwnd.width = TranslatedSize.Width;
1321 hwnd.height = TranslatedSize.Height;
1322 hwnd.ClientRect = Rectangle.Empty;
1325 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));
1327 lock (hwnd.configure_lock) {
1328 if (!hwnd.configure_pending) {
1329 hwnd.Queue.EnqueueLocked (xevent);
1330 hwnd.configure_pending = true;
1334 // We drop configure events for Client windows
1337 private void ShowCaret() {
1338 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1344 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1348 private void HideCaret() {
1349 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1355 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1359 private int NextTimeout (ArrayList timers, DateTime now) {
1362 foreach (Timer timer in timers) {
1363 int next = (int) (timer.Expires - now).TotalMilliseconds;
1365 return 0; // Have a timer that has already expired
1368 if (next < timeout) {
1372 if (timeout < Timer.Minimum) {
1373 timeout = Timer.Minimum;
1381 private void CheckTimers (ArrayList timers, DateTime now) {
1384 count = timers.Count;
1389 for (int i = 0; i < timers.Count; i++) {
1392 timer = (Timer) timers [i];
1394 if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
1403 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1404 MSG msg = new MSG ();
1407 queue = ThreadQueue(Thread.CurrentThread);
1409 queue.DispatchIdle = false;
1413 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1414 if ((Msg)msg.message == Msg.WM_QUIT) {
1415 PostQuitMessage (0);
1419 if (msg.hwnd == hwnd.Handle) {
1420 if ((Msg)msg.message == message)
1422 else if ((Msg)msg.message == Msg.WM_DESTROY)
1426 TranslateMessage (ref msg);
1427 DispatchMessage (ref msg);
1432 queue.DispatchIdle = true;
1436 private void MapWindow(Hwnd hwnd, WindowType windows) {
1438 Form f = Control.FromHandle(hwnd.Handle) as Form;
1440 if (f.WindowState == FormWindowState.Normal) {
1441 f.waiting_showwindow = true;
1442 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1446 // it's possible that our Hwnd is no
1447 // longer valid after making that
1448 // SendMessage call, so check here.
1452 if ((windows & WindowType.Whole) != 0) {
1453 XMapWindow(DisplayHandle, hwnd.whole_window);
1455 if ((windows & WindowType.Client) != 0) {
1456 XMapWindow(DisplayHandle, hwnd.client_window);
1461 if (f != null && f.waiting_showwindow)
1462 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1466 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1469 if (Control.FromHandle(hwnd.Handle) is Form) {
1470 f = Control.FromHandle(hwnd.Handle) as Form;
1471 if (f.WindowState == FormWindowState.Normal) {
1472 f.waiting_showwindow = true;
1473 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1477 // it's possible that our Hwnd is no
1478 // longer valid after making that
1479 // SendMessage call, so check here.
1480 // FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
1484 if ((windows & WindowType.Client) != 0) {
1485 XUnmapWindow(DisplayHandle, hwnd.client_window);
1487 if ((windows & WindowType.Whole) != 0) {
1488 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1491 hwnd.mapped = false;
1493 if (f != null && f.waiting_showwindow)
1494 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1498 private void UpdateMessageQueue (XEventQueue queue) {
1503 now = DateTime.UtcNow;
1506 pending = XPending (DisplayHandle);
1510 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1511 Idle (this, EventArgs.Empty);
1515 pending = XPending (DisplayHandle);
1522 if (queue != null) {
1523 if (queue.Paint.Count > 0)
1526 timeout = NextTimeout (queue.timer_list, now);
1531 int length = pollfds.Length - 1;
1532 lock (wake_waiting_lock) {
1533 if (wake_waiting == false) {
1535 wake_waiting = true;
1539 Syscall.poll (pollfds, (uint)length, timeout);
1540 // Clean out buffer, so we're not busy-looping on the same data
1541 if (length == pollfds.Length) {
1542 if (pollfds[1].revents != 0)
1543 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1544 lock (wake_waiting_lock) {
1545 wake_waiting = false;
1550 pending = XPending (DisplayHandle);
1556 CheckTimers (queue.timer_list, now);
1559 XEvent xevent = new XEvent ();
1562 if (XPending (DisplayHandle) == 0)
1565 XNextEvent (DisplayHandle, ref xevent);
1567 if (xevent.AnyEvent.type == XEventName.KeyPress ||
1568 xevent.AnyEvent.type == XEventName.KeyRelease) {
1569 // PreFilter() handles "shift key state updates.
1570 Keyboard.PreFilter (xevent);
1571 if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
1572 // probably here we could raise WM_IME_KEYDOWN and
1573 // WM_IME_KEYUP, but I'm not sure it is worthy.
1577 else if (XFilterEvent (ref xevent, IntPtr.Zero))
1581 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1586 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1588 switch (xevent.type) {
1589 case XEventName.Expose:
1590 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1593 case XEventName.SelectionClear: {
1594 // Should we do something?
1598 case XEventName.SelectionRequest: {
1599 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1603 sel_event = new XEvent();
1604 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1605 sel_event.SelectionEvent.send_event = true;
1606 sel_event.SelectionEvent.display = DisplayHandle;
1607 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1608 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1609 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1610 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1611 sel_event.SelectionEvent.property = IntPtr.Zero;
1613 // Seems that some apps support asking for supported types
1614 if (xevent.SelectionEvent.target == TARGETS) {
1621 if (Clipboard.Item is String) {
1622 atoms[atom_count++] = (int)Atom.XA_STRING;
1623 atoms[atom_count++] = (int)OEMTEXT;
1624 atoms[atom_count++] = (int)UNICODETEXT;
1625 } else if (Clipboard.Item is Image) {
1626 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1627 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1629 // FIXME - handle other types
1632 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1633 } else if (Clipboard.Item is string) {
1639 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1642 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1643 buffer = Marshal.AllocHGlobal(bytes.Length);
1644 buflen = bytes.Length;
1646 for (int i = 0; i < buflen; i++) {
1647 Marshal.WriteByte(buffer, i, bytes[i]);
1649 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1650 // FIXME - this should encode into ISO2022
1651 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1652 while (Marshal.ReadByte(buffer, buflen) != 0) {
1655 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1656 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1657 while (Marshal.ReadByte(buffer, buflen) != 0) {
1661 buffer = IntPtr.Zero;
1664 if (buffer != IntPtr.Zero) {
1665 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1666 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1667 Marshal.FreeHGlobal(buffer);
1669 } else if (Clipboard.Item is Image) {
1670 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1671 // FIXME - convert image and store as property
1672 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1673 // FIXME - convert image and store as property
1677 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1681 case XEventName.SelectionNotify: {
1682 if (Clipboard.Enumerating) {
1683 Clipboard.Enumerating = false;
1684 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1685 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1686 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1687 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1688 #if DriverDebugExtra
1689 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1693 } else if (Clipboard.Retrieving) {
1694 Clipboard.Retrieving = false;
1695 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1696 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1698 Clipboard.Item = null;
1701 Dnd.HandleSelectionNotifyEvent (ref xevent);
1706 case XEventName.KeyRelease:
1707 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1708 XEvent nextevent = new XEvent ();
1710 XPeekEvent (DisplayHandle, ref nextevent);
1712 if (nextevent.type == XEventName.KeyPress &&
1713 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1714 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1718 goto case XEventName.KeyPress;
1720 case XEventName.MotionNotify: {
1723 /* we can't do motion compression across threads, so just punt if we don't match up */
1724 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1725 peek = hwnd.Queue.Peek();
1726 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1730 goto case XEventName.KeyPress;
1733 case XEventName.KeyPress:
1734 hwnd.Queue.EnqueueLocked (xevent);
1735 /* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
1736 * single physical keypress are not processed correctly */
1738 case XEventName.ButtonPress:
1739 case XEventName.ButtonRelease:
1740 case XEventName.EnterNotify:
1741 case XEventName.LeaveNotify:
1742 case XEventName.CreateNotify:
1743 case XEventName.DestroyNotify:
1744 case XEventName.FocusIn:
1745 case XEventName.FocusOut:
1746 case XEventName.ClientMessage:
1747 case XEventName.ReparentNotify:
1748 case XEventName.MapNotify:
1749 case XEventName.UnmapNotify:
1750 hwnd.Queue.EnqueueLocked (xevent);
1753 case XEventName.ConfigureNotify:
1754 AddConfigureNotify(xevent);
1757 case XEventName.PropertyNotify:
1759 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1761 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1766 IntPtr prop = IntPtr.Zero;
1769 prev_active = ActiveWindow;
1770 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);
1771 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1772 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1775 if (prev_active != ActiveWindow) {
1776 if (prev_active != IntPtr.Zero) {
1777 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1779 if (ActiveWindow != IntPtr.Zero) {
1780 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1783 if (ModalWindows.Count == 0) {
1786 // Modality handling, if we are modal and the new active window is one
1787 // of ours but not the modal one, switch back to the modal window
1789 if (NativeWindow.FromHandle(ActiveWindow) != null) {
1790 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1791 Activate((IntPtr)ModalWindows.Peek());
1798 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1799 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1800 hwnd.cached_window_state = (FormWindowState)(-1);
1801 PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
1809 private IntPtr GetMousewParam(int Delta) {
1812 if ((MouseState & MouseButtons.Left) != 0) {
1813 result |= (int)MsgButtons.MK_LBUTTON;
1816 if ((MouseState & MouseButtons.Middle) != 0) {
1817 result |= (int)MsgButtons.MK_MBUTTON;
1820 if ((MouseState & MouseButtons.Right) != 0) {
1821 result |= (int)MsgButtons.MK_RBUTTON;
1824 Keys mods = ModifierKeys;
1825 if ((mods & Keys.Control) != 0) {
1826 result |= (int)MsgButtons.MK_CONTROL;
1829 if ((mods & Keys.Shift) != 0) {
1830 result |= (int)MsgButtons.MK_SHIFT;
1833 result |= Delta << 16;
1835 return (IntPtr)result;
1837 private IntPtr XGetParent(IntPtr handle) {
1844 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1847 if (Children!=IntPtr.Zero) {
1855 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1857 // we need to workaround a problem with the
1858 // ordering of destruction of Drawables and
1859 // Pictures that exists between cairo and
1860 // RENDER on the server.
1861 if (error_event.request_code == (XRequest)render_major_opcode
1862 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1863 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1867 if (ErrorExceptions) {
1868 XUngrabPointer (display, IntPtr.Zero);
1869 throw new XException (error_event.display, error_event.resourceid,
1870 error_event.serial, error_event.error_code,
1871 error_event.request_code, error_event.minor_code);
1873 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1874 XException.GetMessage (error_event.display, error_event.resourceid,
1875 error_event.serial, error_event.error_code,
1876 error_event.request_code, error_event.minor_code),
1877 Environment.StackTrace);
1882 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1885 Control[] controls = c.Controls.GetAllControls ();
1887 if (c.IsHandleCreated && !c.IsDisposed) {
1888 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1890 #if DriverDebug || DriverDebugDestroy
1891 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1892 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1896 CleanupCachedWindows (hwnd);
1899 for (int i = 0; i < controls.Length; i ++) {
1900 AccumulateDestroyedHandles (controls[i], list);
1906 void CleanupCachedWindows (Hwnd hwnd)
1908 if (ActiveWindow == hwnd.Handle) {
1909 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1910 ActiveWindow = IntPtr.Zero;
1913 if (FocusWindow == hwnd.Handle) {
1914 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1915 FocusWindow = IntPtr.Zero;
1918 if (Grab.Hwnd == hwnd.Handle) {
1919 Grab.Hwnd = IntPtr.Zero;
1920 Grab.Confined = false;
1923 DestroyCaret (hwnd.Handle);
1926 private void PerformNCCalc(Hwnd hwnd) {
1927 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1931 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1933 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1934 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1936 ncp.rgrc1.left = rect.Left;
1937 ncp.rgrc1.top = rect.Top;
1938 ncp.rgrc1.right = rect.Right;
1939 ncp.rgrc1.bottom = rect.Bottom;
1941 Marshal.StructureToPtr(ncp, ptr, true);
1942 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1943 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1944 Marshal.FreeHGlobal(ptr);
1947 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1948 hwnd.ClientRect = rect;
1950 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1953 MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1956 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1958 #endregion // Private Methods
1961 private void MouseHover(object sender, EventArgs e) {
1965 HoverState.Timer.Enabled = false;
1967 if (HoverState.Window != IntPtr.Zero) {
1968 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1970 xevent = new XEvent ();
1972 xevent.type = XEventName.ClientMessage;
1973 xevent.ClientMessageEvent.display = DisplayHandle;
1974 xevent.ClientMessageEvent.window = HoverState.Window;
1975 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1976 xevent.ClientMessageEvent.format = 32;
1977 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1979 hwnd.Queue.EnqueueLocked (xevent);
1986 private void CaretCallback(object sender, EventArgs e) {
1990 Caret.On = !Caret.On;
1992 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1994 #endregion // Callbacks
1996 #region Public Properties
1998 internal override int CaptionHeight {
2004 internal override Size CursorSize {
2009 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
2010 return new Size(x, y);
2012 return new Size(16, 16);
2017 internal override bool DragFullWindows {
2023 internal override Size DragSize {
2025 return new Size(4, 4);
2029 internal override Size FrameBorderSize {
2031 return new Size (4, 4);
2035 internal override Size IconSize {
2041 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2045 current = (long)list;
2048 size = new XIconSize();
2050 for (int i = 0; i < count; i++) {
2051 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2052 current += Marshal.SizeOf(size);
2054 // Look for our preferred size
2055 if (size.min_width == 32) {
2057 return new Size(32, 32);
2060 if (size.max_width == 32) {
2062 return new Size(32, 32);
2065 if (size.min_width < 32 && size.max_width > 32) {
2068 // check if we can fit one
2070 while (x < size.max_width) {
2071 x += size.width_inc;
2074 return new Size(32, 32);
2079 if (largest < size.max_width) {
2080 largest = size.max_width;
2084 // We didn't find a match or we wouldn't be here
2085 return new Size(largest, largest);
2088 return new Size(32, 32);
2093 internal override int KeyboardSpeed {
2096 // A lot harder: need to do:
2097 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2098 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2099 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2101 // And from that we can tell the repetition rate
2103 // Notice, the values must map to:
2104 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2110 internal override int KeyboardDelay {
2113 // Return values must range from 0 to 4, 0 meaning 250ms,
2114 // and 4 meaning 1000 ms.
2116 return 1; // ie, 500 ms
2120 internal override Size MaxWindowTrackSize {
2122 return new Size (WorkingArea.Width, WorkingArea.Height);
2126 internal override bool MenuAccessKeysUnderlined {
2132 internal override Size MinimizedWindowSize {
2134 return new Size(1, 1);
2138 internal override Size MinimizedWindowSpacingSize {
2140 return new Size(1, 1);
2144 internal override Size MinimumWindowSize {
2146 return new Size(110, 22);
2150 internal override Size MinimumFixedToolWindowSize {
2151 get { return new Size (27, 22); }
2154 internal override Size MinimumSizeableToolWindowSize {
2155 get { return new Size (37, 22); }
2158 internal override Size MinimumNoBorderWindowSize {
2159 get { return new Size (2, 2); }
2162 internal override Size MinWindowTrackSize {
2164 return new Size(1, 1);
2168 internal override Keys ModifierKeys {
2170 return Keyboard.ModifierKeys;
2174 internal override Size SmallIconSize {
2180 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2184 current = (long)list;
2187 size = new XIconSize();
2189 for (int i = 0; i < count; i++) {
2190 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2191 current += Marshal.SizeOf(size);
2193 // Look for our preferred size
2194 if (size.min_width == 16) {
2196 return new Size(16, 16);
2199 if (size.max_width == 16) {
2201 return new Size(16, 16);
2204 if (size.min_width < 16 && size.max_width > 16) {
2207 // check if we can fit one
2209 while (x < size.max_width) {
2210 x += size.width_inc;
2213 return new Size(16, 16);
2218 if (smallest == 0 || smallest > size.min_width) {
2219 smallest = size.min_width;
2223 // We didn't find a match or we wouldn't be here
2224 return new Size(smallest, smallest);
2227 return new Size(16, 16);
2232 internal override int MouseButtonCount {
2238 internal override bool MouseButtonsSwapped {
2240 return false; // FIXME - how to detect?
2244 internal override Point MousePosition {
2246 return mouse_position;
2250 internal override Size MouseHoverSize {
2252 return new Size (1, 1);
2256 internal override int MouseHoverTime {
2258 return HoverState.Interval;
2264 internal override bool MouseWheelPresent {
2266 return true; // FIXME - how to detect?
2270 internal override Rectangle VirtualScreen {
2276 IntPtr prop = IntPtr.Zero;
2280 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);
2281 if ((long)nitems < 2)
2284 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2285 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2289 return new Rectangle(0, 0, width, height);
2292 XWindowAttributes attributes=new XWindowAttributes();
2295 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2298 return new Rectangle(0, 0, attributes.width, attributes.height);
2302 internal override Rectangle WorkingArea {
2308 IntPtr prop = IntPtr.Zero;
2311 int current_desktop;
2315 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);
2316 if ((long)nitems < 1) {
2320 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2323 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);
2324 if ((long)nitems < 4 * current_desktop) {
2328 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2329 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2330 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2331 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2334 return new Rectangle(x, y, width, height);
2337 XWindowAttributes attributes=new XWindowAttributes();
2340 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2343 return new Rectangle(0, 0, attributes.width, attributes.height);
2347 internal override bool ThemesEnabled {
2349 return XplatUIX11.themes_enabled;
2354 #endregion // Public properties
2356 #region Public Static Methods
2357 internal override void RaiseIdle (EventArgs e)
2363 internal override IntPtr InitializeDriver() {
2365 if (DisplayHandle==IntPtr.Zero) {
2366 SetDisplay(XOpenDisplay(IntPtr.Zero));
2372 internal override void ShutdownDriver(IntPtr token) {
2374 if (DisplayHandle!=IntPtr.Zero) {
2375 XCloseDisplay(DisplayHandle);
2376 DisplayHandle=IntPtr.Zero;
2381 internal override void EnableThemes() {
2382 themes_enabled = true;
2386 internal override void Activate(IntPtr handle) {
2389 hwnd = Hwnd.ObjectFromHandle(handle);
2393 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2394 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2395 XEventQueue q = null;
2396 lock (unattached_timer_list) {
2397 foreach (Timer t in unattached_timer_list) {
2399 q= (XEventQueue) MessageQueues [Thread.CurrentThread];
2400 t.thread = q.Thread;
2401 q.timer_list.Add (t);
2403 unattached_timer_list.Clear ();
2407 // XRaiseWindow(DisplayHandle, handle);
2413 internal override void AudibleAlert() {
2414 XBell(DisplayHandle, 0);
2419 internal override void CaretVisible(IntPtr handle, bool visible) {
2420 if (Caret.Hwnd == handle) {
2422 if (!Caret.Visible) {
2423 Caret.Visible = true;
2425 Caret.Timer.Start();
2428 Caret.Visible = false;
2435 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2436 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2440 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2446 hwnd = Hwnd.ObjectFromHandle(handle);
2449 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2456 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2457 DataFormats.Format f;
2460 f = DataFormats.Format.List;
2462 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2466 Clipboard.Formats = new ArrayList();
2469 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2471 Clipboard.Enumerating = true;
2472 while (Clipboard.Enumerating) {
2473 UpdateMessageQueue(null);
2478 result = new int[Clipboard.Formats.Count];
2480 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2481 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2484 Clipboard.Formats = null;
2488 internal override void ClipboardClose(IntPtr handle) {
2489 if (handle != ClipMagic) {
2490 throw new ArgumentException("handle is not a valid clipboard handle");
2495 internal override int ClipboardGetID(IntPtr handle, string format) {
2496 if (handle != ClipMagic) {
2497 throw new ArgumentException("handle is not a valid clipboard handle");
2500 if (format == "Text" ) return (int)Atom.XA_STRING;
2501 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2502 //else if (format == "MetaFilePict" ) return 3;
2503 //else if (format == "SymbolicLink" ) return 4;
2504 //else if (format == "DataInterchangeFormat" ) return 5;
2505 //else if (format == "Tiff" ) return 6;
2506 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2507 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2508 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2509 //else if (format == "PenData" ) return 10;
2510 //else if (format == "RiffAudio" ) return 11;
2511 //else if (format == "WaveAudio" ) return 12;
2512 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2513 //else if (format == "EnhancedMetafile" ) return 14;
2514 //else if (format == "FileDrop" ) return 15;
2515 //else if (format == "Locale" ) return 16;
2517 return XInternAtom(DisplayHandle, format, false).ToInt32();
2520 internal override IntPtr ClipboardOpen(bool primary_selection) {
2521 if (!primary_selection)
2522 ClipMagic = CLIPBOARD;
2524 ClipMagic = PRIMARY;
2528 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2529 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2531 Clipboard.Retrieving = true;
2532 while (Clipboard.Retrieving) {
2533 UpdateMessageQueue(null);
2536 return Clipboard.Item;
2539 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2540 Clipboard.Item = obj;
2541 Clipboard.Type = type;
2542 Clipboard.Converter = converter;
2545 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2547 // Clearing the selection
2548 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2552 internal override void CreateCaret (IntPtr handle, int width, int height)
2554 XGCValues gc_values;
2557 hwnd = Hwnd.ObjectFromHandle(handle);
2559 if (Caret.Hwnd != IntPtr.Zero) {
2560 DestroyCaret(Caret.Hwnd);
2563 Caret.Hwnd = handle;
2564 Caret.Window = hwnd.client_window;
2565 Caret.Width = width;
2566 Caret.Height = height;
2567 Caret.Visible = false;
2570 gc_values = new XGCValues();
2571 gc_values.line_width = width;
2573 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2574 if (Caret.gc == IntPtr.Zero) {
2575 Caret.Hwnd = IntPtr.Zero;
2579 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2582 internal override IntPtr CreateWindow (CreateParams cp)
2584 XSetWindowAttributes Attributes;
2586 Hwnd parent_hwnd = null;
2591 IntPtr ParentHandle;
2593 IntPtr ClientWindow;
2594 SetWindowValuemask ValueMask;
2599 Attributes = new XSetWindowAttributes();
2605 if (Width<1) Width=1;
2606 if (Height<1) Height=1;
2608 if (cp.Parent != IntPtr.Zero) {
2609 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2610 ParentHandle = parent_hwnd.client_window;
2612 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2613 // We need to use our foster parent window until this poor child gets it's parent assigned
2614 ParentHandle=FosterParent;
2616 ParentHandle=RootWindow;
2620 // Set the default location location for forms.
2622 if (cp.control is Form) {
2623 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2627 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2629 Attributes.bit_gravity = Gravity.NorthWestGravity;
2630 Attributes.win_gravity = Gravity.NorthWestGravity;
2632 // Save what's under the toolwindow
2633 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2634 Attributes.save_under = true;
2635 ValueMask |= SetWindowValuemask.SaveUnder;
2639 // If we're a popup without caption we override the WM
2640 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2641 Attributes.override_redirect = true;
2642 ValueMask |= SetWindowValuemask.OverrideRedirect;
2648 hwnd.height = Height;
2649 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2650 hwnd.initial_style = cp.WindowStyle;
2651 hwnd.initial_ex_style = cp.WindowExStyle;
2653 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2654 hwnd.enabled = false;
2657 ClientWindow = IntPtr.Zero;
2659 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2660 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2663 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);
2664 if (WholeWindow != IntPtr.Zero) {
2665 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2667 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2668 ValueMask = SetWindowValuemask.ColorMap;
2669 Attributes.colormap = CustomColormap;
2671 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);
2675 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2676 throw new Exception("Could not create X11 windows");
2679 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2680 hwnd.WholeWindow = WholeWindow;
2681 hwnd.ClientWindow = ClientWindow;
2683 #if DriverDebug || DriverDebugCreate
2684 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);
2687 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2688 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2691 hints = new XSizeHints();
2694 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2695 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2700 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
2701 if (hwnd.whole_window != hwnd.client_window)
2702 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
2705 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2707 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2708 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2710 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2713 SetWMStyles(hwnd, cp);
2715 // set the group leader
2716 XWMHints wm_hints = new XWMHints ();
2718 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2719 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2720 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2722 if (ParentHandle != RootWindow) {
2723 wm_hints.window_group = hwnd.whole_window;
2725 wm_hints.window_group = ParentHandle;
2729 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2732 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2733 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2734 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2735 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2738 // for now make all windows dnd enabled
2739 Dnd.SetAllowDrop (hwnd, true);
2741 // Set caption/window title
2742 Text(hwnd.Handle, cp.Caption);
2744 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2745 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2747 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2748 hwnd.visible = true;
2749 MapWindow(hwnd, WindowType.Both);
2750 if (!(Control.FromHandle(hwnd.Handle) is Form))
2751 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2757 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2758 CreateParams create_params = new CreateParams();
2760 create_params.Caption = "";
2761 create_params.X = X;
2762 create_params.Y = Y;
2763 create_params.Width = Width;
2764 create_params.Height = Height;
2766 create_params.ClassName=XplatUI.DefaultClassName;
2767 create_params.ClassStyle = 0;
2768 create_params.ExStyle=0;
2769 create_params.Parent=IntPtr.Zero;
2770 create_params.Param=0;
2772 return CreateWindow(create_params);
2775 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2777 Bitmap cursor_bitmap;
2785 IntPtr cursor_pixmap;
2792 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2796 // Win32 only allows creation cursors of a certain size
2797 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2798 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2799 cursor_mask = new Bitmap(mask, new Size(width, height));
2801 cursor_bitmap = bitmap;
2805 width = cursor_bitmap.Width;
2806 height = cursor_bitmap.Height;
2808 cursor_bits = new Byte[(width / 8) * height];
2809 mask_bits = new Byte[(width / 8) * height];
2811 for (int y = 0; y < height; y++) {
2812 for (int x = 0; x < width; x++) {
2813 c_pixel = cursor_bitmap.GetPixel(x, y);
2814 m_pixel = cursor_mask.GetPixel(x, y);
2816 and = c_pixel == cursor_pixel;
2817 xor = m_pixel == mask_pixel;
2821 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2822 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2823 } else if (and && !xor) {
2825 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2826 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2828 } else if (and && !xor) {
2830 } else if (and && xor) {
2833 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2834 // we want both to be 0 so nothing to be done
2835 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2836 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2842 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2843 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2847 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2848 fg.red = (ushort)65535;
2849 fg.green = (ushort)65535;
2850 fg.blue = (ushort)65535;
2852 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2854 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2856 XFreePixmap(DisplayHandle, cursor_pixmap);
2857 XFreePixmap(DisplayHandle, mask_pixmap);
2862 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2863 CursorFontShape shape;
2870 shape = StdCursorToFontShape (id);
2871 name = shape.ToString ().Replace ("XC_", string.Empty);
2872 size = XcursorGetDefaultSize (DisplayHandle);
2873 theme = XcursorGetTheme (DisplayHandle);
2874 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2876 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);
2879 if (images_ptr == IntPtr.Zero) {
2883 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2885 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2888 if (images.nimage > 0) {
2889 // We only care about the first image.
2890 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2893 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);
2896 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2897 int [] pixels = new int [image.width * image.height];
2898 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2899 bmp = new Bitmap (image.width, image.height);
2900 for (int w = 0; w < image.width; w++) {
2901 for (int h = 0; h < image.height; h++) {
2902 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2908 XcursorImagesDestroy (images_ptr);
2910 } catch (DllNotFoundException ex) {
2911 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2919 internal override IntPtr DefineStdCursor(StdCursor id) {
2920 CursorFontShape shape;
2923 shape = StdCursorToFontShape (id);
2926 cursor = XCreateFontCursor(DisplayHandle, shape);
2931 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2932 CursorFontShape shape;
2933 // FIXME - define missing shapes
2936 case StdCursor.AppStarting: {
2937 shape = CursorFontShape.XC_watch;
2941 case StdCursor.Arrow: {
2942 shape = CursorFontShape.XC_top_left_arrow;
2946 case StdCursor.Cross: {
2947 shape = CursorFontShape.XC_crosshair;
2951 case StdCursor.Default: {
2952 shape = CursorFontShape.XC_top_left_arrow;
2956 case StdCursor.Hand: {
2957 shape = CursorFontShape.XC_hand1;
2961 case StdCursor.Help: {
2962 shape = CursorFontShape.XC_question_arrow;
2966 case StdCursor.HSplit: {
2967 shape = CursorFontShape.XC_sb_v_double_arrow;
2971 case StdCursor.IBeam: {
2972 shape = CursorFontShape.XC_xterm;
2976 case StdCursor.No: {
2977 shape = CursorFontShape.XC_circle;
2981 case StdCursor.NoMove2D: {
2982 shape = CursorFontShape.XC_fleur;
2986 case StdCursor.NoMoveHoriz: {
2987 shape = CursorFontShape.XC_fleur;
2991 case StdCursor.NoMoveVert: {
2992 shape = CursorFontShape.XC_fleur;
2996 case StdCursor.PanEast: {
2997 shape = CursorFontShape.XC_fleur;
3001 case StdCursor.PanNE: {
3002 shape = CursorFontShape.XC_fleur;
3006 case StdCursor.PanNorth: {
3007 shape = CursorFontShape.XC_fleur;
3011 case StdCursor.PanNW: {
3012 shape = CursorFontShape.XC_fleur;
3016 case StdCursor.PanSE: {
3017 shape = CursorFontShape.XC_fleur;
3021 case StdCursor.PanSouth: {
3022 shape = CursorFontShape.XC_fleur;
3026 case StdCursor.PanSW: {
3027 shape = CursorFontShape.XC_fleur;
3031 case StdCursor.PanWest: {
3032 shape = CursorFontShape.XC_sizing;
3036 case StdCursor.SizeAll: {
3037 shape = CursorFontShape.XC_fleur;
3041 case StdCursor.SizeNESW: {
3042 shape = CursorFontShape.XC_top_right_corner;
3046 case StdCursor.SizeNS: {
3047 shape = CursorFontShape.XC_sb_v_double_arrow;
3051 case StdCursor.SizeNWSE: {
3052 shape = CursorFontShape.XC_top_left_corner;
3056 case StdCursor.SizeWE: {
3057 shape = CursorFontShape.XC_sb_h_double_arrow;
3061 case StdCursor.UpArrow: {
3062 shape = CursorFontShape.XC_center_ptr;
3066 case StdCursor.VSplit: {
3067 shape = CursorFontShape.XC_sb_h_double_arrow;
3071 case StdCursor.WaitCursor: {
3072 shape = CursorFontShape.XC_watch;
3077 shape = (CursorFontShape) 0;
3085 internal override IntPtr DefWndProc(ref Message msg) {
3086 switch ((Msg)msg.Msg) {
3088 case Msg.WM_IME_COMPOSITION:
3089 string s = Keyboard.GetCompositionString ();
3090 foreach (char c in s)
3091 SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
3094 case Msg.WM_IME_CHAR:
3095 // On Windows API it sends two WM_CHAR messages for each byte, but
3096 // I wonder if it is worthy to emulate it (also no idea how to
3097 // reconstruct those bytes into chars).
3098 SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
3101 case Msg.WM_PAINT: {
3104 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3106 hwnd.expose_pending = false;
3112 case Msg.WM_NCPAINT: {
3115 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3117 hwnd.nc_expose_pending = false;
3123 case Msg.WM_NCCALCSIZE: {
3126 if (msg.WParam == (IntPtr)1) {
3127 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3129 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3130 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3132 // Add all the stuff X is supposed to draw.
3133 Control ctrl = Control.FromHandle (hwnd.Handle);
3136 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3138 ncp.rgrc1.top += rect.top;
3139 ncp.rgrc1.bottom -= rect.bottom;
3140 ncp.rgrc1.left += rect.left;
3141 ncp.rgrc1.right -= rect.right;
3143 Marshal.StructureToPtr (ncp, msg.LParam, true);
3150 case Msg.WM_CONTEXTMENU: {
3153 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3155 if ((hwnd != null) && (hwnd.parent != null)) {
3156 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3161 case Msg.WM_MOUSEWHEEL: {
3164 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3166 if ((hwnd != null) && (hwnd.parent != null)) {
3167 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3168 if (msg.Result == IntPtr.Zero) {
3175 case Msg.WM_SETCURSOR: {
3178 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3180 break; // not sure how this happens, but it does
3182 // Pass to parent window first
3183 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3185 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3188 if (msg.Result == IntPtr.Zero) {
3191 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3192 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3193 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3194 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3195 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3196 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3199 handle = Cursors.Default.handle;
3202 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3203 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3204 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3205 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3206 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3207 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3210 case HitTest.HTGROWBOX:
3211 case HitTest.HTSIZE:
3212 case HitTest.HTZOOM:
3213 case HitTest.HTVSCROLL:
3214 case HitTest.HTSYSMENU:
3215 case HitTest.HTREDUCE:
3216 case HitTest.HTNOWHERE:
3217 case HitTest.HTMAXBUTTON:
3218 case HitTest.HTMINBUTTON:
3219 case HitTest.HTMENU:
3220 case HitTest.HSCROLL:
3221 case HitTest.HTBOTTOM:
3222 case HitTest.HTCAPTION:
3223 case HitTest.HTCLIENT:
3224 case HitTest.HTCLOSE:
3226 default: handle = Cursors.Default.handle; break;
3228 SetCursor(msg.HWnd, handle);
3236 internal override void DestroyCaret(IntPtr handle) {
3237 if (Caret.Hwnd == handle) {
3238 if (Caret.Visible) {
3242 if (Caret.gc != IntPtr.Zero) {
3243 XFreeGC(DisplayHandle, Caret.gc);
3244 Caret.gc = IntPtr.Zero;
3246 Caret.Hwnd = IntPtr.Zero;
3247 Caret.Visible = false;
3252 internal override void DestroyCursor(IntPtr cursor) {
3254 XFreeCursor(DisplayHandle, cursor);
3258 internal override void DestroyWindow(IntPtr handle) {
3261 hwnd = Hwnd.ObjectFromHandle(handle);
3264 #if DriverDebug || DriverDebugDestroy
3265 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3270 #if DriverDebug || DriverDebugDestroy
3271 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3274 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3276 CleanupCachedWindows (hwnd);
3278 ArrayList windows = new ArrayList ();
3280 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3283 foreach (Hwnd h in windows) {
3284 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3289 if (hwnd.whole_window != IntPtr.Zero) {
3290 #if DriverDebug || DriverDebugDestroy
3291 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3293 Keyboard.DestroyICForWindow (hwnd.whole_window);
3294 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3296 else if (hwnd.client_window != IntPtr.Zero) {
3297 #if DriverDebug || DriverDebugDestroy
3298 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3300 Keyboard.DestroyICForWindow (hwnd.client_window);
3301 XDestroyWindow(DisplayHandle, hwnd.client_window);
3307 internal override IntPtr DispatchMessage(ref MSG msg) {
3308 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3311 IntPtr GetReversibleScreenGC (Color backColor)
3313 XGCValues gc_values;
3317 XColor xcolor = new XColor();
3318 xcolor.red = (ushort)(backColor.R * 257);
3319 xcolor.green = (ushort)(backColor.G * 257);
3320 xcolor.blue = (ushort)(backColor.B * 257);
3321 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3322 pixel = (uint)xcolor.pixel.ToInt32();
3325 gc_values = new XGCValues();
3327 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3328 gc_values.foreground = (IntPtr)pixel;
3330 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3331 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3332 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3337 IntPtr GetReversibleControlGC (Control control, int line_width)
3339 XGCValues gc_values;
3342 gc_values = new XGCValues();
3344 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3345 gc_values.line_width = line_width;
3346 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3348 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3349 //mask = foreground ^ background;
3350 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3351 //XSetBackground(DisplayHandle, gc, background);
3352 //XSetFunction(DisplayHandle, gc, GXxor);
3353 //XSetPlaneMask(DisplayHandle, gc, mask);
3356 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3360 XColor xcolor = new XColor();
3362 xcolor.red = (ushort)(control.ForeColor.R * 257);
3363 xcolor.green = (ushort)(control.ForeColor.G * 257);
3364 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3365 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3366 foreground = (uint)xcolor.pixel.ToInt32();
3368 xcolor.red = (ushort)(control.BackColor.R * 257);
3369 xcolor.green = (ushort)(control.BackColor.G * 257);
3370 xcolor.blue = (ushort)(control.BackColor.B * 257);
3371 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3372 background = (uint)xcolor.pixel.ToInt32();
3374 uint mask = foreground ^ background;
3376 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3377 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3378 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3379 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3384 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3386 if (backColor.GetBrightness() < 0.5)
3387 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3389 IntPtr gc = GetReversibleScreenGC (backColor);
3391 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3393 XFreeGC(DisplayHandle, gc);
3396 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3398 if (backColor.GetBrightness() < 0.5)
3399 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3401 IntPtr gc = GetReversibleScreenGC (backColor);
3403 if (rectangle.Width < 0) {
3404 rectangle.X += rectangle.Width;
3405 rectangle.Width = -rectangle.Width;
3407 if (rectangle.Height < 0) {
3408 rectangle.Y += rectangle.Height;
3409 rectangle.Height = -rectangle.Height;
3413 GCLineStyle line_style = GCLineStyle.LineSolid;
3414 GCCapStyle cap_style = GCCapStyle.CapButt;
3415 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3418 case FrameStyle.Dashed:
3419 line_style = GCLineStyle.LineOnOffDash;
3421 case FrameStyle.Thick:
3426 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3428 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3430 XFreeGC(DisplayHandle, gc);
3433 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3435 if (backColor.GetBrightness() < 0.5)
3436 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3438 IntPtr gc = GetReversibleScreenGC (backColor);
3440 if (rectangle.Width < 0) {
3441 rectangle.X += rectangle.Width;
3442 rectangle.Width = -rectangle.Width;
3444 if (rectangle.Height < 0) {
3445 rectangle.Y += rectangle.Height;
3446 rectangle.Height = -rectangle.Height;
3448 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3450 XFreeGC(DisplayHandle, gc);
3453 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3456 Control control = Control.FromHandle(handle);
3458 gc = GetReversibleControlGC (control, line_width);
3460 if ((rect.Width > 0) && (rect.Height > 0)) {
3461 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3463 if (rect.Width > 0) {
3464 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3466 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3469 XFreeGC(DisplayHandle, gc);
3472 internal override void DoEvents() {
3473 MSG msg = new MSG ();
3476 if (OverrideCursorHandle != IntPtr.Zero) {
3477 OverrideCursorHandle = IntPtr.Zero;
3480 queue = ThreadQueue(Thread.CurrentThread);
3482 queue.DispatchIdle = false;
3484 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3485 TranslateMessage (ref msg);
3486 DispatchMessage (ref msg);
3489 queue.DispatchIdle = true;
3492 internal override void EnableWindow(IntPtr handle, bool Enable) {
3495 hwnd = Hwnd.ObjectFromHandle(handle);
3497 hwnd.Enabled = Enable;
3501 internal override void EndLoop(Thread thread) {
3502 // This is where we one day will shut down the loop for the thread
3505 internal override IntPtr GetActive() {
3510 IntPtr prop = IntPtr.Zero;
3511 IntPtr active = IntPtr.Zero;
3513 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);
3514 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3515 active = (IntPtr)Marshal.ReadInt32(prop);
3519 if (active != IntPtr.Zero) {
3522 hwnd = Hwnd.GetObjectFromWindow(active);
3524 active = hwnd.Handle;
3526 active = IntPtr.Zero;
3532 internal override Region GetClipRegion(IntPtr handle) {
3535 hwnd = Hwnd.ObjectFromHandle(handle);
3537 return hwnd.UserClip;
3543 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3550 internal override void GetDisplaySize(out Size size) {
3551 XWindowAttributes attributes=new XWindowAttributes();
3554 // FIXME - use _NET_WM messages instead?
3555 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3558 size = new Size(attributes.width, attributes.height);
3561 internal override SizeF GetAutoScaleSize(Font font) {
3564 string magic_string = "The quick brown fox jumped over the lazy dog.";
3565 double magic_number = 44.549996948242189;
3567 g = Graphics.FromHwnd(FosterParent);
3569 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3570 return new SizeF(width, font.Height);
3573 internal override IntPtr GetParent(IntPtr handle) {
3576 hwnd = Hwnd.ObjectFromHandle(handle);
3577 if (hwnd != null && hwnd.parent != null) {
3578 return hwnd.parent.Handle;
3583 // This is a nop on win32 and x11
3584 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3588 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3598 if (handle != IntPtr.Zero) {
3599 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3601 use_handle = RootWindow;
3605 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3608 if (handle != IntPtr.Zero) {
3617 internal override IntPtr GetFocus() {
3622 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3623 FontFamily ff = font.FontFamily;
3624 ascent = ff.GetCellAscent (font.Style);
3625 descent = ff.GetCellDescent (font.Style);
3629 internal override Point GetMenuOrigin(IntPtr handle) {
3632 hwnd = Hwnd.ObjectFromHandle(handle);
3635 return hwnd.MenuOrigin;
3640 [MonoTODO("Implement filtering")]
3641 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3648 if (((XEventQueue)queue_id).Count > 0) {
3649 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3651 UpdateMessageQueue ((XEventQueue)queue_id);
3653 if (((XEventQueue)queue_id).Count > 0) {
3654 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3655 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3656 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3658 msg.hwnd= IntPtr.Zero;
3659 msg.message = Msg.WM_ENTERIDLE;
3664 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3666 // Handle messages for windows that are already or are about to be destroyed.
3668 // we need a special block for this because unless we remove the hwnd from the paint
3669 // queue it will always stay there (since we don't handle the expose), and we'll
3670 // effectively loop infinitely trying to repaint a non-existant window.
3671 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3672 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3673 hwnd.Queue.Paint.Remove (hwnd);
3674 goto ProcessNextMessage;
3677 // We need to make sure we only allow DestroyNotify events through for zombie
3678 // hwnds, since much of the event handling code makes requests using the hwnd's
3679 // client_window, and that'll result in BadWindow errors if there's some lag
3680 // between the XDestroyWindow call and the DestroyNotify event.
3681 if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
3682 #if DriverDebug || DriverDebugDestroy
3683 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3685 goto ProcessNextMessage;
3688 if (hwnd.client_window == xevent.AnyEvent.window) {
3690 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3693 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3696 msg.hwnd = hwnd.Handle;
3698 // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE
3699 // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
3700 // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
3701 // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
3703 // - There is no way for us to know which is the last Configure event. We can't traverse the events
3704 // queue, because the next configure event might not be pending yet.
3705 // - We can't get ButtonPress/Release events for the window decorations, because they are not part
3706 // of the window(s) we manage.
3707 // - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
3709 // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure
3710 // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
3712 if (hwnd.resizing_or_moving) {
3713 int root_x, root_y, win_x, win_y, keys_buttons;
3715 XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y,
3716 out win_x, out win_y, out keys_buttons);
3717 if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
3718 (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
3719 (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
3720 hwnd.resizing_or_moving = false;
3721 SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
3726 // If you add a new event to this switch make sure to add it in
3727 // UpdateMessage also unless it is not coming through the X event system.
3729 switch(xevent.type) {
3730 case XEventName.KeyPress: {
3731 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3735 case XEventName.KeyRelease: {
3736 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3740 case XEventName.ButtonPress: {
3741 switch(xevent.ButtonEvent.button) {
3743 MouseState |= MouseButtons.Left;
3745 msg.message = Msg.WM_LBUTTONDOWN;
3747 msg.message = Msg.WM_NCLBUTTONDOWN;
3748 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3750 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3751 msg.wParam=GetMousewParam(0);
3756 MouseState |= MouseButtons.Middle;
3758 msg.message = Msg.WM_MBUTTONDOWN;
3760 msg.message = Msg.WM_NCMBUTTONDOWN;
3761 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3763 msg.wParam=GetMousewParam(0);
3768 MouseState |= MouseButtons.Right;
3770 msg.message = Msg.WM_RBUTTONDOWN;
3772 msg.message = Msg.WM_NCRBUTTONDOWN;
3773 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3775 msg.wParam=GetMousewParam(0);
3780 msg.hwnd = FocusWindow;
3781 msg.message=Msg.WM_MOUSEWHEEL;
3782 msg.wParam=GetMousewParam(120);
3787 msg.hwnd = FocusWindow;
3788 msg.message=Msg.WM_MOUSEWHEEL;
3789 msg.wParam=GetMousewParam(-120);
3795 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3796 mouse_position.X = xevent.ButtonEvent.x;
3797 mouse_position.Y = xevent.ButtonEvent.y;
3799 if (!hwnd.Enabled) {
3802 msg.hwnd = hwnd.EnabledHwnd;
3803 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);
3804 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3807 if (Grab.Hwnd != IntPtr.Zero) {
3808 msg.hwnd = Grab.Hwnd;
3811 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3812 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3813 switch(xevent.ButtonEvent.button) {
3815 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3820 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3825 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3829 ClickPending.Pending = false;
3831 ClickPending.Pending = true;
3832 ClickPending.Hwnd = msg.hwnd;
3833 ClickPending.Message = msg.message;
3834 ClickPending.wParam = msg.wParam;
3835 ClickPending.lParam = msg.lParam;
3836 ClickPending.Time = (long)xevent.ButtonEvent.time;
3839 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3840 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3842 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3843 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3844 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3845 XEvent motionEvent = new XEvent ();
3846 motionEvent.type = XEventName.MotionNotify;
3847 motionEvent.MotionEvent.display = DisplayHandle;
3848 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3849 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3850 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3851 hwnd.Queue.EnqueueLocked (motionEvent);
3857 case XEventName.ButtonRelease: {
3859 switch(xevent.ButtonEvent.button) {
3862 msg.message = Msg.WM_LBUTTONUP;
3864 msg.message = Msg.WM_NCLBUTTONUP;
3865 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3867 MouseState &= ~MouseButtons.Left;
3868 msg.wParam=GetMousewParam(0);
3874 msg.message = Msg.WM_MBUTTONUP;
3876 msg.message = Msg.WM_NCMBUTTONUP;
3877 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3879 MouseState &= ~MouseButtons.Middle;
3880 msg.wParam=GetMousewParam(0);
3886 msg.message = Msg.WM_RBUTTONUP;
3888 msg.message = Msg.WM_NCRBUTTONUP;
3889 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3891 MouseState &= ~MouseButtons.Right;
3892 msg.wParam=GetMousewParam(0);
3897 goto ProcessNextMessage;
3901 goto ProcessNextMessage;
3905 if (!hwnd.Enabled) {
3908 msg.hwnd = hwnd.EnabledHwnd;
3909 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);
3910 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3913 if (Grab.Hwnd != IntPtr.Zero) {
3914 msg.hwnd = Grab.Hwnd;
3917 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3918 mouse_position.X = xevent.ButtonEvent.x;
3919 mouse_position.Y = xevent.ButtonEvent.y;
3921 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3922 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3923 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3924 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3925 XEvent motionEvent = new XEvent ();
3926 motionEvent.type = XEventName.MotionNotify;
3927 motionEvent.MotionEvent.display = DisplayHandle;
3928 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3929 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3930 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3931 hwnd.Queue.EnqueueLocked (motionEvent);
3936 case XEventName.MotionNotify: {
3938 #if DriverDebugExtra
3939 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);
3942 if (Grab.Hwnd != IntPtr.Zero) {
3943 msg.hwnd = Grab.Hwnd;
3946 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3950 if (xevent.MotionEvent.is_hint != 0)
3954 XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3955 out root, out child,
3956 out xevent.MotionEvent.x_root,
3957 out xevent.MotionEvent.y_root,
3958 out xevent.MotionEvent.x,
3959 out xevent.MotionEvent.y, out mask);
3962 msg.message = Msg.WM_MOUSEMOVE;
3963 msg.wParam = GetMousewParam(0);
3964 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3966 if (!hwnd.Enabled) {
3969 msg.hwnd = hwnd.EnabledHwnd;
3970 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);
3971 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3974 mouse_position.X = xevent.MotionEvent.x;
3975 mouse_position.Y = xevent.MotionEvent.y;
3977 if ((HoverState.Timer.Enabled) &&
3978 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3979 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3980 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3981 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3982 HoverState.Timer.Stop();
3983 HoverState.Timer.Start();
3984 HoverState.X = mouse_position.X;
3985 HoverState.Y = mouse_position.Y;
3995 #if DriverDebugExtra
3996 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);
3998 msg.message = Msg.WM_NCMOUSEMOVE;
4000 if (!hwnd.Enabled) {
4001 msg.hwnd = hwnd.EnabledHwnd;
4002 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);
4003 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
4006 // The hit test is sent in screen coordinates
4007 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
4008 xevent.MotionEvent.x, xevent.MotionEvent.y,
4009 out screen_x, out screen_y, out dummy);
4011 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
4012 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
4013 IntPtr.Zero, msg.lParam).ToInt32 ();
4014 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
4016 mouse_position.X = xevent.MotionEvent.x;
4017 mouse_position.Y = xevent.MotionEvent.y;
4023 case XEventName.EnterNotify: {
4024 if (!hwnd.Enabled) {
4025 goto ProcessNextMessage;
4027 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal && xevent.CrossingEvent.window != hwnd.client_window) {
4028 goto ProcessNextMessage;
4030 msg.message = Msg.WM_MOUSE_ENTER;
4031 HoverState.X = xevent.CrossingEvent.x;
4032 HoverState.Y = xevent.CrossingEvent.y;
4033 HoverState.Timer.Enabled = true;
4034 HoverState.Window = xevent.CrossingEvent.window;
4036 // Win32 sends a WM_MOUSEMOVE after mouse enter
4037 XEvent motionEvent = new XEvent ();
4038 motionEvent.type = XEventName.MotionNotify;
4039 motionEvent.MotionEvent.display = DisplayHandle;
4040 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
4041 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
4042 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
4043 hwnd.Queue.EnqueueLocked (motionEvent);
4047 case XEventName.LeaveNotify: {
4048 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
4049 WindowUngrabbed (hwnd.Handle);
4050 goto ProcessNextMessage;
4052 if (!hwnd.Enabled) {
4053 goto ProcessNextMessage;
4055 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
4056 goto ProcessNextMessage;
4059 // Reset the cursor explicitly on X11.
4060 // X11 remembers the last set cursor for the window and in cases where
4061 // the control won't get a WM_SETCURSOR X11 will restore the last
4062 // known cursor, which we don't want.
4064 SetCursor (hwnd.client_window, IntPtr.Zero);
4066 msg.message=Msg.WM_MOUSELEAVE;
4067 HoverState.Timer.Enabled = false;
4068 HoverState.Window = IntPtr.Zero;
4073 case XEventName.CreateNotify: {
4074 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
4075 msg.message = WM_CREATE;
4076 // Set up CreateStruct
4078 goto ProcessNextMessage;
4085 case XEventName.ReparentNotify: {
4086 if (hwnd.parent == null) { // Toplevel
4087 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
4088 hwnd.Reparented = true;
4090 // The location given by the event is not reliable between different wm's,
4091 // so use an alternative way of getting it.
4092 Point location = GetTopLevelWindowLocation (hwnd);
4093 hwnd.X = location.X;
4094 hwnd.Y = location.Y;
4096 if (hwnd.opacity != 0xffffffff) {
4099 opacity = (IntPtr)(Int32)hwnd.opacity;
4100 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4102 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4103 goto ProcessNextMessage;
4105 hwnd.Reparented = false;
4106 goto ProcessNextMessage;
4109 goto ProcessNextMessage;
4112 case XEventName.ConfigureNotify: {
4113 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4114 #if DriverDebugExtra
4115 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);
4118 lock (hwnd.configure_lock) {
4119 Form form = Control.FromHandle (hwnd.client_window) as Form;
4120 if (form != null && !hwnd.resizing_or_moving) {
4121 if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
4122 SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
4123 hwnd.resizing_or_moving = true;
4124 } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
4125 SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
4126 hwnd.resizing_or_moving = true;
4128 if (hwnd.resizing_or_moving)
4129 SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
4132 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4133 hwnd.configure_pending = false;
4135 // We need to adjust our client window to track the resize of whole_window
4136 if (hwnd.whole_window != hwnd.client_window)
4137 PerformNCCalc(hwnd);
4140 goto ProcessNextMessage;
4143 case XEventName.FocusIn: {
4144 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4145 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4146 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4147 // about it having focus again
4148 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4149 goto ProcessNextMessage;
4152 if (FocusWindow == IntPtr.Zero) {
4153 Control c = Control.FromHandle (hwnd.client_window);
4155 goto ProcessNextMessage;
4156 Form form = c.FindForm ();
4158 goto ProcessNextMessage;
4159 if (ActiveWindow != form.Handle) {
4160 ActiveWindow = form.Handle;
4161 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4163 goto ProcessNextMessage;
4165 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4166 Keyboard.FocusIn (FocusWindow);
4167 goto ProcessNextMessage;
4170 case XEventName.FocusOut: {
4171 // Se the comment for our FocusIn handler
4172 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4173 goto ProcessNextMessage;
4176 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4177 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4180 Keyboard.FocusOut(hwnd.client_window);
4181 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4182 goto ProcessNextMessage;
4185 case XEventName.MapNotify: {
4186 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4188 msg.message = Msg.WM_SHOWWINDOW;
4189 msg.wParam = (IntPtr) 1;
4190 // XXX we're missing the lParam..
4193 goto ProcessNextMessage;
4196 case XEventName.UnmapNotify: {
4197 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4198 hwnd.mapped = false;
4199 msg.message = Msg.WM_SHOWWINDOW;
4200 msg.wParam = (IntPtr) 0;
4201 // XXX we're missing the lParam..
4204 goto ProcessNextMessage;
4207 case XEventName.Expose: {
4210 hwnd.expose_pending = false;
4212 hwnd.nc_expose_pending = false;
4214 goto ProcessNextMessage;
4218 if (!hwnd.expose_pending) {
4219 goto ProcessNextMessage;
4222 if (!hwnd.nc_expose_pending) {
4223 goto ProcessNextMessage;
4226 switch (hwnd.border_style) {
4227 case FormBorderStyle.Fixed3D: {
4230 g = Graphics.FromHwnd(hwnd.whole_window);
4231 if (hwnd.border_static)
4232 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4234 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4239 case FormBorderStyle.FixedSingle: {
4242 g = Graphics.FromHwnd(hwnd.whole_window);
4243 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4248 #if DriverDebugExtra
4249 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);
4252 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4253 Region region = new Region (rect);
4254 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4255 msg.message = Msg.WM_NCPAINT;
4256 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4257 msg.refobject = region;
4260 #if DriverDebugExtra
4261 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);
4263 if (Caret.Visible == true) {
4264 Caret.Paused = true;
4268 if (Caret.Visible == true) {
4270 Caret.Paused = false;
4272 msg.message = Msg.WM_PAINT;
4276 case XEventName.DestroyNotify: {
4278 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4279 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4281 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4282 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4283 CleanupCachedWindows (hwnd);
4285 #if DriverDebugDestroy
4286 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4289 msg.hwnd = hwnd.client_window;
4290 msg.message=Msg.WM_DESTROY;
4293 goto ProcessNextMessage;
4299 case XEventName.ClientMessage: {
4300 if (Dnd.HandleClientMessage (ref xevent)) {
4301 goto ProcessNextMessage;
4304 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4305 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4306 goto ProcessNextMessage;
4309 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4310 msg.message = Msg.WM_MOUSEHOVER;
4311 msg.wParam = GetMousewParam(0);
4312 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4316 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4317 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4318 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4319 msg.wParam = xevent.ClientMessageEvent.ptr3;
4320 msg.lParam = xevent.ClientMessageEvent.ptr4;
4321 if (msg.message == (Msg)Msg.WM_QUIT)
4327 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4328 #if DriverDebugXEmbed
4329 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4332 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4333 XSizeHints hints = new XSizeHints();
4336 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4338 hwnd.width = hints.max_width;
4339 hwnd.height = hints.max_height;
4340 hwnd.ClientRect = Rectangle.Empty;
4341 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4345 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4346 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4347 SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
4348 msg.message = Msg.WM_CLOSE;
4352 // We should not get this, but I'll leave the code in case we need it in the future
4353 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4354 goto ProcessNextMessage;
4357 goto ProcessNextMessage;
4361 goto ProcessNextMessage;
4368 internal override bool GetText(IntPtr handle, out string text) {
4375 IntPtr prop = IntPtr.Zero;
4377 XGetWindowProperty(DisplayHandle, handle,
4378 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4379 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4381 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4382 text = Marshal.PtrToStringUni (prop, (int)nitems);
4387 // fallback on the non-_NET property
4390 textptr = IntPtr.Zero;
4392 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4393 if (textptr != IntPtr.Zero) {
4394 text = Marshal.PtrToStringAnsi(textptr);
4405 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) {
4408 hwnd = Hwnd.ObjectFromHandle(handle);
4414 height = hwnd.height;
4416 PerformNCCalc(hwnd);
4418 client_width = hwnd.ClientRect.Width;
4419 client_height = hwnd.ClientRect.Height;
4424 // Should we throw an exception or fail silently?
4425 // throw new ArgumentException("Called with an invalid window handle", "handle");
4435 internal override FormWindowState GetWindowState(IntPtr handle) {
4438 hwnd = Hwnd.ObjectFromHandle(handle);
4440 if (hwnd.cached_window_state == (FormWindowState)(-1))
4441 hwnd.cached_window_state = UpdateWindowState (handle);
4443 return hwnd.cached_window_state;
4446 private FormWindowState UpdateWindowState (IntPtr handle) {
4451 IntPtr prop = IntPtr.Zero;
4455 XWindowAttributes attributes;
4458 hwnd = Hwnd.ObjectFromHandle(handle);
4462 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);
4463 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4464 for (int i = 0; i < (long)nitems; i++) {
4465 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4466 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4468 } else if (atom == _NET_WM_STATE_HIDDEN) {
4476 return FormWindowState.Minimized;
4477 } else if (maximized == 2) {
4478 return FormWindowState.Maximized;
4481 attributes = new XWindowAttributes();
4482 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4483 if (attributes.map_state == MapState.IsUnmapped) {
4484 return (FormWindowState)(-1);
4488 return FormWindowState.Normal;
4491 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4493 GrabConfined = Grab.Confined;
4494 GrabArea = Grab.Area;
4497 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4499 IntPtr confine_to_window;
4501 confine_to_window = IntPtr.Zero;
4503 if (confine_to_handle != IntPtr.Zero) {
4504 XWindowAttributes attributes = new XWindowAttributes();
4506 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4509 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4511 Grab.Area.X = attributes.x;
4512 Grab.Area.Y = attributes.y;
4513 Grab.Area.Width = attributes.width;
4514 Grab.Area.Height = attributes.height;
4515 Grab.Confined = true;
4516 confine_to_window = hwnd.client_window;
4521 hwnd = Hwnd.ObjectFromHandle(handle);
4524 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4525 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4526 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4527 EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4528 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4532 internal override void UngrabWindow(IntPtr hwnd) {
4534 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4535 XFlush(DisplayHandle);
4537 WindowUngrabbed (hwnd);
4540 private void WindowUngrabbed (IntPtr hwnd) {
4541 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4543 Grab.Hwnd = IntPtr.Zero;
4544 Grab.Confined = false;
4547 // lparam should be the handle to the window gaining the mouse capture,
4548 // but X doesn't seem to give us that information.
4549 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4550 // X will send a NotifyUngrab, but since it comes late sometimes we're
4551 // calling WindowUngrabbed directly from UngrabWindow in order to send
4552 // this WM right away.
4553 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4557 internal override void HandleException(Exception e) {
4558 StackTrace st = new StackTrace(e, true);
4559 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4560 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4563 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4566 hwnd = Hwnd.ObjectFromHandle(handle);
4569 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4571 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4575 internal override void InvalidateNC (IntPtr handle) {
4578 hwnd = Hwnd.ObjectFromHandle(handle);
4580 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4583 internal override bool IsEnabled(IntPtr handle) {
4584 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4585 return (hwnd != null && hwnd.Enabled);
4588 internal override bool IsVisible(IntPtr handle) {
4589 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4590 return (hwnd != null && hwnd.visible);
4593 internal override void KillTimer(Timer timer) {
4594 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4596 if (queue == null) {
4597 // This isn't really an error, MS doesn't start the timer if
4598 // it has no assosciated queue. In this case, remove the timer
4599 // from the list of unattached timers (if it was enabled).
4600 lock (unattached_timer_list) {
4601 if (unattached_timer_list.Contains (timer))
4602 unattached_timer_list.Remove (timer);
4606 queue.timer_list.Remove (timer);
4609 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4615 hwnd = Hwnd.ObjectFromHandle(handle);
4618 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4625 internal override void OverrideCursor(IntPtr cursor)
4627 if (Grab.Hwnd != IntPtr.Zero) {
4628 XChangeActivePointerGrab (DisplayHandle,
4629 EventMask.ButtonMotionMask |
4630 EventMask.PointerMotionMask |
4631 EventMask.PointerMotionHintMask |
4632 EventMask.ButtonPressMask |
4633 EventMask.ButtonReleaseMask,
4634 cursor, IntPtr.Zero);
4638 OverrideCursorHandle = cursor;
4641 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4642 PaintEventArgs paint_event;
4647 // handle (and paint_hwnd) refers to the window that is should be painted.
4648 // msg.HWnd (and hwnd) refers to the window that got the paint message.
4651 hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4652 if (msg.HWnd == handle) {
4655 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4658 if (Caret.Visible == true) {
4659 Caret.Paused = true;
4666 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4668 Region clip_region = new Region ();
4669 clip_region.MakeEmpty();
4671 foreach (Rectangle r in hwnd.ClipRectangles) {
4672 clip_region.Union (r);
4675 if (hwnd.UserClip != null) {
4676 clip_region.Intersect(hwnd.UserClip);
4679 dc.Clip = clip_region;
4680 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4681 hwnd.expose_pending = false;
4683 hwnd.ClearInvalidArea();
4685 hwnd.drawing_stack.Push (paint_event);
4686 hwnd.drawing_stack.Push (dc);
4690 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4692 if (!hwnd.nc_invalid.IsEmpty) {
4693 dc.SetClip (hwnd.nc_invalid);
4694 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4696 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4698 hwnd.nc_expose_pending = false;
4700 hwnd.ClearNcInvalidArea ();
4702 hwnd.drawing_stack.Push (paint_event);
4703 hwnd.drawing_stack.Push (dc);
4709 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4712 hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4714 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4718 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4719 pe.SetGraphics (null);
4722 if (Caret.Visible == true) {
4724 Caret.Paused = false;
4728 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4729 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4730 XEventQueue queue = (XEventQueue) queue_id;
4733 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4734 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4738 if (queue.Count > 0) {
4741 // Only call UpdateMessageQueue if real events are pending
4742 // otherwise we go to sleep on the socket
4743 if (XPending(DisplayHandle) != 0) {
4744 UpdateMessageQueue((XEventQueue)queue_id);
4746 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4751 CheckTimers(queue.timer_list, DateTime.UtcNow);
4756 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4759 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4760 XEvent xevent = new XEvent ();
4761 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4763 xevent.type = XEventName.ClientMessage;
4764 xevent.ClientMessageEvent.display = DisplayHandle;
4767 xevent.ClientMessageEvent.window = hwnd.whole_window;
4769 xevent.ClientMessageEvent.window = IntPtr.Zero;
4772 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4773 xevent.ClientMessageEvent.format = 32;
4774 xevent.ClientMessageEvent.ptr1 = handle;
4775 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4776 xevent.ClientMessageEvent.ptr3 = wparam;
4777 xevent.ClientMessageEvent.ptr4 = lparam;
4780 hwnd.Queue.EnqueueLocked (xevent);
4782 ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
4787 internal override void PostQuitMessage(int exitCode) {
4788 ApplicationContext ctx = Application.MWFThread.Current.Context;
4789 Form f = ctx != null ? ctx.MainForm : null;
4791 PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4793 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4794 XFlush(DisplayHandle);
4797 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4802 internal override void RequestNCRecalc(IntPtr handle) {
4805 hwnd = Hwnd.ObjectFromHandle(handle);
4811 PerformNCCalc(hwnd);
4812 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4813 InvalidateNC(handle);
4816 internal override void ResetMouseHover(IntPtr handle) {
4819 hwnd = Hwnd.ObjectFromHandle(handle);
4824 HoverState.Timer.Enabled = true;
4825 HoverState.X = mouse_position.X;
4826 HoverState.Y = mouse_position.Y;
4827 HoverState.Window = handle;
4831 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4837 hwnd = Hwnd.ObjectFromHandle(handle);
4840 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4847 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4853 hwnd = Hwnd.ObjectFromHandle(handle);
4856 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4859 Form form = Control.FromHandle (handle) as Form;
4860 if (form != null && form.window_manager != null) {
4861 dest_y_return -= form.window_manager.TitleBarHeight;
4868 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4871 XGCValues gc_values;
4873 hwnd = Hwnd.ObjectFromHandle(handle);
4875 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4877 /* We have an invalid area in the window we're scrolling.
4878 Adjust our stored invalid rectangle to to match the scrolled amount */
4893 if (area.Contains (hwnd.Invalid))
4894 hwnd.ClearInvalidArea ();
4895 hwnd.AddInvalidArea(r);
4898 gc_values = new XGCValues();
4900 if (with_children) {
4901 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4904 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4906 Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
4907 visible_rect.Intersect (area);
4909 Rectangle dest_rect = visible_rect;
4910 dest_rect.Y += YAmount;
4911 dest_rect.X += XAmount;
4912 dest_rect.Intersect (area);
4914 Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
4915 XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y,
4916 dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
4918 Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
4919 AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
4921 XFreeGC(DisplayHandle, gc);
4924 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4928 hwnd = Hwnd.GetObjectFromWindow(handle);
4930 rect = hwnd.ClientRect;
4933 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4936 Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
4938 Rectangle dirty_area = total_area;
4941 dirty_area.Height -= valid_area.Height;
4942 else if (YAmount < 0) {
4943 dirty_area.Height -= valid_area.Height;
4944 dirty_area.Y += valid_area.Height;
4948 dirty_area.Width -= valid_area.Width;
4949 else if (XAmount < 0) {
4950 dirty_area.Width -= valid_area.Width;
4951 dirty_area.X += valid_area.Width;
4957 Rectangle GetTotalVisibleArea (IntPtr handle)
4959 Control c = Control.FromHandle (handle);
4961 Rectangle visible_area = c.ClientRectangle;
4962 visible_area.Location = c.PointToScreen (Point.Empty);
4964 for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
4965 if (!parent.IsHandleCreated || !parent.Visible)
4966 return visible_area; // Non visible, not need to finish computations
4968 Rectangle r = parent.ClientRectangle;
4969 r.Location = parent.PointToScreen (Point.Empty);
4971 visible_area.Intersect (r);
4974 // If region is null, the entire area is visible.
4975 // Get the area not obscured otherwise.
4976 Region visible_region = GetVisibleRegion (c, visible_area);
4977 if (visible_region != null) {
4978 RectangleF rectf = visible_region.GetBounds (Hwnd.GraphicsContext);
4979 visible_area = new Rectangle ((int) rectf.X, (int) rectf.Y,
4980 (int) rectf.Width, (int) rectf.Height);
4982 visible_region.Dispose ();
4985 visible_area.Location = c.PointToClient (visible_area.Location);
4986 return visible_area;
4989 // Obscured area by other toplevel windows
4990 Region GetVisibleRegion (Control c, Rectangle visible_area)
4992 Region visible_region = null;
4998 Control form = c.FindForm ();
4999 if (form == null || !form.IsHandleCreated)
5002 Hwnd hwnd = Hwnd.GetObjectFromWindow (form.Handle);
5003 IntPtr form_handle = hwnd.whole_window;
5006 XQueryTree (DisplayHandle, RootWindow, out Root, out Parent, out Children, out ChildCount);
5009 int intptr_size = Marshal.SizeOf (typeof (int));
5012 for (int i = 0; i < ChildCount; i++) {
5013 IntPtr window = new IntPtr (Marshal.ReadInt32 (Children, i * intptr_size));
5015 XWindowAttributes win_attrs = new XWindowAttributes ();
5017 XGetWindowAttributes (DisplayHandle, window, ref win_attrs);
5020 Rectangle win_area = new Rectangle (win_attrs.x, win_attrs.y,
5021 win_attrs.width, win_attrs.height);
5023 if (win_attrs.map_state != MapState.IsViewable || !win_area.IntersectsWith (visible_area))
5030 if (visible_region == null)
5031 visible_region = new Region (visible_area);
5033 visible_region.Exclude (win_area);
5038 XQueryTree (DisplayHandle, window, out Root, out Parent, out SubChildren, out SubChildCount);
5041 if (SubChildren != IntPtr.Zero) {
5042 IntPtr sub_win = new IntPtr (Marshal.ReadInt32 (SubChildren));
5045 XFree (SubChildren);
5048 if (sub_win == form_handle)
5053 if (Children != IntPtr.Zero) {
5059 return visible_region;
5062 internal override void SendAsyncMethod (AsyncMethodData method) {
5064 XEvent xevent = new XEvent ();
5066 hwnd = Hwnd.ObjectFromHandle(method.Handle);
5068 xevent.type = XEventName.ClientMessage;
5069 xevent.ClientMessageEvent.display = DisplayHandle;
5070 xevent.ClientMessageEvent.window = method.Handle;
5071 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
5072 xevent.ClientMessageEvent.format = 32;
5073 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
5075 hwnd.Queue.EnqueueLocked (xevent);
5080 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
5082 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
5085 h = Hwnd.ObjectFromHandle(hwnd);
5087 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
5088 AsyncMethodResult result;
5089 AsyncMethodData data;
5091 result = new AsyncMethodResult ();
5092 data = new AsyncMethodData ();
5095 data.Method = new WndProcDelegate (NativeWindow.WndProc);
5096 data.Args = new object[] { hwnd, message, wParam, lParam };
5097 data.Result = result;
5099 SendAsyncMethod (data);
5100 #if DriverDebug || DriverDebugThreads
5101 Console.WriteLine ("Sending {0} message across.", message);
5106 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
5109 internal override int SendInput(IntPtr handle, Queue keys) {
5110 if (handle == IntPtr.Zero)
5113 int count = keys.Count;
5114 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5116 while (keys.Count > 0) {
5118 MSG msg = (MSG)keys.Dequeue();
5120 XEvent xevent = new XEvent ();
5122 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
5123 xevent.KeyEvent.display = DisplayHandle;
5126 xevent.KeyEvent.window = hwnd.whole_window;
5128 xevent.KeyEvent.window = IntPtr.Zero;
5131 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
5133 hwnd.Queue.EnqueueLocked (xevent);
5138 internal override void SetAllowDrop (IntPtr handle, bool value)
5140 // We allow drop on all windows
5143 internal override DragDropEffects StartDrag (IntPtr handle, object data,
5144 DragDropEffects allowed_effects)
5146 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5149 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
5151 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
5154 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
5155 Form form = Control.FromHandle (handle) as Form;
5156 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
5157 border_style == FormBorderStyle.SizableToolWindow)) {
5158 form.window_manager = new ToolWindowManager (form);
5161 RequestNCRecalc(handle);
5164 internal override void SetCaretPos(IntPtr handle, int x, int y) {
5165 if (Caret.Hwnd == handle) {
5172 Keyboard.SetCaretPos (Caret, handle, x, y);
5174 if (Caret.Visible == true) {
5176 Caret.Timer.Start();
5181 internal override void SetClipRegion(IntPtr handle, Region region) {
5184 hwnd = Hwnd.ObjectFromHandle(handle);
5189 hwnd.UserClip = region;
5192 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
5195 if (OverrideCursorHandle == IntPtr.Zero) {
5196 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
5200 LastCursorHandle = cursor;
5201 LastCursorWindow = handle;
5203 hwnd = Hwnd.ObjectFromHandle(handle);
5205 if (cursor != IntPtr.Zero) {
5206 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
5208 XUndefineCursor(DisplayHandle, hwnd.whole_window);
5210 XFlush(DisplayHandle);
5215 hwnd = Hwnd.ObjectFromHandle(handle);
5217 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
5221 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
5222 out int root_x, out int root_y, out int child_x, out int child_y,
5225 /* this code was written with the help of
5226 glance at gdk. I never would have realized we
5227 needed a loop in order to traverse down in the
5228 hierarchy. I would have assumed you'd get the
5229 most deeply nested child and have to do
5230 XQueryTree to move back up the hierarchy..
5231 stupid me, of course. */
5234 XGrabServer (display);
5236 XQueryPointer(display, w, out root, out c,
5237 out root_x, out root_y, out child_x, out child_y,
5243 IntPtr child_last = IntPtr.Zero;
5244 while (c != IntPtr.Zero) {
5246 XQueryPointer(display, c, out root, out c,
5247 out root_x, out root_y, out child_x, out child_y,
5250 XUngrabServer (display);
5256 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5257 if (handle == IntPtr.Zero) {
5260 int root_x, root_y, child_x, child_y, mask;
5263 * QueryPointer before warping
5264 * because if the warp is on
5265 * the RootWindow, the x/y are
5266 * relative to the current
5269 QueryPointer (DisplayHandle, RootWindow,
5272 out root_x, out root_y,
5273 out child_x, out child_y,
5276 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5278 XFlush (DisplayHandle);
5280 /* then we need to a
5281 * QueryPointer after warping
5282 * to manually generate a
5283 * motion event for the window
5286 QueryPointer (DisplayHandle, RootWindow,
5289 out root_x, out root_y,
5290 out child_x, out child_y,
5293 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5294 if (child_hwnd == null) {
5298 XEvent xevent = new XEvent ();
5300 xevent.type = XEventName.MotionNotify;
5301 xevent.MotionEvent.display = DisplayHandle;
5302 xevent.MotionEvent.window = child_hwnd.client_window;
5303 xevent.MotionEvent.root = RootWindow;
5304 xevent.MotionEvent.x = child_x;
5305 xevent.MotionEvent.y = child_y;
5306 xevent.MotionEvent.x_root = root_x;
5307 xevent.MotionEvent.y_root = root_y;
5308 xevent.MotionEvent.state = mask;
5310 child_hwnd.Queue.EnqueueLocked (xevent);
5315 hwnd = Hwnd.ObjectFromHandle(handle);
5317 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5322 internal override void SetFocus(IntPtr handle) {
5324 IntPtr prev_focus_window;
5326 hwnd = Hwnd.ObjectFromHandle(handle);
5328 if (hwnd.client_window == FocusWindow) {
5332 // Win32 doesn't do anything if disabled
5336 prev_focus_window = FocusWindow;
5337 FocusWindow = hwnd.client_window;
5339 if (prev_focus_window != IntPtr.Zero) {
5340 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5342 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5343 Keyboard.FocusIn (FocusWindow);
5345 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5348 internal override void SetIcon(IntPtr handle, Icon icon) {
5351 hwnd = Hwnd.ObjectFromHandle(handle);
5353 SetIcon(hwnd, icon);
5357 internal override void SetMenu(IntPtr handle, Menu menu) {
5360 hwnd = Hwnd.ObjectFromHandle(handle);
5363 RequestNCRecalc(handle);
5366 internal override void SetModal(IntPtr handle, bool Modal) {
5368 ModalWindows.Push(handle);
5370 if (ModalWindows.Contains(handle)) {
5373 if (ModalWindows.Count > 0) {
5374 Activate((IntPtr)ModalWindows.Peek());
5378 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5379 Control ctrl = Control.FromHandle (handle);
5380 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5383 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5386 hwnd = Hwnd.ObjectFromHandle(handle);
5387 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5390 #if DriverDebug || DriverDebugParent
5391 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5393 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5399 internal override void SetTimer (Timer timer) {
5400 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5402 if (queue == null) {
5403 // This isn't really an error, MS doesn't start the timer if
5404 // it has no assosciated queue at this stage (it will be
5405 // enabled when a window is activated).
5406 unattached_timer_list.Add (timer);
5409 queue.timer_list.Add (timer);
5413 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5415 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5419 int[] atoms = new int[8];
5420 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5421 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5425 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5431 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5435 hwnd = Hwnd.ObjectFromHandle(handle);
5437 if (handle_owner != IntPtr.Zero) {
5438 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5444 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5445 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5447 if (hwnd_owner != null) {
5448 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5450 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5455 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5461 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5465 hwnd = Hwnd.ObjectFromHandle(handle);
5466 hwnd.visible = visible;
5470 MapWindow(hwnd, WindowType.Both);
5472 if (Control.FromHandle(handle) is Form) {
5475 s = ((Form)Control.FromHandle(handle)).WindowState;
5478 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5479 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5483 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5486 UnmapWindow(hwnd, WindowType.Both);
5492 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5493 Control ctrl = Control.FromHandle (handle);
5494 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5497 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5503 hwnd = Hwnd.ObjectFromHandle(handle);
5508 min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
5509 min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
5511 hints = new XSizeHints();
5513 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5514 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5516 min = TranslateWindowSizeToXWindowSize (cp, min);
5517 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5518 hints.min_width = min.Width;
5519 hints.min_height = min.Height;
5522 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5524 max = TranslateWindowSizeToXWindowSize (cp, max);
5525 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5526 hints.max_width = max.Width;
5527 hints.max_height = max.Height;
5530 if (hints.flags != IntPtr.Zero) {
5531 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5532 // they will maximize the window to fill the screen/parent no matter what.
5533 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5534 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5537 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5539 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5540 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5541 hints.x = maximized.X;
5542 hints.y = maximized.Y;
5543 hints.width = maximized.Width;
5544 hints.height = maximized.Height;
5546 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5547 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5552 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5555 hwnd = Hwnd.ObjectFromHandle(handle);
5561 // Win32 automatically changes negative width/height to 0.
5567 // X requires a sanity check for width & height; otherwise it dies
5568 if (hwnd.zero_sized && width > 0 && height > 0) {
5570 MapWindow(hwnd, WindowType.Whole);
5572 hwnd.zero_sized = false;
5575 if ((width < 1) || (height < 1)) {
5576 hwnd.zero_sized = true;
5577 UnmapWindow(hwnd, WindowType.Whole);
5580 // Save a server roundtrip (and prevent a feedback loop)
5581 if ((hwnd.x == x) && (hwnd.y == y) &&
5582 (hwnd.width == width) && (hwnd.height == height)) {
5586 if (!hwnd.zero_sized) {
5591 hwnd.height = height;
5592 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5594 if (hwnd.fixed_size) {
5595 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5599 Control ctrl = Control.FromHandle (handle);
5600 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5601 MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5602 PerformNCCalc(hwnd);
5606 // Update our position/size immediately, so
5607 // that future calls to SetWindowPos aren't
5608 // kept from calling XMoveResizeWindow (by the
5609 // "Save a server roundtrip" block above).
5613 hwnd.height = height;
5614 hwnd.ClientRect = Rectangle.Empty;
5617 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5618 FormWindowState current_state;
5621 hwnd = Hwnd.ObjectFromHandle(handle);
5623 current_state = GetWindowState(handle);
5625 if (current_state == state) {
5630 case FormWindowState.Normal: {
5632 if (current_state == FormWindowState.Minimized) {
5633 MapWindow(hwnd, WindowType.Both);
5634 } else if (current_state == FormWindowState.Maximized) {
5635 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5642 case FormWindowState.Minimized: {
5644 if (current_state == FormWindowState.Maximized) {
5645 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5647 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5652 case FormWindowState.Maximized: {
5654 if (current_state == FormWindowState.Minimized) {
5655 MapWindow(hwnd, WindowType.Both);
5658 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5666 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5669 hwnd = Hwnd.ObjectFromHandle(handle);
5670 SetHwndStyles(hwnd, cp);
5671 SetWMStyles(hwnd, cp);
5674 internal override double GetWindowTransparency(IntPtr handle)
5679 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5683 hwnd = Hwnd.ObjectFromHandle(handle);
5689 hwnd.opacity = (uint)(0xffffffff * transparency);
5690 opacity = (IntPtr)((int)hwnd.opacity);
5692 IntPtr w = hwnd.whole_window;
5693 if (hwnd.reparented)
5694 w = XGetParent (hwnd.whole_window);
5695 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5698 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5699 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5707 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5710 } else if (!bottom) {
5711 Hwnd after_hwnd = null;
5713 if (after_handle != IntPtr.Zero) {
5714 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5717 XWindowChanges values = new XWindowChanges();
5719 if (after_hwnd == null) {
5720 // Work around metacity 'issues'
5724 atoms[0] = unixtime();
5725 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5727 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5728 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5730 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5733 values.sibling = after_hwnd.whole_window;
5734 values.stack_mode = StackMode.Below;
5737 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5742 XLowerWindow(DisplayHandle, hwnd.whole_window);
5749 internal override void ShowCursor(bool show) {
5750 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5753 internal override object StartLoop(Thread thread) {
5754 XEventQueue q = ThreadQueue(thread);
5758 internal override TransparencySupport SupportsTransparency() {
5759 // We need to check if the x compositing manager is running
5760 return TransparencySupport.Set;
5763 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5764 GetSystrayManagerWindow();
5766 if (SystrayMgrWindow != IntPtr.Zero) {
5767 XSizeHints size_hints;
5770 hwnd = Hwnd.ObjectFromHandle(handle);
5772 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5776 if (hwnd.client_window != hwnd.whole_window) {
5777 Keyboard.DestroyICForWindow (hwnd.client_window);
5778 XDestroyWindow(DisplayHandle, hwnd.client_window);
5779 hwnd.client_window = hwnd.whole_window;
5782 /* by virtue of the way the tests are ordered when determining if it's PAINT
5783 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5784 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5785 there's a pending expose). */
5786 if (hwnd.nc_expose_pending) {
5787 hwnd.nc_expose_pending = false;
5788 if (!hwnd.expose_pending)
5789 hwnd.Queue.Paint.Remove (hwnd);
5792 size_hints = new XSizeHints();
5794 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5796 size_hints.min_width = 24;
5797 size_hints.min_height = 24;
5798 size_hints.max_width = 24;
5799 size_hints.max_height = 24;
5800 size_hints.base_width = 24;
5801 size_hints.base_height = 24;
5803 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5805 int[] atoms = new int[2];
5806 atoms [0] = 1; // Version 1
5807 atoms [1] = 1; // we want to be mapped
5809 // This line cost me 3 days...
5810 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5812 // Need to pick some reasonable defaults
5814 tt.AutomaticDelay = 350;
5815 tt.InitialDelay = 250;
5816 tt.ReshowDelay = 250;
5817 tt.ShowAlways = true;
5819 if ((tip != null) && (tip != string.Empty)) {
5820 tt.SetToolTip(Control.FromHandle(handle), tip);
5826 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5834 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5837 control = Control.FromHandle(handle);
5838 if (control != null && tt != null) {
5839 tt.SetToolTip(control, tip);
5841 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5848 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5850 SetVisible (handle, false, false);
5852 // The caller can now re-dock it later...
5860 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5862 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5863 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5867 internal override bool Text(IntPtr handle, string text) {
5870 hwnd = Hwnd.ObjectFromHandle(handle);
5873 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5874 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5876 // XXX this has problems with UTF8.
5877 // we need to either use the actual
5878 // text if it's latin-1, or convert it
5879 // to compound text if it's in a
5880 // different charset.
5881 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5886 internal override bool TranslateMessage(ref MSG msg) {
5887 return Keyboard.TranslateMessage (ref msg);
5890 internal override void UpdateWindow(IntPtr handle) {
5893 hwnd = Hwnd.ObjectFromHandle(handle);
5895 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5899 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5900 hwnd.Queue.Paint.Remove(hwnd);
5903 internal override void CreateOffscreenDrawable (IntPtr handle,
5904 int width, int height,
5905 out object offscreen_drawable)
5908 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5910 XGetGeometry (DisplayHandle, handle,
5912 out x_out, out y_out,
5913 out width_out, out height_out,
5914 out border_width_out, out depth_out);
5916 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5918 offscreen_drawable = pixmap;
5922 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5924 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5927 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5929 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5932 internal override void BlitFromOffscreen (IntPtr dest_handle,
5934 object offscreen_drawable,
5935 Graphics offscreen_dc,
5938 XGCValues gc_values;
5941 gc_values = new XGCValues();
5943 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5945 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5946 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5948 XFreeGC (DisplayHandle, gc);
5951 #endregion // Public Static Methods
5954 internal override event EventHandler Idle;
5955 #endregion // Events
5957 #region Xcursor imports
5958 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5959 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5961 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5962 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5964 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5965 internal extern static void XcursorImagesDestroy (IntPtr images);
5967 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5968 internal extern static int XcursorGetDefaultSize (IntPtr display);
5970 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5971 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5973 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5974 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5977 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5978 internal extern static IntPtr XOpenDisplay(IntPtr display);
5979 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5980 internal extern static int XCloseDisplay(IntPtr display);
5981 [DllImport ("libX11", EntryPoint="XSynchronize")]
5982 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5984 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5985 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);
5986 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5987 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5988 [DllImport ("libX11", EntryPoint="XMapWindow")]
5989 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5990 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5991 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5992 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5993 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5994 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5995 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5996 [DllImport ("libX11", EntryPoint="XRootWindow")]
5997 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5998 [DllImport ("libX11", EntryPoint="XNextEvent")]
5999 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
6000 [DllImport ("libX11")]
6001 internal extern static int XConnectionNumber (IntPtr diplay);
6002 [DllImport ("libX11")]
6003 internal extern static int XPending (IntPtr diplay);
6004 [DllImport ("libX11", EntryPoint="XSelectInput")]
6005 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
6007 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
6008 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
6010 [DllImport ("libX11", EntryPoint="XReparentWindow")]
6011 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
6012 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
6013 private extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
6015 internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
6017 int ret = XMoveResizeWindow (display, window, x, y, width, height);
6018 Keyboard.MoveCurrentCaretPos ();
6022 [DllImport ("libX11", EntryPoint="XResizeWindow")]
6023 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
6025 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
6026 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
6028 [DllImport ("libX11", EntryPoint="XFlush")]
6029 internal extern static int XFlush(IntPtr display);
6031 [DllImport ("libX11", EntryPoint="XSetWMName")]
6032 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
6034 [DllImport ("libX11", EntryPoint="XStoreName")]
6035 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
6037 [DllImport ("libX11", EntryPoint="XFetchName")]
6038 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
6040 [DllImport ("libX11", EntryPoint="XSendEvent")]
6041 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
6043 [DllImport ("libX11", EntryPoint="XQueryTree")]
6044 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);
6046 [DllImport ("libX11", EntryPoint="XFree")]
6047 internal extern static int XFree(IntPtr data);
6049 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
6050 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
6052 [DllImport ("libX11", EntryPoint="XLowerWindow")]
6053 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
6055 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
6056 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
6058 [DllImport ("libX11", EntryPoint="XInternAtom")]
6059 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
6061 [DllImport ("libX11", EntryPoint="XInternAtoms")]
6062 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
6064 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
6065 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
6067 [DllImport ("libX11", EntryPoint="XGrabPointer")]
6068 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);
6070 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
6071 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
6073 [DllImport ("libX11", EntryPoint="XQueryPointer")]
6074 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);
6076 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
6077 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);
6079 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6080 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);
6082 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6083 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);
6085 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6086 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);
6088 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6089 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);
6091 [DllImport ("libX11", EntryPoint="XWarpPointer")]
6092 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);
6094 [DllImport ("libX11", EntryPoint="XClearWindow")]
6095 internal extern static int XClearWindow(IntPtr display, IntPtr window);
6097 [DllImport ("libX11", EntryPoint="XClearArea")]
6098 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
6101 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
6102 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
6104 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
6105 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
6107 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
6108 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
6110 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
6111 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
6113 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
6114 internal extern static int XDefaultScreen(IntPtr display);
6116 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
6117 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
6119 [DllImport ("libX11", EntryPoint="XLookupColor")]
6120 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
6122 [DllImport ("libX11", EntryPoint="XAllocColor")]
6123 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
6125 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
6126 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
6128 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6129 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
6131 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6132 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
6134 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6135 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
6137 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6138 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
6140 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6141 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
6143 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6144 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
6146 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6147 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
6149 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
6150 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
6152 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
6153 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
6156 [DllImport ("libX11", EntryPoint="XCreateGC")]
6157 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
6159 [DllImport ("libX11", EntryPoint="XFreeGC")]
6160 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
6162 [DllImport ("libX11", EntryPoint="XSetFunction")]
6163 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
6165 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
6166 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
6168 [DllImport ("libX11", EntryPoint="XDrawLine")]
6169 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
6171 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
6172 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6174 [DllImport ("libX11", EntryPoint="XFillRectangle")]
6175 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6177 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
6178 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
6180 [DllImport ("libX11", EntryPoint="XCopyArea")]
6181 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);
6183 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
6184 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);
6186 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
6187 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
6189 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
6190 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
6192 [DllImport ("libX11", EntryPoint="XDefineCursor")]
6193 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
6195 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
6196 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
6198 [DllImport ("libX11", EntryPoint="XFreeCursor")]
6199 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
6201 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
6202 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
6204 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
6205 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);
6207 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
6208 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
6210 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
6211 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
6213 [DllImport ("libX11", EntryPoint="XFreePixmap")]
6214 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
6216 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
6217 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
6219 [DllImport ("libX11", EntryPoint="XQueryExtension")]
6220 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
6222 [DllImport ("libX11", EntryPoint="XWhitePixel")]
6223 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
6225 [DllImport ("libX11", EntryPoint="XBlackPixel")]
6226 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
6228 [DllImport ("libX11", EntryPoint="XGrabServer")]
6229 internal extern static void XGrabServer(IntPtr display);
6231 [DllImport ("libX11", EntryPoint="XUngrabServer")]
6232 internal extern static void XUngrabServer(IntPtr display);
6234 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
6235 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
6237 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
6238 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6240 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
6241 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6243 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6244 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6246 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6247 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6249 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6250 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6252 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6253 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6255 [DllImport ("libX11", EntryPoint="XInitThreads")]
6256 internal extern static int XInitThreads();
6258 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6259 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6261 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6262 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6264 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6265 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6267 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6268 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6270 [DllImport ("libX11", EntryPoint="XSetForeground")]
6271 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6273 [DllImport ("libX11", EntryPoint="XSetBackground")]
6274 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6276 [DllImport ("libX11", EntryPoint="XBell")]
6277 internal extern static int XBell(IntPtr display, int percent);
6279 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6280 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6282 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6283 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6285 [DllImport ("libX11")]
6286 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6288 [DllImport ("libX11")]
6289 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);