1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
90 private int render_major_opcode;
91 private int render_first_event;
92 private int render_first_error;
95 private static IntPtr ClipMagic;
96 private static ClipboardStruct Clipboard; // Our clipboard
99 private static IntPtr PostAtom; // PostMessage atom
100 private static IntPtr AsyncAtom; // Support for async messages
103 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
105 private static Pollfd[] pollfds; // For watching the X11 socket
106 private static bool wake_waiting;
107 private static object wake_waiting_lock = new object ();
109 private static X11Keyboard Keyboard; //
110 private static X11Dnd Dnd;
111 private static Socket listen; //
112 private static Socket wake; //
113 private static Socket wake_receive; //
114 private static byte[] network_buffer; //
115 private static bool detectable_key_auto_repeat;
118 private static IntPtr ActiveWindow; // Handle of the active window
119 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
122 private static Stack ModalWindows; // Stack of our modal windows
125 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
128 private static IntPtr LastCursorWindow; // The last window we set the cursor on
129 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
130 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
133 private static CaretStruct Caret; //
136 private static IntPtr WM_PROTOCOLS;
137 private static IntPtr WM_DELETE_WINDOW;
138 private static IntPtr WM_TAKE_FOCUS;
139 //private static IntPtr _NET_SUPPORTED;
140 //private static IntPtr _NET_CLIENT_LIST;
141 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
142 private static IntPtr _NET_DESKTOP_GEOMETRY;
143 //private static IntPtr _NET_DESKTOP_VIEWPORT;
144 private static IntPtr _NET_CURRENT_DESKTOP;
145 //private static IntPtr _NET_DESKTOP_NAMES;
146 private static IntPtr _NET_ACTIVE_WINDOW;
147 private static IntPtr _NET_WORKAREA;
148 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
149 //private static IntPtr _NET_VIRTUAL_ROOTS;
150 //private static IntPtr _NET_DESKTOP_LAYOUT;
151 //private static IntPtr _NET_SHOWING_DESKTOP;
152 //private static IntPtr _NET_CLOSE_WINDOW;
153 //private static IntPtr _NET_MOVERESIZE_WINDOW;
154 //private static IntPtr _NET_WM_MOVERESIZE;
155 //private static IntPtr _NET_RESTACK_WINDOW;
156 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
157 private static IntPtr _NET_WM_NAME;
158 //private static IntPtr _NET_WM_VISIBLE_NAME;
159 //private static IntPtr _NET_WM_ICON_NAME;
160 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
161 //private static IntPtr _NET_WM_DESKTOP;
162 private static IntPtr _NET_WM_WINDOW_TYPE;
163 private static IntPtr _NET_WM_STATE;
164 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
165 //private static IntPtr _NET_WM_STRUT;
166 //private static IntPtr _NET_WM_STRUT_PARTIAL;
167 //private static IntPtr _NET_WM_ICON_GEOMETRY;
168 private static IntPtr _NET_WM_ICON;
169 //private static IntPtr _NET_WM_PID;
170 //private static IntPtr _NET_WM_HANDLED_ICONS;
171 private static IntPtr _NET_WM_USER_TIME;
172 private static IntPtr _NET_FRAME_EXTENTS;
173 //private static IntPtr _NET_WM_PING;
174 //private static IntPtr _NET_WM_SYNC_REQUEST;
175 private static IntPtr _NET_SYSTEM_TRAY_S;
176 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
177 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
178 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
179 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
180 private static IntPtr _XEMBED;
181 private static IntPtr _XEMBED_INFO;
182 private static IntPtr _MOTIF_WM_HINTS;
183 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
184 private static IntPtr _NET_WM_STATE_ABOVE;
185 private static IntPtr _NET_WM_STATE_MODAL;
186 private static IntPtr _NET_WM_STATE_HIDDEN;
187 private static IntPtr _NET_WM_CONTEXT_HELP;
188 private static IntPtr _NET_WM_WINDOW_OPACITY;
189 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
190 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
193 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
194 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
195 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
196 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
197 private static IntPtr CLIPBOARD;
198 private static IntPtr PRIMARY;
199 //private static IntPtr DIB;
200 private static IntPtr OEMTEXT;
201 private static IntPtr UNICODETEXT;
202 private static IntPtr TARGETS;
204 // mouse hover message generation
205 private static HoverStruct HoverState; //
207 // double click message generation
208 private static ClickStruct ClickPending; //
210 // Support for mouse grab
211 private static GrabStruct Grab; //
214 Point mouse_position; // Last position of mouse, in screen coords
215 internal static MouseButtons MouseState; // Last state of mouse buttons
218 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
220 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
221 EventMask.ButtonReleaseMask |
222 EventMask.KeyPressMask |
223 EventMask.KeyReleaseMask |
224 EventMask.EnterWindowMask |
225 EventMask.LeaveWindowMask |
226 EventMask.ExposureMask |
227 EventMask.FocusChangeMask |
228 EventMask.PointerMotionMask |
229 EventMask.PointerMotionHintMask |
230 EventMask.SubstructureNotifyMask);
232 static readonly object lockobj = new object ();
234 #endregion // Local Variables
236 private XplatUIX11() {
237 // Handle singleton stuff first
240 // Now regular initialization
241 XlibLock = new object ();
242 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
245 ErrorExceptions = false;
247 // X11 Initialization
248 SetDisplay(XOpenDisplay(IntPtr.Zero));
249 X11DesktopColors.Initialize();
252 // Disable keyboard autorepeat
254 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
255 detectable_key_auto_repeat = true;
257 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
258 detectable_key_auto_repeat = false;
261 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
262 ErrorHandler = new XErrorHandler(HandleError);
263 XSetErrorHandler(ErrorHandler);
267 // Remove our display handle from S.D
268 Graphics.FromHdcInternal (IntPtr.Zero);
271 #endregion // Constructors
273 #region Singleton Specific Code
274 public static XplatUIX11 GetInstance() {
276 if (Instance == null) {
277 Instance=new XplatUIX11();
284 public int Reference {
291 #region Internal Properties
292 internal static IntPtr Display {
294 return DisplayHandle;
298 XplatUIX11.GetInstance().SetDisplay(value);
302 internal static int Screen {
312 internal static IntPtr RootWindowHandle {
322 internal static IntPtr Visual {
328 CustomVisual = value;
332 internal static IntPtr ColorMap {
334 return CustomColormap;
338 CustomColormap = value;
343 #region XExceptionClass
344 internal class XException : ApplicationException {
348 XRequest RequestCode;
352 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
353 this.Display = Display;
354 this.ResourceID = ResourceID;
355 this.Serial = Serial;
356 this.RequestCode = RequestCode;
357 this.ErrorCode = ErrorCode;
358 this.MinorCode = MinorCode;
361 public override string Message {
363 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
367 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
376 sb = new StringBuilder(160);
377 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
378 x_error_text = sb.ToString();
379 hwnd = Hwnd.ObjectFromHandle(ResourceID);
381 hwnd_text = hwnd.ToString();
382 c = Control.FromHandle(hwnd.Handle);
384 control_text = c.ToString();
386 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
389 hwnd_text = "<null>";
390 control_text = "<null>";
394 error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
398 #endregion // XExceptionClass
400 #region Internal Methods
401 internal void SetDisplay(IntPtr display_handle) {
402 if (display_handle != IntPtr.Zero) {
405 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
406 hwnd = Hwnd.ObjectFromHandle(FosterParent);
407 XDestroyWindow(DisplayHandle, FosterParent);
411 if (DisplayHandle != IntPtr.Zero) {
412 XCloseDisplay(DisplayHandle);
415 DisplayHandle=display_handle;
417 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
418 // been hacked to do this for us.
419 Graphics.FromHdcInternal (DisplayHandle);
421 // query for the render extension so
422 // we can ignore the spurious
423 // BadPicture errors that are
424 // generated by cairo/render.
425 XQueryExtension (DisplayHandle, "RENDER",
426 ref render_major_opcode, ref render_first_event, ref render_first_error);
429 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
430 XSynchronize(DisplayHandle, true);
433 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
434 ErrorExceptions = true;
438 ScreenNo = XDefaultScreen(DisplayHandle);
439 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
440 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
442 // Create the foster parent
443 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
444 if (FosterParent==IntPtr.Zero) {
445 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
449 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
450 hwnd.WholeWindow = FosterParent;
451 hwnd.ClientWindow = FosterParent;
453 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
455 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
456 hwnd.whole_window = RootWindow;
457 hwnd.ClientWindow = RootWindow;
459 // For sleeping on the X11 socket
460 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
461 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
465 // To wake up when a timer is ready
466 network_buffer = new byte[10];
468 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
469 wake.Connect(listen.LocalEndPoint);
470 wake_receive = listen.Accept();
473 pollfds = new Pollfd [2];
474 pollfds [0] = new Pollfd ();
475 pollfds [0].fd = XConnectionNumber (DisplayHandle);
476 pollfds [0].events = PollEvents.POLLIN;
478 pollfds [1] = new Pollfd ();
479 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
480 pollfds [1].events = PollEvents.POLLIN;
483 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
484 Dnd = new X11Dnd (DisplayHandle, Keyboard);
486 DoubleClickInterval = 500;
488 HoverState.Interval = 500;
489 HoverState.Timer = new Timer();
490 HoverState.Timer.Enabled = false;
491 HoverState.Timer.Interval = HoverState.Interval;
492 HoverState.Timer.Tick += new EventHandler(MouseHover);
493 HoverState.Size = new Size(4, 4);
497 ActiveWindow = IntPtr.Zero;
498 FocusWindow = IntPtr.Zero;
499 ModalWindows = new Stack(3);
501 MouseState = MouseButtons.None;
502 mouse_position = new Point(0, 0);
504 Caret.Timer = new Timer();
505 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
506 Caret.Timer.Tick += new EventHandler(CaretCallback);
510 // Grab atom changes off the root window to catch certain WM events
511 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
513 // Handle any upcoming errors
514 ErrorHandler = new XErrorHandler(HandleError);
515 XSetErrorHandler(ErrorHandler);
517 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
520 #endregion // Internal Methods
522 #region Private Methods
523 private int unixtime() {
524 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
526 return (int) t.TotalSeconds;
529 private static void SetupAtoms() {
530 // make sure this array stays in sync with the statements below
531 string [] atom_names = new string[] {
536 //"_NET_CLIENT_LIST",
537 //"_NET_NUMBER_OF_DESKTOPS",
538 "_NET_DESKTOP_GEOMETRY",
539 //"_NET_DESKTOP_VIEWPORT",
540 "_NET_CURRENT_DESKTOP",
541 //"_NET_DESKTOP_NAMES",
542 "_NET_ACTIVE_WINDOW",
544 //"_NET_SUPPORTING_WM_CHECK",
545 //"_NET_VIRTUAL_ROOTS",
546 //"_NET_DESKTOP_LAYOUT",
547 //"_NET_SHOWING_DESKTOP",
548 //"_NET_CLOSE_WINDOW",
549 //"_NET_MOVERESIZE_WINDOW",
550 //"_NET_WM_MOVERESIZE",
551 //"_NET_RESTACK_WINDOW",
552 //"_NET_REQUEST_FRAME_EXTENTS",
554 //"_NET_WM_VISIBLE_NAME",
555 //"_NET_WM_ICON_NAME",
556 //"_NET_WM_VISIBLE_ICON_NAME",
558 "_NET_WM_WINDOW_TYPE",
560 //"_NET_WM_ALLOWED_ACTIONS",
562 //"_NET_WM_STRUT_PARTIAL",
563 //"_NET_WM_ICON_GEOMETRY",
566 //"_NET_WM_HANDLED_ICONS",
568 "_NET_FRAME_EXTENTS",
570 //"_NET_WM_SYNC_REQUEST",
571 "_NET_SYSTEM_TRAY_OPCODE",
572 //"_NET_SYSTEM_TRAY_ORIENTATION",
573 "_NET_WM_STATE_MAXIMIZED_HORZ",
574 "_NET_WM_STATE_MAXIMIZED_VERT",
575 "_NET_WM_STATE_HIDDEN",
579 "_NET_WM_STATE_SKIP_TASKBAR",
580 "_NET_WM_STATE_ABOVE",
581 "_NET_WM_STATE_MODAL",
582 "_NET_WM_CONTEXT_HELP",
583 "_NET_WM_WINDOW_OPACITY",
584 //"_NET_WM_WINDOW_TYPE_DESKTOP",
585 //"_NET_WM_WINDOW_TYPE_DOCK",
586 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
587 //"_NET_WM_WINDOW_TYPE_MENU",
588 "_NET_WM_WINDOW_TYPE_UTILITY",
589 "_NET_WM_WINDOW_TYPE_DIALOG",
590 //"_NET_WM_WINDOW_TYPE_SPLASH",
591 "_NET_WM_WINDOW_TYPE_NORMAL",
598 "_SWF_PostMessageAtom",
601 IntPtr[] atoms = new IntPtr [atom_names.Length];;
603 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
606 WM_PROTOCOLS = atoms [off++];
607 WM_DELETE_WINDOW = atoms [off++];
608 WM_TAKE_FOCUS = atoms [off++];
609 //_NET_SUPPORTED = atoms [off++];
610 //_NET_CLIENT_LIST = atoms [off++];
611 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
612 _NET_DESKTOP_GEOMETRY = atoms [off++];
613 //_NET_DESKTOP_VIEWPORT = atoms [off++];
614 _NET_CURRENT_DESKTOP = atoms [off++];
615 //_NET_DESKTOP_NAMES = atoms [off++];
616 _NET_ACTIVE_WINDOW = atoms [off++];
617 _NET_WORKAREA = atoms [off++];
618 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
619 //_NET_VIRTUAL_ROOTS = atoms [off++];
620 //_NET_DESKTOP_LAYOUT = atoms [off++];
621 //_NET_SHOWING_DESKTOP = atoms [off++];
622 //_NET_CLOSE_WINDOW = atoms [off++];
623 //_NET_MOVERESIZE_WINDOW = atoms [off++];
624 //_NET_WM_MOVERESIZE = atoms [off++];
625 //_NET_RESTACK_WINDOW = atoms [off++];
626 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
627 _NET_WM_NAME = atoms [off++];
628 //_NET_WM_VISIBLE_NAME = atoms [off++];
629 //_NET_WM_ICON_NAME = atoms [off++];
630 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
631 //_NET_WM_DESKTOP = atoms [off++];
632 _NET_WM_WINDOW_TYPE = atoms [off++];
633 _NET_WM_STATE = atoms [off++];
634 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
635 //_NET_WM_STRUT = atoms [off++];
636 //_NET_WM_STRUT_PARTIAL = atoms [off++];
637 //_NET_WM_ICON_GEOMETRY = atoms [off++];
638 _NET_WM_ICON = atoms [off++];
639 //_NET_WM_PID = atoms [off++];
640 //_NET_WM_HANDLED_ICONS = atoms [off++];
641 _NET_WM_USER_TIME = atoms [off++];
642 _NET_FRAME_EXTENTS = atoms [off++];
643 //_NET_WM_PING = atoms [off++];
644 //_NET_WM_SYNC_REQUEST = atoms [off++];
645 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
646 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
647 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
648 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
649 _NET_WM_STATE_HIDDEN = atoms [off++];
650 _XEMBED = atoms [off++];
651 _XEMBED_INFO = atoms [off++];
652 _MOTIF_WM_HINTS = atoms [off++];
653 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
654 _NET_WM_STATE_ABOVE = atoms [off++];
655 _NET_WM_STATE_MODAL = atoms [off++];
656 _NET_WM_CONTEXT_HELP = atoms [off++];
657 _NET_WM_WINDOW_OPACITY = atoms [off++];
658 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
659 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
660 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
661 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
662 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
663 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
664 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
665 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
666 CLIPBOARD = atoms [off++];
667 PRIMARY = atoms [off++];
668 OEMTEXT = atoms [off++];
669 UNICODETEXT = atoms [off++];
670 TARGETS = atoms [off++];
671 AsyncAtom = atoms [off++];
672 PostAtom = atoms [off++];
673 HoverState.Atom = atoms [off++];
675 //DIB = (IntPtr)Atom.XA_PIXMAP;
676 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
679 private void GetSystrayManagerWindow() {
680 XGrabServer(DisplayHandle);
681 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
682 XUngrabServer(DisplayHandle);
683 XFlush(DisplayHandle);
686 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
690 xev.ClientMessageEvent.type = XEventName.ClientMessage;
691 xev.ClientMessageEvent.send_event = true;
692 xev.ClientMessageEvent.window = window;
693 xev.ClientMessageEvent.message_type = message_type;
694 xev.ClientMessageEvent.format = 32;
695 xev.ClientMessageEvent.ptr1 = l0;
696 xev.ClientMessageEvent.ptr2 = l1;
697 xev.ClientMessageEvent.ptr3 = l2;
698 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
701 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
705 xev.ClientMessageEvent.type = XEventName.ClientMessage;
706 xev.ClientMessageEvent.send_event = true;
707 xev.ClientMessageEvent.window = window;
708 xev.ClientMessageEvent.message_type = message_type;
709 xev.ClientMessageEvent.format = 32;
710 xev.ClientMessageEvent.ptr1 = l0;
711 xev.ClientMessageEvent.ptr2 = l1;
712 xev.ClientMessageEvent.ptr3 = l2;
713 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
716 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
717 // WM_CREATE and WM_DESTROY causes
718 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
722 if (child == IntPtr.Zero) {
726 hwnd = Hwnd.GetObjectFromWindow (child);
732 if (hwnd.Handle == IntPtr.Zero) {
736 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
740 if (hwnd.Parent == null) {
744 if (hwnd.Parent.Handle == IntPtr.Zero) {
748 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
749 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
751 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
754 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
757 bool StyleSet (int s, WindowStyles ws)
759 return (s & (int)ws) == (int)ws;
762 bool ExStyleSet (int ex, WindowExStyles exws)
764 return (ex & (int)exws) == (int)exws;
767 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
769 return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
772 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
775 * If this is a form with no window manager, X is handling all the border and caption painting
776 * so remove that from the area (since the area we set of the window here is the part of the window
777 * we're painting in only)
779 Rectangle rect = hwnd.ClientRect;
780 Form form = ctrl as Form;
781 CreateParams cp = null;
784 cp = form.GetCreateParams ();
786 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
787 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
788 Rectangle xrect = rect;
790 xrect.Y -= borders.top;
791 xrect.X -= borders.left;
792 xrect.Width += borders.left + borders.right;
793 xrect.Height += borders.top + borders.bottom;
798 if (rect.Width < 1 || rect.Height < 1) {
808 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
810 return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
813 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
816 * If this is a form with no window manager, X is handling all the border and caption painting
817 * so remove that from the area (since the area we set of the window here is the part of the window
818 * we're painting in only)
820 Form form = cp.control as Form;
821 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
822 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
825 xrect.Width -= borders.left + borders.right;
826 xrect.Height -= borders.top + borders.bottom;
830 if (size.Height == 0)
837 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
840 * If this is a form with no window manager, X is handling all the border and caption painting
841 * so remove that from the area (since the area we set of the window here is the part of the window
842 * we're painting in only)
844 Size rect = new Size (xWidth, xHeight);
845 Form form = cp.control as Form;
846 if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
847 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
850 xrect.Width += borders.left + borders.right;
851 xrect.Height += borders.top + borders.bottom;
858 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
864 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
865 frame = FrameExtents (hwnd.whole_window);
870 return new Point (x, y);
873 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) {
876 tool_caption_height = 19;
877 border_static = false;
879 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
880 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
881 border_style = FormBorderStyle.Fixed3D;
882 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
883 border_style = FormBorderStyle.Fixed3D;
884 border_static = true;
885 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
886 border_style = FormBorderStyle.None;
888 border_style = FormBorderStyle.FixedSingle;
890 title_style = TitleStyle.None;
892 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
894 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
895 title_style = TitleStyle.Tool;
897 title_style = TitleStyle.Normal;
901 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
904 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
905 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
906 border_style = (FormBorderStyle) 0xFFFF;
908 border_style = FormBorderStyle.None;
913 title_style = TitleStyle.None;
914 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
915 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
916 title_style = TitleStyle.Tool;
918 title_style = TitleStyle.Normal;
922 border_style = FormBorderStyle.None;
924 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
925 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
926 border_style = FormBorderStyle.SizableToolWindow;
928 border_style = FormBorderStyle.Sizable;
931 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
932 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
933 border_style = FormBorderStyle.Fixed3D;
934 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
935 border_style = FormBorderStyle.Fixed3D;
936 border_static = true;
937 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
938 border_style = FormBorderStyle.FixedDialog;
939 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
940 border_style = FormBorderStyle.FixedToolWindow;
941 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
942 border_style = FormBorderStyle.FixedSingle;
945 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
946 border_style = FormBorderStyle.FixedSingle;
953 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
954 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);
957 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
958 MotifWmHints mwmHints;
959 MotifFunctions functions;
960 MotifDecorations decorations;
963 Rectangle client_rect;
966 bool hide_from_taskbar;
967 IntPtr transient_for_parent;
969 // Windows we manage ourselves don't need WM window styles.
970 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
975 mwmHints = new MotifWmHints();
978 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
979 transient_for_parent = IntPtr.Zero;
981 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
982 mwmHints.functions = (IntPtr)0;
983 mwmHints.decorations = (IntPtr)0;
985 form = cp.control as Form;
987 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
988 /* tool windows get no window manager
992 /* just because the window doesn't get any decorations doesn't
993 mean we should disable the functions. for instance, without
994 MotifFunctions.Maximize, changing the windowstate to Maximized
995 is ignored by metacity. */
996 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
997 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
998 // No functions nor decorations whatsoever.
1000 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
1001 functions |= MotifFunctions.Move;
1002 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1005 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1006 functions |= MotifFunctions.Move | MotifFunctions.Resize;
1007 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1010 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1011 functions |= MotifFunctions.Minimize;
1012 decorations |= MotifDecorations.Minimize;
1015 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1016 functions |= MotifFunctions.Maximize;
1017 decorations |= MotifDecorations.Maximize;
1020 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1021 functions |= MotifFunctions.Resize;
1022 decorations |= MotifDecorations.ResizeH;
1025 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1026 decorations |= MotifDecorations.Border;
1029 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1030 decorations |= MotifDecorations.Border;
1033 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1034 decorations |= MotifDecorations.Border;
1037 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1038 functions |= MotifFunctions.Close;
1041 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1042 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1043 if (cp.Caption == "") {
1044 functions &= ~MotifFunctions.Move;
1045 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1050 if ((functions & MotifFunctions.Resize) == 0) {
1051 hwnd.fixed_size = true;
1052 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1053 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1055 hwnd.fixed_size = false;
1058 mwmHints.functions = (IntPtr)functions;
1059 mwmHints.decorations = (IntPtr)decorations;
1062 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1065 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1066 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1067 // and get those windows in front of their parents
1068 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1069 } else if (form != null && form.Modal) {
1070 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1072 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1075 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1076 hide_from_taskbar = true;
1077 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1078 hide_from_taskbar = true;
1080 hide_from_taskbar = false;
1083 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1084 if (form != null && !hwnd.reparented) {
1085 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1086 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1087 if (owner_hwnd != null)
1088 transient_for_parent = owner_hwnd.whole_window;
1092 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1093 transient_for_parent = hwnd.parent.whole_window;
1096 FormWindowState current_state = GetWindowState (hwnd.Handle);
1097 if (current_state == (FormWindowState)(-1))
1098 current_state = FormWindowState.Normal;
1100 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1105 atoms [0] = window_type.ToInt32 ();
1106 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1108 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1110 if (transient_for_parent != IntPtr.Zero) {
1111 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1114 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1116 if (hide_from_taskbar) {
1117 /* this line keeps the window from showing up in gnome's taskbar */
1118 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1120 /* we need to add these atoms in the
1121 * event we're maximized, since we're
1122 * replacing the existing
1123 * _NET_WM_STATE here. If we don't
1124 * add them, future calls to
1125 * GetWindowState will return Normal
1126 * for a window which is maximized. */
1127 if (current_state == FormWindowState.Maximized) {
1128 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1129 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1132 if (form != null && form.Modal) {
1133 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1136 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1139 IntPtr[] atom_ptrs = new IntPtr[2];
1140 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1141 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1142 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1145 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1149 private void SetIcon(Hwnd hwnd, Icon icon)
1154 // This really needs to do whatever it
1155 // takes to remove the window manager
1156 // menu, not just delete the ICON
1157 // property. This will cause metacity
1158 // to use the "no icon set" icon, and
1159 // we'll still have an icon.
1160 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1168 bitmap = icon.ToBitmap();
1170 size = bitmap.Width * bitmap.Height + 2;
1171 data = new IntPtr[size];
1173 data[index++] = (IntPtr)bitmap.Width;
1174 data[index++] = (IntPtr)bitmap.Height;
1176 for (int y = 0; y < bitmap.Height; y++) {
1177 for (int x = 0; x < bitmap.Width; x++) {
1178 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1182 XChangeProperty (DisplayHandle, hwnd.whole_window,
1183 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1184 PropertyMode.Replace, data, size);
1188 private void WakeupMain () {
1189 wake.Send (new byte [] { 0xFF });
1192 private XEventQueue ThreadQueue(Thread thread) {
1195 queue = (XEventQueue)MessageQueues[thread];
1196 if (queue == null) {
1197 queue = new XEventQueue(thread);
1198 MessageQueues[thread] = queue;
1204 private void TranslatePropertyToClipboard(IntPtr property) {
1209 IntPtr prop = IntPtr.Zero;
1211 Clipboard.Item = null;
1213 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);
1215 if ((long)nitems > 0) {
1216 if (property == (IntPtr)Atom.XA_STRING) {
1217 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1218 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1219 // FIXME - convert bitmap to image
1220 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1221 // FIXME - convert pixmap to image
1222 } else if (property == OEMTEXT) {
1223 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1224 } else if (property == UNICODETEXT) {
1225 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1232 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1234 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1238 // Keep the invalid area as small as needed
1239 if ((x + width) > hwnd.width) {
1240 width = hwnd.width - x;
1243 if ((y + height) > hwnd.height) {
1244 height = hwnd.height - y;
1248 hwnd.AddInvalidArea(x, y, width, height);
1249 if (!hwnd.expose_pending) {
1250 if (!hwnd.nc_expose_pending) {
1251 hwnd.Queue.Paint.Enqueue(hwnd);
1253 hwnd.expose_pending = true;
1256 hwnd.AddNcInvalidArea (x, y, width, height);
1258 if (!hwnd.nc_expose_pending) {
1259 if (!hwnd.expose_pending) {
1260 hwnd.Queue.Paint.Enqueue(hwnd);
1262 hwnd.nc_expose_pending = true;
1267 private static Hwnd.Borders FrameExtents (IntPtr window)
1273 IntPtr prop = IntPtr.Zero;
1274 Hwnd.Borders rect = new Hwnd.Borders ();
1276 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);
1277 if (prop != IntPtr.Zero) {
1278 if (nitems.ToInt32 () == 4) {
1279 rect.left = Marshal.ReadInt32 (prop, 0);
1280 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1281 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1282 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1290 private void AddConfigureNotify (XEvent xevent) {
1293 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1296 if (hwnd == null || hwnd.zombie) {
1299 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1300 if (hwnd.parent == null) {
1301 // The location given by the event is not reliable between different wm's,
1302 // so use an alternative way of getting it.
1303 Point location = GetTopLevelWindowLocation (hwnd);
1304 hwnd.x = location.X;
1305 hwnd.y = location.Y;
1308 // XXX this sucks. this isn't thread safe
1309 Control ctrl = Control.FromHandle (hwnd.Handle);
1310 Size TranslatedSize;
1312 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1314 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1316 hwnd.width = TranslatedSize.Width;
1317 hwnd.height = TranslatedSize.Height;
1318 hwnd.ClientRect = Rectangle.Empty;
1321 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));
1323 lock (hwnd.configure_lock) {
1324 if (!hwnd.configure_pending) {
1325 hwnd.Queue.EnqueueLocked (xevent);
1326 hwnd.configure_pending = true;
1330 // We drop configure events for Client windows
1333 private void ShowCaret() {
1334 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1340 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1344 private void HideCaret() {
1345 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1351 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1355 private int NextTimeout (ArrayList timers, DateTime now) {
1356 int timeout = Int32.MaxValue;
1358 foreach (Timer timer in timers) {
1359 int next = (int) (timer.Expires - now).TotalMilliseconds;
1361 return 0; // Have a timer that has already expired
1364 if (next < timeout) {
1368 if (timeout < Timer.Minimum) {
1369 timeout = Timer.Minimum;
1377 private void CheckTimers (ArrayList timers, DateTime now) {
1380 count = timers.Count;
1385 for (int i = 0; i < timers.Count; i++) {
1388 timer = (Timer) timers [i];
1390 if (timer.Enabled && timer.Expires <= now) {
1397 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1398 MSG msg = new MSG ();
1401 queue = ThreadQueue(Thread.CurrentThread);
1403 queue.DispatchIdle = false;
1407 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1408 if ((Msg)msg.message == Msg.WM_QUIT) {
1409 PostQuitMessage (0);
1413 if (msg.hwnd == hwnd.Handle) {
1414 if ((Msg)msg.message == message)
1416 else if ((Msg)msg.message == Msg.WM_DESTROY)
1420 TranslateMessage (ref msg);
1421 DispatchMessage (ref msg);
1426 queue.DispatchIdle = true;
1430 private void MapWindow(Hwnd hwnd, WindowType windows) {
1432 if (Control.FromHandle(hwnd.Handle) is Form) {
1433 Form f = Control.FromHandle(hwnd.Handle) as Form;
1434 if (f.WindowState == FormWindowState.Normal)
1435 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1438 // it's possible that our Hwnd is no
1439 // longer valid after making that
1440 // SendMessage call, so check here.
1444 bool need_to_wait = false;
1446 if ((windows & WindowType.Whole) != 0) {
1447 XMapWindow(DisplayHandle, hwnd.whole_window);
1449 if ((windows & WindowType.Client) != 0) {
1450 XMapWindow(DisplayHandle, hwnd.client_window);
1452 need_to_wait = true;
1457 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1458 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1462 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1464 if (Control.FromHandle(hwnd.Handle) is Form) {
1465 Form f = Control.FromHandle(hwnd.Handle) as Form;
1466 if (f.WindowState == FormWindowState.Normal)
1467 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1470 // it's possible that our Hwnd is no
1471 // longer valid after making that
1472 // SendMessage call, so check here.
1476 bool need_to_wait = false;
1478 if ((windows & WindowType.Client) != 0) {
1479 XUnmapWindow(DisplayHandle, hwnd.client_window);
1481 need_to_wait = true;
1483 if ((windows & WindowType.Whole) != 0) {
1484 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1487 hwnd.mapped = false;
1489 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1490 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1494 private void UpdateMessageQueue (XEventQueue queue) {
1499 now = DateTime.UtcNow;
1502 pending = XPending (DisplayHandle);
1506 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1507 Idle (this, EventArgs.Empty);
1511 pending = XPending (DisplayHandle);
1518 if (queue != null) {
1519 if (queue.Paint.Count > 0)
1522 timeout = NextTimeout (queue.timer_list, now);
1527 int length = pollfds.Length - 1;
1528 lock (wake_waiting_lock) {
1529 if (wake_waiting == false) {
1531 wake_waiting = true;
1535 Syscall.poll (pollfds, (uint)length, timeout);
1536 // Clean out buffer, so we're not busy-looping on the same data
1537 if (length == pollfds.Length) {
1538 if (pollfds[1].revents != 0)
1539 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1540 lock (wake_waiting_lock) {
1541 wake_waiting = false;
1546 pending = XPending (DisplayHandle);
1552 CheckTimers (queue.timer_list, now);
1555 XEvent xevent = new XEvent ();
1558 if (XPending (DisplayHandle) == 0)
1561 XNextEvent (DisplayHandle, ref xevent);
1563 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1564 if (XFilterEvent(ref xevent, FosterParent)) {
1570 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1575 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1577 switch (xevent.type) {
1578 case XEventName.Expose:
1579 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1582 case XEventName.SelectionClear: {
1583 // Should we do something?
1587 case XEventName.SelectionRequest: {
1588 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1592 sel_event = new XEvent();
1593 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1594 sel_event.SelectionEvent.send_event = true;
1595 sel_event.SelectionEvent.display = DisplayHandle;
1596 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1597 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1598 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1599 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1600 sel_event.SelectionEvent.property = IntPtr.Zero;
1602 // Seems that some apps support asking for supported types
1603 if (xevent.SelectionEvent.target == TARGETS) {
1610 if (Clipboard.Item is String) {
1611 atoms[atom_count++] = (int)Atom.XA_STRING;
1612 atoms[atom_count++] = (int)OEMTEXT;
1613 atoms[atom_count++] = (int)UNICODETEXT;
1614 } else if (Clipboard.Item is Image) {
1615 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1616 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1618 // FIXME - handle other types
1621 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1622 } else if (Clipboard.Item is string) {
1628 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1631 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1632 buffer = Marshal.AllocHGlobal(bytes.Length);
1633 buflen = bytes.Length;
1635 for (int i = 0; i < buflen; i++) {
1636 Marshal.WriteByte(buffer, i, bytes[i]);
1638 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1639 // FIXME - this should encode into ISO2022
1640 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1641 while (Marshal.ReadByte(buffer, buflen) != 0) {
1644 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1645 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1646 while (Marshal.ReadByte(buffer, buflen) != 0) {
1650 buffer = IntPtr.Zero;
1653 if (buffer != IntPtr.Zero) {
1654 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1655 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1656 Marshal.FreeHGlobal(buffer);
1658 } else if (Clipboard.Item is Image) {
1659 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1660 // FIXME - convert image and store as property
1661 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1662 // FIXME - convert image and store as property
1666 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1670 case XEventName.SelectionNotify: {
1671 if (Clipboard.Enumerating) {
1672 Clipboard.Enumerating = false;
1673 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1674 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1675 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1676 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1677 #if DriverDebugExtra
1678 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1682 } else if (Clipboard.Retrieving) {
1683 Clipboard.Retrieving = false;
1684 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1685 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1687 Clipboard.Item = null;
1690 Dnd.HandleSelectionNotifyEvent (ref xevent);
1695 case XEventName.KeyRelease:
1696 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1697 XEvent nextevent = new XEvent ();
1699 XPeekEvent (DisplayHandle, ref nextevent);
1701 if (nextevent.type == XEventName.KeyPress &&
1702 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1703 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1707 goto case XEventName.KeyPress;
1709 case XEventName.MotionNotify: {
1712 /* we can't do motion compression across threads, so just punt if we don't match up */
1713 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1714 peek = hwnd.Queue.Peek();
1715 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1719 goto case XEventName.KeyPress;
1722 case XEventName.KeyPress:
1723 case XEventName.ButtonPress:
1724 case XEventName.ButtonRelease:
1725 case XEventName.EnterNotify:
1726 case XEventName.LeaveNotify:
1727 case XEventName.CreateNotify:
1728 case XEventName.DestroyNotify:
1729 case XEventName.FocusIn:
1730 case XEventName.FocusOut:
1731 case XEventName.ClientMessage:
1732 case XEventName.ReparentNotify:
1733 case XEventName.MapNotify:
1734 case XEventName.UnmapNotify:
1735 hwnd.Queue.EnqueueLocked (xevent);
1738 case XEventName.ConfigureNotify:
1739 AddConfigureNotify(xevent);
1742 case XEventName.PropertyNotify:
1744 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1746 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1751 IntPtr prop = IntPtr.Zero;
1754 prev_active = ActiveWindow;
1755 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);
1756 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1757 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1760 if (prev_active != ActiveWindow) {
1761 if (prev_active != IntPtr.Zero) {
1762 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1764 if (ActiveWindow != IntPtr.Zero) {
1765 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1768 if (ModalWindows.Count == 0) {
1771 // Modality handling, if we are modal and the new active window is one
1772 // of ours but not the modal one, switch back to the modal window
1774 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1775 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1776 Activate((IntPtr)ModalWindows.Peek());
1783 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1784 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1785 hwnd.cached_window_state = (FormWindowState)(-1);
1793 private IntPtr GetMousewParam(int Delta) {
1796 if ((MouseState & MouseButtons.Left) != 0) {
1797 result |= (int)MsgButtons.MK_LBUTTON;
1800 if ((MouseState & MouseButtons.Middle) != 0) {
1801 result |= (int)MsgButtons.MK_MBUTTON;
1804 if ((MouseState & MouseButtons.Right) != 0) {
1805 result |= (int)MsgButtons.MK_RBUTTON;
1808 Keys mods = ModifierKeys;
1809 if ((mods & Keys.Control) != 0) {
1810 result |= (int)MsgButtons.MK_CONTROL;
1813 if ((mods & Keys.Shift) != 0) {
1814 result |= (int)MsgButtons.MK_SHIFT;
1817 result |= Delta << 16;
1819 return (IntPtr)result;
1821 private IntPtr XGetParent(IntPtr handle) {
1828 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1831 if (Children!=IntPtr.Zero) {
1839 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1841 // we need to workaround a problem with the
1842 // ordering of destruction of Drawables and
1843 // Pictures that exists between cairo and
1844 // RENDER on the server.
1845 if (error_event.request_code == (XRequest)render_major_opcode
1846 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1847 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1851 if (ErrorExceptions) {
1852 XUngrabPointer (display, IntPtr.Zero);
1853 throw new XException (error_event.display, error_event.resourceid,
1854 error_event.serial, error_event.error_code,
1855 error_event.request_code, error_event.minor_code);
1857 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1858 XException.GetMessage (error_event.display, error_event.resourceid,
1859 error_event.serial, error_event.error_code,
1860 error_event.request_code, error_event.minor_code),
1861 Environment.StackTrace);
1866 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1869 Control[] controls = c.Controls.GetAllControls ();
1871 if (c.IsHandleCreated && !c.IsDisposed) {
1872 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1874 #if DriverDebug || DriverDebugDestroy
1875 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1876 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1880 CleanupCachedWindows (hwnd);
1883 for (int i = 0; i < controls.Length; i ++) {
1884 AccumulateDestroyedHandles (controls[i], list);
1890 void CleanupCachedWindows (Hwnd hwnd)
1892 if (ActiveWindow == hwnd.Handle) {
1893 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1894 ActiveWindow = IntPtr.Zero;
1897 if (FocusWindow == hwnd.Handle) {
1898 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1899 FocusWindow = IntPtr.Zero;
1902 if (Grab.Hwnd == hwnd.Handle) {
1903 Grab.Hwnd = IntPtr.Zero;
1904 Grab.Confined = false;
1907 DestroyCaret (hwnd.Handle);
1910 private void PerformNCCalc(Hwnd hwnd) {
1911 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1915 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1917 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1918 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1920 ncp.rgrc1.left = rect.Left;
1921 ncp.rgrc1.top = rect.Top;
1922 ncp.rgrc1.right = rect.Right;
1923 ncp.rgrc1.bottom = rect.Bottom;
1925 Marshal.StructureToPtr(ncp, ptr, true);
1926 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1927 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1928 Marshal.FreeHGlobal(ptr);
1931 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1932 hwnd.ClientRect = rect;
1934 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1937 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1940 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1942 #endregion // Private Methods
1945 private void MouseHover(object sender, EventArgs e) {
1949 HoverState.Timer.Enabled = false;
1951 if (HoverState.Window != IntPtr.Zero) {
1952 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1954 xevent = new XEvent ();
1956 xevent.type = XEventName.ClientMessage;
1957 xevent.ClientMessageEvent.display = DisplayHandle;
1958 xevent.ClientMessageEvent.window = HoverState.Window;
1959 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1960 xevent.ClientMessageEvent.format = 32;
1961 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1963 hwnd.Queue.EnqueueLocked (xevent);
1970 private void CaretCallback(object sender, EventArgs e) {
1974 Caret.On = !Caret.On;
1976 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1978 #endregion // Callbacks
1980 #region Public Properties
1982 internal override int CaptionHeight {
1988 internal override Size CursorSize {
1993 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1994 return new Size(x, y);
1996 return new Size(16, 16);
2001 internal override bool DragFullWindows {
2007 internal override Size DragSize {
2009 return new Size(4, 4);
2013 internal override Size FrameBorderSize {
2015 return new Size (4, 4);
2019 internal override Size IconSize {
2025 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2029 current = (long)list;
2032 size = new XIconSize();
2034 for (int i = 0; i < count; i++) {
2035 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2036 current += Marshal.SizeOf(size);
2038 // Look for our preferred size
2039 if (size.min_width == 32) {
2041 return new Size(32, 32);
2044 if (size.max_width == 32) {
2046 return new Size(32, 32);
2049 if (size.min_width < 32 && size.max_width > 32) {
2052 // check if we can fit one
2054 while (x < size.max_width) {
2055 x += size.width_inc;
2058 return new Size(32, 32);
2063 if (largest < size.max_width) {
2064 largest = size.max_width;
2068 // We didn't find a match or we wouldn't be here
2069 return new Size(largest, largest);
2072 return new Size(32, 32);
2077 internal override int KeyboardSpeed {
2080 // A lot harder: need to do:
2081 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2082 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2083 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2085 // And from that we can tell the repetition rate
2087 // Notice, the values must map to:
2088 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2094 internal override int KeyboardDelay {
2097 // Return values must range from 0 to 4, 0 meaning 250ms,
2098 // and 4 meaning 1000 ms.
2100 return 1; // ie, 500 ms
2104 internal override Size MaxWindowTrackSize {
2106 return new Size (WorkingArea.Width, WorkingArea.Height);
2110 internal override bool MenuAccessKeysUnderlined {
2116 internal override Size MinimizedWindowSize {
2118 return new Size(1, 1);
2122 internal override Size MinimizedWindowSpacingSize {
2124 return new Size(1, 1);
2128 internal override Size MinimumWindowSize {
2130 return new Size(0, 0);
2134 internal override Size MinWindowTrackSize {
2136 return new Size(1, 1);
2140 internal override Keys ModifierKeys {
2142 return Keyboard.ModifierKeys;
2146 internal override Size SmallIconSize {
2152 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2156 current = (long)list;
2159 size = new XIconSize();
2161 for (int i = 0; i < count; i++) {
2162 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2163 current += Marshal.SizeOf(size);
2165 // Look for our preferred size
2166 if (size.min_width == 16) {
2168 return new Size(16, 16);
2171 if (size.max_width == 16) {
2173 return new Size(16, 16);
2176 if (size.min_width < 16 && size.max_width > 16) {
2179 // check if we can fit one
2181 while (x < size.max_width) {
2182 x += size.width_inc;
2185 return new Size(16, 16);
2190 if (smallest == 0 || smallest > size.min_width) {
2191 smallest = size.min_width;
2195 // We didn't find a match or we wouldn't be here
2196 return new Size(smallest, smallest);
2199 return new Size(16, 16);
2204 internal override int MouseButtonCount {
2210 internal override bool MouseButtonsSwapped {
2212 return false; // FIXME - how to detect?
2216 internal override Point MousePosition {
2218 return mouse_position;
2222 internal override Size MouseHoverSize {
2224 return new Size (1, 1);
2228 internal override int MouseHoverTime {
2230 return HoverState.Interval;
2236 internal override bool MouseWheelPresent {
2238 return true; // FIXME - how to detect?
2242 internal override Rectangle VirtualScreen {
2248 IntPtr prop = IntPtr.Zero;
2252 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);
2253 if ((long)nitems < 2)
2256 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2257 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2261 return new Rectangle(0, 0, width, height);
2264 XWindowAttributes attributes=new XWindowAttributes();
2267 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2270 return new Rectangle(0, 0, attributes.width, attributes.height);
2274 internal override Rectangle WorkingArea {
2280 IntPtr prop = IntPtr.Zero;
2283 int current_desktop;
2287 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);
2288 if ((long)nitems < 1) {
2292 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2295 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);
2296 if ((long)nitems < 4 * current_desktop) {
2300 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2301 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2302 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2303 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2306 return new Rectangle(x, y, width, height);
2309 XWindowAttributes attributes=new XWindowAttributes();
2312 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2315 return new Rectangle(0, 0, attributes.width, attributes.height);
2319 internal override bool ThemesEnabled {
2321 return XplatUIX11.themes_enabled;
2326 #endregion // Public properties
2328 #region Public Static Methods
2329 internal override void RaiseIdle (EventArgs e)
2335 internal override IntPtr InitializeDriver() {
2337 if (DisplayHandle==IntPtr.Zero) {
2338 SetDisplay(XOpenDisplay(IntPtr.Zero));
2344 internal override void ShutdownDriver(IntPtr token) {
2346 if (DisplayHandle!=IntPtr.Zero) {
2347 XCloseDisplay(DisplayHandle);
2348 DisplayHandle=IntPtr.Zero;
2353 internal override void EnableThemes() {
2354 themes_enabled = true;
2358 internal override void Activate(IntPtr handle) {
2361 hwnd = Hwnd.ObjectFromHandle(handle);
2365 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2366 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2369 // XRaiseWindow(DisplayHandle, handle);
2375 internal override void AudibleAlert() {
2376 XBell(DisplayHandle, 0);
2381 internal override void CaretVisible(IntPtr handle, bool visible) {
2382 if (Caret.Hwnd == handle) {
2384 if (!Caret.Visible) {
2385 Caret.Visible = true;
2387 Caret.Timer.Start();
2390 Caret.Visible = false;
2397 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2398 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2402 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2408 hwnd = Hwnd.ObjectFromHandle(handle);
2411 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2418 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2419 DataFormats.Format f;
2422 f = DataFormats.Format.List;
2424 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2428 Clipboard.Formats = new ArrayList();
2431 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2433 Clipboard.Enumerating = true;
2434 while (Clipboard.Enumerating) {
2435 UpdateMessageQueue(null);
2440 result = new int[Clipboard.Formats.Count];
2442 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2443 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2446 Clipboard.Formats = null;
2450 internal override void ClipboardClose(IntPtr handle) {
2451 if (handle != ClipMagic) {
2452 throw new ArgumentException("handle is not a valid clipboard handle");
2457 internal override int ClipboardGetID(IntPtr handle, string format) {
2458 if (handle != ClipMagic) {
2459 throw new ArgumentException("handle is not a valid clipboard handle");
2462 if (format == "Text" ) return (int)Atom.XA_STRING;
2463 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2464 //else if (format == "MetaFilePict" ) return 3;
2465 //else if (format == "SymbolicLink" ) return 4;
2466 //else if (format == "DataInterchangeFormat" ) return 5;
2467 //else if (format == "Tiff" ) return 6;
2468 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2469 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2470 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2471 //else if (format == "PenData" ) return 10;
2472 //else if (format == "RiffAudio" ) return 11;
2473 //else if (format == "WaveAudio" ) return 12;
2474 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2475 //else if (format == "EnhancedMetafile" ) return 14;
2476 //else if (format == "FileDrop" ) return 15;
2477 //else if (format == "Locale" ) return 16;
2479 return XInternAtom(DisplayHandle, format, false).ToInt32();
2482 internal override IntPtr ClipboardOpen(bool primary_selection) {
2483 if (!primary_selection)
2484 ClipMagic = CLIPBOARD;
2486 ClipMagic = PRIMARY;
2490 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2491 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2493 Clipboard.Retrieving = true;
2494 while (Clipboard.Retrieving) {
2495 UpdateMessageQueue(null);
2498 return Clipboard.Item;
2501 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2502 Clipboard.Item = obj;
2503 Clipboard.Type = type;
2504 Clipboard.Converter = converter;
2507 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2509 // Clearing the selection
2510 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2514 internal override void CreateCaret (IntPtr handle, int width, int height)
2516 XGCValues gc_values;
2519 hwnd = Hwnd.ObjectFromHandle(handle);
2521 if (Caret.Hwnd != IntPtr.Zero) {
2522 DestroyCaret(Caret.Hwnd);
2525 Caret.Hwnd = handle;
2526 Caret.Window = hwnd.client_window;
2527 Caret.Width = width;
2528 Caret.Height = height;
2529 Caret.Visible = false;
2532 gc_values = new XGCValues();
2533 gc_values.line_width = width;
2535 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2536 if (Caret.gc == IntPtr.Zero) {
2537 Caret.Hwnd = IntPtr.Zero;
2541 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2544 internal override IntPtr CreateWindow (CreateParams cp)
2546 XSetWindowAttributes Attributes;
2548 Hwnd parent_hwnd = null;
2553 IntPtr ParentHandle;
2555 IntPtr ClientWindow;
2556 SetWindowValuemask ValueMask;
2561 Attributes = new XSetWindowAttributes();
2567 if (Width<1) Width=1;
2568 if (Height<1) Height=1;
2570 if (cp.Parent != IntPtr.Zero) {
2571 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2572 ParentHandle = parent_hwnd.client_window;
2574 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2575 // We need to use our foster parent window until this poor child gets it's parent assigned
2576 ParentHandle=FosterParent;
2578 ParentHandle=RootWindow;
2582 // Set the default location location for forms.
2584 if (cp.control is Form) {
2585 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2589 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2591 Attributes.bit_gravity = Gravity.NorthWestGravity;
2592 Attributes.win_gravity = Gravity.NorthWestGravity;
2594 // Save what's under the toolwindow
2595 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2596 Attributes.save_under = true;
2597 ValueMask |= SetWindowValuemask.SaveUnder;
2601 // If we're a popup without caption we override the WM
2602 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2603 Attributes.override_redirect = true;
2604 ValueMask |= SetWindowValuemask.OverrideRedirect;
2610 hwnd.height = Height;
2611 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2612 hwnd.initial_style = cp.WindowStyle;
2613 hwnd.initial_ex_style = cp.WindowExStyle;
2615 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2616 hwnd.enabled = false;
2619 ClientWindow = IntPtr.Zero;
2621 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2622 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2625 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);
2626 if (WholeWindow != IntPtr.Zero) {
2627 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2629 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2630 ValueMask = SetWindowValuemask.ColorMap;
2631 Attributes.colormap = CustomColormap;
2633 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);
2637 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2638 throw new Exception("Could not create X11 windows");
2641 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2642 hwnd.WholeWindow = WholeWindow;
2643 hwnd.ClientWindow = ClientWindow;
2645 #if DriverDebug || DriverDebugCreate
2646 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);
2649 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2650 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2653 hints = new XSizeHints();
2656 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2657 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2662 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2663 if (hwnd.whole_window != hwnd.client_window)
2664 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2667 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2669 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2670 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2672 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2675 SetWMStyles(hwnd, cp);
2677 // set the group leader
2678 XWMHints wm_hints = new XWMHints ();
2680 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2681 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2682 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2684 if (ParentHandle != RootWindow) {
2685 wm_hints.window_group = hwnd.whole_window;
2687 wm_hints.window_group = ParentHandle;
2691 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2694 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2695 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2696 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2697 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2700 // for now make all windows dnd enabled
2701 Dnd.SetAllowDrop (hwnd, true);
2703 // Set caption/window title
2704 Text(hwnd.Handle, cp.Caption);
2706 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2707 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2709 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2710 hwnd.visible = true;
2711 MapWindow(hwnd, WindowType.Both);
2712 if (!(Control.FromHandle(hwnd.Handle) is Form))
2713 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2719 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2720 CreateParams create_params = new CreateParams();
2722 create_params.Caption = "";
2723 create_params.X = X;
2724 create_params.Y = Y;
2725 create_params.Width = Width;
2726 create_params.Height = Height;
2728 create_params.ClassName=XplatUI.DefaultClassName;
2729 create_params.ClassStyle = 0;
2730 create_params.ExStyle=0;
2731 create_params.Parent=IntPtr.Zero;
2732 create_params.Param=0;
2734 return CreateWindow(create_params);
2737 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2739 Bitmap cursor_bitmap;
2747 IntPtr cursor_pixmap;
2754 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2758 // Win32 only allows creation cursors of a certain size
2759 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2760 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2761 cursor_mask = new Bitmap(mask, new Size(width, height));
2763 cursor_bitmap = bitmap;
2767 width = cursor_bitmap.Width;
2768 height = cursor_bitmap.Height;
2770 cursor_bits = new Byte[(width / 8) * height];
2771 mask_bits = new Byte[(width / 8) * height];
2773 for (int y = 0; y < height; y++) {
2774 for (int x = 0; x < width; x++) {
2775 c_pixel = cursor_bitmap.GetPixel(x, y);
2776 m_pixel = cursor_mask.GetPixel(x, y);
2778 and = c_pixel == cursor_pixel;
2779 xor = m_pixel == mask_pixel;
2783 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2784 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2785 } else if (and && !xor) {
2787 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2788 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2790 } else if (and && !xor) {
2792 } else if (and && xor) {
2795 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2796 // we want both to be 0 so nothing to be done
2797 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2798 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2804 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2805 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2809 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2810 fg.red = (ushort)65535;
2811 fg.green = (ushort)65535;
2812 fg.blue = (ushort)65535;
2814 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2816 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2818 XFreePixmap(DisplayHandle, cursor_pixmap);
2819 XFreePixmap(DisplayHandle, mask_pixmap);
2824 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2825 CursorFontShape shape;
2832 shape = StdCursorToFontShape (id);
2833 name = shape.ToString ().Replace ("XC_", string.Empty);
2834 size = XcursorGetDefaultSize (DisplayHandle);
2835 theme = XcursorGetTheme (DisplayHandle);
2836 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2838 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);
2841 if (images_ptr == IntPtr.Zero) {
2845 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2847 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2850 if (images.nimage > 0) {
2851 // We only care about the first image.
2852 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2855 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);
2858 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2859 int [] pixels = new int [image.width * image.height];
2860 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2861 bmp = new Bitmap (image.width, image.height);
2862 for (int w = 0; w < image.width; w++) {
2863 for (int h = 0; h < image.height; h++) {
2864 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2870 XcursorImagesDestroy (images_ptr);
2872 } catch (DllNotFoundException ex) {
2873 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2881 internal override IntPtr DefineStdCursor(StdCursor id) {
2882 CursorFontShape shape;
2885 shape = StdCursorToFontShape (id);
2888 cursor = XCreateFontCursor(DisplayHandle, shape);
2893 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2894 CursorFontShape shape;
2895 // FIXME - define missing shapes
2898 case StdCursor.AppStarting: {
2899 shape = CursorFontShape.XC_watch;
2903 case StdCursor.Arrow: {
2904 shape = CursorFontShape.XC_top_left_arrow;
2908 case StdCursor.Cross: {
2909 shape = CursorFontShape.XC_crosshair;
2913 case StdCursor.Default: {
2914 shape = CursorFontShape.XC_top_left_arrow;
2918 case StdCursor.Hand: {
2919 shape = CursorFontShape.XC_hand1;
2923 case StdCursor.Help: {
2924 shape = CursorFontShape.XC_question_arrow;
2928 case StdCursor.HSplit: {
2929 shape = CursorFontShape.XC_sb_v_double_arrow;
2933 case StdCursor.IBeam: {
2934 shape = CursorFontShape.XC_xterm;
2938 case StdCursor.No: {
2939 shape = CursorFontShape.XC_circle;
2943 case StdCursor.NoMove2D: {
2944 shape = CursorFontShape.XC_fleur;
2948 case StdCursor.NoMoveHoriz: {
2949 shape = CursorFontShape.XC_fleur;
2953 case StdCursor.NoMoveVert: {
2954 shape = CursorFontShape.XC_fleur;
2958 case StdCursor.PanEast: {
2959 shape = CursorFontShape.XC_fleur;
2963 case StdCursor.PanNE: {
2964 shape = CursorFontShape.XC_fleur;
2968 case StdCursor.PanNorth: {
2969 shape = CursorFontShape.XC_fleur;
2973 case StdCursor.PanNW: {
2974 shape = CursorFontShape.XC_fleur;
2978 case StdCursor.PanSE: {
2979 shape = CursorFontShape.XC_fleur;
2983 case StdCursor.PanSouth: {
2984 shape = CursorFontShape.XC_fleur;
2988 case StdCursor.PanSW: {
2989 shape = CursorFontShape.XC_fleur;
2993 case StdCursor.PanWest: {
2994 shape = CursorFontShape.XC_sizing;
2998 case StdCursor.SizeAll: {
2999 shape = CursorFontShape.XC_fleur;
3003 case StdCursor.SizeNESW: {
3004 shape = CursorFontShape.XC_top_right_corner;
3008 case StdCursor.SizeNS: {
3009 shape = CursorFontShape.XC_sb_v_double_arrow;
3013 case StdCursor.SizeNWSE: {
3014 shape = CursorFontShape.XC_top_left_corner;
3018 case StdCursor.SizeWE: {
3019 shape = CursorFontShape.XC_sb_h_double_arrow;
3023 case StdCursor.UpArrow: {
3024 shape = CursorFontShape.XC_center_ptr;
3028 case StdCursor.VSplit: {
3029 shape = CursorFontShape.XC_sb_h_double_arrow;
3033 case StdCursor.WaitCursor: {
3034 shape = CursorFontShape.XC_watch;
3039 shape = (CursorFontShape) 0;
3047 internal override IntPtr DefWndProc(ref Message msg) {
3048 switch ((Msg)msg.Msg) {
3049 case Msg.WM_PAINT: {
3052 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3054 hwnd.expose_pending = false;
3060 case Msg.WM_NCPAINT: {
3063 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3065 hwnd.nc_expose_pending = false;
3071 case Msg.WM_NCCALCSIZE: {
3074 if (msg.WParam == (IntPtr)1) {
3075 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3077 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3078 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3080 // Add all the stuff X is supposed to draw.
3081 Control ctrl = Control.FromHandle (hwnd.Handle);
3084 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3086 ncp.rgrc1.top += rect.top;
3087 ncp.rgrc1.bottom -= rect.bottom;
3088 ncp.rgrc1.left += rect.left;
3089 ncp.rgrc1.right -= rect.right;
3091 Marshal.StructureToPtr (ncp, msg.LParam, true);
3098 case Msg.WM_CONTEXTMENU: {
3101 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3103 if ((hwnd != null) && (hwnd.parent != null)) {
3104 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3109 case Msg.WM_MOUSEWHEEL: {
3112 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3114 if ((hwnd != null) && (hwnd.parent != null)) {
3115 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3116 if (msg.Result == IntPtr.Zero) {
3123 case Msg.WM_SETCURSOR: {
3126 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3128 break; // not sure how this happens, but it does
3130 // Pass to parent window first
3131 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3133 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3136 if (msg.Result == IntPtr.Zero) {
3139 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3140 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3141 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3142 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3143 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3144 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3147 handle = Cursors.Default.handle;
3150 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3151 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3152 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3153 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3154 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3155 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3158 case HitTest.HTGROWBOX:
3159 case HitTest.HTSIZE:
3160 case HitTest.HTZOOM:
3161 case HitTest.HTVSCROLL:
3162 case HitTest.HTSYSMENU:
3163 case HitTest.HTREDUCE:
3164 case HitTest.HTNOWHERE:
3165 case HitTest.HTMAXBUTTON:
3166 case HitTest.HTMINBUTTON:
3167 case HitTest.HTMENU:
3168 case HitTest.HSCROLL:
3169 case HitTest.HTBOTTOM:
3170 case HitTest.HTCAPTION:
3171 case HitTest.HTCLIENT:
3172 case HitTest.HTCLOSE:
3174 default: handle = Cursors.Default.handle; break;
3176 SetCursor(msg.HWnd, handle);
3184 internal override void DestroyCaret(IntPtr handle) {
3185 if (Caret.Hwnd == handle) {
3186 if (Caret.Visible) {
3190 if (Caret.gc != IntPtr.Zero) {
3191 XFreeGC(DisplayHandle, Caret.gc);
3192 Caret.gc = IntPtr.Zero;
3194 Caret.Hwnd = IntPtr.Zero;
3195 Caret.Visible = false;
3200 internal override void DestroyCursor(IntPtr cursor) {
3202 XFreeCursor(DisplayHandle, cursor);
3206 internal override void DestroyWindow(IntPtr handle) {
3209 hwnd = Hwnd.ObjectFromHandle(handle);
3212 #if DriverDebug || DriverDebugDestroy
3213 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3218 #if DriverDebug || DriverDebugDestroy
3219 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3222 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3224 CleanupCachedWindows (hwnd);
3226 ArrayList windows = new ArrayList ();
3228 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3231 foreach (Hwnd h in windows) {
3232 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3237 if (hwnd.whole_window != IntPtr.Zero) {
3238 #if DriverDebug || DriverDebugDestroy
3239 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3241 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3243 else if (hwnd.client_window != IntPtr.Zero) {
3244 #if DriverDebug || DriverDebugDestroy
3245 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3247 XDestroyWindow(DisplayHandle, hwnd.client_window);
3253 internal override IntPtr DispatchMessage(ref MSG msg) {
3254 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3257 IntPtr GetReversibleScreenGC (Color backColor)
3259 XGCValues gc_values;
3263 XColor xcolor = new XColor();
3264 xcolor.red = (ushort)(backColor.R * 257);
3265 xcolor.green = (ushort)(backColor.G * 257);
3266 xcolor.blue = (ushort)(backColor.B * 257);
3267 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3268 pixel = (uint)xcolor.pixel.ToInt32();
3271 gc_values = new XGCValues();
3273 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3274 gc_values.foreground = (IntPtr)pixel;
3276 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3277 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3278 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3283 IntPtr GetReversibleControlGC (Control control, int line_width)
3285 XGCValues gc_values;
3288 gc_values = new XGCValues();
3290 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3291 gc_values.line_width = line_width;
3292 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3294 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3295 //mask = foreground ^ background;
3296 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3297 //XSetBackground(DisplayHandle, gc, background);
3298 //XSetFunction(DisplayHandle, gc, GXxor);
3299 //XSetPlaneMask(DisplayHandle, gc, mask);
3302 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3306 XColor xcolor = new XColor();
3308 xcolor.red = (ushort)(control.ForeColor.R * 257);
3309 xcolor.green = (ushort)(control.ForeColor.G * 257);
3310 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3311 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3312 foreground = (uint)xcolor.pixel.ToInt32();
3314 xcolor.red = (ushort)(control.BackColor.R * 257);
3315 xcolor.green = (ushort)(control.BackColor.G * 257);
3316 xcolor.blue = (ushort)(control.BackColor.B * 257);
3317 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3318 background = (uint)xcolor.pixel.ToInt32();
3320 uint mask = foreground ^ background;
3322 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3323 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3324 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3325 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3330 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3332 if (backColor.GetBrightness() < 0.5)
3333 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3335 IntPtr gc = GetReversibleScreenGC (backColor);
3337 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3339 XFreeGC(DisplayHandle, gc);
3342 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3344 if (backColor.GetBrightness() < 0.5)
3345 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3347 IntPtr gc = GetReversibleScreenGC (backColor);
3349 if (rectangle.Width < 0) {
3350 rectangle.X += rectangle.Width;
3351 rectangle.Width = -rectangle.Width;
3353 if (rectangle.Height < 0) {
3354 rectangle.Y += rectangle.Height;
3355 rectangle.Height = -rectangle.Height;
3359 GCLineStyle line_style = GCLineStyle.LineSolid;
3360 GCCapStyle cap_style = GCCapStyle.CapButt;
3361 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3364 case FrameStyle.Dashed:
3365 line_style = GCLineStyle.LineOnOffDash;
3367 case FrameStyle.Thick:
3372 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3374 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3376 XFreeGC(DisplayHandle, gc);
3379 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3381 if (backColor.GetBrightness() < 0.5)
3382 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3384 IntPtr gc = GetReversibleScreenGC (backColor);
3386 if (rectangle.Width < 0) {
3387 rectangle.X += rectangle.Width;
3388 rectangle.Width = -rectangle.Width;
3390 if (rectangle.Height < 0) {
3391 rectangle.Y += rectangle.Height;
3392 rectangle.Height = -rectangle.Height;
3394 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3396 XFreeGC(DisplayHandle, gc);
3399 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3402 Control control = Control.FromHandle(handle);
3404 gc = GetReversibleControlGC (control, line_width);
3406 if ((rect.Width > 0) && (rect.Height > 0)) {
3407 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3409 if (rect.Width > 0) {
3410 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3412 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3415 XFreeGC(DisplayHandle, gc);
3418 internal override void DoEvents() {
3419 MSG msg = new MSG ();
3422 if (OverrideCursorHandle != IntPtr.Zero) {
3423 OverrideCursorHandle = IntPtr.Zero;
3426 queue = ThreadQueue(Thread.CurrentThread);
3428 queue.DispatchIdle = false;
3430 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3431 TranslateMessage (ref msg);
3432 DispatchMessage (ref msg);
3435 queue.DispatchIdle = true;
3438 internal override void EnableWindow(IntPtr handle, bool Enable) {
3441 hwnd = Hwnd.ObjectFromHandle(handle);
3443 hwnd.Enabled = Enable;
3447 internal override void EndLoop(Thread thread) {
3448 // This is where we one day will shut down the loop for the thread
3451 internal override IntPtr GetActive() {
3456 IntPtr prop = IntPtr.Zero;
3457 IntPtr active = IntPtr.Zero;
3459 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);
3460 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3461 active = (IntPtr)Marshal.ReadInt32(prop);
3465 if (active != IntPtr.Zero) {
3468 hwnd = Hwnd.GetObjectFromWindow(active);
3470 active = hwnd.Handle;
3472 active = IntPtr.Zero;
3478 internal override Region GetClipRegion(IntPtr handle) {
3481 hwnd = Hwnd.ObjectFromHandle(handle);
3483 return hwnd.UserClip;
3489 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3496 internal override void GetDisplaySize(out Size size) {
3497 XWindowAttributes attributes=new XWindowAttributes();
3500 // FIXME - use _NET_WM messages instead?
3501 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3504 size = new Size(attributes.width, attributes.height);
3507 internal override SizeF GetAutoScaleSize(Font font) {
3510 string magic_string = "The quick brown fox jumped over the lazy dog.";
3511 double magic_number = 44.549996948242189;
3513 g = Graphics.FromHwnd(FosterParent);
3515 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3516 return new SizeF(width, font.Height);
3519 internal override IntPtr GetParent(IntPtr handle) {
3522 hwnd = Hwnd.ObjectFromHandle(handle);
3523 if (hwnd != null && hwnd.parent != null) {
3524 return hwnd.parent.Handle;
3529 // This is a nop on win32 and x11
3530 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3534 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3544 if (handle != IntPtr.Zero) {
3545 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3547 use_handle = RootWindow;
3551 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3554 if (handle != IntPtr.Zero) {
3563 internal override IntPtr GetFocus() {
3568 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3569 FontFamily ff = font.FontFamily;
3570 ascent = ff.GetCellAscent (font.Style);
3571 descent = ff.GetCellDescent (font.Style);
3575 internal override Point GetMenuOrigin(IntPtr handle) {
3578 hwnd = Hwnd.ObjectFromHandle(handle);
3581 return hwnd.MenuOrigin;
3586 [MonoTODO("Implement filtering")]
3587 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3594 if (((XEventQueue)queue_id).Count > 0) {
3595 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3597 UpdateMessageQueue ((XEventQueue)queue_id);
3599 if (((XEventQueue)queue_id).Count > 0) {
3600 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3601 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3602 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3604 msg.hwnd= IntPtr.Zero;
3605 msg.message = Msg.WM_ENTERIDLE;
3610 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3612 // Handle messages for windows that are already or are about to be destroyed.
3614 // we need a special block for this because unless we remove the hwnd from the paint
3615 // queue it will always stay there (since we don't handle the expose), and we'll
3616 // effectively loop infinitely trying to repaint a non-existant window.
3617 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3618 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3619 hwnd.Queue.Paint.Remove (hwnd);
3620 goto ProcessNextMessage;
3623 // We need to make sure we only allow DestroyNotify events through for zombie
3624 // hwnds, since much of the event handling code makes requests using the hwnd's
3625 // client_window, and that'll result in BadWindow errors if there's some lag
3626 // between the XDestroyWindow call and the DestroyNotify event.
3627 if (hwnd == null || hwnd.zombie) {
3628 #if DriverDebug || DriverDebugDestroy
3629 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3631 goto ProcessNextMessage;
3634 if (hwnd.client_window == xevent.AnyEvent.window) {
3636 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3639 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3642 msg.hwnd = hwnd.Handle;
3645 // If you add a new event to this switch make sure to add it in
3646 // UpdateMessage also unless it is not coming through the X event system.
3648 switch(xevent.type) {
3649 case XEventName.KeyPress: {
3650 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3654 case XEventName.KeyRelease: {
3655 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3659 case XEventName.ButtonPress: {
3660 switch(xevent.ButtonEvent.button) {
3662 MouseState |= MouseButtons.Left;
3664 msg.message = Msg.WM_LBUTTONDOWN;
3666 msg.message = Msg.WM_NCLBUTTONDOWN;
3667 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3669 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3670 msg.wParam=GetMousewParam(0);
3675 MouseState |= MouseButtons.Middle;
3677 msg.message = Msg.WM_MBUTTONDOWN;
3679 msg.message = Msg.WM_NCMBUTTONDOWN;
3680 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3682 msg.wParam=GetMousewParam(0);
3687 MouseState |= MouseButtons.Right;
3689 msg.message = Msg.WM_RBUTTONDOWN;
3691 msg.message = Msg.WM_NCRBUTTONDOWN;
3692 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3694 msg.wParam=GetMousewParam(0);
3699 msg.hwnd = FocusWindow;
3700 msg.message=Msg.WM_MOUSEWHEEL;
3701 msg.wParam=GetMousewParam(120);
3706 msg.hwnd = FocusWindow;
3707 msg.message=Msg.WM_MOUSEWHEEL;
3708 msg.wParam=GetMousewParam(-120);
3714 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3715 mouse_position.X = xevent.ButtonEvent.x;
3716 mouse_position.Y = xevent.ButtonEvent.y;
3718 if (!hwnd.Enabled) {
3721 msg.hwnd = hwnd.EnabledHwnd;
3722 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);
3723 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3726 if (Grab.Hwnd != IntPtr.Zero) {
3727 msg.hwnd = Grab.Hwnd;
3730 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3731 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3732 switch(xevent.ButtonEvent.button) {
3734 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3739 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3744 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3748 ClickPending.Pending = false;
3750 ClickPending.Pending = true;
3751 ClickPending.Hwnd = msg.hwnd;
3752 ClickPending.Message = msg.message;
3753 ClickPending.wParam = msg.wParam;
3754 ClickPending.lParam = msg.lParam;
3755 ClickPending.Time = (long)xevent.ButtonEvent.time;
3758 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3759 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3761 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3762 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3763 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3764 XEvent motionEvent = new XEvent ();
3765 motionEvent.type = XEventName.MotionNotify;
3766 motionEvent.MotionEvent.display = DisplayHandle;
3767 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3768 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3769 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3770 hwnd.Queue.EnqueueLocked (motionEvent);
3776 case XEventName.ButtonRelease: {
3778 switch(xevent.ButtonEvent.button) {
3781 msg.message = Msg.WM_LBUTTONUP;
3783 msg.message = Msg.WM_NCLBUTTONUP;
3784 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3786 MouseState &= ~MouseButtons.Left;
3787 msg.wParam=GetMousewParam(0);
3793 msg.message = Msg.WM_MBUTTONUP;
3795 msg.message = Msg.WM_NCMBUTTONUP;
3796 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3798 MouseState &= ~MouseButtons.Middle;
3799 msg.wParam=GetMousewParam(0);
3805 msg.message = Msg.WM_RBUTTONUP;
3807 msg.message = Msg.WM_NCRBUTTONUP;
3808 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3810 MouseState &= ~MouseButtons.Right;
3811 msg.wParam=GetMousewParam(0);
3816 goto ProcessNextMessage;
3820 goto ProcessNextMessage;
3824 if (!hwnd.Enabled) {
3827 msg.hwnd = hwnd.EnabledHwnd;
3828 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);
3829 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3832 if (Grab.Hwnd != IntPtr.Zero) {
3833 msg.hwnd = Grab.Hwnd;
3836 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3837 mouse_position.X = xevent.ButtonEvent.x;
3838 mouse_position.Y = xevent.ButtonEvent.y;
3840 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3841 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3842 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3843 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3844 XEvent motionEvent = new XEvent ();
3845 motionEvent.type = XEventName.MotionNotify;
3846 motionEvent.MotionEvent.display = DisplayHandle;
3847 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3848 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3849 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3850 hwnd.Queue.EnqueueLocked (motionEvent);
3855 case XEventName.MotionNotify: {
3857 #if DriverDebugExtra
3858 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);
3861 if (Grab.Hwnd != IntPtr.Zero) {
3862 msg.hwnd = Grab.Hwnd;
3865 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3869 if (xevent.MotionEvent.is_hint != 0)
3873 XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3874 out root, out child,
3875 out xevent.MotionEvent.x_root,
3876 out xevent.MotionEvent.y_root,
3877 out xevent.MotionEvent.x,
3878 out xevent.MotionEvent.y, out mask);
3881 msg.message = Msg.WM_MOUSEMOVE;
3882 msg.wParam = GetMousewParam(0);
3883 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3885 if (!hwnd.Enabled) {
3888 msg.hwnd = hwnd.EnabledHwnd;
3889 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);
3890 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3893 mouse_position.X = xevent.MotionEvent.x;
3894 mouse_position.Y = xevent.MotionEvent.y;
3896 if ((HoverState.Timer.Enabled) &&
3897 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3898 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3899 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3900 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3901 HoverState.Timer.Stop();
3902 HoverState.Timer.Start();
3903 HoverState.X = mouse_position.X;
3904 HoverState.Y = mouse_position.Y;
3914 #if DriverDebugExtra
3915 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);
3917 msg.message = Msg.WM_NCMOUSEMOVE;
3919 if (!hwnd.Enabled) {
3920 msg.hwnd = hwnd.EnabledHwnd;
3921 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);
3922 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3925 // The hit test is sent in screen coordinates
3926 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3927 xevent.MotionEvent.x, xevent.MotionEvent.y,
3928 out screen_x, out screen_y, out dummy);
3930 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3931 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3932 IntPtr.Zero, msg.lParam).ToInt32 ();
3933 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3935 mouse_position.X = xevent.MotionEvent.x;
3936 mouse_position.Y = xevent.MotionEvent.y;
3942 case XEventName.EnterNotify: {
3943 if (!hwnd.Enabled) {
3944 goto ProcessNextMessage;
3946 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3947 goto ProcessNextMessage;
3949 msg.message = Msg.WM_MOUSE_ENTER;
3950 HoverState.X = xevent.CrossingEvent.x;
3951 HoverState.Y = xevent.CrossingEvent.y;
3952 HoverState.Timer.Enabled = true;
3953 HoverState.Window = xevent.CrossingEvent.window;
3957 case XEventName.LeaveNotify: {
3958 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3959 WindowUngrabbed (hwnd.Handle);
3960 goto ProcessNextMessage;
3962 if (!hwnd.Enabled) {
3963 goto ProcessNextMessage;
3965 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3966 goto ProcessNextMessage;
3968 msg.message=Msg.WM_MOUSELEAVE;
3969 HoverState.Timer.Enabled = false;
3970 HoverState.Window = IntPtr.Zero;
3975 case XEventName.CreateNotify: {
3976 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3977 msg.message = WM_CREATE;
3978 // Set up CreateStruct
3980 goto ProcessNextMessage;
3987 case XEventName.ReparentNotify: {
3988 if (hwnd.parent == null) { // Toplevel
3989 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3990 hwnd.Reparented = true;
3992 // The location given by the event is not reliable between different wm's,
3993 // so use an alternative way of getting it.
3994 Point location = GetTopLevelWindowLocation (hwnd);
3995 hwnd.X = location.X;
3996 hwnd.Y = location.Y;
3998 if (hwnd.opacity != 0xffffffff) {
4001 opacity = (IntPtr)(Int32)hwnd.opacity;
4002 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4004 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4005 goto ProcessNextMessage;
4007 hwnd.Reparented = false;
4008 goto ProcessNextMessage;
4011 goto ProcessNextMessage;
4014 case XEventName.ConfigureNotify: {
4015 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4016 #if DriverDebugExtra
4017 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);
4019 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
4020 lock (hwnd.configure_lock) {
4021 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4022 hwnd.configure_pending = false;
4025 // We need to adjust our client window to track the resize of whole_window
4026 if (hwnd.whole_window != hwnd.client_window)
4027 PerformNCCalc(hwnd);
4030 goto ProcessNextMessage;
4033 case XEventName.FocusIn: {
4034 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4035 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4036 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4037 // about it having focus again
4038 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4039 goto ProcessNextMessage;
4042 if (FocusWindow == IntPtr.Zero) {
4043 Control c = Control.FromHandle (hwnd.client_window);
4045 goto ProcessNextMessage;
4046 Form form = c.FindForm ();
4048 goto ProcessNextMessage;
4049 if (ActiveWindow != form.Handle) {
4050 ActiveWindow = form.Handle;
4051 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4053 goto ProcessNextMessage;
4055 Keyboard.FocusIn(FocusWindow);
4056 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4057 goto ProcessNextMessage;
4060 case XEventName.FocusOut: {
4061 // Se the comment for our FocusIn handler
4062 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4063 goto ProcessNextMessage;
4065 Keyboard.FocusOut(FocusWindow);
4067 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4068 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4071 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4072 goto ProcessNextMessage;
4075 case XEventName.MapNotify: {
4076 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4078 msg.message = Msg.WM_SHOWWINDOW;
4079 msg.wParam = (IntPtr) 1;
4080 // XXX we're missing the lParam..
4083 goto ProcessNextMessage;
4086 case XEventName.UnmapNotify: {
4087 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4088 hwnd.mapped = false;
4089 msg.message = Msg.WM_SHOWWINDOW;
4090 msg.wParam = (IntPtr) 0;
4091 // XXX we're missing the lParam..
4094 goto ProcessNextMessage;
4097 case XEventName.Expose: {
4100 hwnd.expose_pending = false;
4102 hwnd.nc_expose_pending = false;
4104 goto ProcessNextMessage;
4108 if (!hwnd.expose_pending) {
4109 goto ProcessNextMessage;
4112 if (!hwnd.nc_expose_pending) {
4113 goto ProcessNextMessage;
4116 switch (hwnd.border_style) {
4117 case FormBorderStyle.Fixed3D: {
4120 g = Graphics.FromHwnd(hwnd.whole_window);
4121 if (hwnd.border_static)
4122 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4124 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4129 case FormBorderStyle.FixedSingle: {
4132 g = Graphics.FromHwnd(hwnd.whole_window);
4133 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4138 #if DriverDebugExtra
4139 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);
4142 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4143 Region region = new Region (rect);
4144 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4145 msg.message = Msg.WM_NCPAINT;
4146 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4147 msg.refobject = region;
4150 #if DriverDebugExtra
4151 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);
4153 if (Caret.Visible == true) {
4154 Caret.Paused = true;
4158 if (Caret.Visible == true) {
4160 Caret.Paused = false;
4162 msg.message = Msg.WM_PAINT;
4166 case XEventName.DestroyNotify: {
4168 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4169 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4171 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4172 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4173 CleanupCachedWindows (hwnd);
4175 #if DriverDebugDestroy
4176 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4179 msg.hwnd = hwnd.client_window;
4180 msg.message=Msg.WM_DESTROY;
4183 goto ProcessNextMessage;
4189 case XEventName.ClientMessage: {
4190 if (Dnd.HandleClientMessage (ref xevent)) {
4191 goto ProcessNextMessage;
4194 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4195 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4196 goto ProcessNextMessage;
4199 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4200 msg.message = Msg.WM_MOUSEHOVER;
4201 msg.wParam = GetMousewParam(0);
4202 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4206 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4207 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4208 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4209 msg.wParam = xevent.ClientMessageEvent.ptr3;
4210 msg.lParam = xevent.ClientMessageEvent.ptr4;
4211 if (msg.message == (Msg)Msg.WM_QUIT)
4217 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4218 #if DriverDebugXEmbed
4219 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4222 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4223 XSizeHints hints = new XSizeHints();
4226 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4228 hwnd.width = hints.max_width;
4229 hwnd.height = hints.max_height;
4230 hwnd.ClientRect = Rectangle.Empty;
4231 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4235 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4236 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4237 msg.message = Msg.WM_CLOSE;
4241 // We should not get this, but I'll leave the code in case we need it in the future
4242 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4243 goto ProcessNextMessage;
4246 goto ProcessNextMessage;
4250 goto ProcessNextMessage;
4257 internal override bool GetText(IntPtr handle, out string text) {
4264 IntPtr prop = IntPtr.Zero;
4266 XGetWindowProperty(DisplayHandle, handle,
4267 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4268 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4270 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4271 text = Marshal.PtrToStringUni (prop, (int)nitems);
4276 // fallback on the non-_NET property
4279 textptr = IntPtr.Zero;
4281 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4282 if (textptr != IntPtr.Zero) {
4283 text = Marshal.PtrToStringAnsi(textptr);
4294 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) {
4297 hwnd = Hwnd.ObjectFromHandle(handle);
4303 height = hwnd.height;
4305 PerformNCCalc(hwnd);
4307 client_width = hwnd.ClientRect.Width;
4308 client_height = hwnd.ClientRect.Height;
4313 // Should we throw an exception or fail silently?
4314 // throw new ArgumentException("Called with an invalid window handle", "handle");
4324 internal override FormWindowState GetWindowState(IntPtr handle) {
4327 hwnd = Hwnd.ObjectFromHandle(handle);
4329 if (hwnd.cached_window_state == (FormWindowState)(-1))
4330 hwnd.cached_window_state = UpdateWindowState (handle);
4332 return hwnd.cached_window_state;
4335 private FormWindowState UpdateWindowState (IntPtr handle) {
4340 IntPtr prop = IntPtr.Zero;
4344 XWindowAttributes attributes;
4347 hwnd = Hwnd.ObjectFromHandle(handle);
4351 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);
4352 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4353 for (int i = 0; i < (long)nitems; i++) {
4354 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4355 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4357 } else if (atom == _NET_WM_STATE_HIDDEN) {
4365 return FormWindowState.Minimized;
4366 } else if (maximized == 2) {
4367 return FormWindowState.Maximized;
4370 attributes = new XWindowAttributes();
4371 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4372 if (attributes.map_state == MapState.IsUnmapped) {
4373 return (FormWindowState)(-1);
4377 return FormWindowState.Normal;
4380 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4382 GrabConfined = Grab.Confined;
4383 GrabArea = Grab.Area;
4386 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4388 IntPtr confine_to_window;
4390 confine_to_window = IntPtr.Zero;
4392 if (confine_to_handle != IntPtr.Zero) {
4393 XWindowAttributes attributes = new XWindowAttributes();
4395 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4398 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4400 Grab.Area.X = attributes.x;
4401 Grab.Area.Y = attributes.y;
4402 Grab.Area.Width = attributes.width;
4403 Grab.Area.Height = attributes.height;
4404 Grab.Confined = true;
4405 confine_to_window = hwnd.client_window;
4410 hwnd = Hwnd.ObjectFromHandle(handle);
4413 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4414 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4415 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4416 EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4417 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4421 internal override void UngrabWindow(IntPtr hwnd) {
4423 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4424 XFlush(DisplayHandle);
4426 WindowUngrabbed (hwnd);
4429 private void WindowUngrabbed (IntPtr hwnd) {
4430 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4432 Grab.Hwnd = IntPtr.Zero;
4433 Grab.Confined = false;
4436 // lparam should be the handle to the window gaining the mouse capture,
4437 // but X doesn't seem to give us that information.
4438 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4439 // X will send a NotifyUngrab, but since it comes late sometimes we're
4440 // calling WindowUngrabbed directly from UngrabWindow in order to send
4441 // this WM right away.
4442 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4446 internal override void HandleException(Exception e) {
4447 StackTrace st = new StackTrace(e, true);
4448 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4449 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4452 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4455 hwnd = Hwnd.ObjectFromHandle(handle);
4458 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4460 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4464 internal override void InvalidateNC (IntPtr handle) {
4467 hwnd = Hwnd.ObjectFromHandle(handle);
4469 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4472 internal override bool IsEnabled(IntPtr handle) {
4473 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4474 return (hwnd != null && hwnd.Enabled);
4477 internal override bool IsVisible(IntPtr handle) {
4478 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4479 return (hwnd != null && hwnd.visible);
4482 internal override void KillTimer(Timer timer) {
4483 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4485 if (queue == null) {
4486 // This isn't really an error, MS doesn't start the timer if
4487 // it has no assosciated queue
4490 queue.timer_list.Remove (timer);
4493 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4499 hwnd = Hwnd.ObjectFromHandle(handle);
4502 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4509 internal override void OverrideCursor(IntPtr cursor)
4511 if (Grab.Hwnd != IntPtr.Zero) {
4512 XChangeActivePointerGrab (DisplayHandle,
4513 EventMask.ButtonMotionMask |
4514 EventMask.PointerMotionMask |
4515 EventMask.PointerMotionHintMask |
4516 EventMask.ButtonPressMask |
4517 EventMask.ButtonReleaseMask,
4518 cursor, IntPtr.Zero);
4522 OverrideCursorHandle = cursor;
4525 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4526 PaintEventArgs paint_event;
4531 // handle (and paint_hwnd) refers to the window that is should be painted.
4532 // msg.HWnd (and hwnd) refers to the window that got the paint message.
4535 hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4536 if (msg.HWnd == handle) {
4539 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4542 if (Caret.Visible == true) {
4543 Caret.Paused = true;
4550 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4552 Region clip_region = new Region ();
4553 clip_region.MakeEmpty();
4555 foreach (Rectangle r in hwnd.ClipRectangles) {
4556 clip_region.Union (r);
4559 if (hwnd.UserClip != null) {
4560 clip_region.Intersect(hwnd.UserClip);
4563 dc.Clip = clip_region;
4564 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4565 hwnd.expose_pending = false;
4567 hwnd.ClearInvalidArea();
4569 hwnd.drawing_stack.Push (paint_event);
4570 hwnd.drawing_stack.Push (dc);
4574 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4576 if (!hwnd.nc_invalid.IsEmpty) {
4577 dc.SetClip (hwnd.nc_invalid);
4578 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4580 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4582 hwnd.nc_expose_pending = false;
4584 hwnd.ClearNcInvalidArea ();
4586 hwnd.drawing_stack.Push (paint_event);
4587 hwnd.drawing_stack.Push (dc);
4593 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4596 hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4598 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4602 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4603 pe.SetGraphics (null);
4606 if (Caret.Visible == true) {
4608 Caret.Paused = false;
4612 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4613 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4614 XEventQueue queue = (XEventQueue) queue_id;
4617 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4618 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4622 if (queue.Count > 0) {
4625 // Only call UpdateMessageQueue if real events are pending
4626 // otherwise we go to sleep on the socket
4627 if (XPending(DisplayHandle) != 0) {
4628 UpdateMessageQueue((XEventQueue)queue_id);
4630 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4635 CheckTimers(queue.timer_list, DateTime.UtcNow);
4640 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4643 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4644 XEvent xevent = new XEvent ();
4645 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4647 xevent.type = XEventName.ClientMessage;
4648 xevent.ClientMessageEvent.display = DisplayHandle;
4651 xevent.ClientMessageEvent.window = hwnd.whole_window;
4653 xevent.ClientMessageEvent.window = IntPtr.Zero;
4656 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4657 xevent.ClientMessageEvent.format = 32;
4658 xevent.ClientMessageEvent.ptr1 = handle;
4659 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4660 xevent.ClientMessageEvent.ptr3 = wparam;
4661 xevent.ClientMessageEvent.ptr4 = lparam;
4663 hwnd.Queue.EnqueueLocked (xevent);
4668 internal override void PostQuitMessage(int exitCode) {
4669 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4670 XFlush(DisplayHandle);
4673 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4678 internal override void RequestNCRecalc(IntPtr handle) {
4681 hwnd = Hwnd.ObjectFromHandle(handle);
4687 PerformNCCalc(hwnd);
4688 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4689 InvalidateNC(handle);
4692 internal override void ResetMouseHover(IntPtr handle) {
4695 hwnd = Hwnd.ObjectFromHandle(handle);
4700 HoverState.Timer.Enabled = true;
4701 HoverState.X = mouse_position.X;
4702 HoverState.Y = mouse_position.Y;
4703 HoverState.Window = handle;
4707 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4713 hwnd = Hwnd.ObjectFromHandle(handle);
4716 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4723 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4729 hwnd = Hwnd.ObjectFromHandle(handle);
4732 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4735 Form form = Control.FromHandle (handle) as Form;
4736 if (form != null && form.window_manager != null) {
4737 dest_y_return -= form.window_manager.TitleBarHeight;
4744 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4747 XGCValues gc_values;
4749 hwnd = Hwnd.ObjectFromHandle(handle);
4751 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4753 /* We have an invalid area in the window we're scrolling.
4754 Adjust our stored invalid rectangle to to match the scrolled amount */
4769 if (area.Contains (hwnd.Invalid))
4770 hwnd.ClearInvalidArea ();
4771 hwnd.AddInvalidArea(r);
4774 gc_values = new XGCValues();
4776 if (with_children) {
4777 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4780 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4788 height = area.Height - YAmount;
4789 dest_y = area.Y + YAmount;
4792 src_y = area.Y - YAmount;
4793 height = area.Height + YAmount;
4799 width = area.Width - XAmount;
4800 dest_x = area.X + XAmount;
4803 src_x = area.X - XAmount;
4804 width = area.Width + XAmount;
4808 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4810 // Generate an expose for the area exposed by the horizontal scroll
4811 // We don't use AddExpose since we're
4813 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4814 } else if (XAmount < 0) {
4815 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4818 // Generate an expose for the area exposed by the vertical scroll
4820 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4821 } else if (YAmount < 0) {
4822 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4824 XFreeGC(DisplayHandle, gc);
4827 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4831 hwnd = Hwnd.GetObjectFromWindow(handle);
4833 rect = hwnd.ClientRect;
4836 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4839 internal override void SendAsyncMethod (AsyncMethodData method) {
4841 XEvent xevent = new XEvent ();
4843 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4845 xevent.type = XEventName.ClientMessage;
4846 xevent.ClientMessageEvent.display = DisplayHandle;
4847 xevent.ClientMessageEvent.window = method.Handle;
4848 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4849 xevent.ClientMessageEvent.format = 32;
4850 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4852 hwnd.Queue.EnqueueLocked (xevent);
4857 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4859 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4862 h = Hwnd.ObjectFromHandle(hwnd);
4864 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4865 AsyncMethodResult result;
4866 AsyncMethodData data;
4868 result = new AsyncMethodResult ();
4869 data = new AsyncMethodData ();
4872 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4873 data.Args = new object[] { hwnd, message, wParam, lParam };
4874 data.Result = result;
4876 SendAsyncMethod (data);
4877 #if DriverDebug || DriverDebugThreads
4878 Console.WriteLine ("Sending {0} message across.", message);
4883 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4886 internal override int SendInput(IntPtr handle, Queue keys) {
4887 if (handle == IntPtr.Zero)
4890 int count = keys.Count;
4891 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4893 while (keys.Count > 0) {
4895 MSG msg = (MSG)keys.Dequeue();
4897 XEvent xevent = new XEvent ();
4899 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4900 xevent.KeyEvent.display = DisplayHandle;
4903 xevent.KeyEvent.window = hwnd.whole_window;
4905 xevent.KeyEvent.window = IntPtr.Zero;
4908 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4910 hwnd.Queue.EnqueueLocked (xevent);
4915 internal override void SetAllowDrop (IntPtr handle, bool value)
4917 // We allow drop on all windows
4920 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4921 DragDropEffects allowed_effects)
4923 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4926 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4928 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4931 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4932 Form form = Control.FromHandle (handle) as Form;
4933 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4934 border_style == FormBorderStyle.SizableToolWindow)) {
4935 form.window_manager = new ToolWindowManager (form);
4938 RequestNCRecalc(handle);
4941 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4942 if (Caret.Hwnd == handle) {
4949 if (Caret.Visible == true) {
4951 Caret.Timer.Start();
4956 internal override void SetClipRegion(IntPtr handle, Region region) {
4959 hwnd = Hwnd.ObjectFromHandle(handle);
4964 hwnd.UserClip = region;
4967 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4970 if (OverrideCursorHandle == IntPtr.Zero) {
4971 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4975 LastCursorHandle = cursor;
4976 LastCursorWindow = handle;
4978 hwnd = Hwnd.ObjectFromHandle(handle);
4980 if (cursor != IntPtr.Zero) {
4981 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4983 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4985 XFlush(DisplayHandle);
4990 hwnd = Hwnd.ObjectFromHandle(handle);
4992 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4996 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4997 out int root_x, out int root_y, out int child_x, out int child_y,
5000 /* this code was written with the help of
5001 glance at gdk. I never would have realized we
5002 needed a loop in order to traverse down in the
5003 hierarchy. I would have assumed you'd get the
5004 most deeply nested child and have to do
5005 XQueryTree to move back up the hierarchy..
5006 stupid me, of course. */
5009 XGrabServer (display);
5011 XQueryPointer(display, w, out root, out c,
5012 out root_x, out root_y, out child_x, out child_y,
5018 IntPtr child_last = IntPtr.Zero;
5019 while (c != IntPtr.Zero) {
5021 XQueryPointer(display, c, out root, out c,
5022 out root_x, out root_y, out child_x, out child_y,
5025 XUngrabServer (display);
5031 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5032 if (handle == IntPtr.Zero) {
5035 int root_x, root_y, child_x, child_y, mask;
5038 * QueryPointer before warping
5039 * because if the warp is on
5040 * the RootWindow, the x/y are
5041 * relative to the current
5044 QueryPointer (DisplayHandle, RootWindow,
5047 out root_x, out root_y,
5048 out child_x, out child_y,
5051 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5053 XFlush (DisplayHandle);
5055 /* then we need to a
5056 * QueryPointer after warping
5057 * to manually generate a
5058 * motion event for the window
5061 QueryPointer (DisplayHandle, RootWindow,
5064 out root_x, out root_y,
5065 out child_x, out child_y,
5068 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5069 if (child_hwnd == null) {
5073 XEvent xevent = new XEvent ();
5075 xevent.type = XEventName.MotionNotify;
5076 xevent.MotionEvent.display = DisplayHandle;
5077 xevent.MotionEvent.window = child_hwnd.client_window;
5078 xevent.MotionEvent.root = RootWindow;
5079 xevent.MotionEvent.x = child_x;
5080 xevent.MotionEvent.y = child_y;
5081 xevent.MotionEvent.x_root = root_x;
5082 xevent.MotionEvent.y_root = root_y;
5083 xevent.MotionEvent.state = mask;
5085 child_hwnd.Queue.EnqueueLocked (xevent);
5090 hwnd = Hwnd.ObjectFromHandle(handle);
5092 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5097 internal override void SetFocus(IntPtr handle) {
5099 IntPtr prev_focus_window;
5101 hwnd = Hwnd.ObjectFromHandle(handle);
5103 if (hwnd.client_window == FocusWindow) {
5107 prev_focus_window = FocusWindow;
5108 FocusWindow = hwnd.client_window;
5110 if (prev_focus_window != IntPtr.Zero) {
5111 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5113 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5115 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5118 internal override void SetIcon(IntPtr handle, Icon icon) {
5121 hwnd = Hwnd.ObjectFromHandle(handle);
5123 SetIcon(hwnd, icon);
5127 internal override void SetMenu(IntPtr handle, Menu menu) {
5130 hwnd = Hwnd.ObjectFromHandle(handle);
5133 RequestNCRecalc(handle);
5136 internal override void SetModal(IntPtr handle, bool Modal) {
5138 ModalWindows.Push(handle);
5140 if (ModalWindows.Contains(handle)) {
5143 if (ModalWindows.Count > 0) {
5144 Activate((IntPtr)ModalWindows.Peek());
5148 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5149 Control ctrl = Control.FromHandle (handle);
5150 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5153 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5156 hwnd = Hwnd.ObjectFromHandle(handle);
5157 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5160 #if DriverDebug || DriverDebugParent
5161 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5163 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5169 internal override void SetTimer (Timer timer) {
5170 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5172 if (queue == null) {
5173 // This isn't really an error, MS doesn't start the timer if
5174 // it has no assosciated queue
5177 queue.timer_list.Add (timer);
5181 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5183 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5187 int[] atoms = new int[8];
5188 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5189 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5193 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5199 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5203 hwnd = Hwnd.ObjectFromHandle(handle);
5205 if (handle_owner != IntPtr.Zero) {
5206 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5212 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5213 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5215 if (hwnd_owner != null) {
5216 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5218 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5223 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5229 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5233 hwnd = Hwnd.ObjectFromHandle(handle);
5234 hwnd.visible = visible;
5238 MapWindow(hwnd, WindowType.Both);
5240 if (Control.FromHandle(handle) is Form) {
5243 s = ((Form)Control.FromHandle(handle)).WindowState;
5246 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5247 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5251 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5254 UnmapWindow(hwnd, WindowType.Both);
5260 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5261 Control ctrl = Control.FromHandle (handle);
5262 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5265 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5271 hwnd = Hwnd.ObjectFromHandle(handle);
5276 hints = new XSizeHints();
5278 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5279 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5281 min = TranslateWindowSizeToXWindowSize (cp, min);
5282 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5283 hints.min_width = min.Width;
5284 hints.min_height = min.Height;
5287 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5289 max = TranslateWindowSizeToXWindowSize (cp, max);
5290 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5291 hints.max_width = max.Width;
5292 hints.max_height = max.Height;
5295 if (hints.flags != IntPtr.Zero) {
5296 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5297 // they will maximize the window to fill the screen/parent no matter what.
5298 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5299 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5302 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5304 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5305 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5306 hints.x = maximized.X;
5307 hints.y = maximized.Y;
5308 hints.width = maximized.Width;
5309 hints.height = maximized.Height;
5311 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5312 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5317 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5320 hwnd = Hwnd.ObjectFromHandle(handle);
5326 // Win32 automatically changes negative width/height to 0.
5332 // X requires a sanity check for width & height; otherwise it dies
5333 if (hwnd.zero_sized && width > 0 && height > 0) {
5335 MapWindow(hwnd, WindowType.Whole);
5337 hwnd.zero_sized = false;
5340 if ((width < 1) || (height < 1)) {
5341 hwnd.zero_sized = true;
5342 UnmapWindow(hwnd, WindowType.Whole);
5345 // Save a server roundtrip (and prevent a feedback loop)
5346 if ((hwnd.x == x) && (hwnd.y == y) &&
5347 (hwnd.width == width) && (hwnd.height == height)) {
5351 if (!hwnd.zero_sized) {
5356 hwnd.height = height;
5357 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5359 if (hwnd.fixed_size) {
5360 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5364 Control ctrl = Control.FromHandle (handle);
5365 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5366 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5367 PerformNCCalc(hwnd);
5371 // Update our position/size immediately, so
5372 // that future calls to SetWindowPos aren't
5373 // kept from calling XMoveResizeWindow (by the
5374 // "Save a server roundtrip" block above).
5378 hwnd.height = height;
5379 hwnd.ClientRect = Rectangle.Empty;
5382 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5383 FormWindowState current_state;
5386 hwnd = Hwnd.ObjectFromHandle(handle);
5388 current_state = GetWindowState(handle);
5390 if (current_state == state) {
5395 case FormWindowState.Normal: {
5397 if (current_state == FormWindowState.Minimized) {
5398 MapWindow(hwnd, WindowType.Both);
5399 } else if (current_state == FormWindowState.Maximized) {
5400 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5407 case FormWindowState.Minimized: {
5409 if (current_state == FormWindowState.Maximized) {
5410 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5412 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5417 case FormWindowState.Maximized: {
5419 if (current_state == FormWindowState.Minimized) {
5420 MapWindow(hwnd, WindowType.Both);
5423 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5431 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5434 hwnd = Hwnd.ObjectFromHandle(handle);
5435 SetHwndStyles(hwnd, cp);
5436 SetWMStyles(hwnd, cp);
5439 internal override double GetWindowTransparency(IntPtr handle)
5444 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5448 hwnd = Hwnd.ObjectFromHandle(handle);
5454 hwnd.opacity = (uint)(0xffffffff * transparency);
5455 opacity = (IntPtr)((int)hwnd.opacity);
5457 IntPtr w = hwnd.whole_window;
5458 if (hwnd.reparented)
5459 w = XGetParent (hwnd.whole_window);
5460 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5463 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5464 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5472 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5475 } else if (!bottom) {
5476 Hwnd after_hwnd = null;
5478 if (after_handle != IntPtr.Zero) {
5479 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5482 XWindowChanges values = new XWindowChanges();
5484 if (after_hwnd == null) {
5485 // Work around metacity 'issues'
5489 atoms[0] = unixtime();
5490 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5492 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5493 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5495 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5498 values.sibling = after_hwnd.whole_window;
5499 values.stack_mode = StackMode.Below;
5502 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5507 XLowerWindow(DisplayHandle, hwnd.whole_window);
5514 internal override void ShowCursor(bool show) {
5515 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5518 internal override object StartLoop(Thread thread) {
5519 XEventQueue q = ThreadQueue(thread);
5523 internal override TransparencySupport SupportsTransparency() {
5524 // We need to check if the x compositing manager is running
5525 return TransparencySupport.Set;
5528 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5529 GetSystrayManagerWindow();
5531 if (SystrayMgrWindow != IntPtr.Zero) {
5532 XSizeHints size_hints;
5535 hwnd = Hwnd.ObjectFromHandle(handle);
5537 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5541 if (hwnd.client_window != hwnd.whole_window) {
5542 XDestroyWindow(DisplayHandle, hwnd.client_window);
5543 hwnd.client_window = hwnd.whole_window;
5546 /* by virtue of the way the tests are ordered when determining if it's PAINT
5547 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5548 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5549 there's a pending expose). */
5550 if (hwnd.nc_expose_pending) {
5551 hwnd.nc_expose_pending = false;
5552 if (!hwnd.expose_pending)
5553 hwnd.Queue.Paint.Remove (hwnd);
5556 size_hints = new XSizeHints();
5558 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5560 size_hints.min_width = 24;
5561 size_hints.min_height = 24;
5562 size_hints.max_width = 24;
5563 size_hints.max_height = 24;
5564 size_hints.base_width = 24;
5565 size_hints.base_height = 24;
5567 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5569 int[] atoms = new int[2];
5570 atoms [0] = 1; // Version 1
5571 atoms [1] = 1; // we want to be mapped
5573 // This line cost me 3 days...
5574 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5576 // Need to pick some reasonable defaults
5578 tt.AutomaticDelay = 350;
5579 tt.InitialDelay = 250;
5580 tt.ReshowDelay = 250;
5581 tt.ShowAlways = true;
5583 if ((tip != null) && (tip != string.Empty)) {
5584 tt.SetToolTip(Control.FromHandle(handle), tip);
5590 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5598 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5601 control = Control.FromHandle(handle);
5602 if (control != null && tt != null) {
5603 tt.SetToolTip(control, tip);
5605 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5612 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5614 SetVisible (handle, false, false);
5616 // The caller can now re-dock it later...
5624 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5626 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5627 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5631 internal override bool Text(IntPtr handle, string text) {
5634 hwnd = Hwnd.ObjectFromHandle(handle);
5637 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5638 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5640 // XXX this has problems with UTF8.
5641 // we need to either use the actual
5642 // text if it's latin-1, or convert it
5643 // to compound text if it's in a
5644 // different charset.
5645 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5650 internal override bool TranslateMessage(ref MSG msg) {
5651 return Keyboard.TranslateMessage (ref msg);
5654 internal override void UpdateWindow(IntPtr handle) {
5657 hwnd = Hwnd.ObjectFromHandle(handle);
5659 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5663 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5664 hwnd.Queue.Paint.Remove(hwnd);
5667 internal override void CreateOffscreenDrawable (IntPtr handle,
5668 int width, int height,
5669 out object offscreen_drawable)
5672 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5674 XGetGeometry (DisplayHandle, handle,
5676 out x_out, out y_out,
5677 out width_out, out height_out,
5678 out border_width_out, out depth_out);
5680 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5682 offscreen_drawable = pixmap;
5686 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5688 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5691 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5693 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5696 internal override void BlitFromOffscreen (IntPtr dest_handle,
5698 object offscreen_drawable,
5699 Graphics offscreen_dc,
5702 XGCValues gc_values;
5705 gc_values = new XGCValues();
5707 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5709 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5710 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5712 XFreeGC (DisplayHandle, gc);
5715 #endregion // Public Static Methods
5718 internal override event EventHandler Idle;
5719 #endregion // Events
5721 #region Xcursor imports
5722 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5723 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5725 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5726 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5728 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5729 internal extern static void XcursorImagesDestroy (IntPtr images);
5731 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5732 internal extern static int XcursorGetDefaultSize (IntPtr display);
5734 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5735 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5737 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5738 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5741 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5742 internal extern static IntPtr XOpenDisplay(IntPtr display);
5743 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5744 internal extern static int XCloseDisplay(IntPtr display);
5745 [DllImport ("libX11", EntryPoint="XSynchronize")]
5746 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5748 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5749 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);
5750 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5751 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5752 [DllImport ("libX11", EntryPoint="XMapWindow")]
5753 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5754 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5755 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5756 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5757 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5758 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5759 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5760 [DllImport ("libX11", EntryPoint="XRootWindow")]
5761 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5762 [DllImport ("libX11", EntryPoint="XNextEvent")]
5763 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5764 [DllImport ("libX11")]
5765 internal extern static int XConnectionNumber (IntPtr diplay);
5766 [DllImport ("libX11")]
5767 internal extern static int XPending (IntPtr diplay);
5768 [DllImport ("libX11", EntryPoint="XSelectInput")]
5769 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5771 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5772 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5774 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5775 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5776 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5777 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5779 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5780 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5782 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5783 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5785 [DllImport ("libX11", EntryPoint="XFlush")]
5786 internal extern static int XFlush(IntPtr display);
5788 [DllImport ("libX11", EntryPoint="XSetWMName")]
5789 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5791 [DllImport ("libX11", EntryPoint="XStoreName")]
5792 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5794 [DllImport ("libX11", EntryPoint="XFetchName")]
5795 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5797 [DllImport ("libX11", EntryPoint="XSendEvent")]
5798 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5800 [DllImport ("libX11", EntryPoint="XQueryTree")]
5801 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);
5803 [DllImport ("libX11", EntryPoint="XFree")]
5804 internal extern static int XFree(IntPtr data);
5806 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5807 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5809 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5810 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5812 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5813 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5815 [DllImport ("libX11", EntryPoint="XInternAtom")]
5816 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5818 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5819 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5821 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5822 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5824 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5825 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);
5827 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5828 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5830 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5831 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);
5833 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5834 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);
5836 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5837 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);
5839 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5840 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);
5842 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5843 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);
5845 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5846 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);
5848 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5849 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);
5851 [DllImport ("libX11", EntryPoint="XClearWindow")]
5852 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5854 [DllImport ("libX11", EntryPoint="XClearArea")]
5855 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5858 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5859 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5861 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5862 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5864 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5865 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5867 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5868 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5870 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5871 internal extern static int XDefaultScreen(IntPtr display);
5873 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5874 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5876 [DllImport ("libX11", EntryPoint="XLookupColor")]
5877 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5879 [DllImport ("libX11", EntryPoint="XAllocColor")]
5880 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5882 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5883 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5885 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5886 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5888 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5889 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5891 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5892 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5894 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5895 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5897 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5898 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5900 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5901 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5903 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5904 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5906 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5907 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5909 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5910 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5913 [DllImport ("libX11", EntryPoint="XCreateGC")]
5914 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5916 [DllImport ("libX11", EntryPoint="XFreeGC")]
5917 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5919 [DllImport ("libX11", EntryPoint="XSetFunction")]
5920 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5922 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5923 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5925 [DllImport ("libX11", EntryPoint="XDrawLine")]
5926 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5928 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5929 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5931 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5932 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5934 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5935 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5937 [DllImport ("libX11", EntryPoint="XCopyArea")]
5938 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);
5940 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5941 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);
5943 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5944 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5946 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5947 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5949 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5950 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5952 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5953 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5955 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5956 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5958 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5959 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5961 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5962 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);
5964 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5965 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5967 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5968 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5970 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5971 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5973 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5974 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5976 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5977 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5979 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5980 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5982 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5983 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5985 [DllImport ("libX11", EntryPoint="XGrabServer")]
5986 internal extern static void XGrabServer(IntPtr display);
5988 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5989 internal extern static void XUngrabServer(IntPtr display);
5991 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5992 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5994 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5995 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5997 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5998 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6000 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6001 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6003 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6004 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6006 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6007 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6009 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6010 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6012 [DllImport ("libX11", EntryPoint="XInitThreads")]
6013 internal extern static int XInitThreads();
6015 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6016 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6018 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6019 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6021 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6022 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6024 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6025 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6027 [DllImport ("libX11", EntryPoint="XSetForeground")]
6028 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6030 [DllImport ("libX11", EntryPoint="XSetBackground")]
6031 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6033 [DllImport ("libX11", EntryPoint="XBell")]
6034 internal extern static int XBell(IntPtr display, int percent);
6036 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6037 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6039 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6040 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6042 [DllImport ("libX11")]
6043 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6045 [DllImport ("libX11")]
6046 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);