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)
769 * If this is a form with no window manager, X is handling all the border and caption painting
770 * so remove that from the area (since the area we set of the window here is the part of the window
771 * we're painting in only)
773 Rectangle rect = hwnd.ClientRect;
774 Form form = Control.FromHandle (hwnd.Handle) as Form;
775 if (form != null && form.window_manager == null) {
776 CreateParams cp = form.GetCreateParams ();
777 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
778 Rectangle xrect = rect;
780 xrect.Y -= borders.top;
781 xrect.X -= borders.left;
782 xrect.Width += borders.left + borders.right;
783 xrect.Height += borders.top + borders.bottom;
790 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
793 * If this is a form with no window manager, X is handling all the border and caption painting
794 * so remove that from the area (since the area we set of the window here is the part of the window
795 * we're painting in only)
797 Size rect = new Size (cp.Width, cp.Height);
798 Form form = cp.control as Form;
799 if (form != null && form.window_manager == null) {
800 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
803 xrect.Width -= borders.left + borders.right;
804 xrect.Height -= borders.top + borders.bottom;
808 if (rect.Height == 0)
815 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
818 * If this is a form with no window manager, X is handling all the border and caption painting
819 * so remove that from the area (since the area we set of the window here is the part of the window
820 * we're painting in only)
822 Size rect = new Size (xWidth, xHeight);
823 Form form = cp.control as Form;
824 if (form != null && form.window_manager == null) {
825 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
828 xrect.Width += borders.left + borders.right;
829 xrect.Height += borders.top + borders.bottom;
836 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) {
839 tool_caption_height = 19;
840 border_static = false;
842 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
843 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
844 border_style = FormBorderStyle.Fixed3D;
845 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
846 border_style = FormBorderStyle.Fixed3D;
847 border_static = true;
848 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
849 border_style = FormBorderStyle.None;
851 border_style = FormBorderStyle.FixedSingle;
853 title_style = TitleStyle.None;
855 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
857 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
858 title_style = TitleStyle.Tool;
860 title_style = TitleStyle.Normal;
864 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
867 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
868 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
869 border_style = (FormBorderStyle) 0xFFFF;
871 border_style = FormBorderStyle.None;
876 title_style = TitleStyle.None;
877 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
878 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
879 title_style = TitleStyle.Tool;
881 title_style = TitleStyle.Normal;
885 border_style = FormBorderStyle.None;
887 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
888 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
889 border_style = FormBorderStyle.SizableToolWindow;
891 border_style = FormBorderStyle.Sizable;
894 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
895 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
896 border_style = FormBorderStyle.Fixed3D;
897 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
898 border_style = FormBorderStyle.Fixed3D;
899 border_static = true;
900 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
901 border_style = FormBorderStyle.FixedDialog;
902 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
903 border_style = FormBorderStyle.FixedToolWindow;
904 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
905 border_style = FormBorderStyle.FixedSingle;
908 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
909 border_style = FormBorderStyle.FixedSingle;
916 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
917 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);
920 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
921 MotifWmHints mwmHints;
922 MotifFunctions functions;
923 MotifDecorations decorations;
926 Rectangle client_rect;
928 // Windows we manage ourselves don't need WM window styles.
929 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
934 mwmHints = new MotifWmHints();
938 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
939 mwmHints.functions = (IntPtr)0;
940 mwmHints.decorations = (IntPtr)0;
942 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW) || (cp.control is Form && (cp.control as Form).FormBorderStyle == FormBorderStyle.None)) {
943 /* tool windows get no window manager
947 /* just because the window doesn't get any decorations doesn't
948 mean we should disable the functions. for instance, without
949 MotifFunctions.Maximize, changing the windowstate to Maximized
950 is ignored by metacity. */
951 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
954 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
955 functions |= MotifFunctions.Move;
956 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
959 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
960 functions |= MotifFunctions.Move | MotifFunctions.Resize;
961 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
964 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
965 functions |= MotifFunctions.Minimize;
966 decorations |= MotifDecorations.Minimize;
969 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
970 functions |= MotifFunctions.Maximize;
971 decorations |= MotifDecorations.Maximize;
974 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
975 functions |= MotifFunctions.Resize;
976 decorations |= MotifDecorations.ResizeH;
979 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
980 decorations |= MotifDecorations.Border;
983 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
984 decorations |= MotifDecorations.Border;
987 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
988 decorations |= MotifDecorations.Border;
991 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
992 functions |= MotifFunctions.Close;
995 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
996 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
997 if (cp.Caption == "") {
998 functions &= ~MotifFunctions.Move;
999 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1004 if ((functions & MotifFunctions.Resize) == 0) {
1005 hwnd.fixed_size = true;
1006 XplatUI.SetWindowMinMax(hwnd.Handle, new Rectangle(cp.X, cp.Y, cp.Width, cp.Height), new Size(cp.Width, cp.Height), new Size(cp.Width, cp.Height));
1008 hwnd.fixed_size = false;
1011 mwmHints.functions = (IntPtr)functions;
1012 mwmHints.decorations = (IntPtr)decorations;
1014 FormWindowState current_state = GetWindowState (hwnd.Handle);
1015 if (current_state == (FormWindowState)(-1))
1016 current_state = FormWindowState.Normal;
1018 client_rect = hwnd.ClientRect;
1022 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1023 // and get those windows in front of their parents
1024 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1025 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
1026 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
1027 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1029 Form f = Control.FromHandle(hwnd.Handle) as Form;
1030 if (f != null && !hwnd.reparented) {
1031 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
1032 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
1033 if (owner_hwnd != null)
1034 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
1035 owner_hwnd.whole_window);
1040 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1041 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1042 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
1043 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1045 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
1046 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
1047 /* this line keeps the window from showing up in gnome's taskbar */
1048 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1050 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
1051 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1053 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1054 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1057 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1058 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1060 /* we need to add these atoms in the
1061 * event we're maximized, since we're
1062 * replacing the existing
1063 * _NET_WM_STATE here. If we don't
1064 * add them, future calls to
1065 * GetWindowState will return Normal
1066 * for a window which is maximized. */
1067 if (current_state == FormWindowState.Maximized) {
1068 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1069 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1071 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1074 IntPtr[] atom_ptrs = new IntPtr[2];
1075 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1076 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1077 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1080 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1084 private void SetIcon(Hwnd hwnd, Icon icon)
1089 // This really needs to do whatever it
1090 // takes to remove the window manager
1091 // menu, not just delete the ICON
1092 // property. This will cause metacity
1093 // to use the "no icon set" icon, and
1094 // we'll still have an icon.
1095 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1103 bitmap = icon.ToBitmap();
1105 size = bitmap.Width * bitmap.Height + 2;
1106 data = new IntPtr[size];
1108 data[index++] = (IntPtr)bitmap.Width;
1109 data[index++] = (IntPtr)bitmap.Height;
1111 for (int y = 0; y < bitmap.Height; y++) {
1112 for (int x = 0; x < bitmap.Width; x++) {
1113 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1117 XChangeProperty (DisplayHandle, hwnd.whole_window,
1118 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1119 PropertyMode.Replace, data, size);
1123 private void WakeupMain () {
1124 wake.Send (new byte [] { 0xFF });
1127 private XEventQueue ThreadQueue(Thread thread) {
1130 queue = (XEventQueue)MessageQueues[thread];
1131 if (queue == null) {
1132 queue = new XEventQueue(thread);
1133 MessageQueues[thread] = queue;
1139 private void TranslatePropertyToClipboard(IntPtr property) {
1144 IntPtr prop = IntPtr.Zero;
1146 Clipboard.Item = null;
1148 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);
1150 if ((long)nitems > 0) {
1151 if (property == (IntPtr)Atom.XA_STRING) {
1152 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1153 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1154 // FIXME - convert bitmap to image
1155 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1156 // FIXME - convert pixmap to image
1157 } else if (property == OEMTEXT) {
1158 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1159 } else if (property == UNICODETEXT) {
1160 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1167 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1169 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1173 // Keep the invalid area as small as needed
1174 if ((x + width) > hwnd.width) {
1175 width = hwnd.width - x;
1178 if ((y + height) > hwnd.height) {
1179 height = hwnd.height - y;
1183 hwnd.AddInvalidArea(x, y, width, height);
1184 if (!hwnd.expose_pending) {
1185 if (!hwnd.nc_expose_pending) {
1186 hwnd.Queue.Paint.Enqueue(hwnd);
1188 hwnd.expose_pending = true;
1191 hwnd.AddNcInvalidArea (x, y, width, height);
1193 if (!hwnd.nc_expose_pending) {
1194 if (!hwnd.expose_pending) {
1195 hwnd.Queue.Paint.Enqueue(hwnd);
1197 hwnd.nc_expose_pending = true;
1202 private void FrameExtents(IntPtr window, out int left, out int top) {
1207 IntPtr prop = IntPtr.Zero;
1209 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);
1210 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1211 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1212 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1213 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1214 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1220 if (prop != IntPtr.Zero) {
1226 private void AddConfigureNotify (XEvent xevent) {
1229 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1232 if (hwnd == null || hwnd.zombie) {
1236 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1237 if (hwnd.parent == null) {
1238 // This sucks ass, part 1
1239 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1240 // no standard way of getting our adjustment.
1241 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1242 // Several other WMs do their decorations different yet again and we fail to deal
1243 // with that, since I couldn't find any frigging commonality between them.
1244 // The only sane WM seems to be KDE
1246 if (!xevent.ConfigureEvent.send_event) {
1249 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1251 // This is a synthetic event, coordinates are in root space
1252 hwnd.x = xevent.ConfigureEvent.x;
1253 hwnd.y = xevent.ConfigureEvent.y;
1254 if (hwnd.whacky_wm) {
1258 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1259 hwnd.x -= frame_left;
1260 hwnd.y -= frame_top;
1265 // XXX this sucks. this isn't thread safe
1266 Control ctrl = Control.FromHandle (hwnd.Handle);
1267 Size TranslatedSize;
1269 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1271 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1273 hwnd.width = TranslatedSize.Width;
1274 hwnd.height = TranslatedSize.Height;
1275 hwnd.ClientRect = Rectangle.Empty;
1277 lock (hwnd.configure_lock) {
1278 if (!hwnd.configure_pending) {
1279 hwnd.Queue.EnqueueLocked (xevent);
1280 hwnd.configure_pending = true;
1284 // We drop configure events for Client windows
1287 private void ShowCaret() {
1288 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1294 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1298 private void HideCaret() {
1299 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1305 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1309 private int NextTimeout (ArrayList timers, DateTime now) {
1310 int timeout = Int32.MaxValue;
1312 foreach (Timer timer in timers) {
1313 int next = (int) (timer.Expires - now).TotalMilliseconds;
1315 return 0; // Have a timer that has already expired
1318 if (next < timeout) {
1322 if (timeout < Timer.Minimum) {
1323 timeout = Timer.Minimum;
1331 private void CheckTimers (ArrayList timers, DateTime now) {
1334 count = timers.Count;
1339 for (int i = 0; i < timers.Count; i++) {
1342 timer = (Timer) timers [i];
1344 if (timer.Enabled && timer.Expires <= now) {
1351 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1352 MSG msg = new MSG ();
1355 queue = ThreadQueue(Thread.CurrentThread);
1357 queue.DispatchIdle = false;
1361 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1362 if ((Msg)msg.message == Msg.WM_QUIT) {
1363 PostQuitMessage (0);
1367 if (msg.hwnd == hwnd.Handle) {
1368 if ((Msg)msg.message == message)
1370 else if ((Msg)msg.message == Msg.WM_DESTROY)
1374 TranslateMessage (ref msg);
1375 DispatchMessage (ref msg);
1380 queue.DispatchIdle = true;
1384 private void MapWindow(Hwnd hwnd, WindowType windows) {
1386 if (Control.FromHandle(hwnd.Handle) is Form) {
1387 Form f = Control.FromHandle(hwnd.Handle) as Form;
1388 if (f.WindowState == FormWindowState.Normal)
1389 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1392 // it's possible that our Hwnd is no
1393 // longer valid after making that
1394 // SendMessage call, so check here.
1398 bool need_to_wait = false;
1400 if ((windows & WindowType.Whole) != 0) {
1401 XMapWindow(DisplayHandle, hwnd.whole_window);
1403 if ((windows & WindowType.Client) != 0) {
1404 XMapWindow(DisplayHandle, hwnd.client_window);
1406 need_to_wait = true;
1411 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1412 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1416 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1418 if (Control.FromHandle(hwnd.Handle) is Form) {
1419 Form f = Control.FromHandle(hwnd.Handle) as Form;
1420 if (f.WindowState == FormWindowState.Normal)
1421 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1424 // it's possible that our Hwnd is no
1425 // longer valid after making that
1426 // SendMessage call, so check here.
1430 bool need_to_wait = false;
1432 if ((windows & WindowType.Client) != 0) {
1433 XUnmapWindow(DisplayHandle, hwnd.client_window);
1435 need_to_wait = true;
1437 if ((windows & WindowType.Whole) != 0) {
1438 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1441 hwnd.mapped = false;
1443 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1444 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1448 private void UpdateMessageQueue (XEventQueue queue) {
1453 now = DateTime.UtcNow;
1456 pending = XPending (DisplayHandle);
1460 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1461 Idle (this, EventArgs.Empty);
1465 pending = XPending (DisplayHandle);
1472 if (queue != null) {
1473 if (queue.Paint.Count > 0)
1476 timeout = NextTimeout (queue.timer_list, now);
1481 int length = pollfds.Length - 1;
1482 lock (wake_waiting_lock) {
1483 if (wake_waiting == false) {
1485 wake_waiting = true;
1489 Syscall.poll (pollfds, (uint)length, timeout);
1490 // Clean out buffer, so we're not busy-looping on the same data
1491 if (length == pollfds.Length) {
1492 if (pollfds[1].revents != 0)
1493 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1494 lock (wake_waiting_lock) {
1495 wake_waiting = false;
1500 pending = XPending (DisplayHandle);
1506 CheckTimers (queue.timer_list, now);
1509 XEvent xevent = new XEvent ();
1512 if (XPending (DisplayHandle) == 0)
1515 XNextEvent (DisplayHandle, ref xevent);
1517 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1518 if (XFilterEvent(ref xevent, FosterParent)) {
1524 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1528 switch (xevent.type) {
1529 case XEventName.Expose:
1530 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1533 case XEventName.SelectionClear: {
1534 // Should we do something?
1538 case XEventName.SelectionRequest: {
1539 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1543 sel_event = new XEvent();
1544 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1545 sel_event.SelectionEvent.send_event = true;
1546 sel_event.SelectionEvent.display = DisplayHandle;
1547 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1548 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1549 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1550 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1551 sel_event.SelectionEvent.property = IntPtr.Zero;
1553 // Seems that some apps support asking for supported types
1554 if (xevent.SelectionEvent.target == TARGETS) {
1561 if (Clipboard.Item is String) {
1562 atoms[atom_count++] = (int)Atom.XA_STRING;
1563 atoms[atom_count++] = (int)OEMTEXT;
1564 atoms[atom_count++] = (int)UNICODETEXT;
1565 } else if (Clipboard.Item is Image) {
1566 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1567 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1569 // FIXME - handle other types
1572 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1573 } else if (Clipboard.Item is string) {
1579 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1582 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1583 buffer = Marshal.AllocHGlobal(bytes.Length);
1584 buflen = bytes.Length;
1586 for (int i = 0; i < buflen; i++) {
1587 Marshal.WriteByte(buffer, i, bytes[i]);
1589 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1590 // FIXME - this should encode into ISO2022
1591 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1592 while (Marshal.ReadByte(buffer, buflen) != 0) {
1595 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1596 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1597 while (Marshal.ReadByte(buffer, buflen) != 0) {
1601 buffer = IntPtr.Zero;
1604 if (buffer != IntPtr.Zero) {
1605 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1606 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1607 Marshal.FreeHGlobal(buffer);
1609 } else if (Clipboard.Item is Image) {
1610 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1611 // FIXME - convert image and store as property
1612 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1613 // FIXME - convert image and store as property
1617 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1621 case XEventName.SelectionNotify: {
1622 if (Clipboard.Enumerating) {
1623 Clipboard.Enumerating = false;
1624 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1625 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1626 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1627 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1628 #if DriverDebugExtra
1629 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1633 } else if (Clipboard.Retrieving) {
1634 Clipboard.Retrieving = false;
1635 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1636 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1638 Clipboard.Item = null;
1641 Dnd.HandleSelectionNotifyEvent (ref xevent);
1646 case XEventName.KeyRelease:
1647 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1648 XEvent nextevent = new XEvent ();
1650 XPeekEvent (DisplayHandle, ref nextevent);
1652 if (nextevent.type == XEventName.KeyPress &&
1653 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1654 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1658 goto case XEventName.KeyPress;
1660 case XEventName.MotionNotify: {
1663 /* we can't do motion compression across threads, so just punt if we don't match up */
1664 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1665 peek = hwnd.Queue.Peek();
1666 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1670 goto case XEventName.KeyPress;
1673 case XEventName.KeyPress:
1674 case XEventName.ButtonPress:
1675 case XEventName.ButtonRelease:
1676 case XEventName.EnterNotify:
1677 case XEventName.LeaveNotify:
1678 case XEventName.CreateNotify:
1679 case XEventName.DestroyNotify:
1680 case XEventName.FocusIn:
1681 case XEventName.FocusOut:
1682 case XEventName.ClientMessage:
1683 case XEventName.ReparentNotify:
1684 case XEventName.MapNotify:
1685 case XEventName.UnmapNotify:
1686 hwnd.Queue.EnqueueLocked (xevent);
1689 case XEventName.ConfigureNotify:
1690 AddConfigureNotify(xevent);
1693 case XEventName.PropertyNotify:
1694 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1699 IntPtr prop = IntPtr.Zero;
1702 prev_active = ActiveWindow;
1703 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);
1704 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1705 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1708 if (prev_active != ActiveWindow) {
1709 if (prev_active != IntPtr.Zero) {
1710 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1712 if (ActiveWindow != IntPtr.Zero) {
1713 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1716 if (ModalWindows.Count == 0) {
1719 // Modality handling, if we are modal and the new active window is one
1720 // of ours but not the modal one, switch back to the modal window
1722 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1723 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1724 Activate((IntPtr)ModalWindows.Peek());
1731 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1732 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1733 hwnd.cached_window_state = (FormWindowState)(-1);
1741 private IntPtr GetMousewParam(int Delta) {
1744 if ((MouseState & MouseButtons.Left) != 0) {
1745 result |= (int)MsgButtons.MK_LBUTTON;
1748 if ((MouseState & MouseButtons.Middle) != 0) {
1749 result |= (int)MsgButtons.MK_MBUTTON;
1752 if ((MouseState & MouseButtons.Right) != 0) {
1753 result |= (int)MsgButtons.MK_RBUTTON;
1756 Keys mods = ModifierKeys;
1757 if ((mods & Keys.Control) != 0) {
1758 result |= (int)MsgButtons.MK_CONTROL;
1761 if ((mods & Keys.Shift) != 0) {
1762 result |= (int)MsgButtons.MK_SHIFT;
1765 result |= Delta << 16;
1767 return (IntPtr)result;
1769 private IntPtr XGetParent(IntPtr handle) {
1776 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1779 if (Children!=IntPtr.Zero) {
1787 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1789 // we need to workaround a problem with the
1790 // ordering of destruction of Drawables and
1791 // Pictures that exists between cairo and
1792 // RENDER on the server.
1793 if (error_event.request_code == (XRequest)render_major_opcode
1794 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1795 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1799 if (ErrorExceptions) {
1800 XUngrabPointer (display, IntPtr.Zero);
1801 throw new XException (error_event.display, error_event.resourceid,
1802 error_event.serial, error_event.error_code,
1803 error_event.request_code, error_event.minor_code);
1805 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1806 XException.GetMessage (error_event.display, error_event.resourceid,
1807 error_event.serial, error_event.error_code,
1808 error_event.request_code, error_event.minor_code),
1809 Environment.StackTrace);
1814 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1817 Control[] controls = c.Controls.GetAllControls ();
1819 if (c.IsHandleCreated && !c.IsDisposed) {
1820 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1822 #if DriverDebug || DriverDebugDestroy
1823 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1824 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1828 CleanupCachedWindows (hwnd);
1831 for (int i = 0; i < controls.Length; i ++) {
1832 AccumulateDestroyedHandles (controls[i], list);
1838 void CleanupCachedWindows (Hwnd hwnd)
1840 if (ActiveWindow == hwnd.Handle) {
1841 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1842 ActiveWindow = IntPtr.Zero;
1845 if (FocusWindow == hwnd.Handle) {
1846 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1847 FocusWindow = IntPtr.Zero;
1850 if (Grab.Hwnd == hwnd.Handle) {
1851 Grab.Hwnd = IntPtr.Zero;
1852 Grab.Confined = false;
1855 DestroyCaret (hwnd.Handle);
1858 private void PerformNCCalc(Hwnd hwnd) {
1859 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1863 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1865 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1866 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1868 ncp.rgrc1.left = rect.Left;
1869 ncp.rgrc1.top = rect.Top;
1870 ncp.rgrc1.right = rect.Right;
1871 ncp.rgrc1.bottom = rect.Bottom;
1873 Marshal.StructureToPtr(ncp, ptr, true);
1874 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1875 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1876 Marshal.FreeHGlobal(ptr);
1879 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1880 hwnd.ClientRect = rect;
1882 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1885 if ((rect.Width < 1) || (rect.Height < 1)) {
1886 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1888 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1892 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1894 #endregion // Private Methods
1897 private void MouseHover(object sender, EventArgs e) {
1901 HoverState.Timer.Enabled = false;
1903 if (HoverState.Window != IntPtr.Zero) {
1904 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1906 xevent = new XEvent ();
1908 xevent.type = XEventName.ClientMessage;
1909 xevent.ClientMessageEvent.display = DisplayHandle;
1910 xevent.ClientMessageEvent.window = HoverState.Window;
1911 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1912 xevent.ClientMessageEvent.format = 32;
1913 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1915 hwnd.Queue.EnqueueLocked (xevent);
1922 private void CaretCallback(object sender, EventArgs e) {
1926 Caret.On = !Caret.On;
1928 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1930 #endregion // Callbacks
1932 #region Public Properties
1934 internal override int Caption {
1940 internal override Size CursorSize {
1945 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1946 return new Size(x, y);
1948 return new Size(16, 16);
1953 internal override bool DragFullWindows {
1959 internal override Size DragSize {
1961 return new Size(4, 4);
1965 internal override Size FrameBorderSize {
1967 return new Size (4, 4);
1971 internal override Size IconSize {
1977 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1981 current = (long)list;
1984 size = new XIconSize();
1986 for (int i = 0; i < count; i++) {
1987 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1988 current += Marshal.SizeOf(size);
1990 // Look for our preferred size
1991 if (size.min_width == 32) {
1993 return new Size(32, 32);
1996 if (size.max_width == 32) {
1998 return new Size(32, 32);
2001 if (size.min_width < 32 && size.max_width > 32) {
2004 // check if we can fit one
2006 while (x < size.max_width) {
2007 x += size.width_inc;
2010 return new Size(32, 32);
2015 if (largest < size.max_width) {
2016 largest = size.max_width;
2020 // We didn't find a match or we wouldn't be here
2021 return new Size(largest, largest);
2024 return new Size(32, 32);
2029 internal override int KeyboardSpeed {
2032 // A lot harder: need to do:
2033 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2034 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2035 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2037 // And from that we can tell the repetition rate
2039 // Notice, the values must map to:
2040 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2046 internal override int KeyboardDelay {
2049 // Return values must range from 0 to 4, 0 meaning 250ms,
2050 // and 4 meaning 1000 ms.
2052 return 1; // ie, 500 ms
2056 internal override Size MaxWindowTrackSize {
2058 return new Size (WorkingArea.Width, WorkingArea.Height);
2062 internal override Size MinimizedWindowSize {
2064 return new Size(1, 1);
2068 internal override Size MinimizedWindowSpacingSize {
2070 return new Size(1, 1);
2074 internal override Size MinimumWindowSize {
2076 return new Size(1, 1);
2080 internal override Size MinWindowTrackSize {
2082 return new Size(1, 1);
2086 internal override Keys ModifierKeys {
2088 return Keyboard.ModifierKeys;
2092 internal override Size SmallIconSize {
2098 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2102 current = (long)list;
2105 size = new XIconSize();
2107 for (int i = 0; i < count; i++) {
2108 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2109 current += Marshal.SizeOf(size);
2111 // Look for our preferred size
2112 if (size.min_width == 16) {
2114 return new Size(16, 16);
2117 if (size.max_width == 16) {
2119 return new Size(16, 16);
2122 if (size.min_width < 16 && size.max_width > 16) {
2125 // check if we can fit one
2127 while (x < size.max_width) {
2128 x += size.width_inc;
2131 return new Size(16, 16);
2136 if (smallest == 0 || smallest > size.min_width) {
2137 smallest = size.min_width;
2141 // We didn't find a match or we wouldn't be here
2142 return new Size(smallest, smallest);
2145 return new Size(16, 16);
2150 internal override int MouseButtonCount {
2156 internal override bool MouseButtonsSwapped {
2158 return false; // FIXME - how to detect?
2162 internal override Point MousePosition {
2164 return mouse_position;
2168 internal override Size MouseHoverSize {
2170 return new Size (1, 1);
2174 internal override int MouseHoverTime {
2176 return HoverState.Interval;
2182 internal override bool MouseWheelPresent {
2184 return true; // FIXME - how to detect?
2188 internal override Rectangle VirtualScreen {
2194 IntPtr prop = IntPtr.Zero;
2198 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);
2199 if ((long)nitems < 2)
2202 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2203 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2207 return new Rectangle(0, 0, width, height);
2210 XWindowAttributes attributes=new XWindowAttributes();
2213 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2216 return new Rectangle(0, 0, attributes.width, attributes.height);
2220 internal override Rectangle WorkingArea {
2226 IntPtr prop = IntPtr.Zero;
2229 int current_desktop;
2233 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);
2234 if ((long)nitems < 1) {
2238 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2241 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);
2242 if ((long)nitems < 4 * current_desktop) {
2246 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2247 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2248 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2249 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2252 return new Rectangle(x, y, width, height);
2255 XWindowAttributes attributes=new XWindowAttributes();
2258 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2261 return new Rectangle(0, 0, attributes.width, attributes.height);
2265 internal override bool ThemesEnabled {
2267 return XplatUIX11.themes_enabled;
2272 #endregion // Public properties
2274 #region Public Static Methods
2275 internal override IntPtr InitializeDriver() {
2277 if (DisplayHandle==IntPtr.Zero) {
2278 SetDisplay(XOpenDisplay(IntPtr.Zero));
2284 internal override void ShutdownDriver(IntPtr token) {
2286 if (DisplayHandle!=IntPtr.Zero) {
2287 XCloseDisplay(DisplayHandle);
2288 DisplayHandle=IntPtr.Zero;
2293 internal override void EnableThemes() {
2294 themes_enabled = true;
2298 internal override void Activate(IntPtr handle) {
2301 hwnd = Hwnd.ObjectFromHandle(handle);
2305 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2306 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2309 // XRaiseWindow(DisplayHandle, handle);
2315 internal override void AudibleAlert() {
2316 XBell(DisplayHandle, 0);
2321 internal override void CaretVisible(IntPtr handle, bool visible) {
2322 if (Caret.Hwnd == handle) {
2324 if (!Caret.Visible) {
2325 Caret.Visible = true;
2327 Caret.Timer.Start();
2330 Caret.Visible = false;
2337 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2338 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2342 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2348 hwnd = Hwnd.ObjectFromHandle(handle);
2351 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2358 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2359 DataFormats.Format f;
2362 f = DataFormats.Format.List;
2364 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2368 Clipboard.Formats = new ArrayList();
2371 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2373 Clipboard.Enumerating = true;
2374 while (Clipboard.Enumerating) {
2375 UpdateMessageQueue(null);
2380 result = new int[Clipboard.Formats.Count];
2382 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2383 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2386 Clipboard.Formats = null;
2390 internal override void ClipboardClose(IntPtr handle) {
2391 if (handle != ClipMagic) {
2392 throw new ArgumentException("handle is not a valid clipboard handle");
2397 internal override int ClipboardGetID(IntPtr handle, string format) {
2398 if (handle != ClipMagic) {
2399 throw new ArgumentException("handle is not a valid clipboard handle");
2402 if (format == "Text" ) return (int)Atom.XA_STRING;
2403 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2404 //else if (format == "MetaFilePict" ) return 3;
2405 //else if (format == "SymbolicLink" ) return 4;
2406 //else if (format == "DataInterchangeFormat" ) return 5;
2407 //else if (format == "Tiff" ) return 6;
2408 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2409 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2410 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2411 //else if (format == "PenData" ) return 10;
2412 //else if (format == "RiffAudio" ) return 11;
2413 //else if (format == "WaveAudio" ) return 12;
2414 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2415 //else if (format == "EnhancedMetafile" ) return 14;
2416 //else if (format == "FileDrop" ) return 15;
2417 //else if (format == "Locale" ) return 16;
2419 return XInternAtom(DisplayHandle, format, false).ToInt32();
2422 internal override IntPtr ClipboardOpen(bool primary_selection) {
2423 if (!primary_selection)
2424 ClipMagic = CLIPBOARD;
2426 ClipMagic = PRIMARY;
2430 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2431 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2433 Clipboard.Retrieving = true;
2434 while (Clipboard.Retrieving) {
2435 UpdateMessageQueue(null);
2438 return Clipboard.Item;
2441 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2442 Clipboard.Item = obj;
2443 Clipboard.Type = type;
2444 Clipboard.Converter = converter;
2447 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2449 // Clearing the selection
2450 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2454 internal override void CreateCaret (IntPtr handle, int width, int height)
2456 XGCValues gc_values;
2459 hwnd = Hwnd.ObjectFromHandle(handle);
2461 if (Caret.Hwnd != IntPtr.Zero) {
2462 DestroyCaret(Caret.Hwnd);
2465 Caret.Hwnd = handle;
2466 Caret.Window = hwnd.client_window;
2467 Caret.Width = width;
2468 Caret.Height = height;
2469 Caret.Visible = false;
2472 gc_values = new XGCValues();
2473 gc_values.line_width = width;
2475 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2476 if (Caret.gc == IntPtr.Zero) {
2477 Caret.Hwnd = IntPtr.Zero;
2481 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2484 internal override IntPtr CreateWindow (CreateParams cp)
2486 XSetWindowAttributes Attributes;
2488 Hwnd parent_hwnd = null;
2493 IntPtr ParentHandle;
2495 IntPtr ClientWindow;
2496 Rectangle ClientRect;
2497 SetWindowValuemask ValueMask;
2502 Attributes = new XSetWindowAttributes();
2508 if (Width<1) Width=1;
2509 if (Height<1) Height=1;
2511 if (cp.Parent != IntPtr.Zero) {
2512 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2513 ParentHandle = parent_hwnd.client_window;
2515 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2516 // We need to use our foster parent window until this poor child gets it's parent assigned
2517 ParentHandle=FosterParent;
2519 ParentHandle=RootWindow;
2523 // Set the default location location for forms.
2524 Point previous, next;
2526 if (cp.control is Form) {
2527 if (parent_hwnd != null) {
2528 previous = parent_hwnd.previous_child_startup_location;
2529 within = parent_hwnd.client_rectangle;
2531 previous = Hwnd.previous_main_startup_location;
2532 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
2535 if (previous.X == int.MinValue || previous.Y == int.MinValue) {
2538 next = new Point (previous.X + 22, previous.Y + 22);
2541 if (!within.Contains (next.X * 3, next.Y * 3)) {
2545 if (next == Point.Empty && cp.Parent == IntPtr.Zero) {
2546 next = new Point (22, 22);
2549 if (parent_hwnd != null) {
2550 parent_hwnd.previous_child_startup_location = next;
2552 Hwnd.previous_main_startup_location = next;
2555 if (X == int.MinValue && Y == int.MinValue) {
2560 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2562 Attributes.bit_gravity = Gravity.NorthWestGravity;
2563 Attributes.win_gravity = Gravity.NorthWestGravity;
2565 // Save what's under the toolwindow
2566 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2567 Attributes.save_under = true;
2568 ValueMask |= SetWindowValuemask.SaveUnder;
2572 // If we're a popup without caption we override the WM
2573 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2574 Attributes.override_redirect = true;
2575 ValueMask |= SetWindowValuemask.OverrideRedirect;
2581 hwnd.height = Height;
2582 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2583 hwnd.initial_style = cp.WindowStyle;
2584 hwnd.initial_ex_style = cp.WindowExStyle;
2586 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2587 hwnd.enabled = false;
2590 ClientRect = hwnd.ClientRect;
2591 ClientWindow = IntPtr.Zero;
2594 Size TranslatedSize;
2595 TranslatedSize = TranslateWindowSizeToXWindowSize (cp);
2596 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, TranslatedSize.Width, TranslatedSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2597 if (WholeWindow != IntPtr.Zero) {
2598 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2600 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2601 ValueMask = SetWindowValuemask.ColorMap;
2602 Attributes.colormap = CustomColormap;
2604 Rectangle XClientRect = ClientRect;
2605 if (XClientRect.Height <= 0)
2606 XClientRect.Height = 1;
2607 if (XClientRect.Width <= 0)
2608 XClientRect.Width = 1;
2609 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);
2613 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2614 throw new Exception("Could not create X11 windows");
2617 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2618 hwnd.WholeWindow = WholeWindow;
2619 hwnd.ClientWindow = ClientWindow;
2621 #if DriverDebug || DriverDebugCreate
2622 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);
2625 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2626 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2629 hints = new XSizeHints();
2632 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2633 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2638 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2639 if (hwnd.whole_window != hwnd.client_window)
2640 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2643 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2645 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2646 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2648 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2651 SetWMStyles(hwnd, cp);
2653 // set the group leader
2654 XWMHints wm_hints = new XWMHints ();
2656 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2657 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2658 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2660 if (ParentHandle != RootWindow) {
2661 wm_hints.window_group = hwnd.whole_window;
2663 wm_hints.window_group = ParentHandle;
2667 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2670 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2671 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2672 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2673 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2676 // for now make all windows dnd enabled
2677 Dnd.SetAllowDrop (hwnd, true);
2679 // Set caption/window title
2680 Text(hwnd.Handle, cp.Caption);
2682 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2683 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2685 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2686 hwnd.visible = true;
2687 MapWindow(hwnd, WindowType.Both);
2688 if (!(Control.FromHandle(hwnd.Handle) is Form))
2689 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2695 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2696 CreateParams create_params = new CreateParams();
2698 create_params.Caption = "";
2699 create_params.X = X;
2700 create_params.Y = Y;
2701 create_params.Width = Width;
2702 create_params.Height = Height;
2704 create_params.ClassName=XplatUI.DefaultClassName;
2705 create_params.ClassStyle = 0;
2706 create_params.ExStyle=0;
2707 create_params.Parent=IntPtr.Zero;
2708 create_params.Param=0;
2710 return CreateWindow(create_params);
2713 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2715 Bitmap cursor_bitmap;
2723 IntPtr cursor_pixmap;
2730 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2734 // Win32 only allows creation cursors of a certain size
2735 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2736 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2737 cursor_mask = new Bitmap(mask, new Size(width, height));
2739 cursor_bitmap = bitmap;
2743 width = cursor_bitmap.Width;
2744 height = cursor_bitmap.Height;
2746 cursor_bits = new Byte[(width / 8) * height];
2747 mask_bits = new Byte[(width / 8) * height];
2749 for (int y = 0; y < height; y++) {
2750 for (int x = 0; x < width; x++) {
2751 c_pixel = cursor_bitmap.GetPixel(x, y);
2752 m_pixel = cursor_mask.GetPixel(x, y);
2754 and = c_pixel == cursor_pixel;
2755 xor = m_pixel == mask_pixel;
2759 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2760 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2761 } else if (and && !xor) {
2763 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2764 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2766 } else if (and && !xor) {
2768 } else if (and && xor) {
2771 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2772 // we want both to be 0 so nothing to be done
2773 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2774 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2780 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2781 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2785 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2786 fg.red = (ushort)65535;
2787 fg.green = (ushort)65535;
2788 fg.blue = (ushort)65535;
2790 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2792 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2794 XFreePixmap(DisplayHandle, cursor_pixmap);
2795 XFreePixmap(DisplayHandle, mask_pixmap);
2800 internal override IntPtr DefineStdCursor(StdCursor id) {
2801 CursorFontShape shape;
2804 // FIXME - define missing shapes
2807 case StdCursor.AppStarting: {
2808 shape = CursorFontShape.XC_watch;
2812 case StdCursor.Arrow: {
2813 shape = CursorFontShape.XC_top_left_arrow;
2817 case StdCursor.Cross: {
2818 shape = CursorFontShape.XC_crosshair;
2822 case StdCursor.Default: {
2823 shape = CursorFontShape.XC_top_left_arrow;
2827 case StdCursor.Hand: {
2828 shape = CursorFontShape.XC_hand1;
2832 case StdCursor.Help: {
2833 shape = CursorFontShape.XC_question_arrow;
2837 case StdCursor.HSplit: {
2838 shape = CursorFontShape.XC_sb_v_double_arrow;
2842 case StdCursor.IBeam: {
2843 shape = CursorFontShape.XC_xterm;
2847 case StdCursor.No: {
2848 shape = CursorFontShape.XC_circle;
2852 case StdCursor.NoMove2D: {
2853 shape = CursorFontShape.XC_fleur;
2857 case StdCursor.NoMoveHoriz: {
2858 shape = CursorFontShape.XC_fleur;
2862 case StdCursor.NoMoveVert: {
2863 shape = CursorFontShape.XC_fleur;
2867 case StdCursor.PanEast: {
2868 shape = CursorFontShape.XC_fleur;
2872 case StdCursor.PanNE: {
2873 shape = CursorFontShape.XC_fleur;
2877 case StdCursor.PanNorth: {
2878 shape = CursorFontShape.XC_fleur;
2882 case StdCursor.PanNW: {
2883 shape = CursorFontShape.XC_fleur;
2887 case StdCursor.PanSE: {
2888 shape = CursorFontShape.XC_fleur;
2892 case StdCursor.PanSouth: {
2893 shape = CursorFontShape.XC_fleur;
2897 case StdCursor.PanSW: {
2898 shape = CursorFontShape.XC_fleur;
2902 case StdCursor.PanWest: {
2903 shape = CursorFontShape.XC_sizing;
2907 case StdCursor.SizeAll: {
2908 shape = CursorFontShape.XC_fleur;
2912 case StdCursor.SizeNESW: {
2913 shape = CursorFontShape.XC_top_right_corner;
2917 case StdCursor.SizeNS: {
2918 shape = CursorFontShape.XC_sb_v_double_arrow;
2922 case StdCursor.SizeNWSE: {
2923 shape = CursorFontShape.XC_top_left_corner;
2927 case StdCursor.SizeWE: {
2928 shape = CursorFontShape.XC_sb_h_double_arrow;
2932 case StdCursor.UpArrow: {
2933 shape = CursorFontShape.XC_center_ptr;
2937 case StdCursor.VSplit: {
2938 shape = CursorFontShape.XC_sb_h_double_arrow;
2942 case StdCursor.WaitCursor: {
2943 shape = CursorFontShape.XC_watch;
2953 cursor = XCreateFontCursor(DisplayHandle, shape);
2958 internal override IntPtr DefWndProc(ref Message msg) {
2959 switch ((Msg)msg.Msg) {
2960 case Msg.WM_PAINT: {
2963 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2965 hwnd.expose_pending = false;
2971 case Msg.WM_NCPAINT: {
2974 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2976 hwnd.nc_expose_pending = false;
2982 case Msg.WM_NCCALCSIZE: {
2985 if (msg.WParam == (IntPtr)1) {
2986 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
2988 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
2989 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
2991 // Add all the stuff X is supposed to draw.
2992 Control ctrl = Control.FromHandle (hwnd.Handle);
2993 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
2995 ncp.rgrc1.top += rect.top;
2996 ncp.rgrc1.bottom -= rect.bottom;
2997 ncp.rgrc1.left += rect.left;
2998 ncp.rgrc1.right -= rect.right;
3000 Marshal.StructureToPtr (ncp, msg.LParam, true);
3006 case Msg.WM_CONTEXTMENU: {
3009 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3011 if ((hwnd != null) && (hwnd.parent != null)) {
3012 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3017 case Msg.WM_MOUSEWHEEL: {
3020 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3022 if ((hwnd != null) && (hwnd.parent != null)) {
3023 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3024 if (msg.Result == IntPtr.Zero) {
3031 case Msg.WM_SETCURSOR: {
3034 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3036 break; // not sure how this happens, but it does
3038 // Pass to parent window first
3039 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3041 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3044 if (msg.Result == IntPtr.Zero) {
3047 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3048 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3049 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3050 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3051 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3052 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3055 handle = Cursors.Default.handle;
3058 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3059 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3060 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3061 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3062 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3063 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3066 case HitTest.HTGROWBOX:
3067 case HitTest.HTSIZE:
3068 case HitTest.HTZOOM:
3069 case HitTest.HTVSCROLL:
3070 case HitTest.HTSYSMENU:
3071 case HitTest.HTREDUCE:
3072 case HitTest.HTNOWHERE:
3073 case HitTest.HTMAXBUTTON:
3074 case HitTest.HTMINBUTTON:
3075 case HitTest.HTMENU:
3076 case HitTest.HSCROLL:
3077 case HitTest.HTBOTTOM:
3078 case HitTest.HTCAPTION:
3079 case HitTest.HTCLIENT:
3080 case HitTest.HTCLOSE:
3082 default: handle = Cursors.Default.handle; break;
3084 SetCursor(msg.HWnd, handle);
3092 internal override void DestroyCaret(IntPtr handle) {
3093 if (Caret.Hwnd == handle) {
3094 if (Caret.Visible) {
3098 if (Caret.gc != IntPtr.Zero) {
3099 XFreeGC(DisplayHandle, Caret.gc);
3100 Caret.gc = IntPtr.Zero;
3102 Caret.Hwnd = IntPtr.Zero;
3103 Caret.Visible = false;
3108 internal override void DestroyCursor(IntPtr cursor) {
3110 XFreeCursor(DisplayHandle, cursor);
3114 internal override void DestroyWindow(IntPtr handle) {
3117 hwnd = Hwnd.ObjectFromHandle(handle);
3120 #if DriverDebug || DriverDebugDestroy
3121 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3126 #if DriverDebug || DriverDebugDestroy
3127 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3130 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3132 CleanupCachedWindows (hwnd);
3134 ArrayList windows = new ArrayList ();
3136 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3139 foreach (Hwnd h in windows) {
3140 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3145 if (hwnd.whole_window != IntPtr.Zero) {
3146 #if DriverDebug || DriverDebugDestroy
3147 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3149 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3151 else if (hwnd.client_window != IntPtr.Zero) {
3152 #if DriverDebug || DriverDebugDestroy
3153 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3155 XDestroyWindow(DisplayHandle, hwnd.client_window);
3161 internal override IntPtr DispatchMessage(ref MSG msg) {
3162 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3165 IntPtr GetReversibleScreenGC (Color backColor)
3167 XGCValues gc_values;
3171 XColor xcolor = new XColor();
3172 xcolor.red = (ushort)(backColor.R * 257);
3173 xcolor.green = (ushort)(backColor.G * 257);
3174 xcolor.blue = (ushort)(backColor.B * 257);
3175 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3176 pixel = (uint)xcolor.pixel.ToInt32();
3179 gc_values = new XGCValues();
3181 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3182 gc_values.foreground = (IntPtr)pixel;
3184 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3185 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3186 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3191 IntPtr GetReversibleControlGC (Control control, int line_width)
3193 XGCValues gc_values;
3196 gc_values = new XGCValues();
3198 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3199 gc_values.line_width = line_width;
3200 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3202 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3203 //mask = foreground ^ background;
3204 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3205 //XSetBackground(DisplayHandle, gc, background);
3206 //XSetFunction(DisplayHandle, gc, GXxor);
3207 //XSetPlaneMask(DisplayHandle, gc, mask);
3210 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3214 XColor xcolor = new XColor();
3216 xcolor.red = (ushort)(control.ForeColor.R * 257);
3217 xcolor.green = (ushort)(control.ForeColor.G * 257);
3218 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3219 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3220 foreground = (uint)xcolor.pixel.ToInt32();
3222 xcolor.red = (ushort)(control.BackColor.R * 257);
3223 xcolor.green = (ushort)(control.BackColor.G * 257);
3224 xcolor.blue = (ushort)(control.BackColor.B * 257);
3225 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3226 background = (uint)xcolor.pixel.ToInt32();
3228 uint mask = foreground ^ background;
3230 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3231 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3232 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3233 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3238 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3240 IntPtr gc = GetReversibleScreenGC (backColor);
3242 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3244 XFreeGC(DisplayHandle, gc);
3247 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3249 IntPtr gc = GetReversibleScreenGC (backColor);
3251 if (rectangle.Width < 0) {
3252 rectangle.X += rectangle.Width;
3253 rectangle.Width = -rectangle.Width;
3255 if (rectangle.Height < 0) {
3256 rectangle.Y += rectangle.Height;
3257 rectangle.Height = -rectangle.Height;
3261 GCLineStyle line_style = GCLineStyle.LineSolid;
3262 GCCapStyle cap_style = GCCapStyle.CapButt;
3263 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3266 case FrameStyle.Dashed:
3267 line_style = GCLineStyle.LineOnOffDash;
3269 case FrameStyle.Thick:
3274 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3276 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3278 XFreeGC(DisplayHandle, gc);
3281 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3283 IntPtr gc = GetReversibleScreenGC (backColor);
3285 if (rectangle.Width < 0) {
3286 rectangle.X += rectangle.Width;
3287 rectangle.Width = -rectangle.Width;
3289 if (rectangle.Height < 0) {
3290 rectangle.Y += rectangle.Height;
3291 rectangle.Height = -rectangle.Height;
3293 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3295 XFreeGC(DisplayHandle, gc);
3298 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3300 Control control = Control.FromHandle(handle);
3302 gc = GetReversibleControlGC (control, line_width);
3304 if ((rect.Width > 0) && (rect.Height > 0)) {
3305 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3307 if (rect.Width > 0) {
3308 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3310 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3313 XFreeGC(DisplayHandle, gc);
3316 internal override void DoEvents() {
3317 MSG msg = new MSG ();
3320 if (OverrideCursorHandle != IntPtr.Zero) {
3321 OverrideCursorHandle = IntPtr.Zero;
3324 queue = ThreadQueue(Thread.CurrentThread);
3326 queue.DispatchIdle = false;
3328 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3329 TranslateMessage (ref msg);
3330 DispatchMessage (ref msg);
3333 queue.DispatchIdle = true;
3336 internal override void EnableWindow(IntPtr handle, bool Enable) {
3339 hwnd = Hwnd.ObjectFromHandle(handle);
3341 hwnd.Enabled = Enable;
3345 internal override void EndLoop(Thread thread) {
3346 // This is where we one day will shut down the loop for the thread
3349 internal override IntPtr GetActive() {
3354 IntPtr prop = IntPtr.Zero;
3355 IntPtr active = IntPtr.Zero;
3357 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);
3358 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3359 active = (IntPtr)Marshal.ReadInt32(prop);
3363 if (active != IntPtr.Zero) {
3366 hwnd = Hwnd.GetObjectFromWindow(active);
3368 active = hwnd.Handle;
3370 active = IntPtr.Zero;
3376 internal override Region GetClipRegion(IntPtr handle) {
3379 hwnd = Hwnd.ObjectFromHandle(handle);
3381 return hwnd.UserClip;
3387 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3394 internal override void GetDisplaySize(out Size size) {
3395 XWindowAttributes attributes=new XWindowAttributes();
3398 // FIXME - use _NET_WM messages instead?
3399 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3402 size = new Size(attributes.width, attributes.height);
3405 internal override SizeF GetAutoScaleSize(Font font) {
3408 string magic_string = "The quick brown fox jumped over the lazy dog.";
3409 double magic_number = 44.549996948242189;
3411 g = Graphics.FromHwnd(FosterParent);
3413 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3414 return new SizeF(width, font.Height);
3417 internal override IntPtr GetParent(IntPtr handle) {
3420 hwnd = Hwnd.ObjectFromHandle(handle);
3421 if (hwnd != null && hwnd.parent != null) {
3422 return hwnd.parent.Handle;
3427 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3437 if (handle != IntPtr.Zero) {
3438 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3440 use_handle = RootWindow;
3444 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3447 if (handle != IntPtr.Zero) {
3456 internal override IntPtr GetFocus() {
3461 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3462 FontFamily ff = font.FontFamily;
3463 ascent = ff.GetCellAscent (font.Style);
3464 descent = ff.GetCellDescent (font.Style);
3468 internal override Point GetMenuOrigin(IntPtr handle) {
3471 hwnd = Hwnd.ObjectFromHandle(handle);
3474 return hwnd.MenuOrigin;
3479 [MonoTODO("Implement filtering")]
3480 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3487 if (((XEventQueue)queue_id).Count > 0) {
3488 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3490 UpdateMessageQueue ((XEventQueue)queue_id);
3492 if (((XEventQueue)queue_id).Count > 0) {
3493 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3494 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3495 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3497 msg.hwnd= IntPtr.Zero;
3498 msg.message = Msg.WM_ENTERIDLE;
3503 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3505 // Handle messages for windows that are already or are about to be destroyed.
3507 // we need a special block for this because unless we remove the hwnd from the paint
3508 // queue it will always stay there (since we don't handle the expose), and we'll
3509 // effectively loop infinitely trying to repaint a non-existant window.
3510 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3511 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3512 hwnd.Queue.Paint.Remove (hwnd);
3513 goto ProcessNextMessage;
3516 // We need to make sure we only allow DestroyNotify events through for zombie
3517 // hwnds, since much of the event handling code makes requests using the hwnd's
3518 // client_window, and that'll result in BadWindow errors if there's some lag
3519 // between the XDestroyWindow call and the DestroyNotify event.
3520 if (hwnd == null || hwnd.zombie) {
3521 #if DriverDebug || DriverDebugDestroy
3522 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3524 goto ProcessNextMessage;
3527 if (hwnd.client_window == xevent.AnyEvent.window) {
3529 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3532 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3535 msg.hwnd = hwnd.Handle;
3538 // If you add a new event to this switch make sure to add it in
3539 // UpdateMessage also unless it is not coming through the X event system.
3541 switch(xevent.type) {
3542 case XEventName.KeyPress: {
3544 Dnd.HandleKeyPress (ref xevent);
3545 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3549 case XEventName.KeyRelease: {
3550 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3554 case XEventName.ButtonPress: {
3555 switch(xevent.ButtonEvent.button) {
3557 MouseState |= MouseButtons.Left;
3559 msg.message = Msg.WM_LBUTTONDOWN;
3561 msg.message = Msg.WM_NCLBUTTONDOWN;
3562 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3564 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3565 msg.wParam=GetMousewParam(0);
3570 MouseState |= MouseButtons.Middle;
3572 msg.message = Msg.WM_MBUTTONDOWN;
3574 msg.message = Msg.WM_NCMBUTTONDOWN;
3575 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3577 msg.wParam=GetMousewParam(0);
3582 MouseState |= MouseButtons.Right;
3584 msg.message = Msg.WM_RBUTTONDOWN;
3586 msg.message = Msg.WM_NCRBUTTONDOWN;
3587 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3589 msg.wParam=GetMousewParam(0);
3594 msg.hwnd = FocusWindow;
3595 msg.message=Msg.WM_MOUSEWHEEL;
3596 msg.wParam=GetMousewParam(120);
3601 msg.hwnd = FocusWindow;
3602 msg.message=Msg.WM_MOUSEWHEEL;
3603 msg.wParam=GetMousewParam(-120);
3609 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3610 mouse_position.X = xevent.ButtonEvent.x;
3611 mouse_position.Y = xevent.ButtonEvent.y;
3613 if (!hwnd.Enabled) {
3616 msg.hwnd = hwnd.EnabledHwnd;
3617 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);
3618 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3621 if (Grab.Hwnd != IntPtr.Zero) {
3622 msg.hwnd = Grab.Hwnd;
3625 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3626 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3627 switch(xevent.ButtonEvent.button) {
3629 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3634 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3639 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3643 ClickPending.Pending = false;
3645 ClickPending.Pending = true;
3646 ClickPending.Hwnd = msg.hwnd;
3647 ClickPending.Message = msg.message;
3648 ClickPending.wParam = msg.wParam;
3649 ClickPending.lParam = msg.lParam;
3650 ClickPending.Time = (long)xevent.ButtonEvent.time;
3653 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3654 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3656 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3657 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3658 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3659 XEvent motionEvent = new XEvent ();
3660 motionEvent.type = XEventName.MotionNotify;
3661 motionEvent.MotionEvent.display = DisplayHandle;
3662 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3663 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3664 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3665 hwnd.Queue.EnqueueLocked (motionEvent);
3671 case XEventName.ButtonRelease: {
3673 if (Dnd.HandleButtonRelease (ref xevent)) {
3676 // Allow the LBUTTONUP message to get through
3679 switch(xevent.ButtonEvent.button) {
3682 msg.message = Msg.WM_LBUTTONUP;
3684 msg.message = Msg.WM_NCLBUTTONUP;
3685 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3687 MouseState &= ~MouseButtons.Left;
3688 msg.wParam=GetMousewParam(0);
3694 msg.message = Msg.WM_MBUTTONUP;
3696 msg.message = Msg.WM_NCMBUTTONUP;
3697 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3699 MouseState &= ~MouseButtons.Middle;
3700 msg.wParam=GetMousewParam(0);
3706 msg.message = Msg.WM_RBUTTONUP;
3708 msg.message = Msg.WM_NCRBUTTONUP;
3709 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3711 MouseState &= ~MouseButtons.Right;
3712 msg.wParam=GetMousewParam(0);
3717 goto ProcessNextMessage;
3721 goto ProcessNextMessage;
3725 if (!hwnd.Enabled) {
3728 msg.hwnd = hwnd.EnabledHwnd;
3729 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);
3730 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3733 if (Grab.Hwnd != IntPtr.Zero) {
3734 msg.hwnd = Grab.Hwnd;
3737 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3738 mouse_position.X = xevent.ButtonEvent.x;
3739 mouse_position.Y = xevent.ButtonEvent.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 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3745 XEvent motionEvent = new XEvent ();
3746 motionEvent.type = XEventName.MotionNotify;
3747 motionEvent.MotionEvent.display = DisplayHandle;
3748 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3749 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3750 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3751 hwnd.Queue.EnqueueLocked (motionEvent);
3756 case XEventName.MotionNotify: {
3758 #if DriverDebugExtra
3759 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);
3762 if (Dnd.HandleMotionNotify (ref xevent))
3763 goto ProcessNextMessage;
3764 if (Grab.Hwnd != IntPtr.Zero) {
3765 msg.hwnd = Grab.Hwnd;
3768 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3772 msg.message = Msg.WM_MOUSEMOVE;
3773 msg.wParam = GetMousewParam(0);
3774 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3776 if (!hwnd.Enabled) {
3779 msg.hwnd = hwnd.EnabledHwnd;
3780 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);
3781 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3784 mouse_position.X = xevent.MotionEvent.x;
3785 mouse_position.Y = xevent.MotionEvent.y;
3787 if ((HoverState.Timer.Enabled) &&
3788 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3789 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3790 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3791 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3792 HoverState.Timer.Stop();
3793 HoverState.Timer.Start();
3794 HoverState.X = mouse_position.X;
3795 HoverState.Y = mouse_position.Y;
3805 #if DriverDebugExtra
3806 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);
3808 msg.message = Msg.WM_NCMOUSEMOVE;
3810 if (!hwnd.Enabled) {
3811 msg.hwnd = hwnd.EnabledHwnd;
3812 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);
3813 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3816 // The hit test is sent in screen coordinates
3817 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3818 xevent.MotionEvent.x, xevent.MotionEvent.y,
3819 out screen_x, out screen_y, out dummy);
3821 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3822 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3823 IntPtr.Zero, msg.lParam).ToInt32 ();
3824 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3826 mouse_position.X = xevent.MotionEvent.x;
3827 mouse_position.Y = xevent.MotionEvent.y;
3833 case XEventName.EnterNotify: {
3834 if (!hwnd.Enabled) {
3835 goto ProcessNextMessage;
3837 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3838 goto ProcessNextMessage;
3840 msg.message = Msg.WM_MOUSE_ENTER;
3841 HoverState.X = xevent.CrossingEvent.x;
3842 HoverState.Y = xevent.CrossingEvent.y;
3843 HoverState.Timer.Enabled = true;
3844 HoverState.Window = xevent.CrossingEvent.window;
3848 case XEventName.LeaveNotify: {
3849 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3850 WindowUngrabbed (hwnd.Handle);
3851 goto ProcessNextMessage;
3853 if (!hwnd.Enabled) {
3854 goto ProcessNextMessage;
3856 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3857 goto ProcessNextMessage;
3859 msg.message=Msg.WM_MOUSELEAVE;
3860 HoverState.Timer.Enabled = false;
3861 HoverState.Window = IntPtr.Zero;
3866 case XEventName.CreateNotify: {
3867 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3868 msg.message = WM_CREATE;
3869 // Set up CreateStruct
3871 goto ProcessNextMessage;
3878 case XEventName.ReparentNotify: {
3879 if (hwnd.parent == null) { // Toplevel
3880 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3881 // We need to adjust x/y
3882 // This sucks ass, part 2
3883 // Every WM does the reparenting of toplevel windows different, so there's
3884 // no standard way of getting our adjustment considering frames/decorations
3885 // The code below is needed for metacity. KDE doesn't works just fine without this
3893 hwnd.Reparented = true;
3895 XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out new_x, out new_y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
3896 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3897 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3900 hwnd.whacky_wm = true;
3903 if (hwnd.opacity != 0xffffffff) {
3906 opacity = (IntPtr)(Int32)hwnd.opacity;
3907 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3909 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3910 goto ProcessNextMessage;
3912 hwnd.Reparented = false;
3913 goto ProcessNextMessage;
3916 goto ProcessNextMessage;
3919 case XEventName.ConfigureNotify: {
3920 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3921 #if DriverDebugExtra
3922 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);
3924 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3925 lock (hwnd.configure_lock) {
3926 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3927 hwnd.configure_pending = false;
3930 // We need to adjust our client window to track the resize of whole_window
3931 if (hwnd.whole_window != hwnd.client_window)
3932 PerformNCCalc(hwnd);
3935 goto ProcessNextMessage;
3938 case XEventName.FocusIn: {
3939 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3940 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3941 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3942 // about it having focus again
3943 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3944 goto ProcessNextMessage;
3947 if (FocusWindow == IntPtr.Zero) {
3948 Control c = Control.FromHandle (hwnd.client_window);
3950 goto ProcessNextMessage;
3951 Form form = c.FindForm ();
3953 goto ProcessNextMessage;
3954 if (ActiveWindow != form.Handle) {
3955 ActiveWindow = form.Handle;
3956 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3958 goto ProcessNextMessage;
3960 Keyboard.FocusIn(FocusWindow);
3961 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3962 goto ProcessNextMessage;
3965 case XEventName.FocusOut: {
3966 // Se the comment for our FocusIn handler
3967 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3968 goto ProcessNextMessage;
3970 Keyboard.FocusOut(FocusWindow);
3972 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3973 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3976 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3977 goto ProcessNextMessage;
3980 case XEventName.MapNotify: {
3981 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3983 msg.message = Msg.WM_SHOWWINDOW;
3984 msg.wParam = (IntPtr) 1;
3985 // XXX we're missing the lParam..
3988 goto ProcessNextMessage;
3991 case XEventName.UnmapNotify: {
3992 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3993 hwnd.mapped = false;
3994 msg.message = Msg.WM_SHOWWINDOW;
3995 msg.wParam = (IntPtr) 0;
3996 // XXX we're missing the lParam..
3999 goto ProcessNextMessage;
4002 case XEventName.Expose: {
4005 hwnd.expose_pending = false;
4007 hwnd.nc_expose_pending = false;
4009 goto ProcessNextMessage;
4013 if (!hwnd.expose_pending) {
4014 goto ProcessNextMessage;
4017 if (!hwnd.nc_expose_pending) {
4018 goto ProcessNextMessage;
4021 switch (hwnd.border_style) {
4022 case FormBorderStyle.Fixed3D: {
4025 g = Graphics.FromHwnd(hwnd.whole_window);
4026 if (hwnd.border_static)
4027 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4029 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4034 case FormBorderStyle.FixedSingle: {
4037 g = Graphics.FromHwnd(hwnd.whole_window);
4038 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4043 #if DriverDebugExtra
4044 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);
4047 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4048 Region region = new Region (rect);
4049 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4050 msg.message = Msg.WM_NCPAINT;
4051 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4052 msg.refobject = region;
4055 #if DriverDebugExtra
4056 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);
4058 if (Caret.Visible == true) {
4059 Caret.Paused = true;
4063 if (Caret.Visible == true) {
4065 Caret.Paused = false;
4067 msg.message = Msg.WM_PAINT;
4071 case XEventName.DestroyNotify: {
4073 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4074 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4076 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4077 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4078 CleanupCachedWindows (hwnd);
4080 #if DriverDebugDestroy
4081 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4084 msg.hwnd = hwnd.client_window;
4085 msg.message=Msg.WM_DESTROY;
4088 goto ProcessNextMessage;
4094 case XEventName.ClientMessage: {
4095 if (Dnd.HandleClientMessage (ref xevent)) {
4096 goto ProcessNextMessage;
4099 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4100 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4101 goto ProcessNextMessage;
4104 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4105 msg.message = Msg.WM_MOUSEHOVER;
4106 msg.wParam = GetMousewParam(0);
4107 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4111 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4112 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4113 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4114 msg.wParam = xevent.ClientMessageEvent.ptr3;
4115 msg.lParam = xevent.ClientMessageEvent.ptr4;
4116 if (msg.message == (Msg)Msg.WM_QUIT)
4122 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4123 #if DriverDebugXEmbed
4124 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4127 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4128 XSizeHints hints = new XSizeHints();
4131 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4133 hwnd.width = hints.max_width;
4134 hwnd.height = hints.max_height;
4135 hwnd.ClientRect = Rectangle.Empty;
4136 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4140 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4141 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4142 msg.message = Msg.WM_CLOSE;
4146 // We should not get this, but I'll leave the code in case we need it in the future
4147 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4148 goto ProcessNextMessage;
4151 goto ProcessNextMessage;
4155 goto ProcessNextMessage;
4162 internal override bool GetText(IntPtr handle, out string text) {
4169 IntPtr prop = IntPtr.Zero;
4171 XGetWindowProperty(DisplayHandle, handle,
4172 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4173 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4175 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4176 text = Marshal.PtrToStringUni (prop, (int)nitems);
4181 // fallback on the non-_NET property
4184 textptr = IntPtr.Zero;
4186 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4187 if (textptr != IntPtr.Zero) {
4188 text = Marshal.PtrToStringAnsi(textptr);
4199 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) {
4202 hwnd = Hwnd.ObjectFromHandle(handle);
4208 height = hwnd.height;
4210 PerformNCCalc(hwnd);
4212 client_width = hwnd.ClientRect.Width;
4213 client_height = hwnd.ClientRect.Height;
4218 // Should we throw an exception or fail silently?
4219 // throw new ArgumentException("Called with an invalid window handle", "handle");
4229 internal override FormWindowState GetWindowState(IntPtr handle) {
4232 hwnd = Hwnd.ObjectFromHandle(handle);
4234 if (hwnd.cached_window_state == (FormWindowState)(-1))
4235 hwnd.cached_window_state = UpdateWindowState (handle);
4237 return hwnd.cached_window_state;
4240 private FormWindowState UpdateWindowState (IntPtr handle) {
4245 IntPtr prop = IntPtr.Zero;
4249 XWindowAttributes attributes;
4252 hwnd = Hwnd.ObjectFromHandle(handle);
4256 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);
4257 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4258 for (int i = 0; i < (long)nitems; i++) {
4259 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4260 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4262 } else if (atom == _NET_WM_STATE_HIDDEN) {
4270 return FormWindowState.Minimized;
4271 } else if (maximized == 2) {
4272 return FormWindowState.Maximized;
4275 attributes = new XWindowAttributes();
4276 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4277 if (attributes.map_state == MapState.IsUnmapped) {
4278 return (FormWindowState)(-1);
4282 return FormWindowState.Normal;
4285 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4287 GrabConfined = Grab.Confined;
4288 GrabArea = Grab.Area;
4291 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4293 IntPtr confine_to_window;
4295 confine_to_window = IntPtr.Zero;
4297 if (confine_to_handle != IntPtr.Zero) {
4298 XWindowAttributes attributes = new XWindowAttributes();
4300 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4303 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4305 Grab.Area.X = attributes.x;
4306 Grab.Area.Y = attributes.y;
4307 Grab.Area.Width = attributes.width;
4308 Grab.Area.Height = attributes.height;
4309 Grab.Confined = true;
4310 confine_to_window = hwnd.client_window;
4315 hwnd = Hwnd.ObjectFromHandle(handle);
4318 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4319 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4320 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4321 EventMask.LeaveWindowMask,
4322 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4326 internal override void UngrabWindow(IntPtr hwnd) {
4328 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4329 XFlush(DisplayHandle);
4331 WindowUngrabbed (hwnd);
4334 private void WindowUngrabbed (IntPtr hwnd) {
4335 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4337 Grab.Hwnd = IntPtr.Zero;
4338 Grab.Confined = false;
4341 // lparam should be the handle to the window gaining the mouse capture,
4342 // but X doesn't seem to give us that information.
4343 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4344 // X will send a NotifyUngrab, but since it comes late sometimes we're
4345 // calling WindowUngrabbed directly from UngrabWindow in order to send
4346 // this WM right away.
4347 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4351 internal override void HandleException(Exception e) {
4352 StackTrace st = new StackTrace(e, true);
4353 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4354 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4357 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4360 hwnd = Hwnd.ObjectFromHandle(handle);
4363 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4365 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4369 internal override void InvalidateNC (IntPtr handle) {
4372 hwnd = Hwnd.ObjectFromHandle(handle);
4374 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4377 internal override bool IsEnabled(IntPtr handle) {
4378 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4379 return (hwnd != null && hwnd.Enabled);
4382 internal override bool IsVisible(IntPtr handle) {
4383 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4384 return (hwnd != null && hwnd.visible);
4387 internal override void KillTimer(Timer timer) {
4388 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4390 if (queue == null) {
4391 // This isn't really an error, MS doesn't start the timer if
4392 // it has no assosciated queue
4395 queue.timer_list.Remove (timer);
4398 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4404 hwnd = Hwnd.ObjectFromHandle(handle);
4407 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4414 internal override void OverrideCursor(IntPtr cursor)
4416 if (Grab.Hwnd != IntPtr.Zero) {
4417 XChangeActivePointerGrab (DisplayHandle,
4418 EventMask.ButtonMotionMask |
4419 EventMask.PointerMotionMask |
4420 EventMask.ButtonPressMask |
4421 EventMask.ButtonReleaseMask,
4422 cursor, IntPtr.Zero);
4426 OverrideCursorHandle = cursor;
4429 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4430 PaintEventArgs paint_event;
4433 hwnd = Hwnd.ObjectFromHandle(handle);
4435 if (Caret.Visible == true) {
4436 Caret.Paused = true;
4443 dc = Graphics.FromHwnd (hwnd.client_window);
4445 Region clip_region = new Region ();
4446 clip_region.MakeEmpty();
4448 foreach (Rectangle r in hwnd.ClipRectangles) {
4449 clip_region.Union (r);
4452 if (hwnd.UserClip != null) {
4453 clip_region.Intersect(hwnd.UserClip);
4456 dc.Clip = clip_region;
4457 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4458 hwnd.expose_pending = false;
4460 hwnd.ClearInvalidArea();
4462 hwnd.drawing_stack.Push (paint_event);
4463 hwnd.drawing_stack.Push (dc);
4467 dc = Graphics.FromHwnd (hwnd.whole_window);
4469 if (!hwnd.nc_invalid.IsEmpty) {
4470 dc.SetClip (hwnd.nc_invalid);
4471 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4473 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4475 hwnd.nc_expose_pending = false;
4477 hwnd.ClearNcInvalidArea ();
4479 hwnd.drawing_stack.Push (paint_event);
4480 hwnd.drawing_stack.Push (dc);
4486 internal override void PaintEventEnd(IntPtr handle, bool client) {
4489 hwnd = Hwnd.ObjectFromHandle(handle);
4491 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4495 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4496 pe.SetGraphics (null);
4499 if (Caret.Visible == true) {
4501 Caret.Paused = false;
4505 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4506 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4507 XEventQueue queue = (XEventQueue) queue_id;
4510 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4511 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4515 if (queue.Count > 0) {
4518 // Only call UpdateMessageQueue if real events are pending
4519 // otherwise we go to sleep on the socket
4520 if (XPending(DisplayHandle) != 0) {
4521 UpdateMessageQueue((XEventQueue)queue_id);
4523 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4528 CheckTimers(queue.timer_list, DateTime.UtcNow);
4533 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4536 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4537 XEvent xevent = new XEvent ();
4538 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4540 xevent.type = XEventName.ClientMessage;
4541 xevent.ClientMessageEvent.display = DisplayHandle;
4544 xevent.ClientMessageEvent.window = hwnd.whole_window;
4546 xevent.ClientMessageEvent.window = IntPtr.Zero;
4549 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4550 xevent.ClientMessageEvent.format = 32;
4551 xevent.ClientMessageEvent.ptr1 = handle;
4552 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4553 xevent.ClientMessageEvent.ptr3 = wparam;
4554 xevent.ClientMessageEvent.ptr4 = lparam;
4556 hwnd.Queue.EnqueueLocked (xevent);
4561 internal override void PostQuitMessage(int exitCode) {
4562 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4563 XFlush(DisplayHandle);
4566 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4571 internal override void RequestNCRecalc(IntPtr handle) {
4574 hwnd = Hwnd.ObjectFromHandle(handle);
4580 PerformNCCalc(hwnd);
4581 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4582 InvalidateNC(handle);
4585 internal override void ResetMouseHover(IntPtr handle) {
4588 hwnd = Hwnd.ObjectFromHandle(handle);
4593 HoverState.Timer.Enabled = true;
4594 HoverState.X = mouse_position.X;
4595 HoverState.Y = mouse_position.Y;
4596 HoverState.Window = handle;
4600 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4606 hwnd = Hwnd.ObjectFromHandle(handle);
4609 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4616 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4622 hwnd = Hwnd.ObjectFromHandle(handle);
4625 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4632 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4635 XGCValues gc_values;
4637 hwnd = Hwnd.ObjectFromHandle(handle);
4639 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4641 /* We have an invalid area in the window we're scrolling.
4642 Adjust our stored invalid rectangle to to match the scrolled amount */
4657 if (area.Contains (hwnd.Invalid))
4658 hwnd.ClearInvalidArea ();
4659 hwnd.AddInvalidArea(r);
4662 gc_values = new XGCValues();
4664 if (with_children) {
4665 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4668 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4676 height = area.Height - YAmount;
4677 dest_y = area.Y + YAmount;
4680 src_y = area.Y - YAmount;
4681 height = area.Height + YAmount;
4687 width = area.Width - XAmount;
4688 dest_x = area.X + XAmount;
4691 src_x = area.X - XAmount;
4692 width = area.Width + XAmount;
4696 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4698 // Generate an expose for the area exposed by the horizontal scroll
4699 // We don't use AddExpose since we're
4701 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4702 } else if (XAmount < 0) {
4703 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4706 // Generate an expose for the area exposed by the vertical scroll
4708 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4709 } else if (YAmount < 0) {
4710 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4712 XFreeGC(DisplayHandle, gc);
4715 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4719 hwnd = Hwnd.GetObjectFromWindow(handle);
4721 rect = hwnd.ClientRect;
4724 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4727 internal override void SendAsyncMethod (AsyncMethodData method) {
4729 XEvent xevent = new XEvent ();
4731 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4733 xevent.type = XEventName.ClientMessage;
4734 xevent.ClientMessageEvent.display = DisplayHandle;
4735 xevent.ClientMessageEvent.window = method.Handle;
4736 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4737 xevent.ClientMessageEvent.format = 32;
4738 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4740 hwnd.Queue.EnqueueLocked (xevent);
4745 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4747 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4750 h = Hwnd.ObjectFromHandle(hwnd);
4752 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4753 AsyncMethodResult result;
4754 AsyncMethodData data;
4756 result = new AsyncMethodResult ();
4757 data = new AsyncMethodData ();
4760 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4761 data.Args = new object[] { hwnd, message, wParam, lParam };
4762 data.Result = result;
4764 SendAsyncMethod (data);
4765 #if DriverDebug || DriverDebugThreads
4766 Console.WriteLine ("Sending {0} message across.", message);
4771 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4774 internal override int SendInput(IntPtr handle, Queue keys) {
4775 if (handle == IntPtr.Zero)
4778 int count = keys.Count;
4779 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4781 while (keys.Count > 0) {
4783 MSG msg = (MSG)keys.Dequeue();
4785 XEvent xevent = new XEvent ();
4787 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4788 xevent.KeyEvent.display = DisplayHandle;
4791 xevent.KeyEvent.window = hwnd.whole_window;
4793 xevent.KeyEvent.window = IntPtr.Zero;
4796 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4798 hwnd.Queue.EnqueueLocked (xevent);
4803 internal override void SetAllowDrop (IntPtr handle, bool value)
4805 // We allow drop on all windows
4808 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4809 DragDropEffects allowed_effects)
4811 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4814 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4816 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4819 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4820 Form form = Control.FromHandle (handle) as Form;
4821 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4822 border_style == FormBorderStyle.SizableToolWindow)) {
4823 form.window_manager = new ToolWindowManager (form);
4826 RequestNCRecalc(handle);
4829 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4830 if (Caret.Hwnd == handle) {
4837 if (Caret.Visible == true) {
4839 Caret.Timer.Start();
4844 internal override void SetClipRegion(IntPtr handle, Region region) {
4847 hwnd = Hwnd.ObjectFromHandle(handle);
4852 hwnd.UserClip = region;
4853 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4856 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4859 if (OverrideCursorHandle == IntPtr.Zero) {
4860 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4864 LastCursorHandle = cursor;
4865 LastCursorWindow = handle;
4867 hwnd = Hwnd.ObjectFromHandle(handle);
4869 if (cursor != IntPtr.Zero) {
4870 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4872 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4874 XFlush(DisplayHandle);
4879 hwnd = Hwnd.ObjectFromHandle(handle);
4881 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4885 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4886 out int root_x, out int root_y, out int child_x, out int child_y,
4889 /* this code was written with the help of
4890 glance at gdk. I never would have realized we
4891 needed a loop in order to traverse down in the
4892 hierarchy. I would have assumed you'd get the
4893 most deeply nested child and have to do
4894 XQueryTree to move back up the hierarchy..
4895 stupid me, of course. */
4898 XGrabServer (display);
4900 XQueryPointer(display, w, out root, out c,
4901 out root_x, out root_y, out child_x, out child_y,
4907 IntPtr child_last = IntPtr.Zero;
4908 while (c != IntPtr.Zero) {
4910 XQueryPointer(display, c, out root, out c,
4911 out root_x, out root_y, out child_x, out child_y,
4914 XUngrabServer (display);
4920 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4921 if (handle == IntPtr.Zero) {
4924 int root_x, root_y, child_x, child_y, mask;
4927 * QueryPointer before warping
4928 * because if the warp is on
4929 * the RootWindow, the x/y are
4930 * relative to the current
4933 QueryPointer (DisplayHandle, RootWindow,
4936 out root_x, out root_y,
4937 out child_x, out child_y,
4940 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4942 XFlush (DisplayHandle);
4944 /* then we need to a
4945 * QueryPointer after warping
4946 * to manually generate a
4947 * motion event for the window
4950 QueryPointer (DisplayHandle, RootWindow,
4953 out root_x, out root_y,
4954 out child_x, out child_y,
4957 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4958 if (child_hwnd == null) {
4962 XEvent xevent = new XEvent ();
4964 xevent.type = XEventName.MotionNotify;
4965 xevent.MotionEvent.display = DisplayHandle;
4966 xevent.MotionEvent.window = child_hwnd.client_window;
4967 xevent.MotionEvent.root = RootWindow;
4968 xevent.MotionEvent.x = child_x;
4969 xevent.MotionEvent.y = child_y;
4970 xevent.MotionEvent.x_root = root_x;
4971 xevent.MotionEvent.y_root = root_y;
4972 xevent.MotionEvent.state = mask;
4974 child_hwnd.Queue.EnqueueLocked (xevent);
4979 hwnd = Hwnd.ObjectFromHandle(handle);
4981 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4986 internal override void SetFocus(IntPtr handle) {
4988 IntPtr prev_focus_window;
4990 hwnd = Hwnd.ObjectFromHandle(handle);
4992 if (hwnd.client_window == FocusWindow) {
4996 prev_focus_window = FocusWindow;
4997 FocusWindow = hwnd.client_window;
4999 if (prev_focus_window != IntPtr.Zero) {
5000 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5002 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5004 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5007 internal override void SetIcon(IntPtr handle, Icon icon) {
5010 hwnd = Hwnd.ObjectFromHandle(handle);
5012 SetIcon(hwnd, icon);
5016 internal override void SetMenu(IntPtr handle, Menu menu) {
5019 hwnd = Hwnd.ObjectFromHandle(handle);
5022 RequestNCRecalc(handle);
5025 internal override void SetModal(IntPtr handle, bool Modal) {
5027 ModalWindows.Push(handle);
5029 if (ModalWindows.Contains(handle)) {
5032 if (ModalWindows.Count > 0) {
5033 Activate((IntPtr)ModalWindows.Peek());
5038 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5041 hwnd = Hwnd.ObjectFromHandle(handle);
5042 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5045 #if DriverDebug || DriverDebugParent
5046 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5048 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5054 internal override void SetTimer (Timer timer) {
5055 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5057 if (queue == null) {
5058 // This isn't really an error, MS doesn't start the timer if
5059 // it has no assosciated queue
5062 queue.timer_list.Add (timer);
5066 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5068 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5072 int[] atoms = new int[8];
5073 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5074 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5078 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5084 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5088 hwnd = Hwnd.ObjectFromHandle(handle);
5090 if (handle_owner != IntPtr.Zero) {
5091 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5097 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5098 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5100 if (hwnd_owner != null) {
5101 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5103 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5108 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5114 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5118 hwnd = Hwnd.ObjectFromHandle(handle);
5119 hwnd.visible = visible;
5123 MapWindow(hwnd, WindowType.Both);
5125 if (Control.FromHandle(handle) is Form) {
5128 s = ((Form)Control.FromHandle(handle)).WindowState;
5131 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5132 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5136 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5139 UnmapWindow(hwnd, WindowType.Both);
5145 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5150 hwnd = Hwnd.ObjectFromHandle(handle);
5155 hints = new XSizeHints();
5157 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5158 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5159 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5160 hints.min_width = min.Width;
5161 hints.min_height = min.Height;
5164 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5165 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5166 hints.max_width = max.Width;
5167 hints.max_height = max.Height;
5170 if (hints.flags != IntPtr.Zero) {
5171 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5174 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5175 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5176 hints.x = maximized.X;
5177 hints.y = maximized.Y;
5178 hints.width = maximized.Width;
5179 hints.height = maximized.Height;
5181 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5182 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5187 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5190 hwnd = Hwnd.ObjectFromHandle(handle);
5196 // Win32 automatically changes negative width/height to 0.
5202 // X requires a sanity check for width & height; otherwise it dies
5203 if (hwnd.zero_sized && width > 0 && height > 0) {
5205 MapWindow(hwnd, WindowType.Whole);
5207 hwnd.zero_sized = false;
5210 if ((width < 1) || (height < 1)) {
5211 hwnd.zero_sized = true;
5212 UnmapWindow(hwnd, WindowType.Whole);
5215 // Save a server roundtrip (and prevent a feedback loop)
5216 if ((hwnd.x == x) && (hwnd.y == y) &&
5217 (hwnd.width == width) && (hwnd.height == height)) {
5221 if (!hwnd.zero_sized) {
5226 hwnd.height = height;
5227 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5229 if (hwnd.fixed_size) {
5230 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5234 Control ctrl = Control.FromHandle (handle);
5235 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams ());
5236 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5237 PerformNCCalc(hwnd);
5241 // Update our position/size immediately, so
5242 // that future calls to SetWindowPos aren't
5243 // kept from calling XMoveResizeWindow (by the
5244 // "Save a server roundtrip" block above).
5248 hwnd.height = height;
5249 hwnd.ClientRect = Rectangle.Empty;
5252 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5253 FormWindowState current_state;
5256 hwnd = Hwnd.ObjectFromHandle(handle);
5258 current_state = GetWindowState(handle);
5260 if (current_state == state) {
5265 case FormWindowState.Normal: {
5267 if (current_state == FormWindowState.Minimized) {
5268 MapWindow(hwnd, WindowType.Both);
5269 } else if (current_state == FormWindowState.Maximized) {
5270 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5277 case FormWindowState.Minimized: {
5279 if (current_state == FormWindowState.Maximized) {
5280 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5282 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5287 case FormWindowState.Maximized: {
5289 if (current_state == FormWindowState.Minimized) {
5290 MapWindow(hwnd, WindowType.Both);
5293 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5301 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5304 hwnd = Hwnd.ObjectFromHandle(handle);
5305 SetHwndStyles(hwnd, cp);
5306 SetWMStyles(hwnd, cp);
5309 internal override double GetWindowTransparency(IntPtr handle)
5314 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5318 hwnd = Hwnd.ObjectFromHandle(handle);
5324 hwnd.opacity = (uint)(0xffffffff * transparency);
5325 opacity = (IntPtr)((int)hwnd.opacity);
5327 IntPtr w = hwnd.whole_window;
5328 if (hwnd.reparented)
5329 w = XGetParent (hwnd.whole_window);
5330 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5333 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5334 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5342 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5345 } else if (!bottom) {
5346 Hwnd after_hwnd = null;
5348 if (after_handle != IntPtr.Zero) {
5349 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5352 XWindowChanges values = new XWindowChanges();
5354 if (after_hwnd == null) {
5355 // Work around metacity 'issues'
5359 atoms[0] = unixtime();
5360 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5362 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5363 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5365 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5368 values.sibling = after_hwnd.whole_window;
5369 values.stack_mode = StackMode.Below;
5372 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5377 XLowerWindow(DisplayHandle, hwnd.whole_window);
5384 internal override void ShowCursor(bool show) {
5385 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5388 internal override object StartLoop(Thread thread) {
5389 XEventQueue q = ThreadQueue(thread);
5393 internal override TransparencySupport SupportsTransparency() {
5394 // We need to check if the x compositing manager is running
5395 return TransparencySupport.Set;
5398 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5399 GetSystrayManagerWindow();
5401 if (SystrayMgrWindow != IntPtr.Zero) {
5402 XSizeHints size_hints;
5405 hwnd = Hwnd.ObjectFromHandle(handle);
5407 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5411 if (hwnd.client_window != hwnd.whole_window) {
5412 XDestroyWindow(DisplayHandle, hwnd.client_window);
5413 hwnd.client_window = hwnd.whole_window;
5415 /* by virtue of the way the tests are ordered when determining if it's PAINT
5416 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5417 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5418 there's a pending expose). */
5419 if (hwnd.nc_expose_pending) {
5420 hwnd.nc_expose_pending = false;
5421 if (!hwnd.expose_pending)
5422 hwnd.Queue.Paint.Remove (hwnd);
5426 size_hints = new XSizeHints();
5428 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5430 size_hints.min_width = 24;
5431 size_hints.min_height = 24;
5432 size_hints.max_width = 24;
5433 size_hints.max_height = 24;
5434 size_hints.base_width = 24;
5435 size_hints.base_height = 24;
5437 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5439 int[] atoms = new int[2];
5440 atoms [0] = 1; // Version 1
5441 atoms [1] = 1; // we want to be mapped
5443 // This line cost me 3 days...
5444 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5446 // Need to pick some reasonable defaults
5448 tt.AutomaticDelay = 350;
5449 tt.InitialDelay = 250;
5450 tt.ReshowDelay = 250;
5451 tt.ShowAlways = true;
5453 if ((tip != null) && (tip != string.Empty)) {
5454 tt.SetToolTip(Control.FromHandle(handle), tip);
5460 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5468 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5471 control = Control.FromHandle(handle);
5472 if (control != null && tt != null) {
5473 tt.SetToolTip(control, tip);
5481 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5483 #if GTKSOCKET_SUPPORTS_REPARENTING
5486 hwnd = Hwnd.ObjectFromHandle(handle);
5488 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5489 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5490 * 2. The client can reparent its window out of the embedder window.
5491 * 3. The client can destroy its window.
5493 * this call to SetParent is case 2, but in
5494 * the spec it also mentions that gtk doesn't
5495 * support this at present. Looking at HEAD
5496 * gtksocket-x11.c jives with this statement.
5498 * so we can't reparent. we have to destroy.
5500 SetParent(hwnd.whole_window, FosterParent);
5502 Control control = Control.FromHandle(handle);
5503 if (control is NotifyIcon.NotifyIconWindow)
5504 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5507 // The caller can now re-dock it later...
5515 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5517 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5518 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5522 internal override bool Text(IntPtr handle, string text) {
5525 hwnd = Hwnd.ObjectFromHandle(handle);
5528 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5529 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5531 // XXX this has problems with UTF8.
5532 // we need to either use the actual
5533 // text if it's latin-1, or convert it
5534 // to compound text if it's in a
5535 // different charset.
5536 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5541 internal override bool TranslateMessage(ref MSG msg) {
5542 return Keyboard.TranslateMessage (ref msg);
5545 internal override void UpdateWindow(IntPtr handle) {
5548 hwnd = Hwnd.ObjectFromHandle(handle);
5550 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5554 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5555 hwnd.Queue.Paint.Remove(hwnd);
5558 internal override void CreateOffscreenDrawable (IntPtr handle,
5559 int width, int height,
5560 out object offscreen_drawable)
5563 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5565 XGetGeometry (DisplayHandle, handle,
5567 out x_out, out y_out,
5568 out width_out, out height_out,
5569 out border_width_out, out depth_out);
5571 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5573 offscreen_drawable = pixmap;
5577 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5579 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5582 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5584 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5587 internal override void BlitFromOffscreen (IntPtr dest_handle,
5589 object offscreen_drawable,
5590 Graphics offscreen_dc,
5593 XGCValues gc_values;
5596 gc_values = new XGCValues();
5598 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5600 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5601 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5603 XFreeGC (DisplayHandle, gc);
5606 #endregion // Public Static Methods
5609 internal override event EventHandler Idle;
5610 #endregion // Events
5613 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5614 internal extern static IntPtr XOpenDisplay(IntPtr display);
5615 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5616 internal extern static int XCloseDisplay(IntPtr display);
5617 [DllImport ("libX11", EntryPoint="XSynchronize")]
5618 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5620 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5621 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);
5622 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5623 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5624 [DllImport ("libX11", EntryPoint="XMapWindow")]
5625 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5626 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5627 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5628 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5629 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5630 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5631 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5632 [DllImport ("libX11", EntryPoint="XRootWindow")]
5633 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5634 [DllImport ("libX11", EntryPoint="XNextEvent")]
5635 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5636 [DllImport ("libX11")]
5637 internal extern static int XConnectionNumber (IntPtr diplay);
5638 [DllImport ("libX11")]
5639 internal extern static int XPending (IntPtr diplay);
5640 [DllImport ("libX11", EntryPoint="XSelectInput")]
5641 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5643 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5644 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5646 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5647 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5648 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5649 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5651 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5652 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5654 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5655 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5657 [DllImport ("libX11", EntryPoint="XFlush")]
5658 internal extern static int XFlush(IntPtr display);
5660 [DllImport ("libX11", EntryPoint="XSetWMName")]
5661 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5663 [DllImport ("libX11", EntryPoint="XStoreName")]
5664 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5666 [DllImport ("libX11", EntryPoint="XFetchName")]
5667 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5669 [DllImport ("libX11", EntryPoint="XSendEvent")]
5670 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5672 [DllImport ("libX11", EntryPoint="XQueryTree")]
5673 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);
5675 [DllImport ("libX11", EntryPoint="XFree")]
5676 internal extern static int XFree(IntPtr data);
5678 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5679 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5681 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5682 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5684 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5685 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5687 [DllImport ("libX11", EntryPoint="XInternAtom")]
5688 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5690 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5691 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5693 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5694 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5696 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5697 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);
5699 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5700 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5702 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5703 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);
5705 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5706 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);
5708 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5709 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);
5711 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5712 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);
5714 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5715 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);
5717 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5718 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);
5720 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5721 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);
5723 [DllImport ("libX11", EntryPoint="XClearWindow")]
5724 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5726 [DllImport ("libX11", EntryPoint="XClearArea")]
5727 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5730 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5731 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5733 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5734 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5736 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5737 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5739 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5740 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5742 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5743 internal extern static int XDefaultScreen(IntPtr display);
5745 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5746 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5748 [DllImport ("libX11", EntryPoint="XLookupColor")]
5749 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5751 [DllImport ("libX11", EntryPoint="XAllocColor")]
5752 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5754 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5755 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5757 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5758 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5760 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5761 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5763 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5764 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5766 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5767 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5769 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5770 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5772 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5773 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5775 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5776 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5778 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5779 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5781 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5782 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5785 [DllImport ("libX11", EntryPoint="XCreateGC")]
5786 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5788 [DllImport ("libX11", EntryPoint="XFreeGC")]
5789 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5791 [DllImport ("libX11", EntryPoint="XSetFunction")]
5792 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5794 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5795 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5797 [DllImport ("libX11", EntryPoint="XDrawLine")]
5798 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5800 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5801 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5803 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5804 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5806 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5807 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5809 [DllImport ("libX11", EntryPoint="XCopyArea")]
5810 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);
5812 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5813 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);
5815 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5816 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5818 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5819 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5821 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5822 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5824 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5825 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5827 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5828 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5830 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5831 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5833 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5834 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);
5836 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5837 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5839 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5840 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5842 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5843 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5845 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5846 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5848 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5849 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5851 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5852 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5854 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5855 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5857 [DllImport ("libX11", EntryPoint="XGrabServer")]
5858 internal extern static void XGrabServer(IntPtr display);
5860 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5861 internal extern static void XUngrabServer(IntPtr display);
5863 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5864 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5866 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5867 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5869 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5870 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5872 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5873 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5875 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5876 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5878 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5879 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5881 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5882 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5884 [DllImport ("libX11", EntryPoint="XInitThreads")]
5885 internal extern static int XInitThreads();
5887 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5888 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5890 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5891 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5893 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5894 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5896 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5897 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5899 [DllImport ("libX11", EntryPoint="XSetForeground")]
5900 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5902 [DllImport ("libX11", EntryPoint="XSetBackground")]
5903 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5905 [DllImport ("libX11", EntryPoint="XBell")]
5906 internal extern static int XBell(IntPtr display, int percent);
5908 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5909 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5911 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5912 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5914 [DllImport ("libX11")]
5915 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5917 [DllImport ("libX11")]
5918 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);