1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
90 private int render_major_opcode;
91 private int render_first_event;
92 private int render_first_error;
95 private static IntPtr ClipMagic;
96 private static ClipboardStruct Clipboard; // Our clipboard
99 private static IntPtr PostAtom; // PostMessage atom
100 private static IntPtr AsyncAtom; // Support for async messages
103 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
105 private static Pollfd[] pollfds; // For watching the X11 socket
106 private static bool wake_waiting;
107 private static object wake_waiting_lock = new object ();
109 private static X11Keyboard Keyboard; //
110 private static X11Dnd Dnd;
111 private static Socket listen; //
112 private static Socket wake; //
113 private static Socket wake_receive; //
114 private static byte[] network_buffer; //
115 private static bool detectable_key_auto_repeat;
118 private static IntPtr ActiveWindow; // Handle of the active window
119 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
122 private static Stack ModalWindows; // Stack of our modal windows
125 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
128 private static IntPtr LastCursorWindow; // The last window we set the cursor on
129 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
130 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
133 private static CaretStruct Caret; //
136 private static IntPtr WM_PROTOCOLS;
137 private static IntPtr WM_DELETE_WINDOW;
138 private static IntPtr WM_TAKE_FOCUS;
139 //private static IntPtr _NET_SUPPORTED;
140 //private static IntPtr _NET_CLIENT_LIST;
141 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
142 private static IntPtr _NET_DESKTOP_GEOMETRY;
143 //private static IntPtr _NET_DESKTOP_VIEWPORT;
144 private static IntPtr _NET_CURRENT_DESKTOP;
145 //private static IntPtr _NET_DESKTOP_NAMES;
146 private static IntPtr _NET_ACTIVE_WINDOW;
147 private static IntPtr _NET_WORKAREA;
148 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
149 //private static IntPtr _NET_VIRTUAL_ROOTS;
150 //private static IntPtr _NET_DESKTOP_LAYOUT;
151 //private static IntPtr _NET_SHOWING_DESKTOP;
152 //private static IntPtr _NET_CLOSE_WINDOW;
153 //private static IntPtr _NET_MOVERESIZE_WINDOW;
154 //private static IntPtr _NET_WM_MOVERESIZE;
155 //private static IntPtr _NET_RESTACK_WINDOW;
156 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
157 private static IntPtr _NET_WM_NAME;
158 //private static IntPtr _NET_WM_VISIBLE_NAME;
159 //private static IntPtr _NET_WM_ICON_NAME;
160 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
161 //private static IntPtr _NET_WM_DESKTOP;
162 private static IntPtr _NET_WM_WINDOW_TYPE;
163 private static IntPtr _NET_WM_STATE;
164 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
165 //private static IntPtr _NET_WM_STRUT;
166 //private static IntPtr _NET_WM_STRUT_PARTIAL;
167 //private static IntPtr _NET_WM_ICON_GEOMETRY;
168 private static IntPtr _NET_WM_ICON;
169 //private static IntPtr _NET_WM_PID;
170 //private static IntPtr _NET_WM_HANDLED_ICONS;
171 private static IntPtr _NET_WM_USER_TIME;
172 private static IntPtr _NET_FRAME_EXTENTS;
173 //private static IntPtr _NET_WM_PING;
174 //private static IntPtr _NET_WM_SYNC_REQUEST;
175 private static IntPtr _NET_SYSTEM_TRAY_S;
176 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
177 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
178 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
179 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
180 private static IntPtr _XEMBED;
181 private static IntPtr _XEMBED_INFO;
182 private static IntPtr _MOTIF_WM_HINTS;
183 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
184 private static IntPtr _NET_WM_STATE_ABOVE;
185 private static IntPtr _NET_WM_STATE_MODAL;
186 private static IntPtr _NET_WM_STATE_HIDDEN;
187 private static IntPtr _NET_WM_CONTEXT_HELP;
188 private static IntPtr _NET_WM_WINDOW_OPACITY;
189 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
190 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
193 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
194 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
195 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
196 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
197 private static IntPtr CLIPBOARD;
198 private static IntPtr PRIMARY;
199 //private static IntPtr DIB;
200 private static IntPtr OEMTEXT;
201 private static IntPtr UNICODETEXT;
202 private static IntPtr TARGETS;
204 // mouse hover message generation
205 private static HoverStruct HoverState; //
207 // double click message generation
208 private static ClickStruct ClickPending; //
210 // Support for mouse grab
211 private static GrabStruct Grab; //
214 Point mouse_position; // Last position of mouse, in screen coords
215 internal static MouseButtons MouseState; // Last state of mouse buttons
218 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
220 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
221 EventMask.ButtonReleaseMask |
222 EventMask.KeyPressMask |
223 EventMask.KeyReleaseMask |
224 EventMask.EnterWindowMask |
225 EventMask.LeaveWindowMask |
226 EventMask.ExposureMask |
227 EventMask.FocusChangeMask |
228 EventMask.PointerMotionMask |
229 EventMask.SubstructureNotifyMask);
231 static readonly object lockobj = new object ();
233 #endregion // Local Variables
235 private XplatUIX11() {
236 // Handle singleton stuff first
239 // Now regular initialization
240 XlibLock = new object ();
241 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
244 ErrorExceptions = false;
246 // X11 Initialization
247 SetDisplay(XOpenDisplay(IntPtr.Zero));
248 X11DesktopColors.Initialize();
251 // Disable keyboard autorepeat
253 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
254 detectable_key_auto_repeat = true;
256 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
257 detectable_key_auto_repeat = false;
260 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
261 ErrorHandler = new XErrorHandler(HandleError);
262 XSetErrorHandler(ErrorHandler);
266 // Remove our display handle from S.D
267 Graphics.FromHdcInternal (IntPtr.Zero);
270 #endregion // Constructors
272 #region Singleton Specific Code
273 public static XplatUIX11 GetInstance() {
275 if (Instance == null) {
276 Instance=new XplatUIX11();
283 public int Reference {
290 #region Internal Properties
291 internal static IntPtr Display {
293 return DisplayHandle;
297 XplatUIX11.GetInstance().SetDisplay(value);
301 internal static int Screen {
311 internal static IntPtr RootWindowHandle {
321 internal static IntPtr Visual {
327 CustomVisual = value;
331 internal static IntPtr ColorMap {
333 return CustomColormap;
337 CustomColormap = value;
342 #region XExceptionClass
343 internal class XException : ApplicationException {
347 XRequest RequestCode;
351 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
352 this.Display = Display;
353 this.ResourceID = ResourceID;
354 this.Serial = Serial;
355 this.RequestCode = RequestCode;
356 this.ErrorCode = ErrorCode;
357 this.MinorCode = MinorCode;
360 public override string Message {
362 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
366 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
375 sb = new StringBuilder(160);
376 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
377 x_error_text = sb.ToString();
378 hwnd = Hwnd.ObjectFromHandle(ResourceID);
380 hwnd_text = hwnd.ToString();
381 c = Control.FromHandle(hwnd.Handle);
383 control_text = c.ToString();
385 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
388 hwnd_text = "<null>";
389 control_text = "<null>";
393 error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
397 #endregion // XExceptionClass
399 #region Internal Methods
400 internal void SetDisplay(IntPtr display_handle) {
401 if (display_handle != IntPtr.Zero) {
404 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
405 hwnd = Hwnd.ObjectFromHandle(FosterParent);
406 XDestroyWindow(DisplayHandle, FosterParent);
410 if (DisplayHandle != IntPtr.Zero) {
411 XCloseDisplay(DisplayHandle);
414 DisplayHandle=display_handle;
416 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
417 // been hacked to do this for us.
418 Graphics.FromHdcInternal (DisplayHandle);
420 // query for the render extension so
421 // we can ignore the spurious
422 // BadPicture errors that are
423 // generated by cairo/render.
424 XQueryExtension (DisplayHandle, "RENDER",
425 ref render_major_opcode, ref render_first_event, ref render_first_error);
428 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
429 XSynchronize(DisplayHandle, true);
432 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
433 ErrorExceptions = true;
437 ScreenNo = XDefaultScreen(DisplayHandle);
438 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
439 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
441 // Create the foster parent
442 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
443 if (FosterParent==IntPtr.Zero) {
444 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
448 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
449 hwnd.WholeWindow = FosterParent;
450 hwnd.ClientWindow = FosterParent;
452 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
454 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
455 hwnd.whole_window = RootWindow;
456 hwnd.ClientWindow = RootWindow;
458 // For sleeping on the X11 socket
459 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
460 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
464 // To wake up when a timer is ready
465 network_buffer = new byte[10];
467 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
468 wake.Connect(listen.LocalEndPoint);
469 wake_receive = listen.Accept();
472 pollfds = new Pollfd [2];
473 pollfds [0] = new Pollfd ();
474 pollfds [0].fd = XConnectionNumber (DisplayHandle);
475 pollfds [0].events = PollEvents.POLLIN;
477 pollfds [1] = new Pollfd ();
478 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
479 pollfds [1].events = PollEvents.POLLIN;
482 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
483 Dnd = new X11Dnd (DisplayHandle, Keyboard);
485 DoubleClickInterval = 500;
487 HoverState.Interval = 500;
488 HoverState.Timer = new Timer();
489 HoverState.Timer.Enabled = false;
490 HoverState.Timer.Interval = HoverState.Interval;
491 HoverState.Timer.Tick += new EventHandler(MouseHover);
492 HoverState.Size = new Size(4, 4);
496 ActiveWindow = IntPtr.Zero;
497 FocusWindow = IntPtr.Zero;
498 ModalWindows = new Stack(3);
500 MouseState = MouseButtons.None;
501 mouse_position = new Point(0, 0);
503 Caret.Timer = new Timer();
504 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
505 Caret.Timer.Tick += new EventHandler(CaretCallback);
509 // Grab atom changes off the root window to catch certain WM events
510 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
512 // Handle any upcoming errors
513 ErrorHandler = new XErrorHandler(HandleError);
514 XSetErrorHandler(ErrorHandler);
516 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
519 #endregion // Internal Methods
521 #region Private Methods
522 private int unixtime() {
523 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
525 return (int) t.TotalSeconds;
528 private static void SetupAtoms() {
529 // make sure this array stays in sync with the statements below
530 string [] atom_names = new string[] {
535 //"_NET_CLIENT_LIST",
536 //"_NET_NUMBER_OF_DESKTOPS",
537 "_NET_DESKTOP_GEOMETRY",
538 //"_NET_DESKTOP_VIEWPORT",
539 "_NET_CURRENT_DESKTOP",
540 //"_NET_DESKTOP_NAMES",
541 "_NET_ACTIVE_WINDOW",
543 //"_NET_SUPPORTING_WM_CHECK",
544 //"_NET_VIRTUAL_ROOTS",
545 //"_NET_DESKTOP_LAYOUT",
546 //"_NET_SHOWING_DESKTOP",
547 //"_NET_CLOSE_WINDOW",
548 //"_NET_MOVERESIZE_WINDOW",
549 //"_NET_WM_MOVERESIZE",
550 //"_NET_RESTACK_WINDOW",
551 //"_NET_REQUEST_FRAME_EXTENTS",
553 //"_NET_WM_VISIBLE_NAME",
554 //"_NET_WM_ICON_NAME",
555 //"_NET_WM_VISIBLE_ICON_NAME",
557 "_NET_WM_WINDOW_TYPE",
559 //"_NET_WM_ALLOWED_ACTIONS",
561 //"_NET_WM_STRUT_PARTIAL",
562 //"_NET_WM_ICON_GEOMETRY",
565 //"_NET_WM_HANDLED_ICONS",
567 "_NET_FRAME_EXTENTS",
569 //"_NET_WM_SYNC_REQUEST",
570 "_NET_SYSTEM_TRAY_OPCODE",
571 //"_NET_SYSTEM_TRAY_ORIENTATION",
572 "_NET_WM_STATE_MAXIMIZED_HORZ",
573 "_NET_WM_STATE_MAXIMIZED_VERT",
574 "_NET_WM_STATE_HIDDEN",
578 "_NET_WM_STATE_SKIP_TASKBAR",
579 "_NET_WM_STATE_ABOVE",
580 "_NET_WM_STATE_MODAL",
581 "_NET_WM_CONTEXT_HELP",
582 "_NET_WM_WINDOW_OPACITY",
583 //"_NET_WM_WINDOW_TYPE_DESKTOP",
584 //"_NET_WM_WINDOW_TYPE_DOCK",
585 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
586 //"_NET_WM_WINDOW_TYPE_MENU",
587 "_NET_WM_WINDOW_TYPE_UTILITY",
588 "_NET_WM_WINDOW_TYPE_DIALOG",
589 //"_NET_WM_WINDOW_TYPE_SPLASH",
590 "_NET_WM_WINDOW_TYPE_NORMAL",
597 "_SWF_PostMessageAtom",
600 IntPtr[] atoms = new IntPtr [atom_names.Length];;
602 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
605 WM_PROTOCOLS = atoms [off++];
606 WM_DELETE_WINDOW = atoms [off++];
607 WM_TAKE_FOCUS = atoms [off++];
608 //_NET_SUPPORTED = atoms [off++];
609 //_NET_CLIENT_LIST = atoms [off++];
610 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
611 _NET_DESKTOP_GEOMETRY = atoms [off++];
612 //_NET_DESKTOP_VIEWPORT = atoms [off++];
613 _NET_CURRENT_DESKTOP = atoms [off++];
614 //_NET_DESKTOP_NAMES = atoms [off++];
615 _NET_ACTIVE_WINDOW = atoms [off++];
616 _NET_WORKAREA = atoms [off++];
617 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
618 //_NET_VIRTUAL_ROOTS = atoms [off++];
619 //_NET_DESKTOP_LAYOUT = atoms [off++];
620 //_NET_SHOWING_DESKTOP = atoms [off++];
621 //_NET_CLOSE_WINDOW = atoms [off++];
622 //_NET_MOVERESIZE_WINDOW = atoms [off++];
623 //_NET_WM_MOVERESIZE = atoms [off++];
624 //_NET_RESTACK_WINDOW = atoms [off++];
625 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
626 _NET_WM_NAME = atoms [off++];
627 //_NET_WM_VISIBLE_NAME = atoms [off++];
628 //_NET_WM_ICON_NAME = atoms [off++];
629 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
630 //_NET_WM_DESKTOP = atoms [off++];
631 _NET_WM_WINDOW_TYPE = atoms [off++];
632 _NET_WM_STATE = atoms [off++];
633 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
634 //_NET_WM_STRUT = atoms [off++];
635 //_NET_WM_STRUT_PARTIAL = atoms [off++];
636 //_NET_WM_ICON_GEOMETRY = atoms [off++];
637 _NET_WM_ICON = atoms [off++];
638 //_NET_WM_PID = atoms [off++];
639 //_NET_WM_HANDLED_ICONS = atoms [off++];
640 _NET_WM_USER_TIME = atoms [off++];
641 _NET_FRAME_EXTENTS = atoms [off++];
642 //_NET_WM_PING = atoms [off++];
643 //_NET_WM_SYNC_REQUEST = atoms [off++];
644 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
645 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
646 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
647 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
648 _NET_WM_STATE_HIDDEN = atoms [off++];
649 _XEMBED = atoms [off++];
650 _XEMBED_INFO = atoms [off++];
651 _MOTIF_WM_HINTS = atoms [off++];
652 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
653 _NET_WM_STATE_ABOVE = atoms [off++];
654 _NET_WM_STATE_MODAL = atoms [off++];
655 _NET_WM_CONTEXT_HELP = atoms [off++];
656 _NET_WM_WINDOW_OPACITY = atoms [off++];
657 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
658 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
659 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
660 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
661 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
662 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
663 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
664 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
665 CLIPBOARD = atoms [off++];
666 PRIMARY = atoms [off++];
667 OEMTEXT = atoms [off++];
668 UNICODETEXT = atoms [off++];
669 TARGETS = atoms [off++];
670 AsyncAtom = atoms [off++];
671 PostAtom = atoms [off++];
672 HoverState.Atom = atoms [off++];
674 //DIB = (IntPtr)Atom.XA_PIXMAP;
675 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
678 private void GetSystrayManagerWindow() {
679 XGrabServer(DisplayHandle);
680 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
681 XUngrabServer(DisplayHandle);
682 XFlush(DisplayHandle);
685 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
689 xev.ClientMessageEvent.type = XEventName.ClientMessage;
690 xev.ClientMessageEvent.send_event = true;
691 xev.ClientMessageEvent.window = window;
692 xev.ClientMessageEvent.message_type = message_type;
693 xev.ClientMessageEvent.format = 32;
694 xev.ClientMessageEvent.ptr1 = l0;
695 xev.ClientMessageEvent.ptr2 = l1;
696 xev.ClientMessageEvent.ptr3 = l2;
697 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
700 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
704 xev.ClientMessageEvent.type = XEventName.ClientMessage;
705 xev.ClientMessageEvent.send_event = true;
706 xev.ClientMessageEvent.window = window;
707 xev.ClientMessageEvent.message_type = message_type;
708 xev.ClientMessageEvent.format = 32;
709 xev.ClientMessageEvent.ptr1 = l0;
710 xev.ClientMessageEvent.ptr2 = l1;
711 xev.ClientMessageEvent.ptr3 = l2;
712 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
715 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
716 // WM_CREATE and WM_DESTROY causes
717 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
721 if (child == IntPtr.Zero) {
725 hwnd = Hwnd.GetObjectFromWindow (child);
731 if (hwnd.Handle == IntPtr.Zero) {
735 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
739 if (hwnd.Parent == null) {
743 if (hwnd.Parent.Handle == IntPtr.Zero) {
747 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
748 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
750 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
753 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
756 bool StyleSet (int s, WindowStyles ws)
758 return (s & (int)ws) == (int)ws;
761 bool ExStyleSet (int ex, WindowExStyles exws)
763 return (ex & (int)exws) == (int)exws;
766 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
768 return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
771 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
774 * If this is a form with no window manager, X is handling all the border and caption painting
775 * so remove that from the area (since the area we set of the window here is the part of the window
776 * we're painting in only)
778 Rectangle rect = hwnd.ClientRect;
779 Form form = ctrl as Form;
780 if (form != null && form.window_manager == null) {
781 CreateParams cp = form.GetCreateParams ();
782 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
783 Rectangle xrect = rect;
785 xrect.Y -= borders.top;
786 xrect.X -= borders.left;
787 xrect.Width += borders.left + borders.right;
788 xrect.Height += borders.top + borders.bottom;
793 if (rect.Width < 1 || rect.Height < 1) {
803 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
806 * If this is a form with no window manager, X is handling all the border and caption painting
807 * so remove that from the area (since the area we set of the window here is the part of the window
808 * we're painting in only)
810 Size rect = new Size (cp.Width, cp.Height);
811 Form form = cp.control as Form;
812 if (form != null && form.window_manager == null) {
813 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
816 xrect.Width -= borders.left + borders.right;
817 xrect.Height -= borders.top + borders.bottom;
821 if (rect.Height == 0)
828 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
831 * If this is a form with no window manager, X is handling all the border and caption painting
832 * so remove that from the area (since the area we set of the window here is the part of the window
833 * we're painting in only)
835 Size rect = new Size (xWidth, xHeight);
836 Form form = cp.control as Form;
837 if (form != null && form.window_manager == null) {
838 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
841 xrect.Width += borders.left + borders.right;
842 xrect.Height += borders.top + borders.bottom;
849 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
855 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
856 frame = FrameExtents (hwnd.whole_window);
861 return new Point (x, y);
864 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) {
867 tool_caption_height = 19;
868 border_static = false;
870 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
871 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
872 border_style = FormBorderStyle.Fixed3D;
873 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
874 border_style = FormBorderStyle.Fixed3D;
875 border_static = true;
876 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
877 border_style = FormBorderStyle.None;
879 border_style = FormBorderStyle.FixedSingle;
881 title_style = TitleStyle.None;
883 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
885 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
886 title_style = TitleStyle.Tool;
888 title_style = TitleStyle.Normal;
892 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
895 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
896 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
897 border_style = (FormBorderStyle) 0xFFFF;
899 border_style = FormBorderStyle.None;
904 title_style = TitleStyle.None;
905 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
906 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
907 title_style = TitleStyle.Tool;
909 title_style = TitleStyle.Normal;
913 border_style = FormBorderStyle.None;
915 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
916 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
917 border_style = FormBorderStyle.SizableToolWindow;
919 border_style = FormBorderStyle.Sizable;
922 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
923 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
924 border_style = FormBorderStyle.Fixed3D;
925 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
926 border_style = FormBorderStyle.Fixed3D;
927 border_static = true;
928 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
929 border_style = FormBorderStyle.FixedDialog;
930 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
931 border_style = FormBorderStyle.FixedToolWindow;
932 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
933 border_style = FormBorderStyle.FixedSingle;
936 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
937 border_style = FormBorderStyle.FixedSingle;
944 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
945 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);
948 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
949 MotifWmHints mwmHints;
950 MotifFunctions functions;
951 MotifDecorations decorations;
954 Rectangle client_rect;
957 bool hide_from_taskbar;
958 IntPtr transient_for_parent;
960 // Windows we manage ourselves don't need WM window styles.
961 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
966 mwmHints = new MotifWmHints();
969 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
970 transient_for_parent = IntPtr.Zero;
972 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
973 mwmHints.functions = (IntPtr)0;
974 mwmHints.decorations = (IntPtr)0;
976 form = cp.control as Form;
978 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
979 /* tool windows get no window manager
983 /* just because the window doesn't get any decorations doesn't
984 mean we should disable the functions. for instance, without
985 MotifFunctions.Maximize, changing the windowstate to Maximized
986 is ignored by metacity. */
987 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
988 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
989 // No functions nor decorations whatsoever.
991 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
992 functions |= MotifFunctions.Move;
993 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
996 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
997 functions |= MotifFunctions.Move | MotifFunctions.Resize;
998 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1001 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1002 functions |= MotifFunctions.Minimize;
1003 decorations |= MotifDecorations.Minimize;
1006 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1007 functions |= MotifFunctions.Maximize;
1008 decorations |= MotifDecorations.Maximize;
1011 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1012 functions |= MotifFunctions.Resize;
1013 decorations |= MotifDecorations.ResizeH;
1016 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1017 decorations |= MotifDecorations.Border;
1020 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1021 decorations |= MotifDecorations.Border;
1024 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1025 decorations |= MotifDecorations.Border;
1028 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1029 functions |= MotifFunctions.Close;
1032 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1033 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1034 if (cp.Caption == "") {
1035 functions &= ~MotifFunctions.Move;
1036 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1041 if ((functions & MotifFunctions.Resize) == 0) {
1042 hwnd.fixed_size = true;
1043 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1044 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1046 hwnd.fixed_size = false;
1049 mwmHints.functions = (IntPtr)functions;
1050 mwmHints.decorations = (IntPtr)decorations;
1053 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1056 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1057 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1058 // and get those windows in front of their parents
1059 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1060 } else if (form != null && form.Modal) {
1061 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1063 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1066 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1067 hide_from_taskbar = true;
1068 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1069 hide_from_taskbar = true;
1071 hide_from_taskbar = false;
1074 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1075 if (form != null && !hwnd.reparented) {
1076 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1077 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1078 if (owner_hwnd != null)
1079 transient_for_parent = owner_hwnd.whole_window;
1083 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1084 transient_for_parent = hwnd.parent.whole_window;
1087 FormWindowState current_state = GetWindowState (hwnd.Handle);
1088 if (current_state == (FormWindowState)(-1))
1089 current_state = FormWindowState.Normal;
1091 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1096 atoms [0] = window_type.ToInt32 ();
1097 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1099 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1101 if (transient_for_parent != IntPtr.Zero) {
1102 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1105 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1107 if (hide_from_taskbar) {
1108 /* this line keeps the window from showing up in gnome's taskbar */
1109 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1111 /* we need to add these atoms in the
1112 * event we're maximized, since we're
1113 * replacing the existing
1114 * _NET_WM_STATE here. If we don't
1115 * add them, future calls to
1116 * GetWindowState will return Normal
1117 * for a window which is maximized. */
1118 if (current_state == FormWindowState.Maximized) {
1119 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1120 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1123 if (form != null && form.Modal) {
1124 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1127 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1130 IntPtr[] atom_ptrs = new IntPtr[2];
1131 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1132 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1133 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1136 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1140 private void SetIcon(Hwnd hwnd, Icon icon)
1145 // This really needs to do whatever it
1146 // takes to remove the window manager
1147 // menu, not just delete the ICON
1148 // property. This will cause metacity
1149 // to use the "no icon set" icon, and
1150 // we'll still have an icon.
1151 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1159 bitmap = icon.ToBitmap();
1161 size = bitmap.Width * bitmap.Height + 2;
1162 data = new IntPtr[size];
1164 data[index++] = (IntPtr)bitmap.Width;
1165 data[index++] = (IntPtr)bitmap.Height;
1167 for (int y = 0; y < bitmap.Height; y++) {
1168 for (int x = 0; x < bitmap.Width; x++) {
1169 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1173 XChangeProperty (DisplayHandle, hwnd.whole_window,
1174 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1175 PropertyMode.Replace, data, size);
1179 private void WakeupMain () {
1180 wake.Send (new byte [] { 0xFF });
1183 private XEventQueue ThreadQueue(Thread thread) {
1186 queue = (XEventQueue)MessageQueues[thread];
1187 if (queue == null) {
1188 queue = new XEventQueue(thread);
1189 MessageQueues[thread] = queue;
1195 private void TranslatePropertyToClipboard(IntPtr property) {
1200 IntPtr prop = IntPtr.Zero;
1202 Clipboard.Item = null;
1204 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);
1206 if ((long)nitems > 0) {
1207 if (property == (IntPtr)Atom.XA_STRING) {
1208 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1209 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1210 // FIXME - convert bitmap to image
1211 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1212 // FIXME - convert pixmap to image
1213 } else if (property == OEMTEXT) {
1214 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1215 } else if (property == UNICODETEXT) {
1216 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1223 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1225 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1229 // Keep the invalid area as small as needed
1230 if ((x + width) > hwnd.width) {
1231 width = hwnd.width - x;
1234 if ((y + height) > hwnd.height) {
1235 height = hwnd.height - y;
1239 hwnd.AddInvalidArea(x, y, width, height);
1240 if (!hwnd.expose_pending) {
1241 if (!hwnd.nc_expose_pending) {
1242 hwnd.Queue.Paint.Enqueue(hwnd);
1244 hwnd.expose_pending = true;
1247 hwnd.AddNcInvalidArea (x, y, width, height);
1249 if (!hwnd.nc_expose_pending) {
1250 if (!hwnd.expose_pending) {
1251 hwnd.Queue.Paint.Enqueue(hwnd);
1253 hwnd.nc_expose_pending = true;
1258 private static Hwnd.Borders FrameExtents (IntPtr window)
1264 IntPtr prop = IntPtr.Zero;
1265 Hwnd.Borders rect = new Hwnd.Borders ();
1267 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);
1268 if (prop != IntPtr.Zero) {
1269 if (nitems.ToInt32 () == 4) {
1270 rect.left = Marshal.ReadInt32 (prop, 0);
1271 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1272 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1273 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1281 private void AddConfigureNotify (XEvent xevent) {
1284 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1287 if (hwnd == null || hwnd.zombie) {
1290 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1291 if (hwnd.parent == null) {
1292 // The location given by the event is not reliable between different wm's,
1293 // so use an alternative way of getting it.
1294 Point location = GetTopLevelWindowLocation (hwnd);
1295 hwnd.x = location.X;
1296 hwnd.y = location.Y;
1299 // XXX this sucks. this isn't thread safe
1300 Control ctrl = Control.FromHandle (hwnd.Handle);
1301 Size TranslatedSize;
1303 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1305 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1307 hwnd.width = TranslatedSize.Width;
1308 hwnd.height = TranslatedSize.Height;
1309 hwnd.ClientRect = Rectangle.Empty;
1312 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));
1314 lock (hwnd.configure_lock) {
1315 if (!hwnd.configure_pending) {
1316 hwnd.Queue.EnqueueLocked (xevent);
1317 hwnd.configure_pending = true;
1321 // We drop configure events for Client windows
1324 private void ShowCaret() {
1325 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1331 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1335 private void HideCaret() {
1336 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1342 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1346 private int NextTimeout (ArrayList timers, DateTime now) {
1347 int timeout = Int32.MaxValue;
1349 foreach (Timer timer in timers) {
1350 int next = (int) (timer.Expires - now).TotalMilliseconds;
1352 return 0; // Have a timer that has already expired
1355 if (next < timeout) {
1359 if (timeout < Timer.Minimum) {
1360 timeout = Timer.Minimum;
1368 private void CheckTimers (ArrayList timers, DateTime now) {
1371 count = timers.Count;
1376 for (int i = 0; i < timers.Count; i++) {
1379 timer = (Timer) timers [i];
1381 if (timer.Enabled && timer.Expires <= now) {
1388 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1389 MSG msg = new MSG ();
1392 queue = ThreadQueue(Thread.CurrentThread);
1394 queue.DispatchIdle = false;
1398 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1399 if ((Msg)msg.message == Msg.WM_QUIT) {
1400 PostQuitMessage (0);
1404 if (msg.hwnd == hwnd.Handle) {
1405 if ((Msg)msg.message == message)
1407 else if ((Msg)msg.message == Msg.WM_DESTROY)
1411 TranslateMessage (ref msg);
1412 DispatchMessage (ref msg);
1417 queue.DispatchIdle = true;
1421 private void MapWindow(Hwnd hwnd, WindowType windows) {
1423 if (Control.FromHandle(hwnd.Handle) is Form) {
1424 Form f = Control.FromHandle(hwnd.Handle) as Form;
1425 if (f.WindowState == FormWindowState.Normal)
1426 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1429 // it's possible that our Hwnd is no
1430 // longer valid after making that
1431 // SendMessage call, so check here.
1435 bool need_to_wait = false;
1437 if ((windows & WindowType.Whole) != 0) {
1438 XMapWindow(DisplayHandle, hwnd.whole_window);
1440 if ((windows & WindowType.Client) != 0) {
1441 XMapWindow(DisplayHandle, hwnd.client_window);
1443 need_to_wait = true;
1448 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1449 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1453 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1455 if (Control.FromHandle(hwnd.Handle) is Form) {
1456 Form f = Control.FromHandle(hwnd.Handle) as Form;
1457 if (f.WindowState == FormWindowState.Normal)
1458 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1461 // it's possible that our Hwnd is no
1462 // longer valid after making that
1463 // SendMessage call, so check here.
1467 bool need_to_wait = false;
1469 if ((windows & WindowType.Client) != 0) {
1470 XUnmapWindow(DisplayHandle, hwnd.client_window);
1472 need_to_wait = true;
1474 if ((windows & WindowType.Whole) != 0) {
1475 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1478 hwnd.mapped = false;
1480 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1481 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1485 private void UpdateMessageQueue (XEventQueue queue) {
1490 now = DateTime.UtcNow;
1493 pending = XPending (DisplayHandle);
1497 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1498 Idle (this, EventArgs.Empty);
1502 pending = XPending (DisplayHandle);
1509 if (queue != null) {
1510 if (queue.Paint.Count > 0)
1513 timeout = NextTimeout (queue.timer_list, now);
1518 int length = pollfds.Length - 1;
1519 lock (wake_waiting_lock) {
1520 if (wake_waiting == false) {
1522 wake_waiting = true;
1526 Syscall.poll (pollfds, (uint)length, timeout);
1527 // Clean out buffer, so we're not busy-looping on the same data
1528 if (length == pollfds.Length) {
1529 if (pollfds[1].revents != 0)
1530 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1531 lock (wake_waiting_lock) {
1532 wake_waiting = false;
1537 pending = XPending (DisplayHandle);
1543 CheckTimers (queue.timer_list, now);
1546 XEvent xevent = new XEvent ();
1549 if (XPending (DisplayHandle) == 0)
1552 XNextEvent (DisplayHandle, ref xevent);
1554 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1555 if (XFilterEvent(ref xevent, FosterParent)) {
1561 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1566 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1568 switch (xevent.type) {
1569 case XEventName.Expose:
1570 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1573 case XEventName.SelectionClear: {
1574 // Should we do something?
1578 case XEventName.SelectionRequest: {
1579 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1583 sel_event = new XEvent();
1584 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1585 sel_event.SelectionEvent.send_event = true;
1586 sel_event.SelectionEvent.display = DisplayHandle;
1587 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1588 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1589 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1590 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1591 sel_event.SelectionEvent.property = IntPtr.Zero;
1593 // Seems that some apps support asking for supported types
1594 if (xevent.SelectionEvent.target == TARGETS) {
1601 if (Clipboard.Item is String) {
1602 atoms[atom_count++] = (int)Atom.XA_STRING;
1603 atoms[atom_count++] = (int)OEMTEXT;
1604 atoms[atom_count++] = (int)UNICODETEXT;
1605 } else if (Clipboard.Item is Image) {
1606 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1607 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1609 // FIXME - handle other types
1612 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1613 } else if (Clipboard.Item is string) {
1619 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1622 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1623 buffer = Marshal.AllocHGlobal(bytes.Length);
1624 buflen = bytes.Length;
1626 for (int i = 0; i < buflen; i++) {
1627 Marshal.WriteByte(buffer, i, bytes[i]);
1629 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1630 // FIXME - this should encode into ISO2022
1631 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1632 while (Marshal.ReadByte(buffer, buflen) != 0) {
1635 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1636 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1637 while (Marshal.ReadByte(buffer, buflen) != 0) {
1641 buffer = IntPtr.Zero;
1644 if (buffer != IntPtr.Zero) {
1645 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1646 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1647 Marshal.FreeHGlobal(buffer);
1649 } else if (Clipboard.Item is Image) {
1650 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1651 // FIXME - convert image and store as property
1652 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1653 // FIXME - convert image and store as property
1657 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1661 case XEventName.SelectionNotify: {
1662 if (Clipboard.Enumerating) {
1663 Clipboard.Enumerating = false;
1664 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1665 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1666 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1667 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1668 #if DriverDebugExtra
1669 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1673 } else if (Clipboard.Retrieving) {
1674 Clipboard.Retrieving = false;
1675 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1676 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1678 Clipboard.Item = null;
1681 Dnd.HandleSelectionNotifyEvent (ref xevent);
1686 case XEventName.KeyRelease:
1687 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1688 XEvent nextevent = new XEvent ();
1690 XPeekEvent (DisplayHandle, ref nextevent);
1692 if (nextevent.type == XEventName.KeyPress &&
1693 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1694 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1698 goto case XEventName.KeyPress;
1700 case XEventName.MotionNotify: {
1703 /* we can't do motion compression across threads, so just punt if we don't match up */
1704 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1705 peek = hwnd.Queue.Peek();
1706 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1710 goto case XEventName.KeyPress;
1713 case XEventName.KeyPress:
1714 case XEventName.ButtonPress:
1715 case XEventName.ButtonRelease:
1716 case XEventName.EnterNotify:
1717 case XEventName.LeaveNotify:
1718 case XEventName.CreateNotify:
1719 case XEventName.DestroyNotify:
1720 case XEventName.FocusIn:
1721 case XEventName.FocusOut:
1722 case XEventName.ClientMessage:
1723 case XEventName.ReparentNotify:
1724 case XEventName.MapNotify:
1725 case XEventName.UnmapNotify:
1726 hwnd.Queue.EnqueueLocked (xevent);
1729 case XEventName.ConfigureNotify:
1730 AddConfigureNotify(xevent);
1733 case XEventName.PropertyNotify:
1735 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1737 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1742 IntPtr prop = IntPtr.Zero;
1745 prev_active = ActiveWindow;
1746 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);
1747 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1748 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1751 if (prev_active != ActiveWindow) {
1752 if (prev_active != IntPtr.Zero) {
1753 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1755 if (ActiveWindow != IntPtr.Zero) {
1756 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1759 if (ModalWindows.Count == 0) {
1762 // Modality handling, if we are modal and the new active window is one
1763 // of ours but not the modal one, switch back to the modal window
1765 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1766 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1767 Activate((IntPtr)ModalWindows.Peek());
1774 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1775 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1776 hwnd.cached_window_state = (FormWindowState)(-1);
1784 private IntPtr GetMousewParam(int Delta) {
1787 if ((MouseState & MouseButtons.Left) != 0) {
1788 result |= (int)MsgButtons.MK_LBUTTON;
1791 if ((MouseState & MouseButtons.Middle) != 0) {
1792 result |= (int)MsgButtons.MK_MBUTTON;
1795 if ((MouseState & MouseButtons.Right) != 0) {
1796 result |= (int)MsgButtons.MK_RBUTTON;
1799 Keys mods = ModifierKeys;
1800 if ((mods & Keys.Control) != 0) {
1801 result |= (int)MsgButtons.MK_CONTROL;
1804 if ((mods & Keys.Shift) != 0) {
1805 result |= (int)MsgButtons.MK_SHIFT;
1808 result |= Delta << 16;
1810 return (IntPtr)result;
1812 private IntPtr XGetParent(IntPtr handle) {
1819 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1822 if (Children!=IntPtr.Zero) {
1830 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1832 // we need to workaround a problem with the
1833 // ordering of destruction of Drawables and
1834 // Pictures that exists between cairo and
1835 // RENDER on the server.
1836 if (error_event.request_code == (XRequest)render_major_opcode
1837 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1838 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1842 if (ErrorExceptions) {
1843 XUngrabPointer (display, IntPtr.Zero);
1844 throw new XException (error_event.display, error_event.resourceid,
1845 error_event.serial, error_event.error_code,
1846 error_event.request_code, error_event.minor_code);
1848 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1849 XException.GetMessage (error_event.display, error_event.resourceid,
1850 error_event.serial, error_event.error_code,
1851 error_event.request_code, error_event.minor_code),
1852 Environment.StackTrace);
1857 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1860 Control[] controls = c.Controls.GetAllControls ();
1862 if (c.IsHandleCreated && !c.IsDisposed) {
1863 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1865 #if DriverDebug || DriverDebugDestroy
1866 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1867 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1871 CleanupCachedWindows (hwnd);
1874 for (int i = 0; i < controls.Length; i ++) {
1875 AccumulateDestroyedHandles (controls[i], list);
1881 void CleanupCachedWindows (Hwnd hwnd)
1883 if (ActiveWindow == hwnd.Handle) {
1884 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1885 ActiveWindow = IntPtr.Zero;
1888 if (FocusWindow == hwnd.Handle) {
1889 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1890 FocusWindow = IntPtr.Zero;
1893 if (Grab.Hwnd == hwnd.Handle) {
1894 Grab.Hwnd = IntPtr.Zero;
1895 Grab.Confined = false;
1898 DestroyCaret (hwnd.Handle);
1901 private void PerformNCCalc(Hwnd hwnd) {
1902 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1906 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1908 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1909 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1911 ncp.rgrc1.left = rect.Left;
1912 ncp.rgrc1.top = rect.Top;
1913 ncp.rgrc1.right = rect.Right;
1914 ncp.rgrc1.bottom = rect.Bottom;
1916 Marshal.StructureToPtr(ncp, ptr, true);
1917 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1918 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1919 Marshal.FreeHGlobal(ptr);
1922 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1923 hwnd.ClientRect = rect;
1925 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1928 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1931 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1933 #endregion // Private Methods
1936 private void MouseHover(object sender, EventArgs e) {
1940 HoverState.Timer.Enabled = false;
1942 if (HoverState.Window != IntPtr.Zero) {
1943 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1945 xevent = new XEvent ();
1947 xevent.type = XEventName.ClientMessage;
1948 xevent.ClientMessageEvent.display = DisplayHandle;
1949 xevent.ClientMessageEvent.window = HoverState.Window;
1950 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1951 xevent.ClientMessageEvent.format = 32;
1952 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1954 hwnd.Queue.EnqueueLocked (xevent);
1961 private void CaretCallback(object sender, EventArgs e) {
1965 Caret.On = !Caret.On;
1967 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1969 #endregion // Callbacks
1971 #region Public Properties
1973 internal override int Caption {
1979 internal override Size CursorSize {
1984 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1985 return new Size(x, y);
1987 return new Size(16, 16);
1992 internal override bool DragFullWindows {
1998 internal override Size DragSize {
2000 return new Size(4, 4);
2004 internal override Size FrameBorderSize {
2006 return new Size (4, 4);
2010 internal override Size IconSize {
2016 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2020 current = (long)list;
2023 size = new XIconSize();
2025 for (int i = 0; i < count; i++) {
2026 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2027 current += Marshal.SizeOf(size);
2029 // Look for our preferred size
2030 if (size.min_width == 32) {
2032 return new Size(32, 32);
2035 if (size.max_width == 32) {
2037 return new Size(32, 32);
2040 if (size.min_width < 32 && size.max_width > 32) {
2043 // check if we can fit one
2045 while (x < size.max_width) {
2046 x += size.width_inc;
2049 return new Size(32, 32);
2054 if (largest < size.max_width) {
2055 largest = size.max_width;
2059 // We didn't find a match or we wouldn't be here
2060 return new Size(largest, largest);
2063 return new Size(32, 32);
2068 internal override int KeyboardSpeed {
2071 // A lot harder: need to do:
2072 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2073 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2074 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2076 // And from that we can tell the repetition rate
2078 // Notice, the values must map to:
2079 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2085 internal override int KeyboardDelay {
2088 // Return values must range from 0 to 4, 0 meaning 250ms,
2089 // and 4 meaning 1000 ms.
2091 return 1; // ie, 500 ms
2095 internal override Size MaxWindowTrackSize {
2097 return new Size (WorkingArea.Width, WorkingArea.Height);
2101 internal override Size MinimizedWindowSize {
2103 return new Size(1, 1);
2107 internal override Size MinimizedWindowSpacingSize {
2109 return new Size(1, 1);
2113 internal override Size MinimumWindowSize {
2115 return new Size(1, 1);
2119 internal override Size MinWindowTrackSize {
2121 return new Size(1, 1);
2125 internal override Keys ModifierKeys {
2127 return Keyboard.ModifierKeys;
2131 internal override Size SmallIconSize {
2137 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2141 current = (long)list;
2144 size = new XIconSize();
2146 for (int i = 0; i < count; i++) {
2147 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2148 current += Marshal.SizeOf(size);
2150 // Look for our preferred size
2151 if (size.min_width == 16) {
2153 return new Size(16, 16);
2156 if (size.max_width == 16) {
2158 return new Size(16, 16);
2161 if (size.min_width < 16 && size.max_width > 16) {
2164 // check if we can fit one
2166 while (x < size.max_width) {
2167 x += size.width_inc;
2170 return new Size(16, 16);
2175 if (smallest == 0 || smallest > size.min_width) {
2176 smallest = size.min_width;
2180 // We didn't find a match or we wouldn't be here
2181 return new Size(smallest, smallest);
2184 return new Size(16, 16);
2189 internal override int MouseButtonCount {
2195 internal override bool MouseButtonsSwapped {
2197 return false; // FIXME - how to detect?
2201 internal override Point MousePosition {
2203 return mouse_position;
2207 internal override Size MouseHoverSize {
2209 return new Size (1, 1);
2213 internal override int MouseHoverTime {
2215 return HoverState.Interval;
2221 internal override bool MouseWheelPresent {
2223 return true; // FIXME - how to detect?
2227 internal override Rectangle VirtualScreen {
2233 IntPtr prop = IntPtr.Zero;
2237 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);
2238 if ((long)nitems < 2)
2241 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2242 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2246 return new Rectangle(0, 0, width, height);
2249 XWindowAttributes attributes=new XWindowAttributes();
2252 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2255 return new Rectangle(0, 0, attributes.width, attributes.height);
2259 internal override Rectangle WorkingArea {
2265 IntPtr prop = IntPtr.Zero;
2268 int current_desktop;
2272 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);
2273 if ((long)nitems < 1) {
2277 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2280 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);
2281 if ((long)nitems < 4 * current_desktop) {
2285 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2286 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2287 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2288 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2291 return new Rectangle(x, y, width, height);
2294 XWindowAttributes attributes=new XWindowAttributes();
2297 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2300 return new Rectangle(0, 0, attributes.width, attributes.height);
2304 internal override bool ThemesEnabled {
2306 return XplatUIX11.themes_enabled;
2311 #endregion // Public properties
2313 #region Public Static Methods
2314 internal override IntPtr InitializeDriver() {
2316 if (DisplayHandle==IntPtr.Zero) {
2317 SetDisplay(XOpenDisplay(IntPtr.Zero));
2323 internal override void ShutdownDriver(IntPtr token) {
2325 if (DisplayHandle!=IntPtr.Zero) {
2326 XCloseDisplay(DisplayHandle);
2327 DisplayHandle=IntPtr.Zero;
2332 internal override void EnableThemes() {
2333 themes_enabled = true;
2337 internal override void Activate(IntPtr handle) {
2340 hwnd = Hwnd.ObjectFromHandle(handle);
2344 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2345 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2348 // XRaiseWindow(DisplayHandle, handle);
2354 internal override void AudibleAlert() {
2355 XBell(DisplayHandle, 0);
2360 internal override void CaretVisible(IntPtr handle, bool visible) {
2361 if (Caret.Hwnd == handle) {
2363 if (!Caret.Visible) {
2364 Caret.Visible = true;
2366 Caret.Timer.Start();
2369 Caret.Visible = false;
2376 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2377 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2381 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2387 hwnd = Hwnd.ObjectFromHandle(handle);
2390 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2397 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2398 DataFormats.Format f;
2401 f = DataFormats.Format.List;
2403 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2407 Clipboard.Formats = new ArrayList();
2410 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2412 Clipboard.Enumerating = true;
2413 while (Clipboard.Enumerating) {
2414 UpdateMessageQueue(null);
2419 result = new int[Clipboard.Formats.Count];
2421 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2422 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2425 Clipboard.Formats = null;
2429 internal override void ClipboardClose(IntPtr handle) {
2430 if (handle != ClipMagic) {
2431 throw new ArgumentException("handle is not a valid clipboard handle");
2436 internal override int ClipboardGetID(IntPtr handle, string format) {
2437 if (handle != ClipMagic) {
2438 throw new ArgumentException("handle is not a valid clipboard handle");
2441 if (format == "Text" ) return (int)Atom.XA_STRING;
2442 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2443 //else if (format == "MetaFilePict" ) return 3;
2444 //else if (format == "SymbolicLink" ) return 4;
2445 //else if (format == "DataInterchangeFormat" ) return 5;
2446 //else if (format == "Tiff" ) return 6;
2447 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2448 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2449 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2450 //else if (format == "PenData" ) return 10;
2451 //else if (format == "RiffAudio" ) return 11;
2452 //else if (format == "WaveAudio" ) return 12;
2453 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2454 //else if (format == "EnhancedMetafile" ) return 14;
2455 //else if (format == "FileDrop" ) return 15;
2456 //else if (format == "Locale" ) return 16;
2458 return XInternAtom(DisplayHandle, format, false).ToInt32();
2461 internal override IntPtr ClipboardOpen(bool primary_selection) {
2462 if (!primary_selection)
2463 ClipMagic = CLIPBOARD;
2465 ClipMagic = PRIMARY;
2469 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2470 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2472 Clipboard.Retrieving = true;
2473 while (Clipboard.Retrieving) {
2474 UpdateMessageQueue(null);
2477 return Clipboard.Item;
2480 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2481 Clipboard.Item = obj;
2482 Clipboard.Type = type;
2483 Clipboard.Converter = converter;
2486 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2488 // Clearing the selection
2489 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2493 internal override void CreateCaret (IntPtr handle, int width, int height)
2495 XGCValues gc_values;
2498 hwnd = Hwnd.ObjectFromHandle(handle);
2500 if (Caret.Hwnd != IntPtr.Zero) {
2501 DestroyCaret(Caret.Hwnd);
2504 Caret.Hwnd = handle;
2505 Caret.Window = hwnd.client_window;
2506 Caret.Width = width;
2507 Caret.Height = height;
2508 Caret.Visible = false;
2511 gc_values = new XGCValues();
2512 gc_values.line_width = width;
2514 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2515 if (Caret.gc == IntPtr.Zero) {
2516 Caret.Hwnd = IntPtr.Zero;
2520 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2523 internal override IntPtr CreateWindow (CreateParams cp)
2525 XSetWindowAttributes Attributes;
2527 Hwnd parent_hwnd = null;
2532 IntPtr ParentHandle;
2534 IntPtr ClientWindow;
2535 Rectangle ClientRect;
2536 SetWindowValuemask ValueMask;
2541 Attributes = new XSetWindowAttributes();
2547 if (Width<1) Width=1;
2548 if (Height<1) Height=1;
2550 if (cp.Parent != IntPtr.Zero) {
2551 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2552 ParentHandle = parent_hwnd.client_window;
2554 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2555 // We need to use our foster parent window until this poor child gets it's parent assigned
2556 ParentHandle=FosterParent;
2558 ParentHandle=RootWindow;
2562 // Set the default location location for forms.
2563 Point previous, next;
2565 if (cp.control is Form) {
2566 if (parent_hwnd != null) {
2567 previous = parent_hwnd.previous_child_startup_location;
2568 within = parent_hwnd.client_rectangle;
2570 previous = Hwnd.previous_main_startup_location;
2571 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
2574 if (previous.X == int.MinValue || previous.Y == int.MinValue) {
2577 next = new Point (previous.X + 22, previous.Y + 22);
2580 if (!within.Contains (next.X * 3, next.Y * 3)) {
2584 if (next == Point.Empty && cp.Parent == IntPtr.Zero) {
2585 next = new Point (22, 22);
2588 if (parent_hwnd != null) {
2589 parent_hwnd.previous_child_startup_location = next;
2591 Hwnd.previous_main_startup_location = next;
2594 if (X == int.MinValue && Y == int.MinValue) {
2599 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2601 Attributes.bit_gravity = Gravity.NorthWestGravity;
2602 Attributes.win_gravity = Gravity.NorthWestGravity;
2604 // Save what's under the toolwindow
2605 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2606 Attributes.save_under = true;
2607 ValueMask |= SetWindowValuemask.SaveUnder;
2611 // If we're a popup without caption we override the WM
2612 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2613 Attributes.override_redirect = true;
2614 ValueMask |= SetWindowValuemask.OverrideRedirect;
2620 hwnd.height = Height;
2621 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2622 hwnd.initial_style = cp.WindowStyle;
2623 hwnd.initial_ex_style = cp.WindowExStyle;
2625 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2626 hwnd.enabled = false;
2629 ClientRect = hwnd.ClientRect;
2630 ClientWindow = IntPtr.Zero;
2632 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2633 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2636 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);
2637 if (WholeWindow != IntPtr.Zero) {
2638 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2640 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2641 ValueMask = SetWindowValuemask.ColorMap;
2642 Attributes.colormap = CustomColormap;
2644 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);
2648 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2649 throw new Exception("Could not create X11 windows");
2652 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2653 hwnd.WholeWindow = WholeWindow;
2654 hwnd.ClientWindow = ClientWindow;
2656 #if DriverDebug || DriverDebugCreate
2657 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);
2660 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2661 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2664 hints = new XSizeHints();
2667 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2668 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2673 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2674 if (hwnd.whole_window != hwnd.client_window)
2675 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2678 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2680 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2681 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2683 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2686 SetWMStyles(hwnd, cp);
2688 // set the group leader
2689 XWMHints wm_hints = new XWMHints ();
2691 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2692 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2693 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2695 if (ParentHandle != RootWindow) {
2696 wm_hints.window_group = hwnd.whole_window;
2698 wm_hints.window_group = ParentHandle;
2702 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2705 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2706 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2707 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2708 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2711 // for now make all windows dnd enabled
2712 Dnd.SetAllowDrop (hwnd, true);
2714 // Set caption/window title
2715 Text(hwnd.Handle, cp.Caption);
2717 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2718 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2720 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2721 hwnd.visible = true;
2722 MapWindow(hwnd, WindowType.Both);
2723 if (!(Control.FromHandle(hwnd.Handle) is Form))
2724 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2730 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2731 CreateParams create_params = new CreateParams();
2733 create_params.Caption = "";
2734 create_params.X = X;
2735 create_params.Y = Y;
2736 create_params.Width = Width;
2737 create_params.Height = Height;
2739 create_params.ClassName=XplatUI.DefaultClassName;
2740 create_params.ClassStyle = 0;
2741 create_params.ExStyle=0;
2742 create_params.Parent=IntPtr.Zero;
2743 create_params.Param=0;
2745 return CreateWindow(create_params);
2748 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2750 Bitmap cursor_bitmap;
2758 IntPtr cursor_pixmap;
2765 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2769 // Win32 only allows creation cursors of a certain size
2770 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2771 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2772 cursor_mask = new Bitmap(mask, new Size(width, height));
2774 cursor_bitmap = bitmap;
2778 width = cursor_bitmap.Width;
2779 height = cursor_bitmap.Height;
2781 cursor_bits = new Byte[(width / 8) * height];
2782 mask_bits = new Byte[(width / 8) * height];
2784 for (int y = 0; y < height; y++) {
2785 for (int x = 0; x < width; x++) {
2786 c_pixel = cursor_bitmap.GetPixel(x, y);
2787 m_pixel = cursor_mask.GetPixel(x, y);
2789 and = c_pixel == cursor_pixel;
2790 xor = m_pixel == mask_pixel;
2794 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2795 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2796 } else if (and && !xor) {
2798 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2799 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2801 } else if (and && !xor) {
2803 } else if (and && xor) {
2806 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2807 // we want both to be 0 so nothing to be done
2808 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2809 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2815 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2816 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2820 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2821 fg.red = (ushort)65535;
2822 fg.green = (ushort)65535;
2823 fg.blue = (ushort)65535;
2825 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2827 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2829 XFreePixmap(DisplayHandle, cursor_pixmap);
2830 XFreePixmap(DisplayHandle, mask_pixmap);
2835 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2836 CursorFontShape shape;
2843 shape = StdCursorToFontShape (id);
2844 name = shape.ToString ().Replace ("XC_", string.Empty);
2845 size = XcursorGetDefaultSize (DisplayHandle);
2846 theme = XcursorGetTheme (DisplayHandle);
2847 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2849 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);
2852 if (images_ptr == IntPtr.Zero) {
2856 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2858 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2861 if (images.nimage > 0) {
2862 // We only care about the first image.
2863 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2866 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);
2869 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2870 int [] pixels = new int [image.width * image.height];
2871 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2872 bmp = new Bitmap (image.width, image.height);
2873 for (int w = 0; w < image.width; w++) {
2874 for (int h = 0; h < image.height; h++) {
2875 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2881 XcursorImagesDestroy (images_ptr);
2883 } catch (DllNotFoundException ex) {
2884 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2892 internal override IntPtr DefineStdCursor(StdCursor id) {
2893 CursorFontShape shape;
2896 shape = StdCursorToFontShape (id);
2899 cursor = XCreateFontCursor(DisplayHandle, shape);
2904 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2905 CursorFontShape shape;
2906 // FIXME - define missing shapes
2909 case StdCursor.AppStarting: {
2910 shape = CursorFontShape.XC_watch;
2914 case StdCursor.Arrow: {
2915 shape = CursorFontShape.XC_top_left_arrow;
2919 case StdCursor.Cross: {
2920 shape = CursorFontShape.XC_crosshair;
2924 case StdCursor.Default: {
2925 shape = CursorFontShape.XC_top_left_arrow;
2929 case StdCursor.Hand: {
2930 shape = CursorFontShape.XC_hand1;
2934 case StdCursor.Help: {
2935 shape = CursorFontShape.XC_question_arrow;
2939 case StdCursor.HSplit: {
2940 shape = CursorFontShape.XC_sb_v_double_arrow;
2944 case StdCursor.IBeam: {
2945 shape = CursorFontShape.XC_xterm;
2949 case StdCursor.No: {
2950 shape = CursorFontShape.XC_circle;
2954 case StdCursor.NoMove2D: {
2955 shape = CursorFontShape.XC_fleur;
2959 case StdCursor.NoMoveHoriz: {
2960 shape = CursorFontShape.XC_fleur;
2964 case StdCursor.NoMoveVert: {
2965 shape = CursorFontShape.XC_fleur;
2969 case StdCursor.PanEast: {
2970 shape = CursorFontShape.XC_fleur;
2974 case StdCursor.PanNE: {
2975 shape = CursorFontShape.XC_fleur;
2979 case StdCursor.PanNorth: {
2980 shape = CursorFontShape.XC_fleur;
2984 case StdCursor.PanNW: {
2985 shape = CursorFontShape.XC_fleur;
2989 case StdCursor.PanSE: {
2990 shape = CursorFontShape.XC_fleur;
2994 case StdCursor.PanSouth: {
2995 shape = CursorFontShape.XC_fleur;
2999 case StdCursor.PanSW: {
3000 shape = CursorFontShape.XC_fleur;
3004 case StdCursor.PanWest: {
3005 shape = CursorFontShape.XC_sizing;
3009 case StdCursor.SizeAll: {
3010 shape = CursorFontShape.XC_fleur;
3014 case StdCursor.SizeNESW: {
3015 shape = CursorFontShape.XC_top_right_corner;
3019 case StdCursor.SizeNS: {
3020 shape = CursorFontShape.XC_sb_v_double_arrow;
3024 case StdCursor.SizeNWSE: {
3025 shape = CursorFontShape.XC_top_left_corner;
3029 case StdCursor.SizeWE: {
3030 shape = CursorFontShape.XC_sb_h_double_arrow;
3034 case StdCursor.UpArrow: {
3035 shape = CursorFontShape.XC_center_ptr;
3039 case StdCursor.VSplit: {
3040 shape = CursorFontShape.XC_sb_h_double_arrow;
3044 case StdCursor.WaitCursor: {
3045 shape = CursorFontShape.XC_watch;
3050 shape = (CursorFontShape) 0;
3058 internal override IntPtr DefWndProc(ref Message msg) {
3059 switch ((Msg)msg.Msg) {
3060 case Msg.WM_PAINT: {
3063 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3065 hwnd.expose_pending = false;
3071 case Msg.WM_NCPAINT: {
3074 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3076 hwnd.nc_expose_pending = false;
3082 case Msg.WM_NCCALCSIZE: {
3085 if (msg.WParam == (IntPtr)1) {
3086 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3088 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3089 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3091 // Add all the stuff X is supposed to draw.
3092 Control ctrl = Control.FromHandle (hwnd.Handle);
3093 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3095 ncp.rgrc1.top += rect.top;
3096 ncp.rgrc1.bottom -= rect.bottom;
3097 ncp.rgrc1.left += rect.left;
3098 ncp.rgrc1.right -= rect.right;
3100 Marshal.StructureToPtr (ncp, msg.LParam, true);
3106 case Msg.WM_CONTEXTMENU: {
3109 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3111 if ((hwnd != null) && (hwnd.parent != null)) {
3112 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3117 case Msg.WM_MOUSEWHEEL: {
3120 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3122 if ((hwnd != null) && (hwnd.parent != null)) {
3123 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3124 if (msg.Result == IntPtr.Zero) {
3131 case Msg.WM_SETCURSOR: {
3134 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3136 break; // not sure how this happens, but it does
3138 // Pass to parent window first
3139 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3141 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3144 if (msg.Result == IntPtr.Zero) {
3147 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3148 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3149 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3150 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3151 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3152 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3155 handle = Cursors.Default.handle;
3158 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3159 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3160 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3161 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3162 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3163 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3166 case HitTest.HTGROWBOX:
3167 case HitTest.HTSIZE:
3168 case HitTest.HTZOOM:
3169 case HitTest.HTVSCROLL:
3170 case HitTest.HTSYSMENU:
3171 case HitTest.HTREDUCE:
3172 case HitTest.HTNOWHERE:
3173 case HitTest.HTMAXBUTTON:
3174 case HitTest.HTMINBUTTON:
3175 case HitTest.HTMENU:
3176 case HitTest.HSCROLL:
3177 case HitTest.HTBOTTOM:
3178 case HitTest.HTCAPTION:
3179 case HitTest.HTCLIENT:
3180 case HitTest.HTCLOSE:
3182 default: handle = Cursors.Default.handle; break;
3184 SetCursor(msg.HWnd, handle);
3192 internal override void DestroyCaret(IntPtr handle) {
3193 if (Caret.Hwnd == handle) {
3194 if (Caret.Visible) {
3198 if (Caret.gc != IntPtr.Zero) {
3199 XFreeGC(DisplayHandle, Caret.gc);
3200 Caret.gc = IntPtr.Zero;
3202 Caret.Hwnd = IntPtr.Zero;
3203 Caret.Visible = false;
3208 internal override void DestroyCursor(IntPtr cursor) {
3210 XFreeCursor(DisplayHandle, cursor);
3214 internal override void DestroyWindow(IntPtr handle) {
3217 hwnd = Hwnd.ObjectFromHandle(handle);
3220 #if DriverDebug || DriverDebugDestroy
3221 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3226 #if DriverDebug || DriverDebugDestroy
3227 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3230 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3232 CleanupCachedWindows (hwnd);
3234 ArrayList windows = new ArrayList ();
3236 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3239 foreach (Hwnd h in windows) {
3240 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3245 if (hwnd.whole_window != IntPtr.Zero) {
3246 #if DriverDebug || DriverDebugDestroy
3247 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3249 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3251 else if (hwnd.client_window != IntPtr.Zero) {
3252 #if DriverDebug || DriverDebugDestroy
3253 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3255 XDestroyWindow(DisplayHandle, hwnd.client_window);
3261 internal override IntPtr DispatchMessage(ref MSG msg) {
3262 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3265 IntPtr GetReversibleScreenGC (Color backColor)
3267 XGCValues gc_values;
3271 XColor xcolor = new XColor();
3272 xcolor.red = (ushort)(backColor.R * 257);
3273 xcolor.green = (ushort)(backColor.G * 257);
3274 xcolor.blue = (ushort)(backColor.B * 257);
3275 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3276 pixel = (uint)xcolor.pixel.ToInt32();
3279 gc_values = new XGCValues();
3281 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3282 gc_values.foreground = (IntPtr)pixel;
3284 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3285 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3286 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3291 IntPtr GetReversibleControlGC (Control control, int line_width)
3293 XGCValues gc_values;
3296 gc_values = new XGCValues();
3298 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3299 gc_values.line_width = line_width;
3300 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3302 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3303 //mask = foreground ^ background;
3304 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3305 //XSetBackground(DisplayHandle, gc, background);
3306 //XSetFunction(DisplayHandle, gc, GXxor);
3307 //XSetPlaneMask(DisplayHandle, gc, mask);
3310 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3314 XColor xcolor = new XColor();
3316 xcolor.red = (ushort)(control.ForeColor.R * 257);
3317 xcolor.green = (ushort)(control.ForeColor.G * 257);
3318 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3319 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3320 foreground = (uint)xcolor.pixel.ToInt32();
3322 xcolor.red = (ushort)(control.BackColor.R * 257);
3323 xcolor.green = (ushort)(control.BackColor.G * 257);
3324 xcolor.blue = (ushort)(control.BackColor.B * 257);
3325 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3326 background = (uint)xcolor.pixel.ToInt32();
3328 uint mask = foreground ^ background;
3330 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3331 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3332 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3333 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3338 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3340 IntPtr gc = GetReversibleScreenGC (backColor);
3342 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3344 XFreeGC(DisplayHandle, gc);
3347 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3349 IntPtr gc = GetReversibleScreenGC (backColor);
3351 if (rectangle.Width < 0) {
3352 rectangle.X += rectangle.Width;
3353 rectangle.Width = -rectangle.Width;
3355 if (rectangle.Height < 0) {
3356 rectangle.Y += rectangle.Height;
3357 rectangle.Height = -rectangle.Height;
3361 GCLineStyle line_style = GCLineStyle.LineSolid;
3362 GCCapStyle cap_style = GCCapStyle.CapButt;
3363 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3366 case FrameStyle.Dashed:
3367 line_style = GCLineStyle.LineOnOffDash;
3369 case FrameStyle.Thick:
3374 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3376 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3378 XFreeGC(DisplayHandle, gc);
3381 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3383 IntPtr gc = GetReversibleScreenGC (backColor);
3385 if (rectangle.Width < 0) {
3386 rectangle.X += rectangle.Width;
3387 rectangle.Width = -rectangle.Width;
3389 if (rectangle.Height < 0) {
3390 rectangle.Y += rectangle.Height;
3391 rectangle.Height = -rectangle.Height;
3393 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3395 XFreeGC(DisplayHandle, gc);
3398 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3400 Control control = Control.FromHandle(handle);
3402 gc = GetReversibleControlGC (control, line_width);
3404 if ((rect.Width > 0) && (rect.Height > 0)) {
3405 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3407 if (rect.Width > 0) {
3408 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3410 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3413 XFreeGC(DisplayHandle, gc);
3416 internal override void DoEvents() {
3417 MSG msg = new MSG ();
3420 if (OverrideCursorHandle != IntPtr.Zero) {
3421 OverrideCursorHandle = IntPtr.Zero;
3424 queue = ThreadQueue(Thread.CurrentThread);
3426 queue.DispatchIdle = false;
3428 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3429 TranslateMessage (ref msg);
3430 DispatchMessage (ref msg);
3433 queue.DispatchIdle = true;
3436 internal override void EnableWindow(IntPtr handle, bool Enable) {
3439 hwnd = Hwnd.ObjectFromHandle(handle);
3441 hwnd.Enabled = Enable;
3445 internal override void EndLoop(Thread thread) {
3446 // This is where we one day will shut down the loop for the thread
3449 internal override IntPtr GetActive() {
3454 IntPtr prop = IntPtr.Zero;
3455 IntPtr active = IntPtr.Zero;
3457 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);
3458 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3459 active = (IntPtr)Marshal.ReadInt32(prop);
3463 if (active != IntPtr.Zero) {
3466 hwnd = Hwnd.GetObjectFromWindow(active);
3468 active = hwnd.Handle;
3470 active = IntPtr.Zero;
3476 internal override Region GetClipRegion(IntPtr handle) {
3479 hwnd = Hwnd.ObjectFromHandle(handle);
3481 return hwnd.UserClip;
3487 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3494 internal override void GetDisplaySize(out Size size) {
3495 XWindowAttributes attributes=new XWindowAttributes();
3498 // FIXME - use _NET_WM messages instead?
3499 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3502 size = new Size(attributes.width, attributes.height);
3505 internal override SizeF GetAutoScaleSize(Font font) {
3508 string magic_string = "The quick brown fox jumped over the lazy dog.";
3509 double magic_number = 44.549996948242189;
3511 g = Graphics.FromHwnd(FosterParent);
3513 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3514 return new SizeF(width, font.Height);
3517 internal override IntPtr GetParent(IntPtr handle) {
3520 hwnd = Hwnd.ObjectFromHandle(handle);
3521 if (hwnd != null && hwnd.parent != null) {
3522 return hwnd.parent.Handle;
3527 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3537 if (handle != IntPtr.Zero) {
3538 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3540 use_handle = RootWindow;
3544 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3547 if (handle != IntPtr.Zero) {
3556 internal override IntPtr GetFocus() {
3561 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3562 FontFamily ff = font.FontFamily;
3563 ascent = ff.GetCellAscent (font.Style);
3564 descent = ff.GetCellDescent (font.Style);
3568 internal override Point GetMenuOrigin(IntPtr handle) {
3571 hwnd = Hwnd.ObjectFromHandle(handle);
3574 return hwnd.MenuOrigin;
3579 [MonoTODO("Implement filtering")]
3580 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3587 if (((XEventQueue)queue_id).Count > 0) {
3588 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3590 UpdateMessageQueue ((XEventQueue)queue_id);
3592 if (((XEventQueue)queue_id).Count > 0) {
3593 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3594 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3595 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3597 msg.hwnd= IntPtr.Zero;
3598 msg.message = Msg.WM_ENTERIDLE;
3603 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3605 // Handle messages for windows that are already or are about to be destroyed.
3607 // we need a special block for this because unless we remove the hwnd from the paint
3608 // queue it will always stay there (since we don't handle the expose), and we'll
3609 // effectively loop infinitely trying to repaint a non-existant window.
3610 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3611 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3612 hwnd.Queue.Paint.Remove (hwnd);
3613 goto ProcessNextMessage;
3616 // We need to make sure we only allow DestroyNotify events through for zombie
3617 // hwnds, since much of the event handling code makes requests using the hwnd's
3618 // client_window, and that'll result in BadWindow errors if there's some lag
3619 // between the XDestroyWindow call and the DestroyNotify event.
3620 if (hwnd == null || hwnd.zombie) {
3621 #if DriverDebug || DriverDebugDestroy
3622 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3624 goto ProcessNextMessage;
3627 if (hwnd.client_window == xevent.AnyEvent.window) {
3629 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3632 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3635 msg.hwnd = hwnd.Handle;
3638 // If you add a new event to this switch make sure to add it in
3639 // UpdateMessage also unless it is not coming through the X event system.
3641 switch(xevent.type) {
3642 case XEventName.KeyPress: {
3644 Dnd.HandleKeyPress (ref xevent);
3645 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3649 case XEventName.KeyRelease: {
3650 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3654 case XEventName.ButtonPress: {
3655 switch(xevent.ButtonEvent.button) {
3657 MouseState |= MouseButtons.Left;
3659 msg.message = Msg.WM_LBUTTONDOWN;
3661 msg.message = Msg.WM_NCLBUTTONDOWN;
3662 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3664 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3665 msg.wParam=GetMousewParam(0);
3670 MouseState |= MouseButtons.Middle;
3672 msg.message = Msg.WM_MBUTTONDOWN;
3674 msg.message = Msg.WM_NCMBUTTONDOWN;
3675 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3677 msg.wParam=GetMousewParam(0);
3682 MouseState |= MouseButtons.Right;
3684 msg.message = Msg.WM_RBUTTONDOWN;
3686 msg.message = Msg.WM_NCRBUTTONDOWN;
3687 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3689 msg.wParam=GetMousewParam(0);
3694 msg.hwnd = FocusWindow;
3695 msg.message=Msg.WM_MOUSEWHEEL;
3696 msg.wParam=GetMousewParam(120);
3701 msg.hwnd = FocusWindow;
3702 msg.message=Msg.WM_MOUSEWHEEL;
3703 msg.wParam=GetMousewParam(-120);
3709 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3710 mouse_position.X = xevent.ButtonEvent.x;
3711 mouse_position.Y = xevent.ButtonEvent.y;
3713 if (!hwnd.Enabled) {
3716 msg.hwnd = hwnd.EnabledHwnd;
3717 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);
3718 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3721 if (Grab.Hwnd != IntPtr.Zero) {
3722 msg.hwnd = Grab.Hwnd;
3725 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3726 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3727 switch(xevent.ButtonEvent.button) {
3729 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3734 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3739 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3743 ClickPending.Pending = false;
3745 ClickPending.Pending = true;
3746 ClickPending.Hwnd = msg.hwnd;
3747 ClickPending.Message = msg.message;
3748 ClickPending.wParam = msg.wParam;
3749 ClickPending.lParam = msg.lParam;
3750 ClickPending.Time = (long)xevent.ButtonEvent.time;
3753 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3754 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3756 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3757 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3758 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3759 XEvent motionEvent = new XEvent ();
3760 motionEvent.type = XEventName.MotionNotify;
3761 motionEvent.MotionEvent.display = DisplayHandle;
3762 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3763 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3764 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3765 hwnd.Queue.EnqueueLocked (motionEvent);
3771 case XEventName.ButtonRelease: {
3773 if (Dnd.HandleButtonRelease (ref xevent)) {
3776 // Allow the LBUTTONUP message to get through
3779 switch(xevent.ButtonEvent.button) {
3782 msg.message = Msg.WM_LBUTTONUP;
3784 msg.message = Msg.WM_NCLBUTTONUP;
3785 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3787 MouseState &= ~MouseButtons.Left;
3788 msg.wParam=GetMousewParam(0);
3794 msg.message = Msg.WM_MBUTTONUP;
3796 msg.message = Msg.WM_NCMBUTTONUP;
3797 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3799 MouseState &= ~MouseButtons.Middle;
3800 msg.wParam=GetMousewParam(0);
3806 msg.message = Msg.WM_RBUTTONUP;
3808 msg.message = Msg.WM_NCRBUTTONUP;
3809 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3811 MouseState &= ~MouseButtons.Right;
3812 msg.wParam=GetMousewParam(0);
3817 goto ProcessNextMessage;
3821 goto ProcessNextMessage;
3825 if (!hwnd.Enabled) {
3828 msg.hwnd = hwnd.EnabledHwnd;
3829 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);
3830 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3833 if (Grab.Hwnd != IntPtr.Zero) {
3834 msg.hwnd = Grab.Hwnd;
3837 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3838 mouse_position.X = xevent.ButtonEvent.x;
3839 mouse_position.Y = xevent.ButtonEvent.y;
3841 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3842 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3843 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3844 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3845 XEvent motionEvent = new XEvent ();
3846 motionEvent.type = XEventName.MotionNotify;
3847 motionEvent.MotionEvent.display = DisplayHandle;
3848 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3849 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3850 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3851 hwnd.Queue.EnqueueLocked (motionEvent);
3856 case XEventName.MotionNotify: {
3858 #if DriverDebugExtra
3859 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);
3862 if (Dnd.HandleMotionNotify (ref xevent))
3863 goto ProcessNextMessage;
3864 if (Grab.Hwnd != IntPtr.Zero) {
3865 msg.hwnd = Grab.Hwnd;
3868 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3872 msg.message = Msg.WM_MOUSEMOVE;
3873 msg.wParam = GetMousewParam(0);
3874 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3876 if (!hwnd.Enabled) {
3879 msg.hwnd = hwnd.EnabledHwnd;
3880 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);
3881 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3884 mouse_position.X = xevent.MotionEvent.x;
3885 mouse_position.Y = xevent.MotionEvent.y;
3887 if ((HoverState.Timer.Enabled) &&
3888 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3889 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3890 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3891 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3892 HoverState.Timer.Stop();
3893 HoverState.Timer.Start();
3894 HoverState.X = mouse_position.X;
3895 HoverState.Y = mouse_position.Y;
3905 #if DriverDebugExtra
3906 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);
3908 msg.message = Msg.WM_NCMOUSEMOVE;
3910 if (!hwnd.Enabled) {
3911 msg.hwnd = hwnd.EnabledHwnd;
3912 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);
3913 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3916 // The hit test is sent in screen coordinates
3917 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3918 xevent.MotionEvent.x, xevent.MotionEvent.y,
3919 out screen_x, out screen_y, out dummy);
3921 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3922 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3923 IntPtr.Zero, msg.lParam).ToInt32 ();
3924 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3926 mouse_position.X = xevent.MotionEvent.x;
3927 mouse_position.Y = xevent.MotionEvent.y;
3933 case XEventName.EnterNotify: {
3934 if (!hwnd.Enabled) {
3935 goto ProcessNextMessage;
3937 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3938 goto ProcessNextMessage;
3940 msg.message = Msg.WM_MOUSE_ENTER;
3941 HoverState.X = xevent.CrossingEvent.x;
3942 HoverState.Y = xevent.CrossingEvent.y;
3943 HoverState.Timer.Enabled = true;
3944 HoverState.Window = xevent.CrossingEvent.window;
3948 case XEventName.LeaveNotify: {
3949 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3950 WindowUngrabbed (hwnd.Handle);
3951 goto ProcessNextMessage;
3953 if (!hwnd.Enabled) {
3954 goto ProcessNextMessage;
3956 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3957 goto ProcessNextMessage;
3959 msg.message=Msg.WM_MOUSELEAVE;
3960 HoverState.Timer.Enabled = false;
3961 HoverState.Window = IntPtr.Zero;
3966 case XEventName.CreateNotify: {
3967 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3968 msg.message = WM_CREATE;
3969 // Set up CreateStruct
3971 goto ProcessNextMessage;
3978 case XEventName.ReparentNotify: {
3979 if (hwnd.parent == null) { // Toplevel
3980 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3981 hwnd.Reparented = true;
3983 // The location given by the event is not reliable between different wm's,
3984 // so use an alternative way of getting it.
3985 Point location = GetTopLevelWindowLocation (hwnd);
3986 hwnd.X = location.X;
3987 hwnd.Y = location.Y;
3989 if (hwnd.opacity != 0xffffffff) {
3992 opacity = (IntPtr)(Int32)hwnd.opacity;
3993 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3995 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3996 goto ProcessNextMessage;
3998 hwnd.Reparented = false;
3999 goto ProcessNextMessage;
4002 goto ProcessNextMessage;
4005 case XEventName.ConfigureNotify: {
4006 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4007 #if DriverDebugExtra
4008 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);
4010 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
4011 lock (hwnd.configure_lock) {
4012 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4013 hwnd.configure_pending = false;
4016 // We need to adjust our client window to track the resize of whole_window
4017 if (hwnd.whole_window != hwnd.client_window)
4018 PerformNCCalc(hwnd);
4021 goto ProcessNextMessage;
4024 case XEventName.FocusIn: {
4025 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4026 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4027 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4028 // about it having focus again
4029 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4030 goto ProcessNextMessage;
4033 if (FocusWindow == IntPtr.Zero) {
4034 Control c = Control.FromHandle (hwnd.client_window);
4036 goto ProcessNextMessage;
4037 Form form = c.FindForm ();
4039 goto ProcessNextMessage;
4040 if (ActiveWindow != form.Handle) {
4041 ActiveWindow = form.Handle;
4042 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4044 goto ProcessNextMessage;
4046 Keyboard.FocusIn(FocusWindow);
4047 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4048 goto ProcessNextMessage;
4051 case XEventName.FocusOut: {
4052 // Se the comment for our FocusIn handler
4053 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4054 goto ProcessNextMessage;
4056 Keyboard.FocusOut(FocusWindow);
4058 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4059 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4062 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4063 goto ProcessNextMessage;
4066 case XEventName.MapNotify: {
4067 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4069 msg.message = Msg.WM_SHOWWINDOW;
4070 msg.wParam = (IntPtr) 1;
4071 // XXX we're missing the lParam..
4074 goto ProcessNextMessage;
4077 case XEventName.UnmapNotify: {
4078 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4079 hwnd.mapped = false;
4080 msg.message = Msg.WM_SHOWWINDOW;
4081 msg.wParam = (IntPtr) 0;
4082 // XXX we're missing the lParam..
4085 goto ProcessNextMessage;
4088 case XEventName.Expose: {
4091 hwnd.expose_pending = false;
4093 hwnd.nc_expose_pending = false;
4095 goto ProcessNextMessage;
4099 if (!hwnd.expose_pending) {
4100 goto ProcessNextMessage;
4103 if (!hwnd.nc_expose_pending) {
4104 goto ProcessNextMessage;
4107 switch (hwnd.border_style) {
4108 case FormBorderStyle.Fixed3D: {
4111 g = Graphics.FromHwnd(hwnd.whole_window);
4112 if (hwnd.border_static)
4113 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4115 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4120 case FormBorderStyle.FixedSingle: {
4123 g = Graphics.FromHwnd(hwnd.whole_window);
4124 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4129 #if DriverDebugExtra
4130 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);
4133 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4134 Region region = new Region (rect);
4135 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4136 msg.message = Msg.WM_NCPAINT;
4137 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4138 msg.refobject = region;
4141 #if DriverDebugExtra
4142 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);
4144 if (Caret.Visible == true) {
4145 Caret.Paused = true;
4149 if (Caret.Visible == true) {
4151 Caret.Paused = false;
4153 msg.message = Msg.WM_PAINT;
4157 case XEventName.DestroyNotify: {
4159 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4160 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4162 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4163 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4164 CleanupCachedWindows (hwnd);
4166 #if DriverDebugDestroy
4167 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4170 msg.hwnd = hwnd.client_window;
4171 msg.message=Msg.WM_DESTROY;
4174 goto ProcessNextMessage;
4180 case XEventName.ClientMessage: {
4181 if (Dnd.HandleClientMessage (ref xevent)) {
4182 goto ProcessNextMessage;
4185 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4186 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4187 goto ProcessNextMessage;
4190 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4191 msg.message = Msg.WM_MOUSEHOVER;
4192 msg.wParam = GetMousewParam(0);
4193 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4197 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4198 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4199 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4200 msg.wParam = xevent.ClientMessageEvent.ptr3;
4201 msg.lParam = xevent.ClientMessageEvent.ptr4;
4202 if (msg.message == (Msg)Msg.WM_QUIT)
4208 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4209 #if DriverDebugXEmbed
4210 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4213 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4214 XSizeHints hints = new XSizeHints();
4217 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4219 hwnd.width = hints.max_width;
4220 hwnd.height = hints.max_height;
4221 hwnd.ClientRect = Rectangle.Empty;
4222 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4226 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4227 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4228 msg.message = Msg.WM_CLOSE;
4232 // We should not get this, but I'll leave the code in case we need it in the future
4233 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4234 goto ProcessNextMessage;
4237 goto ProcessNextMessage;
4241 goto ProcessNextMessage;
4248 internal override bool GetText(IntPtr handle, out string text) {
4255 IntPtr prop = IntPtr.Zero;
4257 XGetWindowProperty(DisplayHandle, handle,
4258 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4259 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4261 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4262 text = Marshal.PtrToStringUni (prop, (int)nitems);
4267 // fallback on the non-_NET property
4270 textptr = IntPtr.Zero;
4272 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4273 if (textptr != IntPtr.Zero) {
4274 text = Marshal.PtrToStringAnsi(textptr);
4285 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) {
4288 hwnd = Hwnd.ObjectFromHandle(handle);
4294 height = hwnd.height;
4296 PerformNCCalc(hwnd);
4298 client_width = hwnd.ClientRect.Width;
4299 client_height = hwnd.ClientRect.Height;
4304 // Should we throw an exception or fail silently?
4305 // throw new ArgumentException("Called with an invalid window handle", "handle");
4315 internal override FormWindowState GetWindowState(IntPtr handle) {
4318 hwnd = Hwnd.ObjectFromHandle(handle);
4320 if (hwnd.cached_window_state == (FormWindowState)(-1))
4321 hwnd.cached_window_state = UpdateWindowState (handle);
4323 return hwnd.cached_window_state;
4326 private FormWindowState UpdateWindowState (IntPtr handle) {
4331 IntPtr prop = IntPtr.Zero;
4335 XWindowAttributes attributes;
4338 hwnd = Hwnd.ObjectFromHandle(handle);
4342 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);
4343 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4344 for (int i = 0; i < (long)nitems; i++) {
4345 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4346 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4348 } else if (atom == _NET_WM_STATE_HIDDEN) {
4356 return FormWindowState.Minimized;
4357 } else if (maximized == 2) {
4358 return FormWindowState.Maximized;
4361 attributes = new XWindowAttributes();
4362 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4363 if (attributes.map_state == MapState.IsUnmapped) {
4364 return (FormWindowState)(-1);
4368 return FormWindowState.Normal;
4371 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4373 GrabConfined = Grab.Confined;
4374 GrabArea = Grab.Area;
4377 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4379 IntPtr confine_to_window;
4381 confine_to_window = IntPtr.Zero;
4383 if (confine_to_handle != IntPtr.Zero) {
4384 XWindowAttributes attributes = new XWindowAttributes();
4386 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4389 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4391 Grab.Area.X = attributes.x;
4392 Grab.Area.Y = attributes.y;
4393 Grab.Area.Width = attributes.width;
4394 Grab.Area.Height = attributes.height;
4395 Grab.Confined = true;
4396 confine_to_window = hwnd.client_window;
4401 hwnd = Hwnd.ObjectFromHandle(handle);
4404 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4405 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4406 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4407 EventMask.LeaveWindowMask,
4408 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4412 internal override void UngrabWindow(IntPtr hwnd) {
4414 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4415 XFlush(DisplayHandle);
4417 WindowUngrabbed (hwnd);
4420 private void WindowUngrabbed (IntPtr hwnd) {
4421 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4423 Grab.Hwnd = IntPtr.Zero;
4424 Grab.Confined = false;
4427 // lparam should be the handle to the window gaining the mouse capture,
4428 // but X doesn't seem to give us that information.
4429 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4430 // X will send a NotifyUngrab, but since it comes late sometimes we're
4431 // calling WindowUngrabbed directly from UngrabWindow in order to send
4432 // this WM right away.
4433 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4437 internal override void HandleException(Exception e) {
4438 StackTrace st = new StackTrace(e, true);
4439 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4440 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4443 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4446 hwnd = Hwnd.ObjectFromHandle(handle);
4449 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4451 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4455 internal override void InvalidateNC (IntPtr handle) {
4458 hwnd = Hwnd.ObjectFromHandle(handle);
4460 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4463 internal override bool IsEnabled(IntPtr handle) {
4464 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4465 return (hwnd != null && hwnd.Enabled);
4468 internal override bool IsVisible(IntPtr handle) {
4469 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4470 return (hwnd != null && hwnd.visible);
4473 internal override void KillTimer(Timer timer) {
4474 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4476 if (queue == null) {
4477 // This isn't really an error, MS doesn't start the timer if
4478 // it has no assosciated queue
4481 queue.timer_list.Remove (timer);
4484 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4490 hwnd = Hwnd.ObjectFromHandle(handle);
4493 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4500 internal override void OverrideCursor(IntPtr cursor)
4502 if (Grab.Hwnd != IntPtr.Zero) {
4503 XChangeActivePointerGrab (DisplayHandle,
4504 EventMask.ButtonMotionMask |
4505 EventMask.PointerMotionMask |
4506 EventMask.ButtonPressMask |
4507 EventMask.ButtonReleaseMask,
4508 cursor, IntPtr.Zero);
4512 OverrideCursorHandle = cursor;
4515 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4516 PaintEventArgs paint_event;
4519 hwnd = Hwnd.ObjectFromHandle(handle);
4521 if (Caret.Visible == true) {
4522 Caret.Paused = true;
4529 dc = Graphics.FromHwnd (hwnd.client_window);
4531 Region clip_region = new Region ();
4532 clip_region.MakeEmpty();
4534 foreach (Rectangle r in hwnd.ClipRectangles) {
4535 clip_region.Union (r);
4538 if (hwnd.UserClip != null) {
4539 clip_region.Intersect(hwnd.UserClip);
4542 dc.Clip = clip_region;
4543 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4544 hwnd.expose_pending = false;
4546 hwnd.ClearInvalidArea();
4548 hwnd.drawing_stack.Push (paint_event);
4549 hwnd.drawing_stack.Push (dc);
4553 dc = Graphics.FromHwnd (hwnd.whole_window);
4555 if (!hwnd.nc_invalid.IsEmpty) {
4556 dc.SetClip (hwnd.nc_invalid);
4557 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4559 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4561 hwnd.nc_expose_pending = false;
4563 hwnd.ClearNcInvalidArea ();
4565 hwnd.drawing_stack.Push (paint_event);
4566 hwnd.drawing_stack.Push (dc);
4572 internal override void PaintEventEnd(IntPtr handle, bool client) {
4575 hwnd = Hwnd.ObjectFromHandle(handle);
4577 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4581 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4582 pe.SetGraphics (null);
4585 if (Caret.Visible == true) {
4587 Caret.Paused = false;
4591 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4592 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4593 XEventQueue queue = (XEventQueue) queue_id;
4596 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4597 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4601 if (queue.Count > 0) {
4604 // Only call UpdateMessageQueue if real events are pending
4605 // otherwise we go to sleep on the socket
4606 if (XPending(DisplayHandle) != 0) {
4607 UpdateMessageQueue((XEventQueue)queue_id);
4609 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4614 CheckTimers(queue.timer_list, DateTime.UtcNow);
4619 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4622 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4623 XEvent xevent = new XEvent ();
4624 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4626 xevent.type = XEventName.ClientMessage;
4627 xevent.ClientMessageEvent.display = DisplayHandle;
4630 xevent.ClientMessageEvent.window = hwnd.whole_window;
4632 xevent.ClientMessageEvent.window = IntPtr.Zero;
4635 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4636 xevent.ClientMessageEvent.format = 32;
4637 xevent.ClientMessageEvent.ptr1 = handle;
4638 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4639 xevent.ClientMessageEvent.ptr3 = wparam;
4640 xevent.ClientMessageEvent.ptr4 = lparam;
4642 hwnd.Queue.EnqueueLocked (xevent);
4647 internal override void PostQuitMessage(int exitCode) {
4648 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4649 XFlush(DisplayHandle);
4652 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4657 internal override void RequestNCRecalc(IntPtr handle) {
4660 hwnd = Hwnd.ObjectFromHandle(handle);
4666 PerformNCCalc(hwnd);
4667 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4668 InvalidateNC(handle);
4671 internal override void ResetMouseHover(IntPtr handle) {
4674 hwnd = Hwnd.ObjectFromHandle(handle);
4679 HoverState.Timer.Enabled = true;
4680 HoverState.X = mouse_position.X;
4681 HoverState.Y = mouse_position.Y;
4682 HoverState.Window = handle;
4686 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4692 hwnd = Hwnd.ObjectFromHandle(handle);
4695 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4702 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4708 hwnd = Hwnd.ObjectFromHandle(handle);
4711 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4714 Form form = Control.FromHandle (handle) as Form;
4715 if (form != null && form.window_manager != null) {
4716 dest_y_return -= form.window_manager.TitleBarHeight;
4723 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4726 XGCValues gc_values;
4728 hwnd = Hwnd.ObjectFromHandle(handle);
4730 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4732 /* We have an invalid area in the window we're scrolling.
4733 Adjust our stored invalid rectangle to to match the scrolled amount */
4748 if (area.Contains (hwnd.Invalid))
4749 hwnd.ClearInvalidArea ();
4750 hwnd.AddInvalidArea(r);
4753 gc_values = new XGCValues();
4755 if (with_children) {
4756 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4759 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4767 height = area.Height - YAmount;
4768 dest_y = area.Y + YAmount;
4771 src_y = area.Y - YAmount;
4772 height = area.Height + YAmount;
4778 width = area.Width - XAmount;
4779 dest_x = area.X + XAmount;
4782 src_x = area.X - XAmount;
4783 width = area.Width + XAmount;
4787 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4789 // Generate an expose for the area exposed by the horizontal scroll
4790 // We don't use AddExpose since we're
4792 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4793 } else if (XAmount < 0) {
4794 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4797 // Generate an expose for the area exposed by the vertical scroll
4799 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4800 } else if (YAmount < 0) {
4801 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4803 XFreeGC(DisplayHandle, gc);
4806 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4810 hwnd = Hwnd.GetObjectFromWindow(handle);
4812 rect = hwnd.ClientRect;
4815 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4818 internal override void SendAsyncMethod (AsyncMethodData method) {
4820 XEvent xevent = new XEvent ();
4822 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4824 xevent.type = XEventName.ClientMessage;
4825 xevent.ClientMessageEvent.display = DisplayHandle;
4826 xevent.ClientMessageEvent.window = method.Handle;
4827 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4828 xevent.ClientMessageEvent.format = 32;
4829 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4831 hwnd.Queue.EnqueueLocked (xevent);
4836 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4838 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4841 h = Hwnd.ObjectFromHandle(hwnd);
4843 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4844 AsyncMethodResult result;
4845 AsyncMethodData data;
4847 result = new AsyncMethodResult ();
4848 data = new AsyncMethodData ();
4851 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4852 data.Args = new object[] { hwnd, message, wParam, lParam };
4853 data.Result = result;
4855 SendAsyncMethod (data);
4856 #if DriverDebug || DriverDebugThreads
4857 Console.WriteLine ("Sending {0} message across.", message);
4862 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4865 internal override int SendInput(IntPtr handle, Queue keys) {
4866 if (handle == IntPtr.Zero)
4869 int count = keys.Count;
4870 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4872 while (keys.Count > 0) {
4874 MSG msg = (MSG)keys.Dequeue();
4876 XEvent xevent = new XEvent ();
4878 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4879 xevent.KeyEvent.display = DisplayHandle;
4882 xevent.KeyEvent.window = hwnd.whole_window;
4884 xevent.KeyEvent.window = IntPtr.Zero;
4887 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4889 hwnd.Queue.EnqueueLocked (xevent);
4894 internal override void SetAllowDrop (IntPtr handle, bool value)
4896 // We allow drop on all windows
4899 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4900 DragDropEffects allowed_effects)
4902 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4905 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4907 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4910 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4911 Form form = Control.FromHandle (handle) as Form;
4912 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4913 border_style == FormBorderStyle.SizableToolWindow)) {
4914 form.window_manager = new ToolWindowManager (form);
4917 RequestNCRecalc(handle);
4920 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4921 if (Caret.Hwnd == handle) {
4928 if (Caret.Visible == true) {
4930 Caret.Timer.Start();
4935 internal override void SetClipRegion(IntPtr handle, Region region) {
4938 hwnd = Hwnd.ObjectFromHandle(handle);
4943 hwnd.UserClip = region;
4946 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4949 if (OverrideCursorHandle == IntPtr.Zero) {
4950 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4954 LastCursorHandle = cursor;
4955 LastCursorWindow = handle;
4957 hwnd = Hwnd.ObjectFromHandle(handle);
4959 if (cursor != IntPtr.Zero) {
4960 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4962 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4964 XFlush(DisplayHandle);
4969 hwnd = Hwnd.ObjectFromHandle(handle);
4971 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4975 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4976 out int root_x, out int root_y, out int child_x, out int child_y,
4979 /* this code was written with the help of
4980 glance at gdk. I never would have realized we
4981 needed a loop in order to traverse down in the
4982 hierarchy. I would have assumed you'd get the
4983 most deeply nested child and have to do
4984 XQueryTree to move back up the hierarchy..
4985 stupid me, of course. */
4988 XGrabServer (display);
4990 XQueryPointer(display, w, out root, out c,
4991 out root_x, out root_y, out child_x, out child_y,
4997 IntPtr child_last = IntPtr.Zero;
4998 while (c != IntPtr.Zero) {
5000 XQueryPointer(display, c, out root, out c,
5001 out root_x, out root_y, out child_x, out child_y,
5004 XUngrabServer (display);
5010 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5011 if (handle == IntPtr.Zero) {
5014 int root_x, root_y, child_x, child_y, mask;
5017 * QueryPointer before warping
5018 * because if the warp is on
5019 * the RootWindow, the x/y are
5020 * relative to the current
5023 QueryPointer (DisplayHandle, RootWindow,
5026 out root_x, out root_y,
5027 out child_x, out child_y,
5030 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5032 XFlush (DisplayHandle);
5034 /* then we need to a
5035 * QueryPointer after warping
5036 * to manually generate a
5037 * motion event for the window
5040 QueryPointer (DisplayHandle, RootWindow,
5043 out root_x, out root_y,
5044 out child_x, out child_y,
5047 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5048 if (child_hwnd == null) {
5052 XEvent xevent = new XEvent ();
5054 xevent.type = XEventName.MotionNotify;
5055 xevent.MotionEvent.display = DisplayHandle;
5056 xevent.MotionEvent.window = child_hwnd.client_window;
5057 xevent.MotionEvent.root = RootWindow;
5058 xevent.MotionEvent.x = child_x;
5059 xevent.MotionEvent.y = child_y;
5060 xevent.MotionEvent.x_root = root_x;
5061 xevent.MotionEvent.y_root = root_y;
5062 xevent.MotionEvent.state = mask;
5064 child_hwnd.Queue.EnqueueLocked (xevent);
5069 hwnd = Hwnd.ObjectFromHandle(handle);
5071 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5076 internal override void SetFocus(IntPtr handle) {
5078 IntPtr prev_focus_window;
5080 hwnd = Hwnd.ObjectFromHandle(handle);
5082 if (hwnd.client_window == FocusWindow) {
5086 prev_focus_window = FocusWindow;
5087 FocusWindow = hwnd.client_window;
5089 if (prev_focus_window != IntPtr.Zero) {
5090 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5092 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5094 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5097 internal override void SetIcon(IntPtr handle, Icon icon) {
5100 hwnd = Hwnd.ObjectFromHandle(handle);
5102 SetIcon(hwnd, icon);
5106 internal override void SetMenu(IntPtr handle, Menu menu) {
5109 hwnd = Hwnd.ObjectFromHandle(handle);
5112 RequestNCRecalc(handle);
5115 internal override void SetModal(IntPtr handle, bool Modal) {
5117 ModalWindows.Push(handle);
5119 if (ModalWindows.Contains(handle)) {
5122 if (ModalWindows.Count > 0) {
5123 Activate((IntPtr)ModalWindows.Peek());
5127 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5128 Control ctrl = Control.FromHandle (handle);
5129 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5132 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5135 hwnd = Hwnd.ObjectFromHandle(handle);
5136 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5139 #if DriverDebug || DriverDebugParent
5140 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5142 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5148 internal override void SetTimer (Timer timer) {
5149 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5151 if (queue == null) {
5152 // This isn't really an error, MS doesn't start the timer if
5153 // it has no assosciated queue
5156 queue.timer_list.Add (timer);
5160 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5162 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5166 int[] atoms = new int[8];
5167 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5168 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5172 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5178 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5182 hwnd = Hwnd.ObjectFromHandle(handle);
5184 if (handle_owner != IntPtr.Zero) {
5185 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5191 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5192 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5194 if (hwnd_owner != null) {
5195 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5197 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5202 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5208 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5212 hwnd = Hwnd.ObjectFromHandle(handle);
5213 hwnd.visible = visible;
5217 MapWindow(hwnd, WindowType.Both);
5219 if (Control.FromHandle(handle) is Form) {
5222 s = ((Form)Control.FromHandle(handle)).WindowState;
5225 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5226 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5230 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5233 UnmapWindow(hwnd, WindowType.Both);
5239 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5240 Control ctrl = Control.FromHandle (handle);
5241 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5244 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5250 hwnd = Hwnd.ObjectFromHandle(handle);
5255 hints = new XSizeHints();
5257 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5258 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5260 min = TranslateWindowSizeToXWindowSize (cp);
5261 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5262 hints.min_width = min.Width;
5263 hints.min_height = min.Height;
5266 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5268 max = TranslateWindowSizeToXWindowSize (cp);
5269 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5270 hints.max_width = max.Width;
5271 hints.max_height = max.Height;
5274 if (hints.flags != IntPtr.Zero) {
5275 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5276 // they will maximize the window to fill the screen/parent no matter what.
5277 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5278 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5281 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5283 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5284 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5285 hints.x = maximized.X;
5286 hints.y = maximized.Y;
5287 hints.width = maximized.Width;
5288 hints.height = maximized.Height;
5290 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5291 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5296 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5299 hwnd = Hwnd.ObjectFromHandle(handle);
5305 // Win32 automatically changes negative width/height to 0.
5311 // X requires a sanity check for width & height; otherwise it dies
5312 if (hwnd.zero_sized && width > 0 && height > 0) {
5314 MapWindow(hwnd, WindowType.Whole);
5316 hwnd.zero_sized = false;
5319 if ((width < 1) || (height < 1)) {
5320 hwnd.zero_sized = true;
5321 UnmapWindow(hwnd, WindowType.Whole);
5324 // Save a server roundtrip (and prevent a feedback loop)
5325 if ((hwnd.x == x) && (hwnd.y == y) &&
5326 (hwnd.width == width) && (hwnd.height == height)) {
5330 if (!hwnd.zero_sized) {
5335 hwnd.height = height;
5336 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5338 if (hwnd.fixed_size) {
5339 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5343 Control ctrl = Control.FromHandle (handle);
5344 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams ());
5345 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5346 PerformNCCalc(hwnd);
5350 // Update our position/size immediately, so
5351 // that future calls to SetWindowPos aren't
5352 // kept from calling XMoveResizeWindow (by the
5353 // "Save a server roundtrip" block above).
5357 hwnd.height = height;
5358 hwnd.ClientRect = Rectangle.Empty;
5361 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5362 FormWindowState current_state;
5365 hwnd = Hwnd.ObjectFromHandle(handle);
5367 current_state = GetWindowState(handle);
5369 if (current_state == state) {
5374 case FormWindowState.Normal: {
5376 if (current_state == FormWindowState.Minimized) {
5377 MapWindow(hwnd, WindowType.Both);
5378 } else if (current_state == FormWindowState.Maximized) {
5379 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5386 case FormWindowState.Minimized: {
5388 if (current_state == FormWindowState.Maximized) {
5389 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5391 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5396 case FormWindowState.Maximized: {
5398 if (current_state == FormWindowState.Minimized) {
5399 MapWindow(hwnd, WindowType.Both);
5402 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5410 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5413 hwnd = Hwnd.ObjectFromHandle(handle);
5414 SetHwndStyles(hwnd, cp);
5415 SetWMStyles(hwnd, cp);
5418 internal override double GetWindowTransparency(IntPtr handle)
5423 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5427 hwnd = Hwnd.ObjectFromHandle(handle);
5433 hwnd.opacity = (uint)(0xffffffff * transparency);
5434 opacity = (IntPtr)((int)hwnd.opacity);
5436 IntPtr w = hwnd.whole_window;
5437 if (hwnd.reparented)
5438 w = XGetParent (hwnd.whole_window);
5439 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5442 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5443 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5451 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5454 } else if (!bottom) {
5455 Hwnd after_hwnd = null;
5457 if (after_handle != IntPtr.Zero) {
5458 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5461 XWindowChanges values = new XWindowChanges();
5463 if (after_hwnd == null) {
5464 // Work around metacity 'issues'
5468 atoms[0] = unixtime();
5469 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5471 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5472 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5474 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5477 values.sibling = after_hwnd.whole_window;
5478 values.stack_mode = StackMode.Below;
5481 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5486 XLowerWindow(DisplayHandle, hwnd.whole_window);
5493 internal override void ShowCursor(bool show) {
5494 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5497 internal override object StartLoop(Thread thread) {
5498 XEventQueue q = ThreadQueue(thread);
5502 internal override TransparencySupport SupportsTransparency() {
5503 // We need to check if the x compositing manager is running
5504 return TransparencySupport.Set;
5507 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5508 GetSystrayManagerWindow();
5510 if (SystrayMgrWindow != IntPtr.Zero) {
5511 XSizeHints size_hints;
5514 hwnd = Hwnd.ObjectFromHandle(handle);
5516 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5520 if (hwnd.client_window != hwnd.whole_window) {
5521 XDestroyWindow(DisplayHandle, hwnd.client_window);
5522 hwnd.client_window = hwnd.whole_window;
5524 /* by virtue of the way the tests are ordered when determining if it's PAINT
5525 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5526 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5527 there's a pending expose). */
5528 if (hwnd.nc_expose_pending) {
5529 hwnd.nc_expose_pending = false;
5530 if (!hwnd.expose_pending)
5531 hwnd.Queue.Paint.Remove (hwnd);
5535 size_hints = new XSizeHints();
5537 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5539 size_hints.min_width = 24;
5540 size_hints.min_height = 24;
5541 size_hints.max_width = 24;
5542 size_hints.max_height = 24;
5543 size_hints.base_width = 24;
5544 size_hints.base_height = 24;
5546 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5548 int[] atoms = new int[2];
5549 atoms [0] = 1; // Version 1
5550 atoms [1] = 1; // we want to be mapped
5552 // This line cost me 3 days...
5553 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5555 // Need to pick some reasonable defaults
5557 tt.AutomaticDelay = 350;
5558 tt.InitialDelay = 250;
5559 tt.ReshowDelay = 250;
5560 tt.ShowAlways = true;
5562 if ((tip != null) && (tip != string.Empty)) {
5563 tt.SetToolTip(Control.FromHandle(handle), tip);
5569 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5577 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5580 control = Control.FromHandle(handle);
5581 if (control != null && tt != null) {
5582 tt.SetToolTip(control, tip);
5590 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5592 #if GTKSOCKET_SUPPORTS_REPARENTING
5595 hwnd = Hwnd.ObjectFromHandle(handle);
5597 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5598 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5599 * 2. The client can reparent its window out of the embedder window.
5600 * 3. The client can destroy its window.
5602 * this call to SetParent is case 2, but in
5603 * the spec it also mentions that gtk doesn't
5604 * support this at present. Looking at HEAD
5605 * gtksocket-x11.c jives with this statement.
5607 * so we can't reparent. we have to destroy.
5609 SetParent(hwnd.whole_window, FosterParent);
5611 Control control = Control.FromHandle(handle);
5612 if (control is NotifyIcon.NotifyIconWindow)
5613 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
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);