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)
805 return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
808 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
811 * If this is a form with no window manager, X is handling all the border and caption painting
812 * so remove that from the area (since the area we set of the window here is the part of the window
813 * we're painting in only)
815 Form form = cp.control as Form;
816 if (form != null && form.window_manager == null) {
817 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
820 xrect.Width -= borders.left + borders.right;
821 xrect.Height -= borders.top + borders.bottom;
825 if (size.Height == 0)
832 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
835 * If this is a form with no window manager, X is handling all the border and caption painting
836 * so remove that from the area (since the area we set of the window here is the part of the window
837 * we're painting in only)
839 Size rect = new Size (xWidth, xHeight);
840 Form form = cp.control as Form;
841 if (form != null && form.window_manager == null) {
842 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
845 xrect.Width += borders.left + borders.right;
846 xrect.Height += borders.top + borders.bottom;
853 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
859 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
860 frame = FrameExtents (hwnd.whole_window);
865 return new Point (x, y);
868 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) {
871 tool_caption_height = 19;
872 border_static = false;
874 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
875 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
876 border_style = FormBorderStyle.Fixed3D;
877 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
878 border_style = FormBorderStyle.Fixed3D;
879 border_static = true;
880 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
881 border_style = FormBorderStyle.None;
883 border_style = FormBorderStyle.FixedSingle;
885 title_style = TitleStyle.None;
887 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
889 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
890 title_style = TitleStyle.Tool;
892 title_style = TitleStyle.Normal;
896 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
899 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
900 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
901 border_style = (FormBorderStyle) 0xFFFF;
903 border_style = FormBorderStyle.None;
908 title_style = TitleStyle.None;
909 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
910 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
911 title_style = TitleStyle.Tool;
913 title_style = TitleStyle.Normal;
917 border_style = FormBorderStyle.None;
919 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
920 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
921 border_style = FormBorderStyle.SizableToolWindow;
923 border_style = FormBorderStyle.Sizable;
926 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
927 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
928 border_style = FormBorderStyle.Fixed3D;
929 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
930 border_style = FormBorderStyle.Fixed3D;
931 border_static = true;
932 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
933 border_style = FormBorderStyle.FixedDialog;
934 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
935 border_style = FormBorderStyle.FixedToolWindow;
936 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
937 border_style = FormBorderStyle.FixedSingle;
940 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
941 border_style = FormBorderStyle.FixedSingle;
948 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
949 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);
952 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
953 MotifWmHints mwmHints;
954 MotifFunctions functions;
955 MotifDecorations decorations;
958 Rectangle client_rect;
961 bool hide_from_taskbar;
962 IntPtr transient_for_parent;
964 // Windows we manage ourselves don't need WM window styles.
965 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
970 mwmHints = new MotifWmHints();
973 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
974 transient_for_parent = IntPtr.Zero;
976 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
977 mwmHints.functions = (IntPtr)0;
978 mwmHints.decorations = (IntPtr)0;
980 form = cp.control as Form;
982 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
983 /* tool windows get no window manager
987 /* just because the window doesn't get any decorations doesn't
988 mean we should disable the functions. for instance, without
989 MotifFunctions.Maximize, changing the windowstate to Maximized
990 is ignored by metacity. */
991 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
992 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
993 // No functions nor decorations whatsoever.
995 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
996 functions |= MotifFunctions.Move;
997 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1000 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1001 functions |= MotifFunctions.Move | MotifFunctions.Resize;
1002 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1005 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1006 functions |= MotifFunctions.Minimize;
1007 decorations |= MotifDecorations.Minimize;
1010 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1011 functions |= MotifFunctions.Maximize;
1012 decorations |= MotifDecorations.Maximize;
1015 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1016 functions |= MotifFunctions.Resize;
1017 decorations |= MotifDecorations.ResizeH;
1020 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1021 decorations |= MotifDecorations.Border;
1024 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1025 decorations |= MotifDecorations.Border;
1028 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1029 decorations |= MotifDecorations.Border;
1032 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1033 functions |= MotifFunctions.Close;
1036 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1037 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1038 if (cp.Caption == "") {
1039 functions &= ~MotifFunctions.Move;
1040 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1045 if ((functions & MotifFunctions.Resize) == 0) {
1046 hwnd.fixed_size = true;
1047 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1048 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1050 hwnd.fixed_size = false;
1053 mwmHints.functions = (IntPtr)functions;
1054 mwmHints.decorations = (IntPtr)decorations;
1057 Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1060 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1061 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1062 // and get those windows in front of their parents
1063 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1064 } else if (form != null && form.Modal) {
1065 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1067 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1070 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1071 hide_from_taskbar = true;
1072 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1073 hide_from_taskbar = true;
1075 hide_from_taskbar = false;
1078 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1079 if (form != null && !hwnd.reparented) {
1080 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1081 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1082 if (owner_hwnd != null)
1083 transient_for_parent = owner_hwnd.whole_window;
1087 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1088 transient_for_parent = hwnd.parent.whole_window;
1091 FormWindowState current_state = GetWindowState (hwnd.Handle);
1092 if (current_state == (FormWindowState)(-1))
1093 current_state = FormWindowState.Normal;
1095 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1100 atoms [0] = window_type.ToInt32 ();
1101 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1103 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1105 if (transient_for_parent != IntPtr.Zero) {
1106 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1109 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1111 if (hide_from_taskbar) {
1112 /* this line keeps the window from showing up in gnome's taskbar */
1113 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1115 /* we need to add these atoms in the
1116 * event we're maximized, since we're
1117 * replacing the existing
1118 * _NET_WM_STATE here. If we don't
1119 * add them, future calls to
1120 * GetWindowState will return Normal
1121 * for a window which is maximized. */
1122 if (current_state == FormWindowState.Maximized) {
1123 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1124 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1127 if (form != null && form.Modal) {
1128 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1131 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1134 IntPtr[] atom_ptrs = new IntPtr[2];
1135 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1136 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1137 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1140 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1144 private void SetIcon(Hwnd hwnd, Icon icon)
1149 // This really needs to do whatever it
1150 // takes to remove the window manager
1151 // menu, not just delete the ICON
1152 // property. This will cause metacity
1153 // to use the "no icon set" icon, and
1154 // we'll still have an icon.
1155 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1163 bitmap = icon.ToBitmap();
1165 size = bitmap.Width * bitmap.Height + 2;
1166 data = new IntPtr[size];
1168 data[index++] = (IntPtr)bitmap.Width;
1169 data[index++] = (IntPtr)bitmap.Height;
1171 for (int y = 0; y < bitmap.Height; y++) {
1172 for (int x = 0; x < bitmap.Width; x++) {
1173 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1177 XChangeProperty (DisplayHandle, hwnd.whole_window,
1178 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1179 PropertyMode.Replace, data, size);
1183 private void WakeupMain () {
1184 wake.Send (new byte [] { 0xFF });
1187 private XEventQueue ThreadQueue(Thread thread) {
1190 queue = (XEventQueue)MessageQueues[thread];
1191 if (queue == null) {
1192 queue = new XEventQueue(thread);
1193 MessageQueues[thread] = queue;
1199 private void TranslatePropertyToClipboard(IntPtr property) {
1204 IntPtr prop = IntPtr.Zero;
1206 Clipboard.Item = null;
1208 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);
1210 if ((long)nitems > 0) {
1211 if (property == (IntPtr)Atom.XA_STRING) {
1212 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1213 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1214 // FIXME - convert bitmap to image
1215 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1216 // FIXME - convert pixmap to image
1217 } else if (property == OEMTEXT) {
1218 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1219 } else if (property == UNICODETEXT) {
1220 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1227 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1229 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1233 // Keep the invalid area as small as needed
1234 if ((x + width) > hwnd.width) {
1235 width = hwnd.width - x;
1238 if ((y + height) > hwnd.height) {
1239 height = hwnd.height - y;
1243 hwnd.AddInvalidArea(x, y, width, height);
1244 if (!hwnd.expose_pending) {
1245 if (!hwnd.nc_expose_pending) {
1246 hwnd.Queue.Paint.Enqueue(hwnd);
1248 hwnd.expose_pending = true;
1251 hwnd.AddNcInvalidArea (x, y, width, height);
1253 if (!hwnd.nc_expose_pending) {
1254 if (!hwnd.expose_pending) {
1255 hwnd.Queue.Paint.Enqueue(hwnd);
1257 hwnd.nc_expose_pending = true;
1262 private static Hwnd.Borders FrameExtents (IntPtr window)
1268 IntPtr prop = IntPtr.Zero;
1269 Hwnd.Borders rect = new Hwnd.Borders ();
1271 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);
1272 if (prop != IntPtr.Zero) {
1273 if (nitems.ToInt32 () == 4) {
1274 rect.left = Marshal.ReadInt32 (prop, 0);
1275 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1276 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1277 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1285 private void AddConfigureNotify (XEvent xevent) {
1288 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1291 if (hwnd == null || hwnd.zombie) {
1294 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1295 if (hwnd.parent == null) {
1296 // The location given by the event is not reliable between different wm's,
1297 // so use an alternative way of getting it.
1298 Point location = GetTopLevelWindowLocation (hwnd);
1299 hwnd.x = location.X;
1300 hwnd.y = location.Y;
1303 // XXX this sucks. this isn't thread safe
1304 Control ctrl = Control.FromHandle (hwnd.Handle);
1305 Size TranslatedSize;
1307 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1309 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1311 hwnd.width = TranslatedSize.Width;
1312 hwnd.height = TranslatedSize.Height;
1313 hwnd.ClientRect = Rectangle.Empty;
1316 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));
1318 lock (hwnd.configure_lock) {
1319 if (!hwnd.configure_pending) {
1320 hwnd.Queue.EnqueueLocked (xevent);
1321 hwnd.configure_pending = true;
1325 // We drop configure events for Client windows
1328 private void ShowCaret() {
1329 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1335 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1339 private void HideCaret() {
1340 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1346 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1350 private int NextTimeout (ArrayList timers, DateTime now) {
1351 int timeout = Int32.MaxValue;
1353 foreach (Timer timer in timers) {
1354 int next = (int) (timer.Expires - now).TotalMilliseconds;
1356 return 0; // Have a timer that has already expired
1359 if (next < timeout) {
1363 if (timeout < Timer.Minimum) {
1364 timeout = Timer.Minimum;
1372 private void CheckTimers (ArrayList timers, DateTime now) {
1375 count = timers.Count;
1380 for (int i = 0; i < timers.Count; i++) {
1383 timer = (Timer) timers [i];
1385 if (timer.Enabled && timer.Expires <= now) {
1392 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1393 MSG msg = new MSG ();
1396 queue = ThreadQueue(Thread.CurrentThread);
1398 queue.DispatchIdle = false;
1402 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1403 if ((Msg)msg.message == Msg.WM_QUIT) {
1404 PostQuitMessage (0);
1408 if (msg.hwnd == hwnd.Handle) {
1409 if ((Msg)msg.message == message)
1411 else if ((Msg)msg.message == Msg.WM_DESTROY)
1415 TranslateMessage (ref msg);
1416 DispatchMessage (ref msg);
1421 queue.DispatchIdle = true;
1425 private void MapWindow(Hwnd hwnd, WindowType windows) {
1427 if (Control.FromHandle(hwnd.Handle) is Form) {
1428 Form f = Control.FromHandle(hwnd.Handle) as Form;
1429 if (f.WindowState == FormWindowState.Normal)
1430 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1433 // it's possible that our Hwnd is no
1434 // longer valid after making that
1435 // SendMessage call, so check here.
1439 bool need_to_wait = false;
1441 if ((windows & WindowType.Whole) != 0) {
1442 XMapWindow(DisplayHandle, hwnd.whole_window);
1444 if ((windows & WindowType.Client) != 0) {
1445 XMapWindow(DisplayHandle, hwnd.client_window);
1447 need_to_wait = true;
1452 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1453 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1457 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1459 if (Control.FromHandle(hwnd.Handle) is Form) {
1460 Form f = Control.FromHandle(hwnd.Handle) as Form;
1461 if (f.WindowState == FormWindowState.Normal)
1462 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1465 // it's possible that our Hwnd is no
1466 // longer valid after making that
1467 // SendMessage call, so check here.
1471 bool need_to_wait = false;
1473 if ((windows & WindowType.Client) != 0) {
1474 XUnmapWindow(DisplayHandle, hwnd.client_window);
1476 need_to_wait = true;
1478 if ((windows & WindowType.Whole) != 0) {
1479 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1482 hwnd.mapped = false;
1484 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1485 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1489 private void UpdateMessageQueue (XEventQueue queue) {
1494 now = DateTime.UtcNow;
1497 pending = XPending (DisplayHandle);
1501 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1502 Idle (this, EventArgs.Empty);
1506 pending = XPending (DisplayHandle);
1513 if (queue != null) {
1514 if (queue.Paint.Count > 0)
1517 timeout = NextTimeout (queue.timer_list, now);
1522 int length = pollfds.Length - 1;
1523 lock (wake_waiting_lock) {
1524 if (wake_waiting == false) {
1526 wake_waiting = true;
1530 Syscall.poll (pollfds, (uint)length, timeout);
1531 // Clean out buffer, so we're not busy-looping on the same data
1532 if (length == pollfds.Length) {
1533 if (pollfds[1].revents != 0)
1534 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1535 lock (wake_waiting_lock) {
1536 wake_waiting = false;
1541 pending = XPending (DisplayHandle);
1547 CheckTimers (queue.timer_list, now);
1550 XEvent xevent = new XEvent ();
1553 if (XPending (DisplayHandle) == 0)
1556 XNextEvent (DisplayHandle, ref xevent);
1558 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1559 if (XFilterEvent(ref xevent, FosterParent)) {
1565 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1570 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1572 switch (xevent.type) {
1573 case XEventName.Expose:
1574 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1577 case XEventName.SelectionClear: {
1578 // Should we do something?
1582 case XEventName.SelectionRequest: {
1583 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1587 sel_event = new XEvent();
1588 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1589 sel_event.SelectionEvent.send_event = true;
1590 sel_event.SelectionEvent.display = DisplayHandle;
1591 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1592 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1593 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1594 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1595 sel_event.SelectionEvent.property = IntPtr.Zero;
1597 // Seems that some apps support asking for supported types
1598 if (xevent.SelectionEvent.target == TARGETS) {
1605 if (Clipboard.Item is String) {
1606 atoms[atom_count++] = (int)Atom.XA_STRING;
1607 atoms[atom_count++] = (int)OEMTEXT;
1608 atoms[atom_count++] = (int)UNICODETEXT;
1609 } else if (Clipboard.Item is Image) {
1610 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1611 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1613 // FIXME - handle other types
1616 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1617 } else if (Clipboard.Item is string) {
1623 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1626 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1627 buffer = Marshal.AllocHGlobal(bytes.Length);
1628 buflen = bytes.Length;
1630 for (int i = 0; i < buflen; i++) {
1631 Marshal.WriteByte(buffer, i, bytes[i]);
1633 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1634 // FIXME - this should encode into ISO2022
1635 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1636 while (Marshal.ReadByte(buffer, buflen) != 0) {
1639 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1640 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1641 while (Marshal.ReadByte(buffer, buflen) != 0) {
1645 buffer = IntPtr.Zero;
1648 if (buffer != IntPtr.Zero) {
1649 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1650 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1651 Marshal.FreeHGlobal(buffer);
1653 } else if (Clipboard.Item is Image) {
1654 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1655 // FIXME - convert image and store as property
1656 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1657 // FIXME - convert image and store as property
1661 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1665 case XEventName.SelectionNotify: {
1666 if (Clipboard.Enumerating) {
1667 Clipboard.Enumerating = false;
1668 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1669 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1670 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1671 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1672 #if DriverDebugExtra
1673 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1677 } else if (Clipboard.Retrieving) {
1678 Clipboard.Retrieving = false;
1679 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1680 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1682 Clipboard.Item = null;
1685 Dnd.HandleSelectionNotifyEvent (ref xevent);
1690 case XEventName.KeyRelease:
1691 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1692 XEvent nextevent = new XEvent ();
1694 XPeekEvent (DisplayHandle, ref nextevent);
1696 if (nextevent.type == XEventName.KeyPress &&
1697 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1698 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1702 goto case XEventName.KeyPress;
1704 case XEventName.MotionNotify: {
1707 /* we can't do motion compression across threads, so just punt if we don't match up */
1708 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1709 peek = hwnd.Queue.Peek();
1710 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1714 goto case XEventName.KeyPress;
1717 case XEventName.KeyPress:
1718 case XEventName.ButtonPress:
1719 case XEventName.ButtonRelease:
1720 case XEventName.EnterNotify:
1721 case XEventName.LeaveNotify:
1722 case XEventName.CreateNotify:
1723 case XEventName.DestroyNotify:
1724 case XEventName.FocusIn:
1725 case XEventName.FocusOut:
1726 case XEventName.ClientMessage:
1727 case XEventName.ReparentNotify:
1728 case XEventName.MapNotify:
1729 case XEventName.UnmapNotify:
1730 hwnd.Queue.EnqueueLocked (xevent);
1733 case XEventName.ConfigureNotify:
1734 AddConfigureNotify(xevent);
1737 case XEventName.PropertyNotify:
1739 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1741 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1746 IntPtr prop = IntPtr.Zero;
1749 prev_active = ActiveWindow;
1750 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);
1751 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1752 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1755 if (prev_active != ActiveWindow) {
1756 if (prev_active != IntPtr.Zero) {
1757 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1759 if (ActiveWindow != IntPtr.Zero) {
1760 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1763 if (ModalWindows.Count == 0) {
1766 // Modality handling, if we are modal and the new active window is one
1767 // of ours but not the modal one, switch back to the modal window
1769 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1770 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1771 Activate((IntPtr)ModalWindows.Peek());
1778 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1779 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1780 hwnd.cached_window_state = (FormWindowState)(-1);
1788 private IntPtr GetMousewParam(int Delta) {
1791 if ((MouseState & MouseButtons.Left) != 0) {
1792 result |= (int)MsgButtons.MK_LBUTTON;
1795 if ((MouseState & MouseButtons.Middle) != 0) {
1796 result |= (int)MsgButtons.MK_MBUTTON;
1799 if ((MouseState & MouseButtons.Right) != 0) {
1800 result |= (int)MsgButtons.MK_RBUTTON;
1803 Keys mods = ModifierKeys;
1804 if ((mods & Keys.Control) != 0) {
1805 result |= (int)MsgButtons.MK_CONTROL;
1808 if ((mods & Keys.Shift) != 0) {
1809 result |= (int)MsgButtons.MK_SHIFT;
1812 result |= Delta << 16;
1814 return (IntPtr)result;
1816 private IntPtr XGetParent(IntPtr handle) {
1823 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1826 if (Children!=IntPtr.Zero) {
1834 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1836 // we need to workaround a problem with the
1837 // ordering of destruction of Drawables and
1838 // Pictures that exists between cairo and
1839 // RENDER on the server.
1840 if (error_event.request_code == (XRequest)render_major_opcode
1841 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1842 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1846 if (ErrorExceptions) {
1847 XUngrabPointer (display, IntPtr.Zero);
1848 throw new XException (error_event.display, error_event.resourceid,
1849 error_event.serial, error_event.error_code,
1850 error_event.request_code, error_event.minor_code);
1852 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1853 XException.GetMessage (error_event.display, error_event.resourceid,
1854 error_event.serial, error_event.error_code,
1855 error_event.request_code, error_event.minor_code),
1856 Environment.StackTrace);
1861 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1864 Control[] controls = c.Controls.GetAllControls ();
1866 if (c.IsHandleCreated && !c.IsDisposed) {
1867 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1869 #if DriverDebug || DriverDebugDestroy
1870 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1871 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1875 CleanupCachedWindows (hwnd);
1878 for (int i = 0; i < controls.Length; i ++) {
1879 AccumulateDestroyedHandles (controls[i], list);
1885 void CleanupCachedWindows (Hwnd hwnd)
1887 if (ActiveWindow == hwnd.Handle) {
1888 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1889 ActiveWindow = IntPtr.Zero;
1892 if (FocusWindow == hwnd.Handle) {
1893 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1894 FocusWindow = IntPtr.Zero;
1897 if (Grab.Hwnd == hwnd.Handle) {
1898 Grab.Hwnd = IntPtr.Zero;
1899 Grab.Confined = false;
1902 DestroyCaret (hwnd.Handle);
1905 private void PerformNCCalc(Hwnd hwnd) {
1906 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1910 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1912 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1913 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1915 ncp.rgrc1.left = rect.Left;
1916 ncp.rgrc1.top = rect.Top;
1917 ncp.rgrc1.right = rect.Right;
1918 ncp.rgrc1.bottom = rect.Bottom;
1920 Marshal.StructureToPtr(ncp, ptr, true);
1921 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1922 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1923 Marshal.FreeHGlobal(ptr);
1926 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1927 hwnd.ClientRect = rect;
1929 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1932 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1935 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1937 #endregion // Private Methods
1940 private void MouseHover(object sender, EventArgs e) {
1944 HoverState.Timer.Enabled = false;
1946 if (HoverState.Window != IntPtr.Zero) {
1947 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1949 xevent = new XEvent ();
1951 xevent.type = XEventName.ClientMessage;
1952 xevent.ClientMessageEvent.display = DisplayHandle;
1953 xevent.ClientMessageEvent.window = HoverState.Window;
1954 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1955 xevent.ClientMessageEvent.format = 32;
1956 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1958 hwnd.Queue.EnqueueLocked (xevent);
1965 private void CaretCallback(object sender, EventArgs e) {
1969 Caret.On = !Caret.On;
1971 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1973 #endregion // Callbacks
1975 #region Public Properties
1977 internal override int CaptionHeight {
1983 internal override Size CursorSize {
1988 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1989 return new Size(x, y);
1991 return new Size(16, 16);
1996 internal override bool DragFullWindows {
2002 internal override Size DragSize {
2004 return new Size(4, 4);
2008 internal override Size FrameBorderSize {
2010 return new Size (4, 4);
2014 internal override Size IconSize {
2020 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2024 current = (long)list;
2027 size = new XIconSize();
2029 for (int i = 0; i < count; i++) {
2030 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2031 current += Marshal.SizeOf(size);
2033 // Look for our preferred size
2034 if (size.min_width == 32) {
2036 return new Size(32, 32);
2039 if (size.max_width == 32) {
2041 return new Size(32, 32);
2044 if (size.min_width < 32 && size.max_width > 32) {
2047 // check if we can fit one
2049 while (x < size.max_width) {
2050 x += size.width_inc;
2053 return new Size(32, 32);
2058 if (largest < size.max_width) {
2059 largest = size.max_width;
2063 // We didn't find a match or we wouldn't be here
2064 return new Size(largest, largest);
2067 return new Size(32, 32);
2072 internal override int KeyboardSpeed {
2075 // A lot harder: need to do:
2076 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2077 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2078 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2080 // And from that we can tell the repetition rate
2082 // Notice, the values must map to:
2083 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2089 internal override int KeyboardDelay {
2092 // Return values must range from 0 to 4, 0 meaning 250ms,
2093 // and 4 meaning 1000 ms.
2095 return 1; // ie, 500 ms
2099 internal override Size MaxWindowTrackSize {
2101 return new Size (WorkingArea.Width, WorkingArea.Height);
2105 internal override bool MenuAccessKeysUnderlined {
2111 internal override Size MinimizedWindowSize {
2113 return new Size(1, 1);
2117 internal override Size MinimizedWindowSpacingSize {
2119 return new Size(1, 1);
2123 internal override Size MinimumWindowSize {
2125 return new Size(0, 0);
2129 internal override Size MinWindowTrackSize {
2131 return new Size(1, 1);
2135 internal override Keys ModifierKeys {
2137 return Keyboard.ModifierKeys;
2141 internal override Size SmallIconSize {
2147 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2151 current = (long)list;
2154 size = new XIconSize();
2156 for (int i = 0; i < count; i++) {
2157 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2158 current += Marshal.SizeOf(size);
2160 // Look for our preferred size
2161 if (size.min_width == 16) {
2163 return new Size(16, 16);
2166 if (size.max_width == 16) {
2168 return new Size(16, 16);
2171 if (size.min_width < 16 && size.max_width > 16) {
2174 // check if we can fit one
2176 while (x < size.max_width) {
2177 x += size.width_inc;
2180 return new Size(16, 16);
2185 if (smallest == 0 || smallest > size.min_width) {
2186 smallest = size.min_width;
2190 // We didn't find a match or we wouldn't be here
2191 return new Size(smallest, smallest);
2194 return new Size(16, 16);
2199 internal override int MouseButtonCount {
2205 internal override bool MouseButtonsSwapped {
2207 return false; // FIXME - how to detect?
2211 internal override Point MousePosition {
2213 return mouse_position;
2217 internal override Size MouseHoverSize {
2219 return new Size (1, 1);
2223 internal override int MouseHoverTime {
2225 return HoverState.Interval;
2231 internal override bool MouseWheelPresent {
2233 return true; // FIXME - how to detect?
2237 internal override Rectangle VirtualScreen {
2243 IntPtr prop = IntPtr.Zero;
2247 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);
2248 if ((long)nitems < 2)
2251 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2252 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2256 return new Rectangle(0, 0, width, height);
2259 XWindowAttributes attributes=new XWindowAttributes();
2262 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2265 return new Rectangle(0, 0, attributes.width, attributes.height);
2269 internal override Rectangle WorkingArea {
2275 IntPtr prop = IntPtr.Zero;
2278 int current_desktop;
2282 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);
2283 if ((long)nitems < 1) {
2287 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2290 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);
2291 if ((long)nitems < 4 * current_desktop) {
2295 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2296 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2297 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2298 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2301 return new Rectangle(x, y, width, height);
2304 XWindowAttributes attributes=new XWindowAttributes();
2307 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2310 return new Rectangle(0, 0, attributes.width, attributes.height);
2314 internal override bool ThemesEnabled {
2316 return XplatUIX11.themes_enabled;
2321 #endregion // Public properties
2323 #region Public Static Methods
2324 internal override void RaiseIdle (EventArgs e)
2330 internal override IntPtr InitializeDriver() {
2332 if (DisplayHandle==IntPtr.Zero) {
2333 SetDisplay(XOpenDisplay(IntPtr.Zero));
2339 internal override void ShutdownDriver(IntPtr token) {
2341 if (DisplayHandle!=IntPtr.Zero) {
2342 XCloseDisplay(DisplayHandle);
2343 DisplayHandle=IntPtr.Zero;
2348 internal override void EnableThemes() {
2349 themes_enabled = true;
2353 internal override void Activate(IntPtr handle) {
2356 hwnd = Hwnd.ObjectFromHandle(handle);
2360 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2361 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2364 // XRaiseWindow(DisplayHandle, handle);
2370 internal override void AudibleAlert() {
2371 XBell(DisplayHandle, 0);
2376 internal override void CaretVisible(IntPtr handle, bool visible) {
2377 if (Caret.Hwnd == handle) {
2379 if (!Caret.Visible) {
2380 Caret.Visible = true;
2382 Caret.Timer.Start();
2385 Caret.Visible = false;
2392 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2393 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2397 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2403 hwnd = Hwnd.ObjectFromHandle(handle);
2406 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2413 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2414 DataFormats.Format f;
2417 f = DataFormats.Format.List;
2419 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2423 Clipboard.Formats = new ArrayList();
2426 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2428 Clipboard.Enumerating = true;
2429 while (Clipboard.Enumerating) {
2430 UpdateMessageQueue(null);
2435 result = new int[Clipboard.Formats.Count];
2437 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2438 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2441 Clipboard.Formats = null;
2445 internal override void ClipboardClose(IntPtr handle) {
2446 if (handle != ClipMagic) {
2447 throw new ArgumentException("handle is not a valid clipboard handle");
2452 internal override int ClipboardGetID(IntPtr handle, string format) {
2453 if (handle != ClipMagic) {
2454 throw new ArgumentException("handle is not a valid clipboard handle");
2457 if (format == "Text" ) return (int)Atom.XA_STRING;
2458 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2459 //else if (format == "MetaFilePict" ) return 3;
2460 //else if (format == "SymbolicLink" ) return 4;
2461 //else if (format == "DataInterchangeFormat" ) return 5;
2462 //else if (format == "Tiff" ) return 6;
2463 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2464 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2465 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2466 //else if (format == "PenData" ) return 10;
2467 //else if (format == "RiffAudio" ) return 11;
2468 //else if (format == "WaveAudio" ) return 12;
2469 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2470 //else if (format == "EnhancedMetafile" ) return 14;
2471 //else if (format == "FileDrop" ) return 15;
2472 //else if (format == "Locale" ) return 16;
2474 return XInternAtom(DisplayHandle, format, false).ToInt32();
2477 internal override IntPtr ClipboardOpen(bool primary_selection) {
2478 if (!primary_selection)
2479 ClipMagic = CLIPBOARD;
2481 ClipMagic = PRIMARY;
2485 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2486 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2488 Clipboard.Retrieving = true;
2489 while (Clipboard.Retrieving) {
2490 UpdateMessageQueue(null);
2493 return Clipboard.Item;
2496 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2497 Clipboard.Item = obj;
2498 Clipboard.Type = type;
2499 Clipboard.Converter = converter;
2502 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2504 // Clearing the selection
2505 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2509 internal override void CreateCaret (IntPtr handle, int width, int height)
2511 XGCValues gc_values;
2514 hwnd = Hwnd.ObjectFromHandle(handle);
2516 if (Caret.Hwnd != IntPtr.Zero) {
2517 DestroyCaret(Caret.Hwnd);
2520 Caret.Hwnd = handle;
2521 Caret.Window = hwnd.client_window;
2522 Caret.Width = width;
2523 Caret.Height = height;
2524 Caret.Visible = false;
2527 gc_values = new XGCValues();
2528 gc_values.line_width = width;
2530 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2531 if (Caret.gc == IntPtr.Zero) {
2532 Caret.Hwnd = IntPtr.Zero;
2536 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2539 internal override IntPtr CreateWindow (CreateParams cp)
2541 XSetWindowAttributes Attributes;
2543 Hwnd parent_hwnd = null;
2548 IntPtr ParentHandle;
2550 IntPtr ClientWindow;
2551 SetWindowValuemask ValueMask;
2556 Attributes = new XSetWindowAttributes();
2562 if (Width<1) Width=1;
2563 if (Height<1) Height=1;
2565 if (cp.Parent != IntPtr.Zero) {
2566 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2567 ParentHandle = parent_hwnd.client_window;
2569 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2570 // We need to use our foster parent window until this poor child gets it's parent assigned
2571 ParentHandle=FosterParent;
2573 ParentHandle=RootWindow;
2577 // Set the default location location for forms.
2579 if (cp.control is Form) {
2580 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2584 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2586 Attributes.bit_gravity = Gravity.NorthWestGravity;
2587 Attributes.win_gravity = Gravity.NorthWestGravity;
2589 // Save what's under the toolwindow
2590 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2591 Attributes.save_under = true;
2592 ValueMask |= SetWindowValuemask.SaveUnder;
2596 // If we're a popup without caption we override the WM
2597 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2598 Attributes.override_redirect = true;
2599 ValueMask |= SetWindowValuemask.OverrideRedirect;
2605 hwnd.height = Height;
2606 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2607 hwnd.initial_style = cp.WindowStyle;
2608 hwnd.initial_ex_style = cp.WindowExStyle;
2610 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2611 hwnd.enabled = false;
2614 ClientWindow = IntPtr.Zero;
2616 Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2617 Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2620 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);
2621 if (WholeWindow != IntPtr.Zero) {
2622 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2624 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2625 ValueMask = SetWindowValuemask.ColorMap;
2626 Attributes.colormap = CustomColormap;
2628 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);
2632 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2633 throw new Exception("Could not create X11 windows");
2636 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2637 hwnd.WholeWindow = WholeWindow;
2638 hwnd.ClientWindow = ClientWindow;
2640 #if DriverDebug || DriverDebugCreate
2641 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);
2644 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2645 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2648 hints = new XSizeHints();
2651 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2652 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2657 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2658 if (hwnd.whole_window != hwnd.client_window)
2659 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2662 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2664 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2665 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2667 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2670 SetWMStyles(hwnd, cp);
2672 // set the group leader
2673 XWMHints wm_hints = new XWMHints ();
2675 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2676 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2677 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2679 if (ParentHandle != RootWindow) {
2680 wm_hints.window_group = hwnd.whole_window;
2682 wm_hints.window_group = ParentHandle;
2686 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2689 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2690 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2691 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2692 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2695 // for now make all windows dnd enabled
2696 Dnd.SetAllowDrop (hwnd, true);
2698 // Set caption/window title
2699 Text(hwnd.Handle, cp.Caption);
2701 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2702 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2704 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2705 hwnd.visible = true;
2706 MapWindow(hwnd, WindowType.Both);
2707 if (!(Control.FromHandle(hwnd.Handle) is Form))
2708 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2714 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2715 CreateParams create_params = new CreateParams();
2717 create_params.Caption = "";
2718 create_params.X = X;
2719 create_params.Y = Y;
2720 create_params.Width = Width;
2721 create_params.Height = Height;
2723 create_params.ClassName=XplatUI.DefaultClassName;
2724 create_params.ClassStyle = 0;
2725 create_params.ExStyle=0;
2726 create_params.Parent=IntPtr.Zero;
2727 create_params.Param=0;
2729 return CreateWindow(create_params);
2732 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2734 Bitmap cursor_bitmap;
2742 IntPtr cursor_pixmap;
2749 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2753 // Win32 only allows creation cursors of a certain size
2754 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2755 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2756 cursor_mask = new Bitmap(mask, new Size(width, height));
2758 cursor_bitmap = bitmap;
2762 width = cursor_bitmap.Width;
2763 height = cursor_bitmap.Height;
2765 cursor_bits = new Byte[(width / 8) * height];
2766 mask_bits = new Byte[(width / 8) * height];
2768 for (int y = 0; y < height; y++) {
2769 for (int x = 0; x < width; x++) {
2770 c_pixel = cursor_bitmap.GetPixel(x, y);
2771 m_pixel = cursor_mask.GetPixel(x, y);
2773 and = c_pixel == cursor_pixel;
2774 xor = m_pixel == mask_pixel;
2778 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2779 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2780 } else if (and && !xor) {
2782 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2783 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2785 } else if (and && !xor) {
2787 } else if (and && xor) {
2790 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2791 // we want both to be 0 so nothing to be done
2792 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2793 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2799 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2800 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2804 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2805 fg.red = (ushort)65535;
2806 fg.green = (ushort)65535;
2807 fg.blue = (ushort)65535;
2809 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2811 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2813 XFreePixmap(DisplayHandle, cursor_pixmap);
2814 XFreePixmap(DisplayHandle, mask_pixmap);
2819 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2820 CursorFontShape shape;
2827 shape = StdCursorToFontShape (id);
2828 name = shape.ToString ().Replace ("XC_", string.Empty);
2829 size = XcursorGetDefaultSize (DisplayHandle);
2830 theme = XcursorGetTheme (DisplayHandle);
2831 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2833 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);
2836 if (images_ptr == IntPtr.Zero) {
2840 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2842 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2845 if (images.nimage > 0) {
2846 // We only care about the first image.
2847 XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2850 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);
2853 if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2854 int [] pixels = new int [image.width * image.height];
2855 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2856 bmp = new Bitmap (image.width, image.height);
2857 for (int w = 0; w < image.width; w++) {
2858 for (int h = 0; h < image.height; h++) {
2859 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2865 XcursorImagesDestroy (images_ptr);
2867 } catch (DllNotFoundException ex) {
2868 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2876 internal override IntPtr DefineStdCursor(StdCursor id) {
2877 CursorFontShape shape;
2880 shape = StdCursorToFontShape (id);
2883 cursor = XCreateFontCursor(DisplayHandle, shape);
2888 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2889 CursorFontShape shape;
2890 // FIXME - define missing shapes
2893 case StdCursor.AppStarting: {
2894 shape = CursorFontShape.XC_watch;
2898 case StdCursor.Arrow: {
2899 shape = CursorFontShape.XC_top_left_arrow;
2903 case StdCursor.Cross: {
2904 shape = CursorFontShape.XC_crosshair;
2908 case StdCursor.Default: {
2909 shape = CursorFontShape.XC_top_left_arrow;
2913 case StdCursor.Hand: {
2914 shape = CursorFontShape.XC_hand1;
2918 case StdCursor.Help: {
2919 shape = CursorFontShape.XC_question_arrow;
2923 case StdCursor.HSplit: {
2924 shape = CursorFontShape.XC_sb_v_double_arrow;
2928 case StdCursor.IBeam: {
2929 shape = CursorFontShape.XC_xterm;
2933 case StdCursor.No: {
2934 shape = CursorFontShape.XC_circle;
2938 case StdCursor.NoMove2D: {
2939 shape = CursorFontShape.XC_fleur;
2943 case StdCursor.NoMoveHoriz: {
2944 shape = CursorFontShape.XC_fleur;
2948 case StdCursor.NoMoveVert: {
2949 shape = CursorFontShape.XC_fleur;
2953 case StdCursor.PanEast: {
2954 shape = CursorFontShape.XC_fleur;
2958 case StdCursor.PanNE: {
2959 shape = CursorFontShape.XC_fleur;
2963 case StdCursor.PanNorth: {
2964 shape = CursorFontShape.XC_fleur;
2968 case StdCursor.PanNW: {
2969 shape = CursorFontShape.XC_fleur;
2973 case StdCursor.PanSE: {
2974 shape = CursorFontShape.XC_fleur;
2978 case StdCursor.PanSouth: {
2979 shape = CursorFontShape.XC_fleur;
2983 case StdCursor.PanSW: {
2984 shape = CursorFontShape.XC_fleur;
2988 case StdCursor.PanWest: {
2989 shape = CursorFontShape.XC_sizing;
2993 case StdCursor.SizeAll: {
2994 shape = CursorFontShape.XC_fleur;
2998 case StdCursor.SizeNESW: {
2999 shape = CursorFontShape.XC_top_right_corner;
3003 case StdCursor.SizeNS: {
3004 shape = CursorFontShape.XC_sb_v_double_arrow;
3008 case StdCursor.SizeNWSE: {
3009 shape = CursorFontShape.XC_top_left_corner;
3013 case StdCursor.SizeWE: {
3014 shape = CursorFontShape.XC_sb_h_double_arrow;
3018 case StdCursor.UpArrow: {
3019 shape = CursorFontShape.XC_center_ptr;
3023 case StdCursor.VSplit: {
3024 shape = CursorFontShape.XC_sb_h_double_arrow;
3028 case StdCursor.WaitCursor: {
3029 shape = CursorFontShape.XC_watch;
3034 shape = (CursorFontShape) 0;
3042 internal override IntPtr DefWndProc(ref Message msg) {
3043 switch ((Msg)msg.Msg) {
3044 case Msg.WM_PAINT: {
3047 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3049 hwnd.expose_pending = false;
3055 case Msg.WM_NCPAINT: {
3058 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3060 hwnd.nc_expose_pending = false;
3066 case Msg.WM_NCCALCSIZE: {
3069 if (msg.WParam == (IntPtr)1) {
3070 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3072 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3073 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3075 // Add all the stuff X is supposed to draw.
3076 Control ctrl = Control.FromHandle (hwnd.Handle);
3079 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3081 ncp.rgrc1.top += rect.top;
3082 ncp.rgrc1.bottom -= rect.bottom;
3083 ncp.rgrc1.left += rect.left;
3084 ncp.rgrc1.right -= rect.right;
3086 Marshal.StructureToPtr (ncp, msg.LParam, true);
3093 case Msg.WM_CONTEXTMENU: {
3096 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3098 if ((hwnd != null) && (hwnd.parent != null)) {
3099 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3104 case Msg.WM_MOUSEWHEEL: {
3107 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3109 if ((hwnd != null) && (hwnd.parent != null)) {
3110 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3111 if (msg.Result == IntPtr.Zero) {
3118 case Msg.WM_SETCURSOR: {
3121 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3123 break; // not sure how this happens, but it does
3125 // Pass to parent window first
3126 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3128 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3131 if (msg.Result == IntPtr.Zero) {
3134 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3135 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3136 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3137 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3138 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3139 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3142 handle = Cursors.Default.handle;
3145 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3146 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3147 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3148 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3149 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3150 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3153 case HitTest.HTGROWBOX:
3154 case HitTest.HTSIZE:
3155 case HitTest.HTZOOM:
3156 case HitTest.HTVSCROLL:
3157 case HitTest.HTSYSMENU:
3158 case HitTest.HTREDUCE:
3159 case HitTest.HTNOWHERE:
3160 case HitTest.HTMAXBUTTON:
3161 case HitTest.HTMINBUTTON:
3162 case HitTest.HTMENU:
3163 case HitTest.HSCROLL:
3164 case HitTest.HTBOTTOM:
3165 case HitTest.HTCAPTION:
3166 case HitTest.HTCLIENT:
3167 case HitTest.HTCLOSE:
3169 default: handle = Cursors.Default.handle; break;
3171 SetCursor(msg.HWnd, handle);
3179 internal override void DestroyCaret(IntPtr handle) {
3180 if (Caret.Hwnd == handle) {
3181 if (Caret.Visible) {
3185 if (Caret.gc != IntPtr.Zero) {
3186 XFreeGC(DisplayHandle, Caret.gc);
3187 Caret.gc = IntPtr.Zero;
3189 Caret.Hwnd = IntPtr.Zero;
3190 Caret.Visible = false;
3195 internal override void DestroyCursor(IntPtr cursor) {
3197 XFreeCursor(DisplayHandle, cursor);
3201 internal override void DestroyWindow(IntPtr handle) {
3204 hwnd = Hwnd.ObjectFromHandle(handle);
3207 #if DriverDebug || DriverDebugDestroy
3208 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3213 #if DriverDebug || DriverDebugDestroy
3214 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3217 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3219 CleanupCachedWindows (hwnd);
3221 ArrayList windows = new ArrayList ();
3223 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3226 foreach (Hwnd h in windows) {
3227 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3232 if (hwnd.whole_window != IntPtr.Zero) {
3233 #if DriverDebug || DriverDebugDestroy
3234 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3236 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3238 else if (hwnd.client_window != IntPtr.Zero) {
3239 #if DriverDebug || DriverDebugDestroy
3240 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3242 XDestroyWindow(DisplayHandle, hwnd.client_window);
3248 internal override IntPtr DispatchMessage(ref MSG msg) {
3249 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3252 IntPtr GetReversibleScreenGC (Color backColor)
3254 XGCValues gc_values;
3258 XColor xcolor = new XColor();
3259 xcolor.red = (ushort)(backColor.R * 257);
3260 xcolor.green = (ushort)(backColor.G * 257);
3261 xcolor.blue = (ushort)(backColor.B * 257);
3262 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3263 pixel = (uint)xcolor.pixel.ToInt32();
3266 gc_values = new XGCValues();
3268 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3269 gc_values.foreground = (IntPtr)pixel;
3271 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3272 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3273 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3278 IntPtr GetReversibleControlGC (Control control, int line_width)
3280 XGCValues gc_values;
3283 gc_values = new XGCValues();
3285 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3286 gc_values.line_width = line_width;
3287 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3289 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3290 //mask = foreground ^ background;
3291 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3292 //XSetBackground(DisplayHandle, gc, background);
3293 //XSetFunction(DisplayHandle, gc, GXxor);
3294 //XSetPlaneMask(DisplayHandle, gc, mask);
3297 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3301 XColor xcolor = new XColor();
3303 xcolor.red = (ushort)(control.ForeColor.R * 257);
3304 xcolor.green = (ushort)(control.ForeColor.G * 257);
3305 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3306 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3307 foreground = (uint)xcolor.pixel.ToInt32();
3309 xcolor.red = (ushort)(control.BackColor.R * 257);
3310 xcolor.green = (ushort)(control.BackColor.G * 257);
3311 xcolor.blue = (ushort)(control.BackColor.B * 257);
3312 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3313 background = (uint)xcolor.pixel.ToInt32();
3315 uint mask = foreground ^ background;
3317 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3318 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3319 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3320 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3325 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3327 IntPtr gc = GetReversibleScreenGC (backColor);
3329 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3331 XFreeGC(DisplayHandle, gc);
3334 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3336 IntPtr gc = GetReversibleScreenGC (backColor);
3338 if (rectangle.Width < 0) {
3339 rectangle.X += rectangle.Width;
3340 rectangle.Width = -rectangle.Width;
3342 if (rectangle.Height < 0) {
3343 rectangle.Y += rectangle.Height;
3344 rectangle.Height = -rectangle.Height;
3348 GCLineStyle line_style = GCLineStyle.LineSolid;
3349 GCCapStyle cap_style = GCCapStyle.CapButt;
3350 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3353 case FrameStyle.Dashed:
3354 line_style = GCLineStyle.LineOnOffDash;
3356 case FrameStyle.Thick:
3361 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3363 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3365 XFreeGC(DisplayHandle, gc);
3368 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3370 IntPtr gc = GetReversibleScreenGC (backColor);
3372 if (rectangle.Width < 0) {
3373 rectangle.X += rectangle.Width;
3374 rectangle.Width = -rectangle.Width;
3376 if (rectangle.Height < 0) {
3377 rectangle.Y += rectangle.Height;
3378 rectangle.Height = -rectangle.Height;
3380 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3382 XFreeGC(DisplayHandle, gc);
3385 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3387 Control control = Control.FromHandle(handle);
3389 gc = GetReversibleControlGC (control, line_width);
3391 if ((rect.Width > 0) && (rect.Height > 0)) {
3392 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3394 if (rect.Width > 0) {
3395 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3397 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3400 XFreeGC(DisplayHandle, gc);
3403 internal override void DoEvents() {
3404 MSG msg = new MSG ();
3407 if (OverrideCursorHandle != IntPtr.Zero) {
3408 OverrideCursorHandle = IntPtr.Zero;
3411 queue = ThreadQueue(Thread.CurrentThread);
3413 queue.DispatchIdle = false;
3415 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3416 TranslateMessage (ref msg);
3417 DispatchMessage (ref msg);
3420 queue.DispatchIdle = true;
3423 internal override void EnableWindow(IntPtr handle, bool Enable) {
3426 hwnd = Hwnd.ObjectFromHandle(handle);
3428 hwnd.Enabled = Enable;
3432 internal override void EndLoop(Thread thread) {
3433 // This is where we one day will shut down the loop for the thread
3436 internal override IntPtr GetActive() {
3441 IntPtr prop = IntPtr.Zero;
3442 IntPtr active = IntPtr.Zero;
3444 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);
3445 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3446 active = (IntPtr)Marshal.ReadInt32(prop);
3450 if (active != IntPtr.Zero) {
3453 hwnd = Hwnd.GetObjectFromWindow(active);
3455 active = hwnd.Handle;
3457 active = IntPtr.Zero;
3463 internal override Region GetClipRegion(IntPtr handle) {
3466 hwnd = Hwnd.ObjectFromHandle(handle);
3468 return hwnd.UserClip;
3474 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3481 internal override void GetDisplaySize(out Size size) {
3482 XWindowAttributes attributes=new XWindowAttributes();
3485 // FIXME - use _NET_WM messages instead?
3486 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3489 size = new Size(attributes.width, attributes.height);
3492 internal override SizeF GetAutoScaleSize(Font font) {
3495 string magic_string = "The quick brown fox jumped over the lazy dog.";
3496 double magic_number = 44.549996948242189;
3498 g = Graphics.FromHwnd(FosterParent);
3500 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3501 return new SizeF(width, font.Height);
3504 internal override IntPtr GetParent(IntPtr handle) {
3507 hwnd = Hwnd.ObjectFromHandle(handle);
3508 if (hwnd != null && hwnd.parent != null) {
3509 return hwnd.parent.Handle;
3514 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3524 if (handle != IntPtr.Zero) {
3525 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3527 use_handle = RootWindow;
3531 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3534 if (handle != IntPtr.Zero) {
3543 internal override IntPtr GetFocus() {
3548 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3549 FontFamily ff = font.FontFamily;
3550 ascent = ff.GetCellAscent (font.Style);
3551 descent = ff.GetCellDescent (font.Style);
3555 internal override Point GetMenuOrigin(IntPtr handle) {
3558 hwnd = Hwnd.ObjectFromHandle(handle);
3561 return hwnd.MenuOrigin;
3566 [MonoTODO("Implement filtering")]
3567 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3574 if (((XEventQueue)queue_id).Count > 0) {
3575 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3577 UpdateMessageQueue ((XEventQueue)queue_id);
3579 if (((XEventQueue)queue_id).Count > 0) {
3580 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3581 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3582 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3584 msg.hwnd= IntPtr.Zero;
3585 msg.message = Msg.WM_ENTERIDLE;
3590 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3592 // Handle messages for windows that are already or are about to be destroyed.
3594 // we need a special block for this because unless we remove the hwnd from the paint
3595 // queue it will always stay there (since we don't handle the expose), and we'll
3596 // effectively loop infinitely trying to repaint a non-existant window.
3597 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3598 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3599 hwnd.Queue.Paint.Remove (hwnd);
3600 goto ProcessNextMessage;
3603 // We need to make sure we only allow DestroyNotify events through for zombie
3604 // hwnds, since much of the event handling code makes requests using the hwnd's
3605 // client_window, and that'll result in BadWindow errors if there's some lag
3606 // between the XDestroyWindow call and the DestroyNotify event.
3607 if (hwnd == null || hwnd.zombie) {
3608 #if DriverDebug || DriverDebugDestroy
3609 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3611 goto ProcessNextMessage;
3614 if (hwnd.client_window == xevent.AnyEvent.window) {
3616 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3619 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3622 msg.hwnd = hwnd.Handle;
3625 // If you add a new event to this switch make sure to add it in
3626 // UpdateMessage also unless it is not coming through the X event system.
3628 switch(xevent.type) {
3629 case XEventName.KeyPress: {
3630 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3634 case XEventName.KeyRelease: {
3635 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3639 case XEventName.ButtonPress: {
3640 switch(xevent.ButtonEvent.button) {
3642 MouseState |= MouseButtons.Left;
3644 msg.message = Msg.WM_LBUTTONDOWN;
3646 msg.message = Msg.WM_NCLBUTTONDOWN;
3647 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3649 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3650 msg.wParam=GetMousewParam(0);
3655 MouseState |= MouseButtons.Middle;
3657 msg.message = Msg.WM_MBUTTONDOWN;
3659 msg.message = Msg.WM_NCMBUTTONDOWN;
3660 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3662 msg.wParam=GetMousewParam(0);
3667 MouseState |= MouseButtons.Right;
3669 msg.message = Msg.WM_RBUTTONDOWN;
3671 msg.message = Msg.WM_NCRBUTTONDOWN;
3672 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3674 msg.wParam=GetMousewParam(0);
3679 msg.hwnd = FocusWindow;
3680 msg.message=Msg.WM_MOUSEWHEEL;
3681 msg.wParam=GetMousewParam(120);
3686 msg.hwnd = FocusWindow;
3687 msg.message=Msg.WM_MOUSEWHEEL;
3688 msg.wParam=GetMousewParam(-120);
3694 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3695 mouse_position.X = xevent.ButtonEvent.x;
3696 mouse_position.Y = xevent.ButtonEvent.y;
3698 if (!hwnd.Enabled) {
3701 msg.hwnd = hwnd.EnabledHwnd;
3702 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);
3703 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3706 if (Grab.Hwnd != IntPtr.Zero) {
3707 msg.hwnd = Grab.Hwnd;
3710 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3711 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3712 switch(xevent.ButtonEvent.button) {
3714 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3719 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3724 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3728 ClickPending.Pending = false;
3730 ClickPending.Pending = true;
3731 ClickPending.Hwnd = msg.hwnd;
3732 ClickPending.Message = msg.message;
3733 ClickPending.wParam = msg.wParam;
3734 ClickPending.lParam = msg.lParam;
3735 ClickPending.Time = (long)xevent.ButtonEvent.time;
3738 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3739 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3741 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3742 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3743 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3744 XEvent motionEvent = new XEvent ();
3745 motionEvent.type = XEventName.MotionNotify;
3746 motionEvent.MotionEvent.display = DisplayHandle;
3747 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3748 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3749 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3750 hwnd.Queue.EnqueueLocked (motionEvent);
3756 case XEventName.ButtonRelease: {
3758 switch(xevent.ButtonEvent.button) {
3761 msg.message = Msg.WM_LBUTTONUP;
3763 msg.message = Msg.WM_NCLBUTTONUP;
3764 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3766 MouseState &= ~MouseButtons.Left;
3767 msg.wParam=GetMousewParam(0);
3773 msg.message = Msg.WM_MBUTTONUP;
3775 msg.message = Msg.WM_NCMBUTTONUP;
3776 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3778 MouseState &= ~MouseButtons.Middle;
3779 msg.wParam=GetMousewParam(0);
3785 msg.message = Msg.WM_RBUTTONUP;
3787 msg.message = Msg.WM_NCRBUTTONUP;
3788 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3790 MouseState &= ~MouseButtons.Right;
3791 msg.wParam=GetMousewParam(0);
3796 goto ProcessNextMessage;
3800 goto ProcessNextMessage;
3804 if (!hwnd.Enabled) {
3807 msg.hwnd = hwnd.EnabledHwnd;
3808 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);
3809 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3812 if (Grab.Hwnd != IntPtr.Zero) {
3813 msg.hwnd = Grab.Hwnd;
3816 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3817 mouse_position.X = xevent.ButtonEvent.x;
3818 mouse_position.Y = xevent.ButtonEvent.y;
3820 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3821 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3822 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3823 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3824 XEvent motionEvent = new XEvent ();
3825 motionEvent.type = XEventName.MotionNotify;
3826 motionEvent.MotionEvent.display = DisplayHandle;
3827 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3828 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3829 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3830 hwnd.Queue.EnqueueLocked (motionEvent);
3835 case XEventName.MotionNotify: {
3837 #if DriverDebugExtra
3838 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);
3841 if (Grab.Hwnd != IntPtr.Zero) {
3842 msg.hwnd = Grab.Hwnd;
3845 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3849 msg.message = Msg.WM_MOUSEMOVE;
3850 msg.wParam = GetMousewParam(0);
3851 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3853 if (!hwnd.Enabled) {
3856 msg.hwnd = hwnd.EnabledHwnd;
3857 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);
3858 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3861 mouse_position.X = xevent.MotionEvent.x;
3862 mouse_position.Y = xevent.MotionEvent.y;
3864 if ((HoverState.Timer.Enabled) &&
3865 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3866 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3867 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3868 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3869 HoverState.Timer.Stop();
3870 HoverState.Timer.Start();
3871 HoverState.X = mouse_position.X;
3872 HoverState.Y = mouse_position.Y;
3882 #if DriverDebugExtra
3883 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);
3885 msg.message = Msg.WM_NCMOUSEMOVE;
3887 if (!hwnd.Enabled) {
3888 msg.hwnd = hwnd.EnabledHwnd;
3889 XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
3890 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3893 // The hit test is sent in screen coordinates
3894 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3895 xevent.MotionEvent.x, xevent.MotionEvent.y,
3896 out screen_x, out screen_y, out dummy);
3898 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3899 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3900 IntPtr.Zero, msg.lParam).ToInt32 ();
3901 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3903 mouse_position.X = xevent.MotionEvent.x;
3904 mouse_position.Y = xevent.MotionEvent.y;
3910 case XEventName.EnterNotify: {
3911 if (!hwnd.Enabled) {
3912 goto ProcessNextMessage;
3914 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3915 goto ProcessNextMessage;
3917 msg.message = Msg.WM_MOUSE_ENTER;
3918 HoverState.X = xevent.CrossingEvent.x;
3919 HoverState.Y = xevent.CrossingEvent.y;
3920 HoverState.Timer.Enabled = true;
3921 HoverState.Window = xevent.CrossingEvent.window;
3925 case XEventName.LeaveNotify: {
3926 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3927 WindowUngrabbed (hwnd.Handle);
3928 goto ProcessNextMessage;
3930 if (!hwnd.Enabled) {
3931 goto ProcessNextMessage;
3933 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3934 goto ProcessNextMessage;
3936 msg.message=Msg.WM_MOUSELEAVE;
3937 HoverState.Timer.Enabled = false;
3938 HoverState.Window = IntPtr.Zero;
3943 case XEventName.CreateNotify: {
3944 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3945 msg.message = WM_CREATE;
3946 // Set up CreateStruct
3948 goto ProcessNextMessage;
3955 case XEventName.ReparentNotify: {
3956 if (hwnd.parent == null) { // Toplevel
3957 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3958 hwnd.Reparented = true;
3960 // The location given by the event is not reliable between different wm's,
3961 // so use an alternative way of getting it.
3962 Point location = GetTopLevelWindowLocation (hwnd);
3963 hwnd.X = location.X;
3964 hwnd.Y = location.Y;
3966 if (hwnd.opacity != 0xffffffff) {
3969 opacity = (IntPtr)(Int32)hwnd.opacity;
3970 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3972 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3973 goto ProcessNextMessage;
3975 hwnd.Reparented = false;
3976 goto ProcessNextMessage;
3979 goto ProcessNextMessage;
3982 case XEventName.ConfigureNotify: {
3983 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3984 #if DriverDebugExtra
3985 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);
3987 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3988 lock (hwnd.configure_lock) {
3989 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3990 hwnd.configure_pending = false;
3993 // We need to adjust our client window to track the resize of whole_window
3994 if (hwnd.whole_window != hwnd.client_window)
3995 PerformNCCalc(hwnd);
3998 goto ProcessNextMessage;
4001 case XEventName.FocusIn: {
4002 // We received focus. We use X11 focus only to know if the app window does or does not have focus
4003 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4004 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
4005 // about it having focus again
4006 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4007 goto ProcessNextMessage;
4010 if (FocusWindow == IntPtr.Zero) {
4011 Control c = Control.FromHandle (hwnd.client_window);
4013 goto ProcessNextMessage;
4014 Form form = c.FindForm ();
4016 goto ProcessNextMessage;
4017 if (ActiveWindow != form.Handle) {
4018 ActiveWindow = form.Handle;
4019 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4021 goto ProcessNextMessage;
4023 Keyboard.FocusIn(FocusWindow);
4024 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4025 goto ProcessNextMessage;
4028 case XEventName.FocusOut: {
4029 // Se the comment for our FocusIn handler
4030 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4031 goto ProcessNextMessage;
4033 Keyboard.FocusOut(FocusWindow);
4035 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4036 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4039 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4040 goto ProcessNextMessage;
4043 case XEventName.MapNotify: {
4044 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4046 msg.message = Msg.WM_SHOWWINDOW;
4047 msg.wParam = (IntPtr) 1;
4048 // XXX we're missing the lParam..
4051 goto ProcessNextMessage;
4054 case XEventName.UnmapNotify: {
4055 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4056 hwnd.mapped = false;
4057 msg.message = Msg.WM_SHOWWINDOW;
4058 msg.wParam = (IntPtr) 0;
4059 // XXX we're missing the lParam..
4062 goto ProcessNextMessage;
4065 case XEventName.Expose: {
4068 hwnd.expose_pending = false;
4070 hwnd.nc_expose_pending = false;
4072 goto ProcessNextMessage;
4076 if (!hwnd.expose_pending) {
4077 goto ProcessNextMessage;
4080 if (!hwnd.nc_expose_pending) {
4081 goto ProcessNextMessage;
4084 switch (hwnd.border_style) {
4085 case FormBorderStyle.Fixed3D: {
4088 g = Graphics.FromHwnd(hwnd.whole_window);
4089 if (hwnd.border_static)
4090 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4092 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4097 case FormBorderStyle.FixedSingle: {
4100 g = Graphics.FromHwnd(hwnd.whole_window);
4101 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4106 #if DriverDebugExtra
4107 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);
4110 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4111 Region region = new Region (rect);
4112 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4113 msg.message = Msg.WM_NCPAINT;
4114 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4115 msg.refobject = region;
4118 #if DriverDebugExtra
4119 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);
4121 if (Caret.Visible == true) {
4122 Caret.Paused = true;
4126 if (Caret.Visible == true) {
4128 Caret.Paused = false;
4130 msg.message = Msg.WM_PAINT;
4134 case XEventName.DestroyNotify: {
4136 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4137 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4139 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4140 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4141 CleanupCachedWindows (hwnd);
4143 #if DriverDebugDestroy
4144 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4147 msg.hwnd = hwnd.client_window;
4148 msg.message=Msg.WM_DESTROY;
4151 goto ProcessNextMessage;
4157 case XEventName.ClientMessage: {
4158 if (Dnd.HandleClientMessage (ref xevent)) {
4159 goto ProcessNextMessage;
4162 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4163 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4164 goto ProcessNextMessage;
4167 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4168 msg.message = Msg.WM_MOUSEHOVER;
4169 msg.wParam = GetMousewParam(0);
4170 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4174 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4175 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4176 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4177 msg.wParam = xevent.ClientMessageEvent.ptr3;
4178 msg.lParam = xevent.ClientMessageEvent.ptr4;
4179 if (msg.message == (Msg)Msg.WM_QUIT)
4185 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4186 #if DriverDebugXEmbed
4187 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4190 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4191 XSizeHints hints = new XSizeHints();
4194 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4196 hwnd.width = hints.max_width;
4197 hwnd.height = hints.max_height;
4198 hwnd.ClientRect = Rectangle.Empty;
4199 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4203 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4204 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4205 msg.message = Msg.WM_CLOSE;
4209 // We should not get this, but I'll leave the code in case we need it in the future
4210 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4211 goto ProcessNextMessage;
4214 goto ProcessNextMessage;
4218 goto ProcessNextMessage;
4225 internal override bool GetText(IntPtr handle, out string text) {
4232 IntPtr prop = IntPtr.Zero;
4234 XGetWindowProperty(DisplayHandle, handle,
4235 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4236 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4238 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4239 text = Marshal.PtrToStringUni (prop, (int)nitems);
4244 // fallback on the non-_NET property
4247 textptr = IntPtr.Zero;
4249 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4250 if (textptr != IntPtr.Zero) {
4251 text = Marshal.PtrToStringAnsi(textptr);
4262 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) {
4265 hwnd = Hwnd.ObjectFromHandle(handle);
4271 height = hwnd.height;
4273 PerformNCCalc(hwnd);
4275 client_width = hwnd.ClientRect.Width;
4276 client_height = hwnd.ClientRect.Height;
4281 // Should we throw an exception or fail silently?
4282 // throw new ArgumentException("Called with an invalid window handle", "handle");
4292 internal override FormWindowState GetWindowState(IntPtr handle) {
4295 hwnd = Hwnd.ObjectFromHandle(handle);
4297 if (hwnd.cached_window_state == (FormWindowState)(-1))
4298 hwnd.cached_window_state = UpdateWindowState (handle);
4300 return hwnd.cached_window_state;
4303 private FormWindowState UpdateWindowState (IntPtr handle) {
4308 IntPtr prop = IntPtr.Zero;
4312 XWindowAttributes attributes;
4315 hwnd = Hwnd.ObjectFromHandle(handle);
4319 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);
4320 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4321 for (int i = 0; i < (long)nitems; i++) {
4322 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4323 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4325 } else if (atom == _NET_WM_STATE_HIDDEN) {
4333 return FormWindowState.Minimized;
4334 } else if (maximized == 2) {
4335 return FormWindowState.Maximized;
4338 attributes = new XWindowAttributes();
4339 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4340 if (attributes.map_state == MapState.IsUnmapped) {
4341 return (FormWindowState)(-1);
4345 return FormWindowState.Normal;
4348 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4350 GrabConfined = Grab.Confined;
4351 GrabArea = Grab.Area;
4354 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4356 IntPtr confine_to_window;
4358 confine_to_window = IntPtr.Zero;
4360 if (confine_to_handle != IntPtr.Zero) {
4361 XWindowAttributes attributes = new XWindowAttributes();
4363 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4366 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4368 Grab.Area.X = attributes.x;
4369 Grab.Area.Y = attributes.y;
4370 Grab.Area.Width = attributes.width;
4371 Grab.Area.Height = attributes.height;
4372 Grab.Confined = true;
4373 confine_to_window = hwnd.client_window;
4378 hwnd = Hwnd.ObjectFromHandle(handle);
4381 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4382 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4383 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4384 EventMask.LeaveWindowMask,
4385 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4389 internal override void UngrabWindow(IntPtr hwnd) {
4391 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4392 XFlush(DisplayHandle);
4394 WindowUngrabbed (hwnd);
4397 private void WindowUngrabbed (IntPtr hwnd) {
4398 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4400 Grab.Hwnd = IntPtr.Zero;
4401 Grab.Confined = false;
4404 // lparam should be the handle to the window gaining the mouse capture,
4405 // but X doesn't seem to give us that information.
4406 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4407 // X will send a NotifyUngrab, but since it comes late sometimes we're
4408 // calling WindowUngrabbed directly from UngrabWindow in order to send
4409 // this WM right away.
4410 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4414 internal override void HandleException(Exception e) {
4415 StackTrace st = new StackTrace(e, true);
4416 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4417 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4420 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4423 hwnd = Hwnd.ObjectFromHandle(handle);
4426 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4428 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4432 internal override void InvalidateNC (IntPtr handle) {
4435 hwnd = Hwnd.ObjectFromHandle(handle);
4437 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4440 internal override bool IsEnabled(IntPtr handle) {
4441 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4442 return (hwnd != null && hwnd.Enabled);
4445 internal override bool IsVisible(IntPtr handle) {
4446 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4447 return (hwnd != null && hwnd.visible);
4450 internal override void KillTimer(Timer timer) {
4451 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4453 if (queue == null) {
4454 // This isn't really an error, MS doesn't start the timer if
4455 // it has no assosciated queue
4458 queue.timer_list.Remove (timer);
4461 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4467 hwnd = Hwnd.ObjectFromHandle(handle);
4470 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4477 internal override void OverrideCursor(IntPtr cursor)
4479 if (Grab.Hwnd != IntPtr.Zero) {
4480 XChangeActivePointerGrab (DisplayHandle,
4481 EventMask.ButtonMotionMask |
4482 EventMask.PointerMotionMask |
4483 EventMask.ButtonPressMask |
4484 EventMask.ButtonReleaseMask,
4485 cursor, IntPtr.Zero);
4489 OverrideCursorHandle = cursor;
4492 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4493 PaintEventArgs paint_event;
4498 // handle (and paint_hwnd) refers to the window that is should be painted.
4499 // msg.HWnd (and hwnd) refers to the window that got the paint message.
4502 hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4503 if (msg.HWnd == handle) {
4506 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4509 if (Caret.Visible == true) {
4510 Caret.Paused = true;
4517 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4519 Region clip_region = new Region ();
4520 clip_region.MakeEmpty();
4522 foreach (Rectangle r in hwnd.ClipRectangles) {
4523 clip_region.Union (r);
4526 if (hwnd.UserClip != null) {
4527 clip_region.Intersect(hwnd.UserClip);
4530 dc.Clip = clip_region;
4531 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4532 hwnd.expose_pending = false;
4534 hwnd.ClearInvalidArea();
4536 hwnd.drawing_stack.Push (paint_event);
4537 hwnd.drawing_stack.Push (dc);
4541 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4543 if (!hwnd.nc_invalid.IsEmpty) {
4544 dc.SetClip (hwnd.nc_invalid);
4545 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4547 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4549 hwnd.nc_expose_pending = false;
4551 hwnd.ClearNcInvalidArea ();
4553 hwnd.drawing_stack.Push (paint_event);
4554 hwnd.drawing_stack.Push (dc);
4560 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4563 hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4565 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4569 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4570 pe.SetGraphics (null);
4573 if (Caret.Visible == true) {
4575 Caret.Paused = false;
4579 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4580 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4581 XEventQueue queue = (XEventQueue) queue_id;
4584 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4585 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4589 if (queue.Count > 0) {
4592 // Only call UpdateMessageQueue if real events are pending
4593 // otherwise we go to sleep on the socket
4594 if (XPending(DisplayHandle) != 0) {
4595 UpdateMessageQueue((XEventQueue)queue_id);
4597 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4602 CheckTimers(queue.timer_list, DateTime.UtcNow);
4607 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4610 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4611 XEvent xevent = new XEvent ();
4612 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4614 xevent.type = XEventName.ClientMessage;
4615 xevent.ClientMessageEvent.display = DisplayHandle;
4618 xevent.ClientMessageEvent.window = hwnd.whole_window;
4620 xevent.ClientMessageEvent.window = IntPtr.Zero;
4623 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4624 xevent.ClientMessageEvent.format = 32;
4625 xevent.ClientMessageEvent.ptr1 = handle;
4626 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4627 xevent.ClientMessageEvent.ptr3 = wparam;
4628 xevent.ClientMessageEvent.ptr4 = lparam;
4630 hwnd.Queue.EnqueueLocked (xevent);
4635 internal override void PostQuitMessage(int exitCode) {
4636 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4637 XFlush(DisplayHandle);
4640 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4645 internal override void RequestNCRecalc(IntPtr handle) {
4648 hwnd = Hwnd.ObjectFromHandle(handle);
4654 PerformNCCalc(hwnd);
4655 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4656 InvalidateNC(handle);
4659 internal override void ResetMouseHover(IntPtr handle) {
4662 hwnd = Hwnd.ObjectFromHandle(handle);
4667 HoverState.Timer.Enabled = true;
4668 HoverState.X = mouse_position.X;
4669 HoverState.Y = mouse_position.Y;
4670 HoverState.Window = handle;
4674 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4680 hwnd = Hwnd.ObjectFromHandle(handle);
4683 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4690 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4696 hwnd = Hwnd.ObjectFromHandle(handle);
4699 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4702 Form form = Control.FromHandle (handle) as Form;
4703 if (form != null && form.window_manager != null) {
4704 dest_y_return -= form.window_manager.TitleBarHeight;
4711 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4714 XGCValues gc_values;
4716 hwnd = Hwnd.ObjectFromHandle(handle);
4718 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4720 /* We have an invalid area in the window we're scrolling.
4721 Adjust our stored invalid rectangle to to match the scrolled amount */
4736 if (area.Contains (hwnd.Invalid))
4737 hwnd.ClearInvalidArea ();
4738 hwnd.AddInvalidArea(r);
4741 gc_values = new XGCValues();
4743 if (with_children) {
4744 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4747 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4755 height = area.Height - YAmount;
4756 dest_y = area.Y + YAmount;
4759 src_y = area.Y - YAmount;
4760 height = area.Height + YAmount;
4766 width = area.Width - XAmount;
4767 dest_x = area.X + XAmount;
4770 src_x = area.X - XAmount;
4771 width = area.Width + XAmount;
4775 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4777 // Generate an expose for the area exposed by the horizontal scroll
4778 // We don't use AddExpose since we're
4780 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4781 } else if (XAmount < 0) {
4782 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4785 // Generate an expose for the area exposed by the vertical scroll
4787 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4788 } else if (YAmount < 0) {
4789 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4791 XFreeGC(DisplayHandle, gc);
4794 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4798 hwnd = Hwnd.GetObjectFromWindow(handle);
4800 rect = hwnd.ClientRect;
4803 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4806 internal override void SendAsyncMethod (AsyncMethodData method) {
4808 XEvent xevent = new XEvent ();
4810 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4812 xevent.type = XEventName.ClientMessage;
4813 xevent.ClientMessageEvent.display = DisplayHandle;
4814 xevent.ClientMessageEvent.window = method.Handle;
4815 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4816 xevent.ClientMessageEvent.format = 32;
4817 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4819 hwnd.Queue.EnqueueLocked (xevent);
4824 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4826 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4829 h = Hwnd.ObjectFromHandle(hwnd);
4831 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4832 AsyncMethodResult result;
4833 AsyncMethodData data;
4835 result = new AsyncMethodResult ();
4836 data = new AsyncMethodData ();
4839 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4840 data.Args = new object[] { hwnd, message, wParam, lParam };
4841 data.Result = result;
4843 SendAsyncMethod (data);
4844 #if DriverDebug || DriverDebugThreads
4845 Console.WriteLine ("Sending {0} message across.", message);
4850 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4853 internal override int SendInput(IntPtr handle, Queue keys) {
4854 if (handle == IntPtr.Zero)
4857 int count = keys.Count;
4858 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4860 while (keys.Count > 0) {
4862 MSG msg = (MSG)keys.Dequeue();
4864 XEvent xevent = new XEvent ();
4866 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4867 xevent.KeyEvent.display = DisplayHandle;
4870 xevent.KeyEvent.window = hwnd.whole_window;
4872 xevent.KeyEvent.window = IntPtr.Zero;
4875 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4877 hwnd.Queue.EnqueueLocked (xevent);
4882 internal override void SetAllowDrop (IntPtr handle, bool value)
4884 // We allow drop on all windows
4887 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4888 DragDropEffects allowed_effects)
4890 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4893 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4895 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4898 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4899 Form form = Control.FromHandle (handle) as Form;
4900 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4901 border_style == FormBorderStyle.SizableToolWindow)) {
4902 form.window_manager = new ToolWindowManager (form);
4905 RequestNCRecalc(handle);
4908 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4909 if (Caret.Hwnd == handle) {
4916 if (Caret.Visible == true) {
4918 Caret.Timer.Start();
4923 internal override void SetClipRegion(IntPtr handle, Region region) {
4926 hwnd = Hwnd.ObjectFromHandle(handle);
4931 hwnd.UserClip = region;
4934 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4937 if (OverrideCursorHandle == IntPtr.Zero) {
4938 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4942 LastCursorHandle = cursor;
4943 LastCursorWindow = handle;
4945 hwnd = Hwnd.ObjectFromHandle(handle);
4947 if (cursor != IntPtr.Zero) {
4948 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4950 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4952 XFlush(DisplayHandle);
4957 hwnd = Hwnd.ObjectFromHandle(handle);
4959 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4963 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4964 out int root_x, out int root_y, out int child_x, out int child_y,
4967 /* this code was written with the help of
4968 glance at gdk. I never would have realized we
4969 needed a loop in order to traverse down in the
4970 hierarchy. I would have assumed you'd get the
4971 most deeply nested child and have to do
4972 XQueryTree to move back up the hierarchy..
4973 stupid me, of course. */
4976 XGrabServer (display);
4978 XQueryPointer(display, w, out root, out c,
4979 out root_x, out root_y, out child_x, out child_y,
4985 IntPtr child_last = IntPtr.Zero;
4986 while (c != IntPtr.Zero) {
4988 XQueryPointer(display, c, out root, out c,
4989 out root_x, out root_y, out child_x, out child_y,
4992 XUngrabServer (display);
4998 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4999 if (handle == IntPtr.Zero) {
5002 int root_x, root_y, child_x, child_y, mask;
5005 * QueryPointer before warping
5006 * because if the warp is on
5007 * the RootWindow, the x/y are
5008 * relative to the current
5011 QueryPointer (DisplayHandle, RootWindow,
5014 out root_x, out root_y,
5015 out child_x, out child_y,
5018 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5020 XFlush (DisplayHandle);
5022 /* then we need to a
5023 * QueryPointer after warping
5024 * to manually generate a
5025 * motion event for the window
5028 QueryPointer (DisplayHandle, RootWindow,
5031 out root_x, out root_y,
5032 out child_x, out child_y,
5035 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5036 if (child_hwnd == null) {
5040 XEvent xevent = new XEvent ();
5042 xevent.type = XEventName.MotionNotify;
5043 xevent.MotionEvent.display = DisplayHandle;
5044 xevent.MotionEvent.window = child_hwnd.client_window;
5045 xevent.MotionEvent.root = RootWindow;
5046 xevent.MotionEvent.x = child_x;
5047 xevent.MotionEvent.y = child_y;
5048 xevent.MotionEvent.x_root = root_x;
5049 xevent.MotionEvent.y_root = root_y;
5050 xevent.MotionEvent.state = mask;
5052 child_hwnd.Queue.EnqueueLocked (xevent);
5057 hwnd = Hwnd.ObjectFromHandle(handle);
5059 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5064 internal override void SetFocus(IntPtr handle) {
5066 IntPtr prev_focus_window;
5068 hwnd = Hwnd.ObjectFromHandle(handle);
5070 if (hwnd.client_window == FocusWindow) {
5074 prev_focus_window = FocusWindow;
5075 FocusWindow = hwnd.client_window;
5077 if (prev_focus_window != IntPtr.Zero) {
5078 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5080 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5082 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5085 internal override void SetIcon(IntPtr handle, Icon icon) {
5088 hwnd = Hwnd.ObjectFromHandle(handle);
5090 SetIcon(hwnd, icon);
5094 internal override void SetMenu(IntPtr handle, Menu menu) {
5097 hwnd = Hwnd.ObjectFromHandle(handle);
5100 RequestNCRecalc(handle);
5103 internal override void SetModal(IntPtr handle, bool Modal) {
5105 ModalWindows.Push(handle);
5107 if (ModalWindows.Contains(handle)) {
5110 if (ModalWindows.Count > 0) {
5111 Activate((IntPtr)ModalWindows.Peek());
5115 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5116 Control ctrl = Control.FromHandle (handle);
5117 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5120 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5123 hwnd = Hwnd.ObjectFromHandle(handle);
5124 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5127 #if DriverDebug || DriverDebugParent
5128 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5130 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5136 internal override void SetTimer (Timer timer) {
5137 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5139 if (queue == null) {
5140 // This isn't really an error, MS doesn't start the timer if
5141 // it has no assosciated queue
5144 queue.timer_list.Add (timer);
5148 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5150 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5154 int[] atoms = new int[8];
5155 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5156 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5160 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5166 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5170 hwnd = Hwnd.ObjectFromHandle(handle);
5172 if (handle_owner != IntPtr.Zero) {
5173 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5179 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5180 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5182 if (hwnd_owner != null) {
5183 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5185 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5190 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5196 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5200 hwnd = Hwnd.ObjectFromHandle(handle);
5201 hwnd.visible = visible;
5205 MapWindow(hwnd, WindowType.Both);
5207 if (Control.FromHandle(handle) is Form) {
5210 s = ((Form)Control.FromHandle(handle)).WindowState;
5213 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5214 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5218 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5221 UnmapWindow(hwnd, WindowType.Both);
5227 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5228 Control ctrl = Control.FromHandle (handle);
5229 SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5232 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5238 hwnd = Hwnd.ObjectFromHandle(handle);
5243 hints = new XSizeHints();
5245 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5246 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5248 min = TranslateWindowSizeToXWindowSize (cp, min);
5249 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5250 hints.min_width = min.Width;
5251 hints.min_height = min.Height;
5254 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5256 max = TranslateWindowSizeToXWindowSize (cp, max);
5257 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5258 hints.max_width = max.Width;
5259 hints.max_height = max.Height;
5262 if (hints.flags != IntPtr.Zero) {
5263 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5264 // they will maximize the window to fill the screen/parent no matter what.
5265 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5266 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5269 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5271 maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5272 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5273 hints.x = maximized.X;
5274 hints.y = maximized.Y;
5275 hints.width = maximized.Width;
5276 hints.height = maximized.Height;
5278 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5279 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5284 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5287 hwnd = Hwnd.ObjectFromHandle(handle);
5293 // Win32 automatically changes negative width/height to 0.
5299 // X requires a sanity check for width & height; otherwise it dies
5300 if (hwnd.zero_sized && width > 0 && height > 0) {
5302 MapWindow(hwnd, WindowType.Whole);
5304 hwnd.zero_sized = false;
5307 if ((width < 1) || (height < 1)) {
5308 hwnd.zero_sized = true;
5309 UnmapWindow(hwnd, WindowType.Whole);
5312 // Save a server roundtrip (and prevent a feedback loop)
5313 if ((hwnd.x == x) && (hwnd.y == y) &&
5314 (hwnd.width == width) && (hwnd.height == height)) {
5318 if (!hwnd.zero_sized) {
5323 hwnd.height = height;
5324 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5326 if (hwnd.fixed_size) {
5327 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5331 Control ctrl = Control.FromHandle (handle);
5332 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5333 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5334 PerformNCCalc(hwnd);
5338 // Update our position/size immediately, so
5339 // that future calls to SetWindowPos aren't
5340 // kept from calling XMoveResizeWindow (by the
5341 // "Save a server roundtrip" block above).
5345 hwnd.height = height;
5346 hwnd.ClientRect = Rectangle.Empty;
5349 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5350 FormWindowState current_state;
5353 hwnd = Hwnd.ObjectFromHandle(handle);
5355 current_state = GetWindowState(handle);
5357 if (current_state == state) {
5362 case FormWindowState.Normal: {
5364 if (current_state == FormWindowState.Minimized) {
5365 MapWindow(hwnd, WindowType.Both);
5366 } else if (current_state == FormWindowState.Maximized) {
5367 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5374 case FormWindowState.Minimized: {
5376 if (current_state == FormWindowState.Maximized) {
5377 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5379 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5384 case FormWindowState.Maximized: {
5386 if (current_state == FormWindowState.Minimized) {
5387 MapWindow(hwnd, WindowType.Both);
5390 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5398 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5401 hwnd = Hwnd.ObjectFromHandle(handle);
5402 SetHwndStyles(hwnd, cp);
5403 SetWMStyles(hwnd, cp);
5406 internal override double GetWindowTransparency(IntPtr handle)
5411 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5415 hwnd = Hwnd.ObjectFromHandle(handle);
5421 hwnd.opacity = (uint)(0xffffffff * transparency);
5422 opacity = (IntPtr)((int)hwnd.opacity);
5424 IntPtr w = hwnd.whole_window;
5425 if (hwnd.reparented)
5426 w = XGetParent (hwnd.whole_window);
5427 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5430 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5431 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5439 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5442 } else if (!bottom) {
5443 Hwnd after_hwnd = null;
5445 if (after_handle != IntPtr.Zero) {
5446 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5449 XWindowChanges values = new XWindowChanges();
5451 if (after_hwnd == null) {
5452 // Work around metacity 'issues'
5456 atoms[0] = unixtime();
5457 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5459 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5460 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5462 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5465 values.sibling = after_hwnd.whole_window;
5466 values.stack_mode = StackMode.Below;
5469 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5474 XLowerWindow(DisplayHandle, hwnd.whole_window);
5481 internal override void ShowCursor(bool show) {
5482 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5485 internal override object StartLoop(Thread thread) {
5486 XEventQueue q = ThreadQueue(thread);
5490 internal override TransparencySupport SupportsTransparency() {
5491 // We need to check if the x compositing manager is running
5492 return TransparencySupport.Set;
5495 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5496 GetSystrayManagerWindow();
5498 if (SystrayMgrWindow != IntPtr.Zero) {
5499 XSizeHints size_hints;
5502 hwnd = Hwnd.ObjectFromHandle(handle);
5504 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5508 if (hwnd.client_window != hwnd.whole_window) {
5509 XDestroyWindow(DisplayHandle, hwnd.client_window);
5510 hwnd.client_window = hwnd.whole_window;
5513 /* by virtue of the way the tests are ordered when determining if it's PAINT
5514 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5515 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5516 there's a pending expose). */
5517 if (hwnd.nc_expose_pending) {
5518 hwnd.nc_expose_pending = false;
5519 if (!hwnd.expose_pending)
5520 hwnd.Queue.Paint.Remove (hwnd);
5523 size_hints = new XSizeHints();
5525 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5527 size_hints.min_width = 24;
5528 size_hints.min_height = 24;
5529 size_hints.max_width = 24;
5530 size_hints.max_height = 24;
5531 size_hints.base_width = 24;
5532 size_hints.base_height = 24;
5534 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5536 int[] atoms = new int[2];
5537 atoms [0] = 1; // Version 1
5538 atoms [1] = 1; // we want to be mapped
5540 // This line cost me 3 days...
5541 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5543 // Need to pick some reasonable defaults
5545 tt.AutomaticDelay = 350;
5546 tt.InitialDelay = 250;
5547 tt.ReshowDelay = 250;
5548 tt.ShowAlways = true;
5550 if ((tip != null) && (tip != string.Empty)) {
5551 tt.SetToolTip(Control.FromHandle(handle), tip);
5557 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5565 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5568 control = Control.FromHandle(handle);
5569 if (control != null && tt != null) {
5570 tt.SetToolTip(control, tip);
5578 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5580 SetVisible (handle, false, false);
5582 // The caller can now re-dock it later...
5590 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5592 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5593 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5597 internal override bool Text(IntPtr handle, string text) {
5600 hwnd = Hwnd.ObjectFromHandle(handle);
5603 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5604 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5606 // XXX this has problems with UTF8.
5607 // we need to either use the actual
5608 // text if it's latin-1, or convert it
5609 // to compound text if it's in a
5610 // different charset.
5611 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5616 internal override bool TranslateMessage(ref MSG msg) {
5617 return Keyboard.TranslateMessage (ref msg);
5620 internal override void UpdateWindow(IntPtr handle) {
5623 hwnd = Hwnd.ObjectFromHandle(handle);
5625 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5629 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5630 hwnd.Queue.Paint.Remove(hwnd);
5633 internal override void CreateOffscreenDrawable (IntPtr handle,
5634 int width, int height,
5635 out object offscreen_drawable)
5638 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5640 XGetGeometry (DisplayHandle, handle,
5642 out x_out, out y_out,
5643 out width_out, out height_out,
5644 out border_width_out, out depth_out);
5646 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5648 offscreen_drawable = pixmap;
5652 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5654 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5657 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5659 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5662 internal override void BlitFromOffscreen (IntPtr dest_handle,
5664 object offscreen_drawable,
5665 Graphics offscreen_dc,
5668 XGCValues gc_values;
5671 gc_values = new XGCValues();
5673 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5675 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5676 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5678 XFreeGC (DisplayHandle, gc);
5681 #endregion // Public Static Methods
5684 internal override event EventHandler Idle;
5685 #endregion // Events
5687 #region Xcursor imports
5688 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5689 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5691 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5692 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5694 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5695 internal extern static void XcursorImagesDestroy (IntPtr images);
5697 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5698 internal extern static int XcursorGetDefaultSize (IntPtr display);
5700 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5701 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5703 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5704 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5707 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5708 internal extern static IntPtr XOpenDisplay(IntPtr display);
5709 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5710 internal extern static int XCloseDisplay(IntPtr display);
5711 [DllImport ("libX11", EntryPoint="XSynchronize")]
5712 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5714 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5715 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);
5716 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5717 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5718 [DllImport ("libX11", EntryPoint="XMapWindow")]
5719 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5720 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5721 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5722 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5723 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5724 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5725 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5726 [DllImport ("libX11", EntryPoint="XRootWindow")]
5727 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5728 [DllImport ("libX11", EntryPoint="XNextEvent")]
5729 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5730 [DllImport ("libX11")]
5731 internal extern static int XConnectionNumber (IntPtr diplay);
5732 [DllImport ("libX11")]
5733 internal extern static int XPending (IntPtr diplay);
5734 [DllImport ("libX11", EntryPoint="XSelectInput")]
5735 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5737 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5738 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5740 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5741 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5742 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5743 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5745 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5746 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5748 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5749 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5751 [DllImport ("libX11", EntryPoint="XFlush")]
5752 internal extern static int XFlush(IntPtr display);
5754 [DllImport ("libX11", EntryPoint="XSetWMName")]
5755 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5757 [DllImport ("libX11", EntryPoint="XStoreName")]
5758 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5760 [DllImport ("libX11", EntryPoint="XFetchName")]
5761 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5763 [DllImport ("libX11", EntryPoint="XSendEvent")]
5764 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5766 [DllImport ("libX11", EntryPoint="XQueryTree")]
5767 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);
5769 [DllImport ("libX11", EntryPoint="XFree")]
5770 internal extern static int XFree(IntPtr data);
5772 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5773 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5775 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5776 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5778 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5779 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5781 [DllImport ("libX11", EntryPoint="XInternAtom")]
5782 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5784 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5785 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5787 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5788 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5790 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5791 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);
5793 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5794 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5796 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5797 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);
5799 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5800 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);
5802 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5803 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);
5805 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5806 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);
5808 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5809 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);
5811 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5812 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);
5814 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5815 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);
5817 [DllImport ("libX11", EntryPoint="XClearWindow")]
5818 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5820 [DllImport ("libX11", EntryPoint="XClearArea")]
5821 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5824 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5825 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5827 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5828 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5830 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5831 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5833 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5834 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5836 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5837 internal extern static int XDefaultScreen(IntPtr display);
5839 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5840 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5842 [DllImport ("libX11", EntryPoint="XLookupColor")]
5843 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5845 [DllImport ("libX11", EntryPoint="XAllocColor")]
5846 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5848 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5849 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5851 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5852 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5854 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5855 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5857 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5858 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5860 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5861 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5863 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5864 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5866 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5867 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5869 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5870 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5872 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5873 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5875 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5876 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5879 [DllImport ("libX11", EntryPoint="XCreateGC")]
5880 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5882 [DllImport ("libX11", EntryPoint="XFreeGC")]
5883 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5885 [DllImport ("libX11", EntryPoint="XSetFunction")]
5886 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5888 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5889 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5891 [DllImport ("libX11", EntryPoint="XDrawLine")]
5892 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5894 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5895 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5897 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5898 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5900 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5901 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5903 [DllImport ("libX11", EntryPoint="XCopyArea")]
5904 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);
5906 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5907 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);
5909 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5910 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5912 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5913 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5915 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5916 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5918 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5919 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5921 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5922 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5924 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5925 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5927 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5928 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);
5930 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5931 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5933 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5934 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5936 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5937 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5939 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5940 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5942 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5943 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5945 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5946 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5948 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5949 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5951 [DllImport ("libX11", EntryPoint="XGrabServer")]
5952 internal extern static void XGrabServer(IntPtr display);
5954 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5955 internal extern static void XUngrabServer(IntPtr display);
5957 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5958 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5960 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5961 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5963 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5964 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5966 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5967 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5969 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5970 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5972 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5973 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5975 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5976 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5978 [DllImport ("libX11", EntryPoint="XInitThreads")]
5979 internal extern static int XInitThreads();
5981 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5982 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5984 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5985 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5987 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5988 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5990 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5991 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5993 [DllImport ("libX11", EntryPoint="XSetForeground")]
5994 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5996 [DllImport ("libX11", EntryPoint="XSetBackground")]
5997 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5999 [DllImport ("libX11", EntryPoint="XBell")]
6000 internal extern static int XBell(IntPtr display, int percent);
6002 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6003 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6005 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6006 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6008 [DllImport ("libX11")]
6009 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6011 [DllImport ("libX11")]
6012 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);