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 CaptionHeight {
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 bool MenuAccessKeysUnderlined {
2107 internal override Size MinimizedWindowSize {
2109 return new Size(1, 1);
2113 internal override Size MinimizedWindowSpacingSize {
2115 return new Size(1, 1);
2119 internal override Size MinimumWindowSize {
2121 return new Size(1, 1);
2125 internal override Size MinWindowTrackSize {
2127 return new Size(1, 1);
2131 internal override Keys ModifierKeys {
2133 return Keyboard.ModifierKeys;
2137 internal override Size SmallIconSize {
2143 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2147 current = (long)list;
2150 size = new XIconSize();
2152 for (int i = 0; i < count; i++) {
2153 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2154 current += Marshal.SizeOf(size);
2156 // Look for our preferred size
2157 if (size.min_width == 16) {
2159 return new Size(16, 16);
2162 if (size.max_width == 16) {
2164 return new Size(16, 16);
2167 if (size.min_width < 16 && size.max_width > 16) {
2170 // check if we can fit one
2172 while (x < size.max_width) {
2173 x += size.width_inc;
2176 return new Size(16, 16);
2181 if (smallest == 0 || smallest > size.min_width) {
2182 smallest = size.min_width;
2186 // We didn't find a match or we wouldn't be here
2187 return new Size(smallest, smallest);
2190 return new Size(16, 16);
2195 internal override int MouseButtonCount {
2201 internal override bool MouseButtonsSwapped {
2203 return false; // FIXME - how to detect?
2207 internal override Point MousePosition {
2209 return mouse_position;
2213 internal override Size MouseHoverSize {
2215 return new Size (1, 1);
2219 internal override int MouseHoverTime {
2221 return HoverState.Interval;
2227 internal override bool MouseWheelPresent {
2229 return true; // FIXME - how to detect?
2233 internal override Rectangle VirtualScreen {
2239 IntPtr prop = IntPtr.Zero;
2243 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);
2244 if ((long)nitems < 2)
2247 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2248 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2252 return new Rectangle(0, 0, width, height);
2255 XWindowAttributes attributes=new XWindowAttributes();
2258 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2261 return new Rectangle(0, 0, attributes.width, attributes.height);
2265 internal override Rectangle WorkingArea {
2271 IntPtr prop = IntPtr.Zero;
2274 int current_desktop;
2278 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);
2279 if ((long)nitems < 1) {
2283 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2286 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);
2287 if ((long)nitems < 4 * current_desktop) {
2291 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2292 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2293 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2294 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2297 return new Rectangle(x, y, width, height);
2300 XWindowAttributes attributes=new XWindowAttributes();
2303 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2306 return new Rectangle(0, 0, attributes.width, attributes.height);
2310 internal override bool ThemesEnabled {
2312 return XplatUIX11.themes_enabled;
2317 #endregion // Public properties
2319 #region Public Static Methods
2320 internal override IntPtr InitializeDriver() {
2322 if (DisplayHandle==IntPtr.Zero) {
2323 SetDisplay(XOpenDisplay(IntPtr.Zero));
2329 internal override void ShutdownDriver(IntPtr token) {
2331 if (DisplayHandle!=IntPtr.Zero) {
2332 XCloseDisplay(DisplayHandle);
2333 DisplayHandle=IntPtr.Zero;
2338 internal override void EnableThemes() {
2339 themes_enabled = true;
2343 internal override void Activate(IntPtr handle) {
2346 hwnd = Hwnd.ObjectFromHandle(handle);
2350 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2351 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2354 // XRaiseWindow(DisplayHandle, handle);
2360 internal override void AudibleAlert() {
2361 XBell(DisplayHandle, 0);
2366 internal override void CaretVisible(IntPtr handle, bool visible) {
2367 if (Caret.Hwnd == handle) {
2369 if (!Caret.Visible) {
2370 Caret.Visible = true;
2372 Caret.Timer.Start();
2375 Caret.Visible = false;
2382 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2383 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2387 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2393 hwnd = Hwnd.ObjectFromHandle(handle);
2396 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2403 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2404 DataFormats.Format f;
2407 f = DataFormats.Format.List;
2409 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2413 Clipboard.Formats = new ArrayList();
2416 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2418 Clipboard.Enumerating = true;
2419 while (Clipboard.Enumerating) {
2420 UpdateMessageQueue(null);
2425 result = new int[Clipboard.Formats.Count];
2427 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2428 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2431 Clipboard.Formats = null;
2435 internal override void ClipboardClose(IntPtr handle) {
2436 if (handle != ClipMagic) {
2437 throw new ArgumentException("handle is not a valid clipboard handle");
2442 internal override int ClipboardGetID(IntPtr handle, string format) {
2443 if (handle != ClipMagic) {
2444 throw new ArgumentException("handle is not a valid clipboard handle");
2447 if (format == "Text" ) return (int)Atom.XA_STRING;
2448 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2449 //else if (format == "MetaFilePict" ) return 3;
2450 //else if (format == "SymbolicLink" ) return 4;
2451 //else if (format == "DataInterchangeFormat" ) return 5;
2452 //else if (format == "Tiff" ) return 6;
2453 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2454 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2455 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2456 //else if (format == "PenData" ) return 10;
2457 //else if (format == "RiffAudio" ) return 11;
2458 //else if (format == "WaveAudio" ) return 12;
2459 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2460 //else if (format == "EnhancedMetafile" ) return 14;
2461 //else if (format == "FileDrop" ) return 15;
2462 //else if (format == "Locale" ) return 16;
2464 return XInternAtom(DisplayHandle, format, false).ToInt32();
2467 internal override IntPtr ClipboardOpen(bool primary_selection) {
2468 if (!primary_selection)
2469 ClipMagic = CLIPBOARD;
2471 ClipMagic = PRIMARY;
2475 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2476 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2478 Clipboard.Retrieving = true;
2479 while (Clipboard.Retrieving) {
2480 UpdateMessageQueue(null);
2483 return Clipboard.Item;
2486 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2487 Clipboard.Item = obj;
2488 Clipboard.Type = type;
2489 Clipboard.Converter = converter;
2492 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2494 // Clearing the selection
2495 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2499 internal override void CreateCaret (IntPtr handle, int width, int height)
2501 XGCValues gc_values;
2504 hwnd = Hwnd.ObjectFromHandle(handle);
2506 if (Caret.Hwnd != IntPtr.Zero) {
2507 DestroyCaret(Caret.Hwnd);
2510 Caret.Hwnd = handle;
2511 Caret.Window = hwnd.client_window;
2512 Caret.Width = width;
2513 Caret.Height = height;
2514 Caret.Visible = false;
2517 gc_values = new XGCValues();
2518 gc_values.line_width = width;
2520 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2521 if (Caret.gc == IntPtr.Zero) {
2522 Caret.Hwnd = IntPtr.Zero;
2526 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2529 internal override IntPtr CreateWindow (CreateParams cp)
2531 XSetWindowAttributes Attributes;
2533 Hwnd parent_hwnd = null;
2538 IntPtr ParentHandle;
2540 IntPtr ClientWindow;
2541 SetWindowValuemask ValueMask;
2546 Attributes = new XSetWindowAttributes();
2552 if (Width<1) Width=1;
2553 if (Height<1) Height=1;
2555 if (cp.Parent != IntPtr.Zero) {
2556 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2557 ParentHandle = parent_hwnd.client_window;
2559 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2560 // We need to use our foster parent window until this poor child gets it's parent assigned
2561 ParentHandle=FosterParent;
2563 ParentHandle=RootWindow;
2567 // Set the default location location for forms.
2568 Point previous, next;
2570 if (cp.control is Form) {
2571 if (parent_hwnd != null) {
2572 previous = parent_hwnd.previous_child_startup_location;
2573 within = parent_hwnd.client_rectangle;
2575 previous = Hwnd.previous_main_startup_location;
2576 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
2579 if (previous.X == int.MinValue || previous.Y == int.MinValue) {
2582 next = new Point (previous.X + 22, previous.Y + 22);
2585 if (!within.Contains (next.X * 3, next.Y * 3)) {
2589 if (next == Point.Empty && cp.Parent == IntPtr.Zero) {
2590 next = new Point (22, 22);
2593 if (parent_hwnd != null) {
2594 parent_hwnd.previous_child_startup_location = next;
2596 Hwnd.previous_main_startup_location = next;
2599 if (X == int.MinValue && Y == int.MinValue) {
2604 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2606 Attributes.bit_gravity = Gravity.NorthWestGravity;
2607 Attributes.win_gravity = Gravity.NorthWestGravity;
2609 // Save what's under the toolwindow
2610 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2611 Attributes.save_under = true;
2612 ValueMask |= SetWindowValuemask.SaveUnder;
2616 // If we're a popup without caption we override the WM
2617 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2618 Attributes.override_redirect = true;
2619 ValueMask |= SetWindowValuemask.OverrideRedirect;
2625 hwnd.height = Height;
2626 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2627 hwnd.initial_style = cp.WindowStyle;
2628 hwnd.initial_ex_style = cp.WindowExStyle;
2630 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2631 hwnd.enabled = false;
2634 ClientWindow = IntPtr.Zero;
2636 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2637 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2640 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);
2641 if (WholeWindow != IntPtr.Zero) {
2642 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2644 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2645 ValueMask = SetWindowValuemask.ColorMap;
2646 Attributes.colormap = CustomColormap;
2648 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);
2652 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2653 throw new Exception("Could not create X11 windows");
2656 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2657 hwnd.WholeWindow = WholeWindow;
2658 hwnd.ClientWindow = ClientWindow;
2660 #if DriverDebug || DriverDebugCreate
2661 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);
2664 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2665 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2668 hints = new XSizeHints();
2671 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2672 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2677 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2678 if (hwnd.whole_window != hwnd.client_window)
2679 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2682 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2684 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2685 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2687 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2690 SetWMStyles(hwnd, cp);
2692 // set the group leader
2693 XWMHints wm_hints = new XWMHints ();
2695 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2696 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2697 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2699 if (ParentHandle != RootWindow) {
2700 wm_hints.window_group = hwnd.whole_window;
2702 wm_hints.window_group = ParentHandle;
2706 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2709 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2710 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2711 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2712 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2715 // for now make all windows dnd enabled
2716 Dnd.SetAllowDrop (hwnd, true);
2718 // Set caption/window title
2719 Text(hwnd.Handle, cp.Caption);
2721 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2722 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2724 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2725 hwnd.visible = true;
2726 MapWindow(hwnd, WindowType.Both);
2727 if (!(Control.FromHandle(hwnd.Handle) is Form))
2728 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2734 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2735 CreateParams create_params = new CreateParams();
2737 create_params.Caption = "";
2738 create_params.X = X;
2739 create_params.Y = Y;
2740 create_params.Width = Width;
2741 create_params.Height = Height;
2743 create_params.ClassName=XplatUI.DefaultClassName;
2744 create_params.ClassStyle = 0;
2745 create_params.ExStyle=0;
2746 create_params.Parent=IntPtr.Zero;
2747 create_params.Param=0;
2749 return CreateWindow(create_params);
2752 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2754 Bitmap cursor_bitmap;
2762 IntPtr cursor_pixmap;
2769 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2773 // Win32 only allows creation cursors of a certain size
2774 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2775 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2776 cursor_mask = new Bitmap(mask, new Size(width, height));
2778 cursor_bitmap = bitmap;
2782 width = cursor_bitmap.Width;
2783 height = cursor_bitmap.Height;
2785 cursor_bits = new Byte[(width / 8) * height];
2786 mask_bits = new Byte[(width / 8) * height];
2788 for (int y = 0; y < height; y++) {
2789 for (int x = 0; x < width; x++) {
2790 c_pixel = cursor_bitmap.GetPixel(x, y);
2791 m_pixel = cursor_mask.GetPixel(x, y);
2793 and = c_pixel == cursor_pixel;
2794 xor = m_pixel == mask_pixel;
2798 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2799 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2800 } else if (and && !xor) {
2802 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2803 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2805 } else if (and && !xor) {
2807 } else if (and && xor) {
2810 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2811 // we want both to be 0 so nothing to be done
2812 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2813 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2819 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2820 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2824 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2825 fg.red = (ushort)65535;
2826 fg.green = (ushort)65535;
2827 fg.blue = (ushort)65535;
2829 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2831 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2833 XFreePixmap(DisplayHandle, cursor_pixmap);
2834 XFreePixmap(DisplayHandle, mask_pixmap);
2839 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2840 CursorFontShape shape;
2847 shape = StdCursorToFontShape (id);
2848 name = shape.ToString ().Replace ("XC_", string.Empty);
2849 size = XcursorGetDefaultSize (DisplayHandle);
2850 theme = XcursorGetTheme (DisplayHandle);
2851 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2853 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);
2856 if (images_ptr == IntPtr.Zero) {
2860 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2862 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2865 if (images.nimage > 0) {
2866 // We only care about the first image.
2867 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2870 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);
2873 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2874 int [] pixels = new int [image.width * image.height];
2875 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2876 bmp = new Bitmap (image.width, image.height);
2877 for (int w = 0; w < image.width; w++) {
2878 for (int h = 0; h < image.height; h++) {
2879 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2885 XcursorImagesDestroy (images_ptr);
2887 } catch (DllNotFoundException ex) {
2888 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2896 internal override IntPtr DefineStdCursor(StdCursor id) {
2897 CursorFontShape shape;
2900 shape = StdCursorToFontShape (id);
2903 cursor = XCreateFontCursor(DisplayHandle, shape);
2908 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2909 CursorFontShape shape;
2910 // FIXME - define missing shapes
2913 case StdCursor.AppStarting: {
2914 shape = CursorFontShape.XC_watch;
2918 case StdCursor.Arrow: {
2919 shape = CursorFontShape.XC_top_left_arrow;
2923 case StdCursor.Cross: {
2924 shape = CursorFontShape.XC_crosshair;
2928 case StdCursor.Default: {
2929 shape = CursorFontShape.XC_top_left_arrow;
2933 case StdCursor.Hand: {
2934 shape = CursorFontShape.XC_hand1;
2938 case StdCursor.Help: {
2939 shape = CursorFontShape.XC_question_arrow;
2943 case StdCursor.HSplit: {
2944 shape = CursorFontShape.XC_sb_v_double_arrow;
2948 case StdCursor.IBeam: {
2949 shape = CursorFontShape.XC_xterm;
2953 case StdCursor.No: {
2954 shape = CursorFontShape.XC_circle;
2958 case StdCursor.NoMove2D: {
2959 shape = CursorFontShape.XC_fleur;
2963 case StdCursor.NoMoveHoriz: {
2964 shape = CursorFontShape.XC_fleur;
2968 case StdCursor.NoMoveVert: {
2969 shape = CursorFontShape.XC_fleur;
2973 case StdCursor.PanEast: {
2974 shape = CursorFontShape.XC_fleur;
2978 case StdCursor.PanNE: {
2979 shape = CursorFontShape.XC_fleur;
2983 case StdCursor.PanNorth: {
2984 shape = CursorFontShape.XC_fleur;
2988 case StdCursor.PanNW: {
2989 shape = CursorFontShape.XC_fleur;
2993 case StdCursor.PanSE: {
2994 shape = CursorFontShape.XC_fleur;
2998 case StdCursor.PanSouth: {
2999 shape = CursorFontShape.XC_fleur;
3003 case StdCursor.PanSW: {
3004 shape = CursorFontShape.XC_fleur;
3008 case StdCursor.PanWest: {
3009 shape = CursorFontShape.XC_sizing;
3013 case StdCursor.SizeAll: {
3014 shape = CursorFontShape.XC_fleur;
3018 case StdCursor.SizeNESW: {
3019 shape = CursorFontShape.XC_top_right_corner;
3023 case StdCursor.SizeNS: {
3024 shape = CursorFontShape.XC_sb_v_double_arrow;
3028 case StdCursor.SizeNWSE: {
3029 shape = CursorFontShape.XC_top_left_corner;
3033 case StdCursor.SizeWE: {
3034 shape = CursorFontShape.XC_sb_h_double_arrow;
3038 case StdCursor.UpArrow: {
3039 shape = CursorFontShape.XC_center_ptr;
3043 case StdCursor.VSplit: {
3044 shape = CursorFontShape.XC_sb_h_double_arrow;
3048 case StdCursor.WaitCursor: {
3049 shape = CursorFontShape.XC_watch;
3054 shape = (CursorFontShape) 0;
3062 internal override IntPtr DefWndProc(ref Message msg) {
3063 switch ((Msg)msg.Msg) {
3064 case Msg.WM_PAINT: {
3067 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3069 hwnd.expose_pending = false;
3075 case Msg.WM_NCPAINT: {
3078 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3080 hwnd.nc_expose_pending = false;
3086 case Msg.WM_NCCALCSIZE: {
3089 if (msg.WParam == (IntPtr)1) {
3090 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3092 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3093 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3095 // Add all the stuff X is supposed to draw.
3096 Control ctrl = Control.FromHandle (hwnd.Handle);
3097 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3099 ncp.rgrc1.top += rect.top;
3100 ncp.rgrc1.bottom -= rect.bottom;
3101 ncp.rgrc1.left += rect.left;
3102 ncp.rgrc1.right -= rect.right;
3104 Marshal.StructureToPtr (ncp, msg.LParam, true);
3110 case Msg.WM_CONTEXTMENU: {
3113 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3115 if ((hwnd != null) && (hwnd.parent != null)) {
3116 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3121 case Msg.WM_MOUSEWHEEL: {
3124 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3126 if ((hwnd != null) && (hwnd.parent != null)) {
3127 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3128 if (msg.Result == IntPtr.Zero) {
3135 case Msg.WM_SETCURSOR: {
3138 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3140 break; // not sure how this happens, but it does
3142 // Pass to parent window first
3143 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3145 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3148 if (msg.Result == IntPtr.Zero) {
3151 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3152 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3153 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3154 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3155 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3156 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3159 handle = Cursors.Default.handle;
3162 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3163 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3164 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3165 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3166 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3167 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3170 case HitTest.HTGROWBOX:
3171 case HitTest.HTSIZE:
3172 case HitTest.HTZOOM:
3173 case HitTest.HTVSCROLL:
3174 case HitTest.HTSYSMENU:
3175 case HitTest.HTREDUCE:
3176 case HitTest.HTNOWHERE:
3177 case HitTest.HTMAXBUTTON:
3178 case HitTest.HTMINBUTTON:
3179 case HitTest.HTMENU:
3180 case HitTest.HSCROLL:
3181 case HitTest.HTBOTTOM:
3182 case HitTest.HTCAPTION:
3183 case HitTest.HTCLIENT:
3184 case HitTest.HTCLOSE:
3186 default: handle = Cursors.Default.handle; break;
3188 SetCursor(msg.HWnd, handle);
3196 internal override void DestroyCaret(IntPtr handle) {
3197 if (Caret.Hwnd == handle) {
3198 if (Caret.Visible) {
3202 if (Caret.gc != IntPtr.Zero) {
3203 XFreeGC(DisplayHandle, Caret.gc);
3204 Caret.gc = IntPtr.Zero;
3206 Caret.Hwnd = IntPtr.Zero;
3207 Caret.Visible = false;
3212 internal override void DestroyCursor(IntPtr cursor) {
3214 XFreeCursor(DisplayHandle, cursor);
3218 internal override void DestroyWindow(IntPtr handle) {
3221 hwnd = Hwnd.ObjectFromHandle(handle);
3224 #if DriverDebug || DriverDebugDestroy
3225 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3230 #if DriverDebug || DriverDebugDestroy
3231 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3234 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3236 CleanupCachedWindows (hwnd);
3238 ArrayList windows = new ArrayList ();
3240 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3243 foreach (Hwnd h in windows) {
3244 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3249 if (hwnd.whole_window != IntPtr.Zero) {
3250 #if DriverDebug || DriverDebugDestroy
3251 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3253 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3255 else if (hwnd.client_window != IntPtr.Zero) {
3256 #if DriverDebug || DriverDebugDestroy
3257 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3259 XDestroyWindow(DisplayHandle, hwnd.client_window);
3265 internal override IntPtr DispatchMessage(ref MSG msg) {
3266 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3269 IntPtr GetReversibleScreenGC (Color backColor)
3271 XGCValues gc_values;
3275 XColor xcolor = new XColor();
3276 xcolor.red = (ushort)(backColor.R * 257);
3277 xcolor.green = (ushort)(backColor.G * 257);
3278 xcolor.blue = (ushort)(backColor.B * 257);
3279 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3280 pixel = (uint)xcolor.pixel.ToInt32();
3283 gc_values = new XGCValues();
3285 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3286 gc_values.foreground = (IntPtr)pixel;
3288 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3289 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3290 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3295 IntPtr GetReversibleControlGC (Control control, int line_width)
3297 XGCValues gc_values;
3300 gc_values = new XGCValues();
3302 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3303 gc_values.line_width = line_width;
3304 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3306 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3307 //mask = foreground ^ background;
3308 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3309 //XSetBackground(DisplayHandle, gc, background);
3310 //XSetFunction(DisplayHandle, gc, GXxor);
3311 //XSetPlaneMask(DisplayHandle, gc, mask);
3314 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3318 XColor xcolor = new XColor();
3320 xcolor.red = (ushort)(control.ForeColor.R * 257);
3321 xcolor.green = (ushort)(control.ForeColor.G * 257);
3322 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3323 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3324 foreground = (uint)xcolor.pixel.ToInt32();
3326 xcolor.red = (ushort)(control.BackColor.R * 257);
3327 xcolor.green = (ushort)(control.BackColor.G * 257);
3328 xcolor.blue = (ushort)(control.BackColor.B * 257);
3329 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3330 background = (uint)xcolor.pixel.ToInt32();
3332 uint mask = foreground ^ background;
3334 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3335 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3336 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3337 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3342 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3344 IntPtr gc = GetReversibleScreenGC (backColor);
3346 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3348 XFreeGC(DisplayHandle, gc);
3351 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3353 IntPtr gc = GetReversibleScreenGC (backColor);
3355 if (rectangle.Width < 0) {
3356 rectangle.X += rectangle.Width;
3357 rectangle.Width = -rectangle.Width;
3359 if (rectangle.Height < 0) {
3360 rectangle.Y += rectangle.Height;
3361 rectangle.Height = -rectangle.Height;
3365 GCLineStyle line_style = GCLineStyle.LineSolid;
3366 GCCapStyle cap_style = GCCapStyle.CapButt;
3367 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3370 case FrameStyle.Dashed:
3371 line_style = GCLineStyle.LineOnOffDash;
3373 case FrameStyle.Thick:
3378 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3380 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3382 XFreeGC(DisplayHandle, gc);
3385 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3387 IntPtr gc = GetReversibleScreenGC (backColor);
3389 if (rectangle.Width < 0) {
3390 rectangle.X += rectangle.Width;
3391 rectangle.Width = -rectangle.Width;
3393 if (rectangle.Height < 0) {
3394 rectangle.Y += rectangle.Height;
3395 rectangle.Height = -rectangle.Height;
3397 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3399 XFreeGC(DisplayHandle, gc);
3402 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3404 Control control = Control.FromHandle(handle);
3406 gc = GetReversibleControlGC (control, line_width);
3408 if ((rect.Width > 0) && (rect.Height > 0)) {
3409 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3411 if (rect.Width > 0) {
3412 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3414 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3417 XFreeGC(DisplayHandle, gc);
3420 internal override void DoEvents() {
3421 MSG msg = new MSG ();
3424 if (OverrideCursorHandle != IntPtr.Zero) {
3425 OverrideCursorHandle = IntPtr.Zero;
3428 queue = ThreadQueue(Thread.CurrentThread);
3430 queue.DispatchIdle = false;
3432 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3433 TranslateMessage (ref msg);
3434 DispatchMessage (ref msg);
3437 queue.DispatchIdle = true;
3440 internal override void EnableWindow(IntPtr handle, bool Enable) {
3443 hwnd = Hwnd.ObjectFromHandle(handle);
3445 hwnd.Enabled = Enable;
3449 internal override void EndLoop(Thread thread) {
3450 // This is where we one day will shut down the loop for the thread
3453 internal override IntPtr GetActive() {
3458 IntPtr prop = IntPtr.Zero;
3459 IntPtr active = IntPtr.Zero;
3461 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);
3462 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3463 active = (IntPtr)Marshal.ReadInt32(prop);
3467 if (active != IntPtr.Zero) {
3470 hwnd = Hwnd.GetObjectFromWindow(active);
3472 active = hwnd.Handle;
3474 active = IntPtr.Zero;
3480 internal override Region GetClipRegion(IntPtr handle) {
3483 hwnd = Hwnd.ObjectFromHandle(handle);
3485 return hwnd.UserClip;
3491 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3498 internal override void GetDisplaySize(out Size size) {
3499 XWindowAttributes attributes=new XWindowAttributes();
3502 // FIXME - use _NET_WM messages instead?
3503 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3506 size = new Size(attributes.width, attributes.height);
3509 internal override SizeF GetAutoScaleSize(Font font) {
3512 string magic_string = "The quick brown fox jumped over the lazy dog.";
3513 double magic_number = 44.549996948242189;
3515 g = Graphics.FromHwnd(FosterParent);
3517 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3518 return new SizeF(width, font.Height);
3521 internal override IntPtr GetParent(IntPtr handle) {
3524 hwnd = Hwnd.ObjectFromHandle(handle);
3525 if (hwnd != null && hwnd.parent != null) {
3526 return hwnd.parent.Handle;
3531 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3541 if (handle != IntPtr.Zero) {
3542 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3544 use_handle = RootWindow;
3548 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3551 if (handle != IntPtr.Zero) {
3560 internal override IntPtr GetFocus() {
3565 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3566 FontFamily ff = font.FontFamily;
3567 ascent = ff.GetCellAscent (font.Style);
3568 descent = ff.GetCellDescent (font.Style);
3572 internal override Point GetMenuOrigin(IntPtr handle) {
3575 hwnd = Hwnd.ObjectFromHandle(handle);
3578 return hwnd.MenuOrigin;
3583 [MonoTODO("Implement filtering")]
3584 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3591 if (((XEventQueue)queue_id).Count > 0) {
3592 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3594 UpdateMessageQueue ((XEventQueue)queue_id);
3596 if (((XEventQueue)queue_id).Count > 0) {
3597 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3598 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3599 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3601 msg.hwnd= IntPtr.Zero;
3602 msg.message = Msg.WM_ENTERIDLE;
3607 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3609 // Handle messages for windows that are already or are about to be destroyed.
3611 // we need a special block for this because unless we remove the hwnd from the paint
3612 // queue it will always stay there (since we don't handle the expose), and we'll
3613 // effectively loop infinitely trying to repaint a non-existant window.
3614 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3615 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3616 hwnd.Queue.Paint.Remove (hwnd);
3617 goto ProcessNextMessage;
3620 // We need to make sure we only allow DestroyNotify events through for zombie
3621 // hwnds, since much of the event handling code makes requests using the hwnd's
3622 // client_window, and that'll result in BadWindow errors if there's some lag
3623 // between the XDestroyWindow call and the DestroyNotify event.
3624 if (hwnd == null || hwnd.zombie) {
3625 #if DriverDebug || DriverDebugDestroy
3626 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3628 goto ProcessNextMessage;
3631 if (hwnd.client_window == xevent.AnyEvent.window) {
3633 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3636 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3639 msg.hwnd = hwnd.Handle;
3642 // If you add a new event to this switch make sure to add it in
3643 // UpdateMessage also unless it is not coming through the X event system.
3645 switch(xevent.type) {
3646 case XEventName.KeyPress: {
3648 Dnd.HandleKeyPress (ref xevent);
3649 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3653 case XEventName.KeyRelease: {
3654 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3658 case XEventName.ButtonPress: {
3659 switch(xevent.ButtonEvent.button) {
3661 MouseState |= MouseButtons.Left;
3663 msg.message = Msg.WM_LBUTTONDOWN;
3665 msg.message = Msg.WM_NCLBUTTONDOWN;
3666 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3668 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3669 msg.wParam=GetMousewParam(0);
3674 MouseState |= MouseButtons.Middle;
3676 msg.message = Msg.WM_MBUTTONDOWN;
3678 msg.message = Msg.WM_NCMBUTTONDOWN;
3679 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3681 msg.wParam=GetMousewParam(0);
3686 MouseState |= MouseButtons.Right;
3688 msg.message = Msg.WM_RBUTTONDOWN;
3690 msg.message = Msg.WM_NCRBUTTONDOWN;
3691 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3693 msg.wParam=GetMousewParam(0);
3698 msg.hwnd = FocusWindow;
3699 msg.message=Msg.WM_MOUSEWHEEL;
3700 msg.wParam=GetMousewParam(120);
3705 msg.hwnd = FocusWindow;
3706 msg.message=Msg.WM_MOUSEWHEEL;
3707 msg.wParam=GetMousewParam(-120);
3713 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3714 mouse_position.X = xevent.ButtonEvent.x;
3715 mouse_position.Y = xevent.ButtonEvent.y;
3717 if (!hwnd.Enabled) {
3720 msg.hwnd = hwnd.EnabledHwnd;
3721 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);
3722 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3725 if (Grab.Hwnd != IntPtr.Zero) {
3726 msg.hwnd = Grab.Hwnd;
3729 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3730 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3731 switch(xevent.ButtonEvent.button) {
3733 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3738 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3743 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3747 ClickPending.Pending = false;
3749 ClickPending.Pending = true;
3750 ClickPending.Hwnd = msg.hwnd;
3751 ClickPending.Message = msg.message;
3752 ClickPending.wParam = msg.wParam;
3753 ClickPending.lParam = msg.lParam;
3754 ClickPending.Time = (long)xevent.ButtonEvent.time;
3757 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3758 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3760 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3761 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3762 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3763 XEvent motionEvent = new XEvent ();
3764 motionEvent.type = XEventName.MotionNotify;
3765 motionEvent.MotionEvent.display = DisplayHandle;
3766 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3767 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3768 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3769 hwnd.Queue.EnqueueLocked (motionEvent);
3775 case XEventName.ButtonRelease: {
3777 if (Dnd.HandleButtonRelease (ref xevent)) {
3780 // Allow the LBUTTONUP message to get through
3783 switch(xevent.ButtonEvent.button) {
3786 msg.message = Msg.WM_LBUTTONUP;
3788 msg.message = Msg.WM_NCLBUTTONUP;
3789 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3791 MouseState &= ~MouseButtons.Left;
3792 msg.wParam=GetMousewParam(0);
3798 msg.message = Msg.WM_MBUTTONUP;
3800 msg.message = Msg.WM_NCMBUTTONUP;
3801 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3803 MouseState &= ~MouseButtons.Middle;
3804 msg.wParam=GetMousewParam(0);
3810 msg.message = Msg.WM_RBUTTONUP;
3812 msg.message = Msg.WM_NCRBUTTONUP;
3813 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3815 MouseState &= ~MouseButtons.Right;
3816 msg.wParam=GetMousewParam(0);
3821 goto ProcessNextMessage;
3825 goto ProcessNextMessage;
3829 if (!hwnd.Enabled) {
3832 msg.hwnd = hwnd.EnabledHwnd;
3833 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);
3834 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3837 if (Grab.Hwnd != IntPtr.Zero) {
3838 msg.hwnd = Grab.Hwnd;
3841 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3842 mouse_position.X = xevent.ButtonEvent.x;
3843 mouse_position.Y = xevent.ButtonEvent.y;
3845 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3846 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3847 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3848 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3849 XEvent motionEvent = new XEvent ();
3850 motionEvent.type = XEventName.MotionNotify;
3851 motionEvent.MotionEvent.display = DisplayHandle;
3852 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3853 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3854 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3855 hwnd.Queue.EnqueueLocked (motionEvent);
3860 case XEventName.MotionNotify: {
3862 #if DriverDebugExtra
3863 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);
3866 if (Dnd.HandleMotionNotify (ref xevent))
3867 goto ProcessNextMessage;
3868 if (Grab.Hwnd != IntPtr.Zero) {
3869 msg.hwnd = Grab.Hwnd;
3872 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3876 msg.message = Msg.WM_MOUSEMOVE;
3877 msg.wParam = GetMousewParam(0);
3878 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3880 if (!hwnd.Enabled) {
3883 msg.hwnd = hwnd.EnabledHwnd;
3884 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);
3885 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3888 mouse_position.X = xevent.MotionEvent.x;
3889 mouse_position.Y = xevent.MotionEvent.y;
3891 if ((HoverState.Timer.Enabled) &&
3892 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3893 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3894 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3895 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3896 HoverState.Timer.Stop();
3897 HoverState.Timer.Start();
3898 HoverState.X = mouse_position.X;
3899 HoverState.Y = mouse_position.Y;
3909 #if DriverDebugExtra
3910 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);
3912 msg.message = Msg.WM_NCMOUSEMOVE;
3914 if (!hwnd.Enabled) {
3915 msg.hwnd = hwnd.EnabledHwnd;
3916 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);
3917 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3920 // The hit test is sent in screen coordinates
3921 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3922 xevent.MotionEvent.x, xevent.MotionEvent.y,
3923 out screen_x, out screen_y, out dummy);
3925 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3926 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3927 IntPtr.Zero, msg.lParam).ToInt32 ();
3928 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3930 mouse_position.X = xevent.MotionEvent.x;
3931 mouse_position.Y = xevent.MotionEvent.y;
3937 case XEventName.EnterNotify: {
3938 if (!hwnd.Enabled) {
3939 goto ProcessNextMessage;
3941 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3942 goto ProcessNextMessage;
3944 msg.message = Msg.WM_MOUSE_ENTER;
3945 HoverState.X = xevent.CrossingEvent.x;
3946 HoverState.Y = xevent.CrossingEvent.y;
3947 HoverState.Timer.Enabled = true;
3948 HoverState.Window = xevent.CrossingEvent.window;
3952 case XEventName.LeaveNotify: {
3953 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3954 WindowUngrabbed (hwnd.Handle);
3955 goto ProcessNextMessage;
3957 if (!hwnd.Enabled) {
3958 goto ProcessNextMessage;
3960 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3961 goto ProcessNextMessage;
3963 msg.message=Msg.WM_MOUSELEAVE;
3964 HoverState.Timer.Enabled = false;
3965 HoverState.Window = IntPtr.Zero;
3970 case XEventName.CreateNotify: {
3971 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3972 msg.message = WM_CREATE;
3973 // Set up CreateStruct
3975 goto ProcessNextMessage;
3982 case XEventName.ReparentNotify: {
3983 if (hwnd.parent == null) { // Toplevel
3984 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3985 hwnd.Reparented = true;
3987 // The location given by the event is not reliable between different wm's,
3988 // so use an alternative way of getting it.
3989 Point location = GetTopLevelWindowLocation (hwnd);
3990 hwnd.X = location.X;
3991 hwnd.Y = location.Y;
3993 if (hwnd.opacity != 0xffffffff) {
3996 opacity = (IntPtr)(Int32)hwnd.opacity;
3997 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3999 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4000 goto ProcessNextMessage;
4002 hwnd.Reparented = false;
4003 goto ProcessNextMessage;
4006 goto ProcessNextMessage;
4009 case XEventName.ConfigureNotify: {
4010 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4011 #if DriverDebugExtra
4012 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);
4014 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
4015 lock (hwnd.configure_lock) {
4016 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4017 hwnd.configure_pending = false;
4020 // We need to adjust our client window to track the resize of whole_window
4021 if (hwnd.whole_window != hwnd.client_window)
4022 PerformNCCalc(hwnd);
4025 goto ProcessNextMessage;
4028 case XEventName.FocusIn: {
4029 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4030 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4031 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4032 // about it having focus again
4033 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4034 goto ProcessNextMessage;
4037 if (FocusWindow == IntPtr.Zero) {
4038 Control c = Control.FromHandle (hwnd.client_window);
4040 goto ProcessNextMessage;
4041 Form form = c.FindForm ();
4043 goto ProcessNextMessage;
4044 if (ActiveWindow != form.Handle) {
4045 ActiveWindow = form.Handle;
4046 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4048 goto ProcessNextMessage;
4050 Keyboard.FocusIn(FocusWindow);
4051 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4052 goto ProcessNextMessage;
4055 case XEventName.FocusOut: {
4056 // Se the comment for our FocusIn handler
4057 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4058 goto ProcessNextMessage;
4060 Keyboard.FocusOut(FocusWindow);
4062 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4063 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4066 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4067 goto ProcessNextMessage;
4070 case XEventName.MapNotify: {
4071 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4073 msg.message = Msg.WM_SHOWWINDOW;
4074 msg.wParam = (IntPtr) 1;
4075 // XXX we're missing the lParam..
4078 goto ProcessNextMessage;
4081 case XEventName.UnmapNotify: {
4082 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4083 hwnd.mapped = false;
4084 msg.message = Msg.WM_SHOWWINDOW;
4085 msg.wParam = (IntPtr) 0;
4086 // XXX we're missing the lParam..
4089 goto ProcessNextMessage;
4092 case XEventName.Expose: {
4095 hwnd.expose_pending = false;
4097 hwnd.nc_expose_pending = false;
4099 goto ProcessNextMessage;
4103 if (!hwnd.expose_pending) {
4104 goto ProcessNextMessage;
4107 if (!hwnd.nc_expose_pending) {
4108 goto ProcessNextMessage;
4111 switch (hwnd.border_style) {
4112 case FormBorderStyle.Fixed3D: {
4115 g = Graphics.FromHwnd(hwnd.whole_window);
4116 if (hwnd.border_static)
4117 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4119 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4124 case FormBorderStyle.FixedSingle: {
4127 g = Graphics.FromHwnd(hwnd.whole_window);
4128 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4133 #if DriverDebugExtra
4134 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);
4137 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4138 Region region = new Region (rect);
4139 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4140 msg.message = Msg.WM_NCPAINT;
4141 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4142 msg.refobject = region;
4145 #if DriverDebugExtra
4146 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);
4148 if (Caret.Visible == true) {
4149 Caret.Paused = true;
4153 if (Caret.Visible == true) {
4155 Caret.Paused = false;
4157 msg.message = Msg.WM_PAINT;
4161 case XEventName.DestroyNotify: {
4163 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4164 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4166 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4167 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4168 CleanupCachedWindows (hwnd);
4170 #if DriverDebugDestroy
4171 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4174 msg.hwnd = hwnd.client_window;
4175 msg.message=Msg.WM_DESTROY;
4178 goto ProcessNextMessage;
4184 case XEventName.ClientMessage: {
4185 if (Dnd.HandleClientMessage (ref xevent)) {
4186 goto ProcessNextMessage;
4189 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4190 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4191 goto ProcessNextMessage;
4194 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4195 msg.message = Msg.WM_MOUSEHOVER;
4196 msg.wParam = GetMousewParam(0);
4197 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4201 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4202 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4203 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4204 msg.wParam = xevent.ClientMessageEvent.ptr3;
4205 msg.lParam = xevent.ClientMessageEvent.ptr4;
4206 if (msg.message == (Msg)Msg.WM_QUIT)
4212 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4213 #if DriverDebugXEmbed
4214 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4217 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4218 XSizeHints hints = new XSizeHints();
4221 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4223 hwnd.width = hints.max_width;
4224 hwnd.height = hints.max_height;
4225 hwnd.ClientRect = Rectangle.Empty;
4226 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4230 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4231 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4232 msg.message = Msg.WM_CLOSE;
4236 // We should not get this, but I'll leave the code in case we need it in the future
4237 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4238 goto ProcessNextMessage;
4241 goto ProcessNextMessage;
4245 goto ProcessNextMessage;
4252 internal override bool GetText(IntPtr handle, out string text) {
4259 IntPtr prop = IntPtr.Zero;
4261 XGetWindowProperty(DisplayHandle, handle,
4262 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4263 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4265 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4266 text = Marshal.PtrToStringUni (prop, (int)nitems);
4271 // fallback on the non-_NET property
4274 textptr = IntPtr.Zero;
4276 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4277 if (textptr != IntPtr.Zero) {
4278 text = Marshal.PtrToStringAnsi(textptr);
4289 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) {
4292 hwnd = Hwnd.ObjectFromHandle(handle);
4298 height = hwnd.height;
4300 PerformNCCalc(hwnd);
4302 client_width = hwnd.ClientRect.Width;
4303 client_height = hwnd.ClientRect.Height;
4308 // Should we throw an exception or fail silently?
4309 // throw new ArgumentException("Called with an invalid window handle", "handle");
4319 internal override FormWindowState GetWindowState(IntPtr handle) {
4322 hwnd = Hwnd.ObjectFromHandle(handle);
4324 if (hwnd.cached_window_state == (FormWindowState)(-1))
4325 hwnd.cached_window_state = UpdateWindowState (handle);
4327 return hwnd.cached_window_state;
4330 private FormWindowState UpdateWindowState (IntPtr handle) {
4335 IntPtr prop = IntPtr.Zero;
4339 XWindowAttributes attributes;
4342 hwnd = Hwnd.ObjectFromHandle(handle);
4346 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);
4347 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4348 for (int i = 0; i < (long)nitems; i++) {
4349 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4350 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4352 } else if (atom == _NET_WM_STATE_HIDDEN) {
4360 return FormWindowState.Minimized;
4361 } else if (maximized == 2) {
4362 return FormWindowState.Maximized;
4365 attributes = new XWindowAttributes();
4366 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4367 if (attributes.map_state == MapState.IsUnmapped) {
4368 return (FormWindowState)(-1);
4372 return FormWindowState.Normal;
4375 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4377 GrabConfined = Grab.Confined;
4378 GrabArea = Grab.Area;
4381 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4383 IntPtr confine_to_window;
4385 confine_to_window = IntPtr.Zero;
4387 if (confine_to_handle != IntPtr.Zero) {
4388 XWindowAttributes attributes = new XWindowAttributes();
4390 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4393 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4395 Grab.Area.X = attributes.x;
4396 Grab.Area.Y = attributes.y;
4397 Grab.Area.Width = attributes.width;
4398 Grab.Area.Height = attributes.height;
4399 Grab.Confined = true;
4400 confine_to_window = hwnd.client_window;
4405 hwnd = Hwnd.ObjectFromHandle(handle);
4408 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4409 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4410 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4411 EventMask.LeaveWindowMask,
4412 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4416 internal override void UngrabWindow(IntPtr hwnd) {
4418 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4419 XFlush(DisplayHandle);
4421 WindowUngrabbed (hwnd);
4424 private void WindowUngrabbed (IntPtr hwnd) {
4425 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4427 Grab.Hwnd = IntPtr.Zero;
4428 Grab.Confined = false;
4431 // lparam should be the handle to the window gaining the mouse capture,
4432 // but X doesn't seem to give us that information.
4433 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4434 // X will send a NotifyUngrab, but since it comes late sometimes we're
4435 // calling WindowUngrabbed directly from UngrabWindow in order to send
4436 // this WM right away.
4437 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4441 internal override void HandleException(Exception e) {
4442 StackTrace st = new StackTrace(e, true);
4443 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4444 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4447 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4450 hwnd = Hwnd.ObjectFromHandle(handle);
4453 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4455 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4459 internal override void InvalidateNC (IntPtr handle) {
4462 hwnd = Hwnd.ObjectFromHandle(handle);
4464 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4467 internal override bool IsEnabled(IntPtr handle) {
4468 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4469 return (hwnd != null && hwnd.Enabled);
4472 internal override bool IsVisible(IntPtr handle) {
4473 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4474 return (hwnd != null && hwnd.visible);
4477 internal override void KillTimer(Timer timer) {
4478 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4480 if (queue == null) {
4481 // This isn't really an error, MS doesn't start the timer if
4482 // it has no assosciated queue
4485 queue.timer_list.Remove (timer);
4488 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4494 hwnd = Hwnd.ObjectFromHandle(handle);
4497 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4504 internal override void OverrideCursor(IntPtr cursor)
4506 if (Grab.Hwnd != IntPtr.Zero) {
4507 XChangeActivePointerGrab (DisplayHandle,
4508 EventMask.ButtonMotionMask |
4509 EventMask.PointerMotionMask |
4510 EventMask.ButtonPressMask |
4511 EventMask.ButtonReleaseMask,
4512 cursor, IntPtr.Zero);
4516 OverrideCursorHandle = cursor;
4519 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4520 PaintEventArgs paint_event;
4523 hwnd = Hwnd.ObjectFromHandle(handle);
4525 if (Caret.Visible == true) {
4526 Caret.Paused = true;
4533 dc = Graphics.FromHwnd (hwnd.client_window);
4535 Region clip_region = new Region ();
4536 clip_region.MakeEmpty();
4538 foreach (Rectangle r in hwnd.ClipRectangles) {
4539 clip_region.Union (r);
4542 if (hwnd.UserClip != null) {
4543 clip_region.Intersect(hwnd.UserClip);
4546 dc.Clip = clip_region;
4547 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4548 hwnd.expose_pending = false;
4550 hwnd.ClearInvalidArea();
4552 hwnd.drawing_stack.Push (paint_event);
4553 hwnd.drawing_stack.Push (dc);
4557 dc = Graphics.FromHwnd (hwnd.whole_window);
4559 if (!hwnd.nc_invalid.IsEmpty) {
4560 dc.SetClip (hwnd.nc_invalid);
4561 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4563 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4565 hwnd.nc_expose_pending = false;
4567 hwnd.ClearNcInvalidArea ();
4569 hwnd.drawing_stack.Push (paint_event);
4570 hwnd.drawing_stack.Push (dc);
4576 internal override void PaintEventEnd(IntPtr handle, bool client) {
4579 hwnd = Hwnd.ObjectFromHandle(handle);
4581 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4585 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4586 pe.SetGraphics (null);
4589 if (Caret.Visible == true) {
4591 Caret.Paused = false;
4595 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4596 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4597 XEventQueue queue = (XEventQueue) queue_id;
4600 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4601 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4605 if (queue.Count > 0) {
4608 // Only call UpdateMessageQueue if real events are pending
4609 // otherwise we go to sleep on the socket
4610 if (XPending(DisplayHandle) != 0) {
4611 UpdateMessageQueue((XEventQueue)queue_id);
4613 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4618 CheckTimers(queue.timer_list, DateTime.UtcNow);
4623 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4626 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4627 XEvent xevent = new XEvent ();
4628 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4630 xevent.type = XEventName.ClientMessage;
4631 xevent.ClientMessageEvent.display = DisplayHandle;
4634 xevent.ClientMessageEvent.window = hwnd.whole_window;
4636 xevent.ClientMessageEvent.window = IntPtr.Zero;
4639 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4640 xevent.ClientMessageEvent.format = 32;
4641 xevent.ClientMessageEvent.ptr1 = handle;
4642 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4643 xevent.ClientMessageEvent.ptr3 = wparam;
4644 xevent.ClientMessageEvent.ptr4 = lparam;
4646 hwnd.Queue.EnqueueLocked (xevent);
4651 internal override void PostQuitMessage(int exitCode) {
4652 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4653 XFlush(DisplayHandle);
4656 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4661 internal override void RequestNCRecalc(IntPtr handle) {
4664 hwnd = Hwnd.ObjectFromHandle(handle);
4670 PerformNCCalc(hwnd);
4671 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4672 InvalidateNC(handle);
4675 internal override void ResetMouseHover(IntPtr handle) {
4678 hwnd = Hwnd.ObjectFromHandle(handle);
4683 HoverState.Timer.Enabled = true;
4684 HoverState.X = mouse_position.X;
4685 HoverState.Y = mouse_position.Y;
4686 HoverState.Window = handle;
4690 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4696 hwnd = Hwnd.ObjectFromHandle(handle);
4699 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4706 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4712 hwnd = Hwnd.ObjectFromHandle(handle);
4715 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4718 Form form = Control.FromHandle (handle) as Form;
4719 if (form != null && form.window_manager != null) {
4720 dest_y_return -= form.window_manager.TitleBarHeight;
4727 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4730 XGCValues gc_values;
4732 hwnd = Hwnd.ObjectFromHandle(handle);
4734 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4736 /* We have an invalid area in the window we're scrolling.
4737 Adjust our stored invalid rectangle to to match the scrolled amount */
4752 if (area.Contains (hwnd.Invalid))
4753 hwnd.ClearInvalidArea ();
4754 hwnd.AddInvalidArea(r);
4757 gc_values = new XGCValues();
4759 if (with_children) {
4760 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4763 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4771 height = area.Height - YAmount;
4772 dest_y = area.Y + YAmount;
4775 src_y = area.Y - YAmount;
4776 height = area.Height + YAmount;
4782 width = area.Width - XAmount;
4783 dest_x = area.X + XAmount;
4786 src_x = area.X - XAmount;
4787 width = area.Width + XAmount;
4791 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4793 // Generate an expose for the area exposed by the horizontal scroll
4794 // We don't use AddExpose since we're
4796 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4797 } else if (XAmount < 0) {
4798 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4801 // Generate an expose for the area exposed by the vertical scroll
4803 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4804 } else if (YAmount < 0) {
4805 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4807 XFreeGC(DisplayHandle, gc);
4810 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4814 hwnd = Hwnd.GetObjectFromWindow(handle);
4816 rect = hwnd.ClientRect;
4819 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4822 internal override void SendAsyncMethod (AsyncMethodData method) {
4824 XEvent xevent = new XEvent ();
4826 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4828 xevent.type = XEventName.ClientMessage;
4829 xevent.ClientMessageEvent.display = DisplayHandle;
4830 xevent.ClientMessageEvent.window = method.Handle;
4831 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4832 xevent.ClientMessageEvent.format = 32;
4833 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4835 hwnd.Queue.EnqueueLocked (xevent);
4840 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4842 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4845 h = Hwnd.ObjectFromHandle(hwnd);
4847 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4848 AsyncMethodResult result;
4849 AsyncMethodData data;
4851 result = new AsyncMethodResult ();
4852 data = new AsyncMethodData ();
4855 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4856 data.Args = new object[] { hwnd, message, wParam, lParam };
4857 data.Result = result;
4859 SendAsyncMethod (data);
4860 #if DriverDebug || DriverDebugThreads
4861 Console.WriteLine ("Sending {0} message across.", message);
4866 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4869 internal override int SendInput(IntPtr handle, Queue keys) {
4870 if (handle == IntPtr.Zero)
4873 int count = keys.Count;
4874 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4876 while (keys.Count > 0) {
4878 MSG msg = (MSG)keys.Dequeue();
4880 XEvent xevent = new XEvent ();
4882 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4883 xevent.KeyEvent.display = DisplayHandle;
4886 xevent.KeyEvent.window = hwnd.whole_window;
4888 xevent.KeyEvent.window = IntPtr.Zero;
4891 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4893 hwnd.Queue.EnqueueLocked (xevent);
4898 internal override void SetAllowDrop (IntPtr handle, bool value)
4900 // We allow drop on all windows
4903 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4904 DragDropEffects allowed_effects)
4906 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4909 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4911 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4914 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4915 Form form = Control.FromHandle (handle) as Form;
4916 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4917 border_style == FormBorderStyle.SizableToolWindow)) {
4918 form.window_manager = new ToolWindowManager (form);
4921 RequestNCRecalc(handle);
4924 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4925 if (Caret.Hwnd == handle) {
4932 if (Caret.Visible == true) {
4934 Caret.Timer.Start();
4939 internal override void SetClipRegion(IntPtr handle, Region region) {
4942 hwnd = Hwnd.ObjectFromHandle(handle);
4947 hwnd.UserClip = region;
4950 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4953 if (OverrideCursorHandle == IntPtr.Zero) {
4954 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4958 LastCursorHandle = cursor;
4959 LastCursorWindow = handle;
4961 hwnd = Hwnd.ObjectFromHandle(handle);
4963 if (cursor != IntPtr.Zero) {
4964 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4966 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4968 XFlush(DisplayHandle);
4973 hwnd = Hwnd.ObjectFromHandle(handle);
4975 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4979 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4980 out int root_x, out int root_y, out int child_x, out int child_y,
4983 /* this code was written with the help of
4984 glance at gdk. I never would have realized we
4985 needed a loop in order to traverse down in the
4986 hierarchy. I would have assumed you'd get the
4987 most deeply nested child and have to do
4988 XQueryTree to move back up the hierarchy..
4989 stupid me, of course. */
4992 XGrabServer (display);
4994 XQueryPointer(display, w, out root, out c,
4995 out root_x, out root_y, out child_x, out child_y,
5001 IntPtr child_last = IntPtr.Zero;
5002 while (c != IntPtr.Zero) {
5004 XQueryPointer(display, c, out root, out c,
5005 out root_x, out root_y, out child_x, out child_y,
5008 XUngrabServer (display);
5014 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5015 if (handle == IntPtr.Zero) {
5018 int root_x, root_y, child_x, child_y, mask;
5021 * QueryPointer before warping
5022 * because if the warp is on
5023 * the RootWindow, the x/y are
5024 * relative to the current
5027 QueryPointer (DisplayHandle, RootWindow,
5030 out root_x, out root_y,
5031 out child_x, out child_y,
5034 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5036 XFlush (DisplayHandle);
5038 /* then we need to a
5039 * QueryPointer after warping
5040 * to manually generate a
5041 * motion event for the window
5044 QueryPointer (DisplayHandle, RootWindow,
5047 out root_x, out root_y,
5048 out child_x, out child_y,
5051 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5052 if (child_hwnd == null) {
5056 XEvent xevent = new XEvent ();
5058 xevent.type = XEventName.MotionNotify;
5059 xevent.MotionEvent.display = DisplayHandle;
5060 xevent.MotionEvent.window = child_hwnd.client_window;
5061 xevent.MotionEvent.root = RootWindow;
5062 xevent.MotionEvent.x = child_x;
5063 xevent.MotionEvent.y = child_y;
5064 xevent.MotionEvent.x_root = root_x;
5065 xevent.MotionEvent.y_root = root_y;
5066 xevent.MotionEvent.state = mask;
5068 child_hwnd.Queue.EnqueueLocked (xevent);
5073 hwnd = Hwnd.ObjectFromHandle(handle);
5075 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5080 internal override void SetFocus(IntPtr handle) {
5082 IntPtr prev_focus_window;
5084 hwnd = Hwnd.ObjectFromHandle(handle);
5086 if (hwnd.client_window == FocusWindow) {
5090 prev_focus_window = FocusWindow;
5091 FocusWindow = hwnd.client_window;
5093 if (prev_focus_window != IntPtr.Zero) {
5094 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5096 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5098 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5101 internal override void SetIcon(IntPtr handle, Icon icon) {
5104 hwnd = Hwnd.ObjectFromHandle(handle);
5106 SetIcon(hwnd, icon);
5110 internal override void SetMenu(IntPtr handle, Menu menu) {
5113 hwnd = Hwnd.ObjectFromHandle(handle);
5116 RequestNCRecalc(handle);
5119 internal override void SetModal(IntPtr handle, bool Modal) {
5121 ModalWindows.Push(handle);
5123 if (ModalWindows.Contains(handle)) {
5126 if (ModalWindows.Count > 0) {
5127 Activate((IntPtr)ModalWindows.Peek());
5131 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5132 Control ctrl = Control.FromHandle (handle);
5133 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5136 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5139 hwnd = Hwnd.ObjectFromHandle(handle);
5140 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5143 #if DriverDebug || DriverDebugParent
5144 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5146 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5152 internal override void SetTimer (Timer timer) {
5153 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5155 if (queue == null) {
5156 // This isn't really an error, MS doesn't start the timer if
5157 // it has no assosciated queue
5160 queue.timer_list.Add (timer);
5164 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5166 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5170 int[] atoms = new int[8];
5171 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5172 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5176 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5182 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5186 hwnd = Hwnd.ObjectFromHandle(handle);
5188 if (handle_owner != IntPtr.Zero) {
5189 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5195 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5196 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5198 if (hwnd_owner != null) {
5199 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5201 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5206 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5212 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5216 hwnd = Hwnd.ObjectFromHandle(handle);
5217 hwnd.visible = visible;
5221 MapWindow(hwnd, WindowType.Both);
5223 if (Control.FromHandle(handle) is Form) {
5226 s = ((Form)Control.FromHandle(handle)).WindowState;
5229 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5230 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5234 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5237 UnmapWindow(hwnd, WindowType.Both);
5243 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5244 Control ctrl = Control.FromHandle (handle);
5245 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5248 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5254 hwnd = Hwnd.ObjectFromHandle(handle);
5259 hints = new XSizeHints();
5261 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5262 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5264 min = TranslateWindowSizeToXWindowSize (cp);
5265 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5266 hints.min_width = min.Width;
5267 hints.min_height = min.Height;
5270 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5272 max = TranslateWindowSizeToXWindowSize (cp);
5273 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5274 hints.max_width = max.Width;
5275 hints.max_height = max.Height;
5278 if (hints.flags != IntPtr.Zero) {
5279 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5280 // they will maximize the window to fill the screen/parent no matter what.
5281 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5282 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5285 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5287 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5288 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5289 hints.x = maximized.X;
5290 hints.y = maximized.Y;
5291 hints.width = maximized.Width;
5292 hints.height = maximized.Height;
5294 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5295 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5300 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5303 hwnd = Hwnd.ObjectFromHandle(handle);
5309 // Win32 automatically changes negative width/height to 0.
5315 // X requires a sanity check for width & height; otherwise it dies
5316 if (hwnd.zero_sized && width > 0 && height > 0) {
5318 MapWindow(hwnd, WindowType.Whole);
5320 hwnd.zero_sized = false;
5323 if ((width < 1) || (height < 1)) {
5324 hwnd.zero_sized = true;
5325 UnmapWindow(hwnd, WindowType.Whole);
5328 // Save a server roundtrip (and prevent a feedback loop)
5329 if ((hwnd.x == x) && (hwnd.y == y) &&
5330 (hwnd.width == width) && (hwnd.height == height)) {
5334 if (!hwnd.zero_sized) {
5339 hwnd.height = height;
5340 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5342 if (hwnd.fixed_size) {
5343 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5347 Control ctrl = Control.FromHandle (handle);
5348 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams ());
5349 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5350 PerformNCCalc(hwnd);
5354 // Update our position/size immediately, so
5355 // that future calls to SetWindowPos aren't
5356 // kept from calling XMoveResizeWindow (by the
5357 // "Save a server roundtrip" block above).
5361 hwnd.height = height;
5362 hwnd.ClientRect = Rectangle.Empty;
5365 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5366 FormWindowState current_state;
5369 hwnd = Hwnd.ObjectFromHandle(handle);
5371 current_state = GetWindowState(handle);
5373 if (current_state == state) {
5378 case FormWindowState.Normal: {
5380 if (current_state == FormWindowState.Minimized) {
5381 MapWindow(hwnd, WindowType.Both);
5382 } else if (current_state == FormWindowState.Maximized) {
5383 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5390 case FormWindowState.Minimized: {
5392 if (current_state == FormWindowState.Maximized) {
5393 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5395 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5400 case FormWindowState.Maximized: {
5402 if (current_state == FormWindowState.Minimized) {
5403 MapWindow(hwnd, WindowType.Both);
5406 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5414 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5417 hwnd = Hwnd.ObjectFromHandle(handle);
5418 SetHwndStyles(hwnd, cp);
5419 SetWMStyles(hwnd, cp);
5422 internal override double GetWindowTransparency(IntPtr handle)
5427 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5431 hwnd = Hwnd.ObjectFromHandle(handle);
5437 hwnd.opacity = (uint)(0xffffffff * transparency);
5438 opacity = (IntPtr)((int)hwnd.opacity);
5440 IntPtr w = hwnd.whole_window;
5441 if (hwnd.reparented)
5442 w = XGetParent (hwnd.whole_window);
5443 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5446 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5447 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5455 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5458 } else if (!bottom) {
5459 Hwnd after_hwnd = null;
5461 if (after_handle != IntPtr.Zero) {
5462 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5465 XWindowChanges values = new XWindowChanges();
5467 if (after_hwnd == null) {
5468 // Work around metacity 'issues'
5472 atoms[0] = unixtime();
5473 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5475 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5476 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5478 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5481 values.sibling = after_hwnd.whole_window;
5482 values.stack_mode = StackMode.Below;
5485 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5490 XLowerWindow(DisplayHandle, hwnd.whole_window);
5497 internal override void ShowCursor(bool show) {
5498 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5501 internal override object StartLoop(Thread thread) {
5502 XEventQueue q = ThreadQueue(thread);
5506 internal override TransparencySupport SupportsTransparency() {
5507 // We need to check if the x compositing manager is running
5508 return TransparencySupport.Set;
5511 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5512 GetSystrayManagerWindow();
5514 if (SystrayMgrWindow != IntPtr.Zero) {
5515 XSizeHints size_hints;
5518 hwnd = Hwnd.ObjectFromHandle(handle);
5520 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5524 if (hwnd.client_window != hwnd.whole_window) {
5525 XDestroyWindow(DisplayHandle, hwnd.client_window);
5526 hwnd.client_window = hwnd.whole_window;
5529 /* by virtue of the way the tests are ordered when determining if it's PAINT
5530 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5531 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5532 there's a pending expose). */
5533 if (hwnd.nc_expose_pending) {
5534 hwnd.nc_expose_pending = false;
5535 if (!hwnd.expose_pending)
5536 hwnd.Queue.Paint.Remove (hwnd);
5539 size_hints = new XSizeHints();
5541 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5543 size_hints.min_width = 24;
5544 size_hints.min_height = 24;
5545 size_hints.max_width = 24;
5546 size_hints.max_height = 24;
5547 size_hints.base_width = 24;
5548 size_hints.base_height = 24;
5550 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5552 int[] atoms = new int[2];
5553 atoms [0] = 1; // Version 1
5554 atoms [1] = 1; // we want to be mapped
5556 // This line cost me 3 days...
5557 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5559 // Need to pick some reasonable defaults
5561 tt.AutomaticDelay = 350;
5562 tt.InitialDelay = 250;
5563 tt.ReshowDelay = 250;
5564 tt.ShowAlways = true;
5566 if ((tip != null) && (tip != string.Empty)) {
5567 tt.SetToolTip(Control.FromHandle(handle), tip);
5573 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5581 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5584 control = Control.FromHandle(handle);
5585 if (control != null && tt != null) {
5586 tt.SetToolTip(control, tip);
5594 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5596 SetVisible (handle, false, false);
5598 // The caller can now re-dock it later...
5606 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5608 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5609 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5613 internal override bool Text(IntPtr handle, string text) {
5616 hwnd = Hwnd.ObjectFromHandle(handle);
5619 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5620 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5622 // XXX this has problems with UTF8.
5623 // we need to either use the actual
5624 // text if it's latin-1, or convert it
5625 // to compound text if it's in a
5626 // different charset.
5627 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5632 internal override bool TranslateMessage(ref MSG msg) {
5633 return Keyboard.TranslateMessage (ref msg);
5636 internal override void UpdateWindow(IntPtr handle) {
5639 hwnd = Hwnd.ObjectFromHandle(handle);
5641 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5645 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5646 hwnd.Queue.Paint.Remove(hwnd);
5649 internal override void CreateOffscreenDrawable (IntPtr handle,
5650 int width, int height,
5651 out object offscreen_drawable)
5654 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5656 XGetGeometry (DisplayHandle, handle,
5658 out x_out, out y_out,
5659 out width_out, out height_out,
5660 out border_width_out, out depth_out);
5662 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5664 offscreen_drawable = pixmap;
5668 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5670 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5673 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5675 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5678 internal override void BlitFromOffscreen (IntPtr dest_handle,
5680 object offscreen_drawable,
5681 Graphics offscreen_dc,
5684 XGCValues gc_values;
5687 gc_values = new XGCValues();
5689 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5691 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5692 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5694 XFreeGC (DisplayHandle, gc);
5697 #endregion // Public Static Methods
5700 internal override event EventHandler Idle;
5701 #endregion // Events
5703 #region Xcursor imports
5704 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5705 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5707 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5708 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5710 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5711 internal extern static void XcursorImagesDestroy (IntPtr images);
5713 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5714 internal extern static int XcursorGetDefaultSize (IntPtr display);
5716 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5717 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5719 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5720 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5723 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5724 internal extern static IntPtr XOpenDisplay(IntPtr display);
5725 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5726 internal extern static int XCloseDisplay(IntPtr display);
5727 [DllImport ("libX11", EntryPoint="XSynchronize")]
5728 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5730 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5731 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);
5732 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5733 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5734 [DllImport ("libX11", EntryPoint="XMapWindow")]
5735 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5736 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5737 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5738 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5739 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5740 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5741 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5742 [DllImport ("libX11", EntryPoint="XRootWindow")]
5743 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5744 [DllImport ("libX11", EntryPoint="XNextEvent")]
5745 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5746 [DllImport ("libX11")]
5747 internal extern static int XConnectionNumber (IntPtr diplay);
5748 [DllImport ("libX11")]
5749 internal extern static int XPending (IntPtr diplay);
5750 [DllImport ("libX11", EntryPoint="XSelectInput")]
5751 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5753 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5754 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5756 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5757 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5758 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5759 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5761 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5762 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5764 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5765 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5767 [DllImport ("libX11", EntryPoint="XFlush")]
5768 internal extern static int XFlush(IntPtr display);
5770 [DllImport ("libX11", EntryPoint="XSetWMName")]
5771 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5773 [DllImport ("libX11", EntryPoint="XStoreName")]
5774 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5776 [DllImport ("libX11", EntryPoint="XFetchName")]
5777 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5779 [DllImport ("libX11", EntryPoint="XSendEvent")]
5780 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5782 [DllImport ("libX11", EntryPoint="XQueryTree")]
5783 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);
5785 [DllImport ("libX11", EntryPoint="XFree")]
5786 internal extern static int XFree(IntPtr data);
5788 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5789 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5791 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5792 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5794 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5795 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5797 [DllImport ("libX11", EntryPoint="XInternAtom")]
5798 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5800 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5801 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5803 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5804 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5806 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5807 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);
5809 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5810 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5812 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5813 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);
5815 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5816 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);
5818 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5819 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);
5821 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5822 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);
5824 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5825 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);
5827 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5828 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);
5830 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5831 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);
5833 [DllImport ("libX11", EntryPoint="XClearWindow")]
5834 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5836 [DllImport ("libX11", EntryPoint="XClearArea")]
5837 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5840 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5841 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5843 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5844 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5846 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5847 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5849 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5850 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5852 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5853 internal extern static int XDefaultScreen(IntPtr display);
5855 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5856 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5858 [DllImport ("libX11", EntryPoint="XLookupColor")]
5859 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5861 [DllImport ("libX11", EntryPoint="XAllocColor")]
5862 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5864 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5865 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5867 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5868 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5870 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5871 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5873 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5874 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5876 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5877 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5879 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5880 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5882 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5883 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5885 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5886 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5888 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5889 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5891 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5892 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5895 [DllImport ("libX11", EntryPoint="XCreateGC")]
5896 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5898 [DllImport ("libX11", EntryPoint="XFreeGC")]
5899 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5901 [DllImport ("libX11", EntryPoint="XSetFunction")]
5902 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5904 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5905 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5907 [DllImport ("libX11", EntryPoint="XDrawLine")]
5908 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5910 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5911 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5913 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5914 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5916 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5917 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5919 [DllImport ("libX11", EntryPoint="XCopyArea")]
5920 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);
5922 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5923 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);
5925 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5926 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5928 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5929 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5931 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5932 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5934 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5935 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5937 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5938 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5940 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5941 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5943 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5944 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);
5946 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5947 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5949 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5950 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5952 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5953 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5955 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5956 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5958 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5959 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5961 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5962 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5964 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5965 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5967 [DllImport ("libX11", EntryPoint="XGrabServer")]
5968 internal extern static void XGrabServer(IntPtr display);
5970 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5971 internal extern static void XUngrabServer(IntPtr display);
5973 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5974 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5976 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5977 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5979 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5980 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5982 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5983 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5985 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5986 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5988 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5989 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5991 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5992 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5994 [DllImport ("libX11", EntryPoint="XInitThreads")]
5995 internal extern static int XInitThreads();
5997 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5998 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6000 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6001 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6003 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6004 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6006 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6007 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6009 [DllImport ("libX11", EntryPoint="XSetForeground")]
6010 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6012 [DllImport ("libX11", EntryPoint="XSetBackground")]
6013 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6015 [DllImport ("libX11", EntryPoint="XBell")]
6016 internal extern static int XBell(IntPtr display, int percent);
6018 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6019 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6021 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6022 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6024 [DllImport ("libX11")]
6025 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6027 [DllImport ("libX11")]
6028 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);