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;
788 if (rect.Width < 1 || rect.Height < 1) {
798 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
801 * If this is a form with no window manager, X is handling all the border and caption painting
802 * so remove that from the area (since the area we set of the window here is the part of the window
803 * we're painting in only)
805 Size rect = new Size (cp.Width, cp.Height);
806 Form form = cp.control as Form;
807 if (form != null && form.window_manager == null) {
808 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
811 xrect.Width -= borders.left + borders.right;
812 xrect.Height -= borders.top + borders.bottom;
816 if (rect.Height == 0)
823 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
826 * If this is a form with no window manager, X is handling all the border and caption painting
827 * so remove that from the area (since the area we set of the window here is the part of the window
828 * we're painting in only)
830 Size rect = new Size (xWidth, xHeight);
831 Form form = cp.control as Form;
832 if (form != null && form.window_manager == null) {
833 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
836 xrect.Width += borders.left + borders.right;
837 xrect.Height += borders.top + borders.bottom;
844 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
850 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
851 frame = FrameExtents (hwnd.whole_window);
856 return new Point (x, y);
859 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) {
862 tool_caption_height = 19;
863 border_static = false;
865 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
866 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
867 border_style = FormBorderStyle.Fixed3D;
868 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
869 border_style = FormBorderStyle.Fixed3D;
870 border_static = true;
871 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
872 border_style = FormBorderStyle.None;
874 border_style = FormBorderStyle.FixedSingle;
876 title_style = TitleStyle.None;
878 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
880 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
881 title_style = TitleStyle.Tool;
883 title_style = TitleStyle.Normal;
887 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
890 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
891 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
892 border_style = (FormBorderStyle) 0xFFFF;
894 border_style = FormBorderStyle.None;
899 title_style = TitleStyle.None;
900 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
901 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
902 title_style = TitleStyle.Tool;
904 title_style = TitleStyle.Normal;
908 border_style = FormBorderStyle.None;
910 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
911 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
912 border_style = FormBorderStyle.SizableToolWindow;
914 border_style = FormBorderStyle.Sizable;
917 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
918 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
919 border_style = FormBorderStyle.Fixed3D;
920 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
921 border_style = FormBorderStyle.Fixed3D;
922 border_static = true;
923 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
924 border_style = FormBorderStyle.FixedDialog;
925 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
926 border_style = FormBorderStyle.FixedToolWindow;
927 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
928 border_style = FormBorderStyle.FixedSingle;
931 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
932 border_style = FormBorderStyle.FixedSingle;
939 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
940 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);
943 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
944 MotifWmHints mwmHints;
945 MotifFunctions functions;
946 MotifDecorations decorations;
949 Rectangle client_rect;
952 bool hide_from_taskbar;
953 IntPtr transient_for_parent;
955 // Windows we manage ourselves don't need WM window styles.
956 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
961 mwmHints = new MotifWmHints();
964 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
965 transient_for_parent = IntPtr.Zero;
967 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
968 mwmHints.functions = (IntPtr)0;
969 mwmHints.decorations = (IntPtr)0;
971 form = cp.control as Form;
973 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
974 /* tool windows get no window manager
978 /* just because the window doesn't get any decorations doesn't
979 mean we should disable the functions. for instance, without
980 MotifFunctions.Maximize, changing the windowstate to Maximized
981 is ignored by metacity. */
982 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
983 } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
984 // No functions nor decorations whatsoever.
986 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
987 functions |= MotifFunctions.Move;
988 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
991 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
992 functions |= MotifFunctions.Move | MotifFunctions.Resize;
993 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
996 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
997 functions |= MotifFunctions.Minimize;
998 decorations |= MotifDecorations.Minimize;
1001 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1002 functions |= MotifFunctions.Maximize;
1003 decorations |= MotifDecorations.Maximize;
1006 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1007 functions |= MotifFunctions.Resize;
1008 decorations |= MotifDecorations.ResizeH;
1011 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1012 decorations |= MotifDecorations.Border;
1015 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1016 decorations |= MotifDecorations.Border;
1019 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1020 decorations |= MotifDecorations.Border;
1023 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1024 functions |= MotifFunctions.Close;
1027 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1028 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1029 if (cp.Caption == "") {
1030 functions &= ~MotifFunctions.Move;
1031 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1036 if ((functions & MotifFunctions.Resize) == 0) {
1037 hwnd.fixed_size = true;
1038 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));
1040 hwnd.fixed_size = false;
1043 mwmHints.functions = (IntPtr)functions;
1044 mwmHints.decorations = (IntPtr)decorations;
1046 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1047 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1048 // and get those windows in front of their parents
1049 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1050 } else if (form != null && form.Modal) {
1051 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1053 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1056 if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1057 hide_from_taskbar = true;
1058 } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
1059 hide_from_taskbar = true;
1061 hide_from_taskbar = false;
1064 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1065 if (form != null && !hwnd.reparented) {
1066 if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1067 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1068 if (owner_hwnd != null)
1069 transient_for_parent = owner_hwnd.whole_window;
1073 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1074 transient_for_parent = hwnd.parent.whole_window;
1077 FormWindowState current_state = GetWindowState (hwnd.Handle);
1078 if (current_state == (FormWindowState)(-1))
1079 current_state = FormWindowState.Normal;
1081 client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1086 atoms [0] = window_type.ToInt32 ();
1087 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1089 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1091 if (transient_for_parent != IntPtr.Zero) {
1092 XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1095 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1097 if (hide_from_taskbar) {
1098 /* this line keeps the window from showing up in gnome's taskbar */
1099 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1101 /* we need to add these atoms in the
1102 * event we're maximized, since we're
1103 * replacing the existing
1104 * _NET_WM_STATE here. If we don't
1105 * add them, future calls to
1106 * GetWindowState will return Normal
1107 * for a window which is maximized. */
1108 if (current_state == FormWindowState.Maximized) {
1109 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1110 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1113 if (form != null && form.Modal) {
1114 atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1117 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1120 IntPtr[] atom_ptrs = new IntPtr[2];
1121 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1122 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1123 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1126 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1130 private void SetIcon(Hwnd hwnd, Icon icon)
1135 // This really needs to do whatever it
1136 // takes to remove the window manager
1137 // menu, not just delete the ICON
1138 // property. This will cause metacity
1139 // to use the "no icon set" icon, and
1140 // we'll still have an icon.
1141 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1149 bitmap = icon.ToBitmap();
1151 size = bitmap.Width * bitmap.Height + 2;
1152 data = new IntPtr[size];
1154 data[index++] = (IntPtr)bitmap.Width;
1155 data[index++] = (IntPtr)bitmap.Height;
1157 for (int y = 0; y < bitmap.Height; y++) {
1158 for (int x = 0; x < bitmap.Width; x++) {
1159 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1163 XChangeProperty (DisplayHandle, hwnd.whole_window,
1164 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1165 PropertyMode.Replace, data, size);
1169 private void WakeupMain () {
1170 wake.Send (new byte [] { 0xFF });
1173 private XEventQueue ThreadQueue(Thread thread) {
1176 queue = (XEventQueue)MessageQueues[thread];
1177 if (queue == null) {
1178 queue = new XEventQueue(thread);
1179 MessageQueues[thread] = queue;
1185 private void TranslatePropertyToClipboard(IntPtr property) {
1190 IntPtr prop = IntPtr.Zero;
1192 Clipboard.Item = null;
1194 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);
1196 if ((long)nitems > 0) {
1197 if (property == (IntPtr)Atom.XA_STRING) {
1198 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1199 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1200 // FIXME - convert bitmap to image
1201 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1202 // FIXME - convert pixmap to image
1203 } else if (property == OEMTEXT) {
1204 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1205 } else if (property == UNICODETEXT) {
1206 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1213 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1215 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1219 // Keep the invalid area as small as needed
1220 if ((x + width) > hwnd.width) {
1221 width = hwnd.width - x;
1224 if ((y + height) > hwnd.height) {
1225 height = hwnd.height - y;
1229 hwnd.AddInvalidArea(x, y, width, height);
1230 if (!hwnd.expose_pending) {
1231 if (!hwnd.nc_expose_pending) {
1232 hwnd.Queue.Paint.Enqueue(hwnd);
1234 hwnd.expose_pending = true;
1237 hwnd.AddNcInvalidArea (x, y, width, height);
1239 if (!hwnd.nc_expose_pending) {
1240 if (!hwnd.expose_pending) {
1241 hwnd.Queue.Paint.Enqueue(hwnd);
1243 hwnd.nc_expose_pending = true;
1248 private static Hwnd.Borders FrameExtents (IntPtr window)
1254 IntPtr prop = IntPtr.Zero;
1255 Hwnd.Borders rect = new Hwnd.Borders ();
1257 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);
1258 if (prop != IntPtr.Zero) {
1259 if (nitems.ToInt32 () == 4) {
1260 rect.left = Marshal.ReadInt32 (prop, 0);
1261 rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1262 rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1263 rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1271 private void AddConfigureNotify (XEvent xevent) {
1274 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1277 if (hwnd == null || hwnd.zombie) {
1280 if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1281 if (hwnd.parent == null) {
1282 // The location given by the event is not reliable between different wm's,
1283 // so use an alternative way of getting it.
1284 Point location = GetTopLevelWindowLocation (hwnd);
1285 hwnd.x = location.X;
1286 hwnd.y = location.Y;
1289 // XXX this sucks. this isn't thread safe
1290 Control ctrl = Control.FromHandle (hwnd.Handle);
1291 Size TranslatedSize;
1293 TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1295 TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1297 hwnd.width = TranslatedSize.Width;
1298 hwnd.height = TranslatedSize.Height;
1299 hwnd.ClientRect = Rectangle.Empty;
1302 Console.WriteLine ("AddConfigureNotify (hwnd.Handle = {1}, hwnd.rect = {0})", new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle);
1304 lock (hwnd.configure_lock) {
1305 if (!hwnd.configure_pending) {
1306 hwnd.Queue.EnqueueLocked (xevent);
1307 hwnd.configure_pending = true;
1311 // We drop configure events for Client windows
1314 private void ShowCaret() {
1315 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1321 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1325 private void HideCaret() {
1326 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1332 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1336 private int NextTimeout (ArrayList timers, DateTime now) {
1337 int timeout = Int32.MaxValue;
1339 foreach (Timer timer in timers) {
1340 int next = (int) (timer.Expires - now).TotalMilliseconds;
1342 return 0; // Have a timer that has already expired
1345 if (next < timeout) {
1349 if (timeout < Timer.Minimum) {
1350 timeout = Timer.Minimum;
1358 private void CheckTimers (ArrayList timers, DateTime now) {
1361 count = timers.Count;
1366 for (int i = 0; i < timers.Count; i++) {
1369 timer = (Timer) timers [i];
1371 if (timer.Enabled && timer.Expires <= now) {
1378 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1379 MSG msg = new MSG ();
1382 queue = ThreadQueue(Thread.CurrentThread);
1384 queue.DispatchIdle = false;
1388 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1389 if ((Msg)msg.message == Msg.WM_QUIT) {
1390 PostQuitMessage (0);
1394 if (msg.hwnd == hwnd.Handle) {
1395 if ((Msg)msg.message == message)
1397 else if ((Msg)msg.message == Msg.WM_DESTROY)
1401 TranslateMessage (ref msg);
1402 DispatchMessage (ref msg);
1407 queue.DispatchIdle = true;
1411 private void MapWindow(Hwnd hwnd, WindowType windows) {
1413 if (Control.FromHandle(hwnd.Handle) is Form) {
1414 Form f = Control.FromHandle(hwnd.Handle) as Form;
1415 if (f.WindowState == FormWindowState.Normal)
1416 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1419 // it's possible that our Hwnd is no
1420 // longer valid after making that
1421 // SendMessage call, so check here.
1425 bool need_to_wait = false;
1427 if ((windows & WindowType.Whole) != 0) {
1428 XMapWindow(DisplayHandle, hwnd.whole_window);
1430 if ((windows & WindowType.Client) != 0) {
1431 XMapWindow(DisplayHandle, hwnd.client_window);
1433 need_to_wait = true;
1438 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1439 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1443 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1445 if (Control.FromHandle(hwnd.Handle) is Form) {
1446 Form f = Control.FromHandle(hwnd.Handle) as Form;
1447 if (f.WindowState == FormWindowState.Normal)
1448 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1451 // it's possible that our Hwnd is no
1452 // longer valid after making that
1453 // SendMessage call, so check here.
1457 bool need_to_wait = false;
1459 if ((windows & WindowType.Client) != 0) {
1460 XUnmapWindow(DisplayHandle, hwnd.client_window);
1462 need_to_wait = true;
1464 if ((windows & WindowType.Whole) != 0) {
1465 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1468 hwnd.mapped = false;
1470 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1471 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1475 private void UpdateMessageQueue (XEventQueue queue) {
1480 now = DateTime.UtcNow;
1483 pending = XPending (DisplayHandle);
1487 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1488 Idle (this, EventArgs.Empty);
1492 pending = XPending (DisplayHandle);
1499 if (queue != null) {
1500 if (queue.Paint.Count > 0)
1503 timeout = NextTimeout (queue.timer_list, now);
1508 int length = pollfds.Length - 1;
1509 lock (wake_waiting_lock) {
1510 if (wake_waiting == false) {
1512 wake_waiting = true;
1516 Syscall.poll (pollfds, (uint)length, timeout);
1517 // Clean out buffer, so we're not busy-looping on the same data
1518 if (length == pollfds.Length) {
1519 if (pollfds[1].revents != 0)
1520 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1521 lock (wake_waiting_lock) {
1522 wake_waiting = false;
1527 pending = XPending (DisplayHandle);
1533 CheckTimers (queue.timer_list, now);
1536 XEvent xevent = new XEvent ();
1539 if (XPending (DisplayHandle) == 0)
1542 XNextEvent (DisplayHandle, ref xevent);
1544 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1545 if (XFilterEvent(ref xevent, FosterParent)) {
1551 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1556 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1558 switch (xevent.type) {
1559 case XEventName.Expose:
1560 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1563 case XEventName.SelectionClear: {
1564 // Should we do something?
1568 case XEventName.SelectionRequest: {
1569 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1573 sel_event = new XEvent();
1574 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1575 sel_event.SelectionEvent.send_event = true;
1576 sel_event.SelectionEvent.display = DisplayHandle;
1577 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1578 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1579 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1580 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1581 sel_event.SelectionEvent.property = IntPtr.Zero;
1583 // Seems that some apps support asking for supported types
1584 if (xevent.SelectionEvent.target == TARGETS) {
1591 if (Clipboard.Item is String) {
1592 atoms[atom_count++] = (int)Atom.XA_STRING;
1593 atoms[atom_count++] = (int)OEMTEXT;
1594 atoms[atom_count++] = (int)UNICODETEXT;
1595 } else if (Clipboard.Item is Image) {
1596 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1597 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1599 // FIXME - handle other types
1602 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1603 } else if (Clipboard.Item is string) {
1609 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1612 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1613 buffer = Marshal.AllocHGlobal(bytes.Length);
1614 buflen = bytes.Length;
1616 for (int i = 0; i < buflen; i++) {
1617 Marshal.WriteByte(buffer, i, bytes[i]);
1619 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1620 // FIXME - this should encode into ISO2022
1621 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1622 while (Marshal.ReadByte(buffer, buflen) != 0) {
1625 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1626 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1627 while (Marshal.ReadByte(buffer, buflen) != 0) {
1631 buffer = IntPtr.Zero;
1634 if (buffer != IntPtr.Zero) {
1635 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1636 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1637 Marshal.FreeHGlobal(buffer);
1639 } else if (Clipboard.Item is Image) {
1640 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1641 // FIXME - convert image and store as property
1642 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1643 // FIXME - convert image and store as property
1647 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1651 case XEventName.SelectionNotify: {
1652 if (Clipboard.Enumerating) {
1653 Clipboard.Enumerating = false;
1654 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1655 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1656 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1657 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1658 #if DriverDebugExtra
1659 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1663 } else if (Clipboard.Retrieving) {
1664 Clipboard.Retrieving = false;
1665 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1666 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1668 Clipboard.Item = null;
1671 Dnd.HandleSelectionNotifyEvent (ref xevent);
1676 case XEventName.KeyRelease:
1677 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1678 XEvent nextevent = new XEvent ();
1680 XPeekEvent (DisplayHandle, ref nextevent);
1682 if (nextevent.type == XEventName.KeyPress &&
1683 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1684 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1688 goto case XEventName.KeyPress;
1690 case XEventName.MotionNotify: {
1693 /* we can't do motion compression across threads, so just punt if we don't match up */
1694 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1695 peek = hwnd.Queue.Peek();
1696 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1700 goto case XEventName.KeyPress;
1703 case XEventName.KeyPress:
1704 case XEventName.ButtonPress:
1705 case XEventName.ButtonRelease:
1706 case XEventName.EnterNotify:
1707 case XEventName.LeaveNotify:
1708 case XEventName.CreateNotify:
1709 case XEventName.DestroyNotify:
1710 case XEventName.FocusIn:
1711 case XEventName.FocusOut:
1712 case XEventName.ClientMessage:
1713 case XEventName.ReparentNotify:
1714 case XEventName.MapNotify:
1715 case XEventName.UnmapNotify:
1716 hwnd.Queue.EnqueueLocked (xevent);
1719 case XEventName.ConfigureNotify:
1720 AddConfigureNotify(xevent);
1723 case XEventName.PropertyNotify:
1725 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1727 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1732 IntPtr prop = IntPtr.Zero;
1735 prev_active = ActiveWindow;
1736 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);
1737 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1738 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1741 if (prev_active != ActiveWindow) {
1742 if (prev_active != IntPtr.Zero) {
1743 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1745 if (ActiveWindow != IntPtr.Zero) {
1746 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1749 if (ModalWindows.Count == 0) {
1752 // Modality handling, if we are modal and the new active window is one
1753 // of ours but not the modal one, switch back to the modal window
1755 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1756 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1757 Activate((IntPtr)ModalWindows.Peek());
1764 else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1765 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1766 hwnd.cached_window_state = (FormWindowState)(-1);
1774 private IntPtr GetMousewParam(int Delta) {
1777 if ((MouseState & MouseButtons.Left) != 0) {
1778 result |= (int)MsgButtons.MK_LBUTTON;
1781 if ((MouseState & MouseButtons.Middle) != 0) {
1782 result |= (int)MsgButtons.MK_MBUTTON;
1785 if ((MouseState & MouseButtons.Right) != 0) {
1786 result |= (int)MsgButtons.MK_RBUTTON;
1789 Keys mods = ModifierKeys;
1790 if ((mods & Keys.Control) != 0) {
1791 result |= (int)MsgButtons.MK_CONTROL;
1794 if ((mods & Keys.Shift) != 0) {
1795 result |= (int)MsgButtons.MK_SHIFT;
1798 result |= Delta << 16;
1800 return (IntPtr)result;
1802 private IntPtr XGetParent(IntPtr handle) {
1809 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1812 if (Children!=IntPtr.Zero) {
1820 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1822 // we need to workaround a problem with the
1823 // ordering of destruction of Drawables and
1824 // Pictures that exists between cairo and
1825 // RENDER on the server.
1826 if (error_event.request_code == (XRequest)render_major_opcode
1827 && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1828 && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1832 if (ErrorExceptions) {
1833 XUngrabPointer (display, IntPtr.Zero);
1834 throw new XException (error_event.display, error_event.resourceid,
1835 error_event.serial, error_event.error_code,
1836 error_event.request_code, error_event.minor_code);
1838 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1839 XException.GetMessage (error_event.display, error_event.resourceid,
1840 error_event.serial, error_event.error_code,
1841 error_event.request_code, error_event.minor_code),
1842 Environment.StackTrace);
1847 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1850 Control[] controls = c.Controls.GetAllControls ();
1852 if (c.IsHandleCreated && !c.IsDisposed) {
1853 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1855 #if DriverDebug || DriverDebugDestroy
1856 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1857 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1861 CleanupCachedWindows (hwnd);
1864 for (int i = 0; i < controls.Length; i ++) {
1865 AccumulateDestroyedHandles (controls[i], list);
1871 void CleanupCachedWindows (Hwnd hwnd)
1873 if (ActiveWindow == hwnd.Handle) {
1874 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1875 ActiveWindow = IntPtr.Zero;
1878 if (FocusWindow == hwnd.Handle) {
1879 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1880 FocusWindow = IntPtr.Zero;
1883 if (Grab.Hwnd == hwnd.Handle) {
1884 Grab.Hwnd = IntPtr.Zero;
1885 Grab.Confined = false;
1888 DestroyCaret (hwnd.Handle);
1891 private void PerformNCCalc(Hwnd hwnd) {
1892 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1896 rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1898 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1899 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1901 ncp.rgrc1.left = rect.Left;
1902 ncp.rgrc1.top = rect.Top;
1903 ncp.rgrc1.right = rect.Right;
1904 ncp.rgrc1.bottom = rect.Bottom;
1906 Marshal.StructureToPtr(ncp, ptr, true);
1907 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1908 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1909 Marshal.FreeHGlobal(ptr);
1912 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1913 hwnd.ClientRect = rect;
1915 rect = TranslateClientRectangleToXClientRectangle (hwnd);
1918 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1921 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1923 #endregion // Private Methods
1926 private void MouseHover(object sender, EventArgs e) {
1930 HoverState.Timer.Enabled = false;
1932 if (HoverState.Window != IntPtr.Zero) {
1933 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1935 xevent = new XEvent ();
1937 xevent.type = XEventName.ClientMessage;
1938 xevent.ClientMessageEvent.display = DisplayHandle;
1939 xevent.ClientMessageEvent.window = HoverState.Window;
1940 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1941 xevent.ClientMessageEvent.format = 32;
1942 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1944 hwnd.Queue.EnqueueLocked (xevent);
1951 private void CaretCallback(object sender, EventArgs e) {
1955 Caret.On = !Caret.On;
1957 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1959 #endregion // Callbacks
1961 #region Public Properties
1963 internal override int Caption {
1969 internal override Size CursorSize {
1974 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1975 return new Size(x, y);
1977 return new Size(16, 16);
1982 internal override bool DragFullWindows {
1988 internal override Size DragSize {
1990 return new Size(4, 4);
1994 internal override Size FrameBorderSize {
1996 return new Size (4, 4);
2000 internal override Size IconSize {
2006 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2010 current = (long)list;
2013 size = new XIconSize();
2015 for (int i = 0; i < count; i++) {
2016 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2017 current += Marshal.SizeOf(size);
2019 // Look for our preferred size
2020 if (size.min_width == 32) {
2022 return new Size(32, 32);
2025 if (size.max_width == 32) {
2027 return new Size(32, 32);
2030 if (size.min_width < 32 && size.max_width > 32) {
2033 // check if we can fit one
2035 while (x < size.max_width) {
2036 x += size.width_inc;
2039 return new Size(32, 32);
2044 if (largest < size.max_width) {
2045 largest = size.max_width;
2049 // We didn't find a match or we wouldn't be here
2050 return new Size(largest, largest);
2053 return new Size(32, 32);
2058 internal override int KeyboardSpeed {
2061 // A lot harder: need to do:
2062 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
2063 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
2064 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
2066 // And from that we can tell the repetition rate
2068 // Notice, the values must map to:
2069 // [0, 31] which maps to 2.5 to 30 repetitions per second.
2075 internal override int KeyboardDelay {
2078 // Return values must range from 0 to 4, 0 meaning 250ms,
2079 // and 4 meaning 1000 ms.
2081 return 1; // ie, 500 ms
2085 internal override Size MaxWindowTrackSize {
2087 return new Size (WorkingArea.Width, WorkingArea.Height);
2091 internal override Size MinimizedWindowSize {
2093 return new Size(1, 1);
2097 internal override Size MinimizedWindowSpacingSize {
2099 return new Size(1, 1);
2103 internal override Size MinimumWindowSize {
2105 return new Size(1, 1);
2109 internal override Size MinWindowTrackSize {
2111 return new Size(1, 1);
2115 internal override Keys ModifierKeys {
2117 return Keyboard.ModifierKeys;
2121 internal override Size SmallIconSize {
2127 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2131 current = (long)list;
2134 size = new XIconSize();
2136 for (int i = 0; i < count; i++) {
2137 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2138 current += Marshal.SizeOf(size);
2140 // Look for our preferred size
2141 if (size.min_width == 16) {
2143 return new Size(16, 16);
2146 if (size.max_width == 16) {
2148 return new Size(16, 16);
2151 if (size.min_width < 16 && size.max_width > 16) {
2154 // check if we can fit one
2156 while (x < size.max_width) {
2157 x += size.width_inc;
2160 return new Size(16, 16);
2165 if (smallest == 0 || smallest > size.min_width) {
2166 smallest = size.min_width;
2170 // We didn't find a match or we wouldn't be here
2171 return new Size(smallest, smallest);
2174 return new Size(16, 16);
2179 internal override int MouseButtonCount {
2185 internal override bool MouseButtonsSwapped {
2187 return false; // FIXME - how to detect?
2191 internal override Point MousePosition {
2193 return mouse_position;
2197 internal override Size MouseHoverSize {
2199 return new Size (1, 1);
2203 internal override int MouseHoverTime {
2205 return HoverState.Interval;
2211 internal override bool MouseWheelPresent {
2213 return true; // FIXME - how to detect?
2217 internal override Rectangle VirtualScreen {
2223 IntPtr prop = IntPtr.Zero;
2227 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);
2228 if ((long)nitems < 2)
2231 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2232 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2236 return new Rectangle(0, 0, width, height);
2239 XWindowAttributes attributes=new XWindowAttributes();
2242 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2245 return new Rectangle(0, 0, attributes.width, attributes.height);
2249 internal override Rectangle WorkingArea {
2255 IntPtr prop = IntPtr.Zero;
2258 int current_desktop;
2262 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);
2263 if ((long)nitems < 1) {
2267 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2270 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);
2271 if ((long)nitems < 4 * current_desktop) {
2275 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2276 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2277 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2278 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2281 return new Rectangle(x, y, width, height);
2284 XWindowAttributes attributes=new XWindowAttributes();
2287 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2290 return new Rectangle(0, 0, attributes.width, attributes.height);
2294 internal override bool ThemesEnabled {
2296 return XplatUIX11.themes_enabled;
2301 #endregion // Public properties
2303 #region Public Static Methods
2304 internal override IntPtr InitializeDriver() {
2306 if (DisplayHandle==IntPtr.Zero) {
2307 SetDisplay(XOpenDisplay(IntPtr.Zero));
2313 internal override void ShutdownDriver(IntPtr token) {
2315 if (DisplayHandle!=IntPtr.Zero) {
2316 XCloseDisplay(DisplayHandle);
2317 DisplayHandle=IntPtr.Zero;
2322 internal override void EnableThemes() {
2323 themes_enabled = true;
2327 internal override void Activate(IntPtr handle) {
2330 hwnd = Hwnd.ObjectFromHandle(handle);
2334 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2335 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2338 // XRaiseWindow(DisplayHandle, handle);
2344 internal override void AudibleAlert() {
2345 XBell(DisplayHandle, 0);
2350 internal override void CaretVisible(IntPtr handle, bool visible) {
2351 if (Caret.Hwnd == handle) {
2353 if (!Caret.Visible) {
2354 Caret.Visible = true;
2356 Caret.Timer.Start();
2359 Caret.Visible = false;
2366 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2367 WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2371 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2377 hwnd = Hwnd.ObjectFromHandle(handle);
2380 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2387 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2388 DataFormats.Format f;
2391 f = DataFormats.Format.List;
2393 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2397 Clipboard.Formats = new ArrayList();
2400 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2402 Clipboard.Enumerating = true;
2403 while (Clipboard.Enumerating) {
2404 UpdateMessageQueue(null);
2409 result = new int[Clipboard.Formats.Count];
2411 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2412 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2415 Clipboard.Formats = null;
2419 internal override void ClipboardClose(IntPtr handle) {
2420 if (handle != ClipMagic) {
2421 throw new ArgumentException("handle is not a valid clipboard handle");
2426 internal override int ClipboardGetID(IntPtr handle, string format) {
2427 if (handle != ClipMagic) {
2428 throw new ArgumentException("handle is not a valid clipboard handle");
2431 if (format == "Text" ) return (int)Atom.XA_STRING;
2432 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2433 //else if (format == "MetaFilePict" ) return 3;
2434 //else if (format == "SymbolicLink" ) return 4;
2435 //else if (format == "DataInterchangeFormat" ) return 5;
2436 //else if (format == "Tiff" ) return 6;
2437 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2438 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2439 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2440 //else if (format == "PenData" ) return 10;
2441 //else if (format == "RiffAudio" ) return 11;
2442 //else if (format == "WaveAudio" ) return 12;
2443 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2444 //else if (format == "EnhancedMetafile" ) return 14;
2445 //else if (format == "FileDrop" ) return 15;
2446 //else if (format == "Locale" ) return 16;
2448 return XInternAtom(DisplayHandle, format, false).ToInt32();
2451 internal override IntPtr ClipboardOpen(bool primary_selection) {
2452 if (!primary_selection)
2453 ClipMagic = CLIPBOARD;
2455 ClipMagic = PRIMARY;
2459 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2460 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2462 Clipboard.Retrieving = true;
2463 while (Clipboard.Retrieving) {
2464 UpdateMessageQueue(null);
2467 return Clipboard.Item;
2470 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2471 Clipboard.Item = obj;
2472 Clipboard.Type = type;
2473 Clipboard.Converter = converter;
2476 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2478 // Clearing the selection
2479 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2483 internal override void CreateCaret (IntPtr handle, int width, int height)
2485 XGCValues gc_values;
2488 hwnd = Hwnd.ObjectFromHandle(handle);
2490 if (Caret.Hwnd != IntPtr.Zero) {
2491 DestroyCaret(Caret.Hwnd);
2494 Caret.Hwnd = handle;
2495 Caret.Window = hwnd.client_window;
2496 Caret.Width = width;
2497 Caret.Height = height;
2498 Caret.Visible = false;
2501 gc_values = new XGCValues();
2502 gc_values.line_width = width;
2504 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2505 if (Caret.gc == IntPtr.Zero) {
2506 Caret.Hwnd = IntPtr.Zero;
2510 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2513 internal override IntPtr CreateWindow (CreateParams cp)
2515 XSetWindowAttributes Attributes;
2517 Hwnd parent_hwnd = null;
2522 IntPtr ParentHandle;
2524 IntPtr ClientWindow;
2525 Rectangle ClientRect;
2526 SetWindowValuemask ValueMask;
2531 Attributes = new XSetWindowAttributes();
2537 if (Width<1) Width=1;
2538 if (Height<1) Height=1;
2540 if (cp.Parent != IntPtr.Zero) {
2541 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2542 ParentHandle = parent_hwnd.client_window;
2544 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2545 // We need to use our foster parent window until this poor child gets it's parent assigned
2546 ParentHandle=FosterParent;
2548 ParentHandle=RootWindow;
2552 // Set the default location location for forms.
2553 Point previous, next;
2555 if (cp.control is Form) {
2556 if (parent_hwnd != null) {
2557 previous = parent_hwnd.previous_child_startup_location;
2558 within = parent_hwnd.client_rectangle;
2560 previous = Hwnd.previous_main_startup_location;
2561 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
2564 if (previous.X == int.MinValue || previous.Y == int.MinValue) {
2567 next = new Point (previous.X + 22, previous.Y + 22);
2570 if (!within.Contains (next.X * 3, next.Y * 3)) {
2574 if (next == Point.Empty && cp.Parent == IntPtr.Zero) {
2575 next = new Point (22, 22);
2578 if (parent_hwnd != null) {
2579 parent_hwnd.previous_child_startup_location = next;
2581 Hwnd.previous_main_startup_location = next;
2584 if (X == int.MinValue && Y == int.MinValue) {
2589 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2591 Attributes.bit_gravity = Gravity.NorthWestGravity;
2592 Attributes.win_gravity = Gravity.NorthWestGravity;
2594 // Save what's under the toolwindow
2595 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2596 Attributes.save_under = true;
2597 ValueMask |= SetWindowValuemask.SaveUnder;
2601 // If we're a popup without caption we override the WM
2602 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2603 Attributes.override_redirect = true;
2604 ValueMask |= SetWindowValuemask.OverrideRedirect;
2610 hwnd.height = Height;
2611 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2612 hwnd.initial_style = cp.WindowStyle;
2613 hwnd.initial_ex_style = cp.WindowExStyle;
2615 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2616 hwnd.enabled = false;
2619 ClientRect = hwnd.ClientRect;
2620 ClientWindow = IntPtr.Zero;
2623 Size TranslatedSize;
2624 TranslatedSize = TranslateWindowSizeToXWindowSize (cp);
2625 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);
2626 if (WholeWindow != IntPtr.Zero) {
2627 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2629 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2630 ValueMask = SetWindowValuemask.ColorMap;
2631 Attributes.colormap = CustomColormap;
2633 Rectangle XClientRect = ClientRect;
2634 if (XClientRect.Height <= 0)
2635 XClientRect.Height = 1;
2636 if (XClientRect.Width <= 0)
2637 XClientRect.Width = 1;
2638 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);
2642 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2643 throw new Exception("Could not create X11 windows");
2646 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2647 hwnd.WholeWindow = WholeWindow;
2648 hwnd.ClientWindow = ClientWindow;
2650 #if DriverDebug || DriverDebugCreate
2651 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);
2654 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2655 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2658 hints = new XSizeHints();
2661 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2662 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2667 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
2668 if (hwnd.whole_window != hwnd.client_window)
2669 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2672 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2674 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2675 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2677 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2680 SetWMStyles(hwnd, cp);
2682 // set the group leader
2683 XWMHints wm_hints = new XWMHints ();
2685 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2686 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2687 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2689 if (ParentHandle != RootWindow) {
2690 wm_hints.window_group = hwnd.whole_window;
2692 wm_hints.window_group = ParentHandle;
2696 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2699 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2700 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2701 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2702 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2705 // for now make all windows dnd enabled
2706 Dnd.SetAllowDrop (hwnd, true);
2708 // Set caption/window title
2709 Text(hwnd.Handle, cp.Caption);
2711 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2712 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2714 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2715 hwnd.visible = true;
2716 MapWindow(hwnd, WindowType.Both);
2717 if (!(Control.FromHandle(hwnd.Handle) is Form))
2718 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2724 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2725 CreateParams create_params = new CreateParams();
2727 create_params.Caption = "";
2728 create_params.X = X;
2729 create_params.Y = Y;
2730 create_params.Width = Width;
2731 create_params.Height = Height;
2733 create_params.ClassName=XplatUI.DefaultClassName;
2734 create_params.ClassStyle = 0;
2735 create_params.ExStyle=0;
2736 create_params.Parent=IntPtr.Zero;
2737 create_params.Param=0;
2739 return CreateWindow(create_params);
2742 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2744 Bitmap cursor_bitmap;
2752 IntPtr cursor_pixmap;
2759 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2763 // Win32 only allows creation cursors of a certain size
2764 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2765 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2766 cursor_mask = new Bitmap(mask, new Size(width, height));
2768 cursor_bitmap = bitmap;
2772 width = cursor_bitmap.Width;
2773 height = cursor_bitmap.Height;
2775 cursor_bits = new Byte[(width / 8) * height];
2776 mask_bits = new Byte[(width / 8) * height];
2778 for (int y = 0; y < height; y++) {
2779 for (int x = 0; x < width; x++) {
2780 c_pixel = cursor_bitmap.GetPixel(x, y);
2781 m_pixel = cursor_mask.GetPixel(x, y);
2783 and = c_pixel == cursor_pixel;
2784 xor = m_pixel == mask_pixel;
2788 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2789 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2790 } else if (and && !xor) {
2792 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2793 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2795 } else if (and && !xor) {
2797 } else if (and && xor) {
2800 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2801 // we want both to be 0 so nothing to be done
2802 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2803 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2809 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2810 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2814 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2815 fg.red = (ushort)65535;
2816 fg.green = (ushort)65535;
2817 fg.blue = (ushort)65535;
2819 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2821 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2823 XFreePixmap(DisplayHandle, cursor_pixmap);
2824 XFreePixmap(DisplayHandle, mask_pixmap);
2829 internal override IntPtr DefineStdCursor(StdCursor id) {
2830 CursorFontShape shape;
2833 // FIXME - define missing shapes
2836 case StdCursor.AppStarting: {
2837 shape = CursorFontShape.XC_watch;
2841 case StdCursor.Arrow: {
2842 shape = CursorFontShape.XC_top_left_arrow;
2846 case StdCursor.Cross: {
2847 shape = CursorFontShape.XC_crosshair;
2851 case StdCursor.Default: {
2852 shape = CursorFontShape.XC_top_left_arrow;
2856 case StdCursor.Hand: {
2857 shape = CursorFontShape.XC_hand1;
2861 case StdCursor.Help: {
2862 shape = CursorFontShape.XC_question_arrow;
2866 case StdCursor.HSplit: {
2867 shape = CursorFontShape.XC_sb_v_double_arrow;
2871 case StdCursor.IBeam: {
2872 shape = CursorFontShape.XC_xterm;
2876 case StdCursor.No: {
2877 shape = CursorFontShape.XC_circle;
2881 case StdCursor.NoMove2D: {
2882 shape = CursorFontShape.XC_fleur;
2886 case StdCursor.NoMoveHoriz: {
2887 shape = CursorFontShape.XC_fleur;
2891 case StdCursor.NoMoveVert: {
2892 shape = CursorFontShape.XC_fleur;
2896 case StdCursor.PanEast: {
2897 shape = CursorFontShape.XC_fleur;
2901 case StdCursor.PanNE: {
2902 shape = CursorFontShape.XC_fleur;
2906 case StdCursor.PanNorth: {
2907 shape = CursorFontShape.XC_fleur;
2911 case StdCursor.PanNW: {
2912 shape = CursorFontShape.XC_fleur;
2916 case StdCursor.PanSE: {
2917 shape = CursorFontShape.XC_fleur;
2921 case StdCursor.PanSouth: {
2922 shape = CursorFontShape.XC_fleur;
2926 case StdCursor.PanSW: {
2927 shape = CursorFontShape.XC_fleur;
2931 case StdCursor.PanWest: {
2932 shape = CursorFontShape.XC_sizing;
2936 case StdCursor.SizeAll: {
2937 shape = CursorFontShape.XC_fleur;
2941 case StdCursor.SizeNESW: {
2942 shape = CursorFontShape.XC_top_right_corner;
2946 case StdCursor.SizeNS: {
2947 shape = CursorFontShape.XC_sb_v_double_arrow;
2951 case StdCursor.SizeNWSE: {
2952 shape = CursorFontShape.XC_top_left_corner;
2956 case StdCursor.SizeWE: {
2957 shape = CursorFontShape.XC_sb_h_double_arrow;
2961 case StdCursor.UpArrow: {
2962 shape = CursorFontShape.XC_center_ptr;
2966 case StdCursor.VSplit: {
2967 shape = CursorFontShape.XC_sb_h_double_arrow;
2971 case StdCursor.WaitCursor: {
2972 shape = CursorFontShape.XC_watch;
2982 cursor = XCreateFontCursor(DisplayHandle, shape);
2987 internal override IntPtr DefWndProc(ref Message msg) {
2988 switch ((Msg)msg.Msg) {
2989 case Msg.WM_PAINT: {
2992 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2994 hwnd.expose_pending = false;
3000 case Msg.WM_NCPAINT: {
3003 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3005 hwnd.nc_expose_pending = false;
3011 case Msg.WM_NCCALCSIZE: {
3014 if (msg.WParam == (IntPtr)1) {
3015 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3017 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3018 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3020 // Add all the stuff X is supposed to draw.
3021 Control ctrl = Control.FromHandle (hwnd.Handle);
3022 Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3024 ncp.rgrc1.top += rect.top;
3025 ncp.rgrc1.bottom -= rect.bottom;
3026 ncp.rgrc1.left += rect.left;
3027 ncp.rgrc1.right -= rect.right;
3029 Marshal.StructureToPtr (ncp, msg.LParam, true);
3035 case Msg.WM_CONTEXTMENU: {
3038 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3040 if ((hwnd != null) && (hwnd.parent != null)) {
3041 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3046 case Msg.WM_MOUSEWHEEL: {
3049 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3051 if ((hwnd != null) && (hwnd.parent != null)) {
3052 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3053 if (msg.Result == IntPtr.Zero) {
3060 case Msg.WM_SETCURSOR: {
3063 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3065 break; // not sure how this happens, but it does
3067 // Pass to parent window first
3068 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3070 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3073 if (msg.Result == IntPtr.Zero) {
3076 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3077 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
3078 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
3079 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
3080 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
3081 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3084 handle = Cursors.Default.handle;
3087 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
3088 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
3089 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
3090 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
3091 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
3092 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
3095 case HitTest.HTGROWBOX:
3096 case HitTest.HTSIZE:
3097 case HitTest.HTZOOM:
3098 case HitTest.HTVSCROLL:
3099 case HitTest.HTSYSMENU:
3100 case HitTest.HTREDUCE:
3101 case HitTest.HTNOWHERE:
3102 case HitTest.HTMAXBUTTON:
3103 case HitTest.HTMINBUTTON:
3104 case HitTest.HTMENU:
3105 case HitTest.HSCROLL:
3106 case HitTest.HTBOTTOM:
3107 case HitTest.HTCAPTION:
3108 case HitTest.HTCLIENT:
3109 case HitTest.HTCLOSE:
3111 default: handle = Cursors.Default.handle; break;
3113 SetCursor(msg.HWnd, handle);
3121 internal override void DestroyCaret(IntPtr handle) {
3122 if (Caret.Hwnd == handle) {
3123 if (Caret.Visible) {
3127 if (Caret.gc != IntPtr.Zero) {
3128 XFreeGC(DisplayHandle, Caret.gc);
3129 Caret.gc = IntPtr.Zero;
3131 Caret.Hwnd = IntPtr.Zero;
3132 Caret.Visible = false;
3137 internal override void DestroyCursor(IntPtr cursor) {
3139 XFreeCursor(DisplayHandle, cursor);
3143 internal override void DestroyWindow(IntPtr handle) {
3146 hwnd = Hwnd.ObjectFromHandle(handle);
3149 #if DriverDebug || DriverDebugDestroy
3150 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3155 #if DriverDebug || DriverDebugDestroy
3156 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3159 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3161 CleanupCachedWindows (hwnd);
3163 ArrayList windows = new ArrayList ();
3165 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3168 foreach (Hwnd h in windows) {
3169 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3174 if (hwnd.whole_window != IntPtr.Zero) {
3175 #if DriverDebug || DriverDebugDestroy
3176 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3178 XDestroyWindow(DisplayHandle, hwnd.whole_window);
3180 else if (hwnd.client_window != IntPtr.Zero) {
3181 #if DriverDebug || DriverDebugDestroy
3182 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3184 XDestroyWindow(DisplayHandle, hwnd.client_window);
3190 internal override IntPtr DispatchMessage(ref MSG msg) {
3191 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3194 IntPtr GetReversibleScreenGC (Color backColor)
3196 XGCValues gc_values;
3200 XColor xcolor = new XColor();
3201 xcolor.red = (ushort)(backColor.R * 257);
3202 xcolor.green = (ushort)(backColor.G * 257);
3203 xcolor.blue = (ushort)(backColor.B * 257);
3204 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3205 pixel = (uint)xcolor.pixel.ToInt32();
3208 gc_values = new XGCValues();
3210 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3211 gc_values.foreground = (IntPtr)pixel;
3213 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3214 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3215 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3220 IntPtr GetReversibleControlGC (Control control, int line_width)
3222 XGCValues gc_values;
3225 gc_values = new XGCValues();
3227 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3228 gc_values.line_width = line_width;
3229 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3231 // This logic will give us true rubber bands: (libsx, SANE_XOR)
3232 //mask = foreground ^ background;
3233 //XSetForeground(DisplayHandle, gc, 0xffffffff);
3234 //XSetBackground(DisplayHandle, gc, background);
3235 //XSetFunction(DisplayHandle, gc, GXxor);
3236 //XSetPlaneMask(DisplayHandle, gc, mask);
3239 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3243 XColor xcolor = new XColor();
3245 xcolor.red = (ushort)(control.ForeColor.R * 257);
3246 xcolor.green = (ushort)(control.ForeColor.G * 257);
3247 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3248 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3249 foreground = (uint)xcolor.pixel.ToInt32();
3251 xcolor.red = (ushort)(control.BackColor.R * 257);
3252 xcolor.green = (ushort)(control.BackColor.G * 257);
3253 xcolor.blue = (ushort)(control.BackColor.B * 257);
3254 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3255 background = (uint)xcolor.pixel.ToInt32();
3257 uint mask = foreground ^ background;
3259 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3260 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3261 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3262 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3267 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3269 IntPtr gc = GetReversibleScreenGC (backColor);
3271 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3273 XFreeGC(DisplayHandle, gc);
3276 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3278 IntPtr gc = GetReversibleScreenGC (backColor);
3280 if (rectangle.Width < 0) {
3281 rectangle.X += rectangle.Width;
3282 rectangle.Width = -rectangle.Width;
3284 if (rectangle.Height < 0) {
3285 rectangle.Y += rectangle.Height;
3286 rectangle.Height = -rectangle.Height;
3290 GCLineStyle line_style = GCLineStyle.LineSolid;
3291 GCCapStyle cap_style = GCCapStyle.CapButt;
3292 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3295 case FrameStyle.Dashed:
3296 line_style = GCLineStyle.LineOnOffDash;
3298 case FrameStyle.Thick:
3303 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3305 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3307 XFreeGC(DisplayHandle, gc);
3310 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3312 IntPtr gc = GetReversibleScreenGC (backColor);
3314 if (rectangle.Width < 0) {
3315 rectangle.X += rectangle.Width;
3316 rectangle.Width = -rectangle.Width;
3318 if (rectangle.Height < 0) {
3319 rectangle.Y += rectangle.Height;
3320 rectangle.Height = -rectangle.Height;
3322 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3324 XFreeGC(DisplayHandle, gc);
3327 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3329 Control control = Control.FromHandle(handle);
3331 gc = GetReversibleControlGC (control, line_width);
3333 if ((rect.Width > 0) && (rect.Height > 0)) {
3334 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3336 if (rect.Width > 0) {
3337 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3339 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3342 XFreeGC(DisplayHandle, gc);
3345 internal override void DoEvents() {
3346 MSG msg = new MSG ();
3349 if (OverrideCursorHandle != IntPtr.Zero) {
3350 OverrideCursorHandle = IntPtr.Zero;
3353 queue = ThreadQueue(Thread.CurrentThread);
3355 queue.DispatchIdle = false;
3357 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3358 TranslateMessage (ref msg);
3359 DispatchMessage (ref msg);
3362 queue.DispatchIdle = true;
3365 internal override void EnableWindow(IntPtr handle, bool Enable) {
3368 hwnd = Hwnd.ObjectFromHandle(handle);
3370 hwnd.Enabled = Enable;
3374 internal override void EndLoop(Thread thread) {
3375 // This is where we one day will shut down the loop for the thread
3378 internal override IntPtr GetActive() {
3383 IntPtr prop = IntPtr.Zero;
3384 IntPtr active = IntPtr.Zero;
3386 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);
3387 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3388 active = (IntPtr)Marshal.ReadInt32(prop);
3392 if (active != IntPtr.Zero) {
3395 hwnd = Hwnd.GetObjectFromWindow(active);
3397 active = hwnd.Handle;
3399 active = IntPtr.Zero;
3405 internal override Region GetClipRegion(IntPtr handle) {
3408 hwnd = Hwnd.ObjectFromHandle(handle);
3410 return hwnd.UserClip;
3416 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3423 internal override void GetDisplaySize(out Size size) {
3424 XWindowAttributes attributes=new XWindowAttributes();
3427 // FIXME - use _NET_WM messages instead?
3428 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3431 size = new Size(attributes.width, attributes.height);
3434 internal override SizeF GetAutoScaleSize(Font font) {
3437 string magic_string = "The quick brown fox jumped over the lazy dog.";
3438 double magic_number = 44.549996948242189;
3440 g = Graphics.FromHwnd(FosterParent);
3442 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3443 return new SizeF(width, font.Height);
3446 internal override IntPtr GetParent(IntPtr handle) {
3449 hwnd = Hwnd.ObjectFromHandle(handle);
3450 if (hwnd != null && hwnd.parent != null) {
3451 return hwnd.parent.Handle;
3456 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3466 if (handle != IntPtr.Zero) {
3467 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3469 use_handle = RootWindow;
3473 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3476 if (handle != IntPtr.Zero) {
3485 internal override IntPtr GetFocus() {
3490 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3491 FontFamily ff = font.FontFamily;
3492 ascent = ff.GetCellAscent (font.Style);
3493 descent = ff.GetCellDescent (font.Style);
3497 internal override Point GetMenuOrigin(IntPtr handle) {
3500 hwnd = Hwnd.ObjectFromHandle(handle);
3503 return hwnd.MenuOrigin;
3508 [MonoTODO("Implement filtering")]
3509 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3516 if (((XEventQueue)queue_id).Count > 0) {
3517 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3519 UpdateMessageQueue ((XEventQueue)queue_id);
3521 if (((XEventQueue)queue_id).Count > 0) {
3522 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3523 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3524 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3526 msg.hwnd= IntPtr.Zero;
3527 msg.message = Msg.WM_ENTERIDLE;
3532 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3534 // Handle messages for windows that are already or are about to be destroyed.
3536 // we need a special block for this because unless we remove the hwnd from the paint
3537 // queue it will always stay there (since we don't handle the expose), and we'll
3538 // effectively loop infinitely trying to repaint a non-existant window.
3539 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3540 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3541 hwnd.Queue.Paint.Remove (hwnd);
3542 goto ProcessNextMessage;
3545 // We need to make sure we only allow DestroyNotify events through for zombie
3546 // hwnds, since much of the event handling code makes requests using the hwnd's
3547 // client_window, and that'll result in BadWindow errors if there's some lag
3548 // between the XDestroyWindow call and the DestroyNotify event.
3549 if (hwnd == null || hwnd.zombie) {
3550 #if DriverDebug || DriverDebugDestroy
3551 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3553 goto ProcessNextMessage;
3556 if (hwnd.client_window == xevent.AnyEvent.window) {
3558 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3561 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3564 msg.hwnd = hwnd.Handle;
3567 // If you add a new event to this switch make sure to add it in
3568 // UpdateMessage also unless it is not coming through the X event system.
3570 switch(xevent.type) {
3571 case XEventName.KeyPress: {
3573 Dnd.HandleKeyPress (ref xevent);
3574 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3578 case XEventName.KeyRelease: {
3579 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3583 case XEventName.ButtonPress: {
3584 switch(xevent.ButtonEvent.button) {
3586 MouseState |= MouseButtons.Left;
3588 msg.message = Msg.WM_LBUTTONDOWN;
3590 msg.message = Msg.WM_NCLBUTTONDOWN;
3591 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3593 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3594 msg.wParam=GetMousewParam(0);
3599 MouseState |= MouseButtons.Middle;
3601 msg.message = Msg.WM_MBUTTONDOWN;
3603 msg.message = Msg.WM_NCMBUTTONDOWN;
3604 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3606 msg.wParam=GetMousewParam(0);
3611 MouseState |= MouseButtons.Right;
3613 msg.message = Msg.WM_RBUTTONDOWN;
3615 msg.message = Msg.WM_NCRBUTTONDOWN;
3616 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3618 msg.wParam=GetMousewParam(0);
3623 msg.hwnd = FocusWindow;
3624 msg.message=Msg.WM_MOUSEWHEEL;
3625 msg.wParam=GetMousewParam(120);
3630 msg.hwnd = FocusWindow;
3631 msg.message=Msg.WM_MOUSEWHEEL;
3632 msg.wParam=GetMousewParam(-120);
3638 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3639 mouse_position.X = xevent.ButtonEvent.x;
3640 mouse_position.Y = xevent.ButtonEvent.y;
3642 if (!hwnd.Enabled) {
3645 msg.hwnd = hwnd.EnabledHwnd;
3646 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);
3647 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3650 if (Grab.Hwnd != IntPtr.Zero) {
3651 msg.hwnd = Grab.Hwnd;
3654 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3655 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3656 switch(xevent.ButtonEvent.button) {
3658 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3663 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3668 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3672 ClickPending.Pending = false;
3674 ClickPending.Pending = true;
3675 ClickPending.Hwnd = msg.hwnd;
3676 ClickPending.Message = msg.message;
3677 ClickPending.wParam = msg.wParam;
3678 ClickPending.lParam = msg.lParam;
3679 ClickPending.Time = (long)xevent.ButtonEvent.time;
3682 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3683 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3685 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3686 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3687 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3688 XEvent motionEvent = new XEvent ();
3689 motionEvent.type = XEventName.MotionNotify;
3690 motionEvent.MotionEvent.display = DisplayHandle;
3691 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3692 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3693 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3694 hwnd.Queue.EnqueueLocked (motionEvent);
3700 case XEventName.ButtonRelease: {
3702 if (Dnd.HandleButtonRelease (ref xevent)) {
3705 // Allow the LBUTTONUP message to get through
3708 switch(xevent.ButtonEvent.button) {
3711 msg.message = Msg.WM_LBUTTONUP;
3713 msg.message = Msg.WM_NCLBUTTONUP;
3714 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3716 MouseState &= ~MouseButtons.Left;
3717 msg.wParam=GetMousewParam(0);
3723 msg.message = Msg.WM_MBUTTONUP;
3725 msg.message = Msg.WM_NCMBUTTONUP;
3726 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3728 MouseState &= ~MouseButtons.Middle;
3729 msg.wParam=GetMousewParam(0);
3735 msg.message = Msg.WM_RBUTTONUP;
3737 msg.message = Msg.WM_NCRBUTTONUP;
3738 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3740 MouseState &= ~MouseButtons.Right;
3741 msg.wParam=GetMousewParam(0);
3746 goto ProcessNextMessage;
3750 goto ProcessNextMessage;
3754 if (!hwnd.Enabled) {
3757 msg.hwnd = hwnd.EnabledHwnd;
3758 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);
3759 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3762 if (Grab.Hwnd != IntPtr.Zero) {
3763 msg.hwnd = Grab.Hwnd;
3766 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3767 mouse_position.X = xevent.ButtonEvent.x;
3768 mouse_position.Y = xevent.ButtonEvent.y;
3770 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3771 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
3772 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3773 if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3774 XEvent motionEvent = new XEvent ();
3775 motionEvent.type = XEventName.MotionNotify;
3776 motionEvent.MotionEvent.display = DisplayHandle;
3777 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3778 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3779 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3780 hwnd.Queue.EnqueueLocked (motionEvent);
3785 case XEventName.MotionNotify: {
3787 #if DriverDebugExtra
3788 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);
3791 if (Dnd.HandleMotionNotify (ref xevent))
3792 goto ProcessNextMessage;
3793 if (Grab.Hwnd != IntPtr.Zero) {
3794 msg.hwnd = Grab.Hwnd;
3797 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3801 msg.message = Msg.WM_MOUSEMOVE;
3802 msg.wParam = GetMousewParam(0);
3803 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3805 if (!hwnd.Enabled) {
3808 msg.hwnd = hwnd.EnabledHwnd;
3809 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);
3810 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3813 mouse_position.X = xevent.MotionEvent.x;
3814 mouse_position.Y = xevent.MotionEvent.y;
3816 if ((HoverState.Timer.Enabled) &&
3817 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3818 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3819 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3820 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3821 HoverState.Timer.Stop();
3822 HoverState.Timer.Start();
3823 HoverState.X = mouse_position.X;
3824 HoverState.Y = mouse_position.Y;
3834 #if DriverDebugExtra
3835 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);
3837 msg.message = Msg.WM_NCMOUSEMOVE;
3839 if (!hwnd.Enabled) {
3840 msg.hwnd = hwnd.EnabledHwnd;
3841 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);
3842 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3845 // The hit test is sent in screen coordinates
3846 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3847 xevent.MotionEvent.x, xevent.MotionEvent.y,
3848 out screen_x, out screen_y, out dummy);
3850 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3851 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3852 IntPtr.Zero, msg.lParam).ToInt32 ();
3853 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3855 mouse_position.X = xevent.MotionEvent.x;
3856 mouse_position.Y = xevent.MotionEvent.y;
3862 case XEventName.EnterNotify: {
3863 if (!hwnd.Enabled) {
3864 goto ProcessNextMessage;
3866 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3867 goto ProcessNextMessage;
3869 msg.message = Msg.WM_MOUSE_ENTER;
3870 HoverState.X = xevent.CrossingEvent.x;
3871 HoverState.Y = xevent.CrossingEvent.y;
3872 HoverState.Timer.Enabled = true;
3873 HoverState.Window = xevent.CrossingEvent.window;
3877 case XEventName.LeaveNotify: {
3878 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3879 WindowUngrabbed (hwnd.Handle);
3880 goto ProcessNextMessage;
3882 if (!hwnd.Enabled) {
3883 goto ProcessNextMessage;
3885 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3886 goto ProcessNextMessage;
3888 msg.message=Msg.WM_MOUSELEAVE;
3889 HoverState.Timer.Enabled = false;
3890 HoverState.Window = IntPtr.Zero;
3895 case XEventName.CreateNotify: {
3896 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3897 msg.message = WM_CREATE;
3898 // Set up CreateStruct
3900 goto ProcessNextMessage;
3907 case XEventName.ReparentNotify: {
3908 if (hwnd.parent == null) { // Toplevel
3909 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3910 hwnd.Reparented = true;
3912 // The location given by the event is not reliable between different wm's,
3913 // so use an alternative way of getting it.
3914 Point location = GetTopLevelWindowLocation (hwnd);
3915 hwnd.X = location.X;
3916 hwnd.Y = location.Y;
3918 if (hwnd.opacity != 0xffffffff) {
3921 opacity = (IntPtr)(Int32)hwnd.opacity;
3922 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3924 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3925 goto ProcessNextMessage;
3927 hwnd.Reparented = false;
3928 goto ProcessNextMessage;
3931 goto ProcessNextMessage;
3934 case XEventName.ConfigureNotify: {
3935 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3936 #if DriverDebugExtra
3937 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);
3939 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3940 lock (hwnd.configure_lock) {
3941 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3942 hwnd.configure_pending = false;
3945 // We need to adjust our client window to track the resize of whole_window
3946 if (hwnd.whole_window != hwnd.client_window)
3947 PerformNCCalc(hwnd);
3950 goto ProcessNextMessage;
3953 case XEventName.FocusIn: {
3954 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3955 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3956 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3957 // about it having focus again
3958 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3959 goto ProcessNextMessage;
3962 if (FocusWindow == IntPtr.Zero) {
3963 Control c = Control.FromHandle (hwnd.client_window);
3965 goto ProcessNextMessage;
3966 Form form = c.FindForm ();
3968 goto ProcessNextMessage;
3969 if (ActiveWindow != form.Handle) {
3970 ActiveWindow = form.Handle;
3971 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3973 goto ProcessNextMessage;
3975 Keyboard.FocusIn(FocusWindow);
3976 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3977 goto ProcessNextMessage;
3980 case XEventName.FocusOut: {
3981 // Se the comment for our FocusIn handler
3982 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3983 goto ProcessNextMessage;
3985 Keyboard.FocusOut(FocusWindow);
3987 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3988 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3991 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3992 goto ProcessNextMessage;
3995 case XEventName.MapNotify: {
3996 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3998 msg.message = Msg.WM_SHOWWINDOW;
3999 msg.wParam = (IntPtr) 1;
4000 // XXX we're missing the lParam..
4003 goto ProcessNextMessage;
4006 case XEventName.UnmapNotify: {
4007 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4008 hwnd.mapped = false;
4009 msg.message = Msg.WM_SHOWWINDOW;
4010 msg.wParam = (IntPtr) 0;
4011 // XXX we're missing the lParam..
4014 goto ProcessNextMessage;
4017 case XEventName.Expose: {
4020 hwnd.expose_pending = false;
4022 hwnd.nc_expose_pending = false;
4024 goto ProcessNextMessage;
4028 if (!hwnd.expose_pending) {
4029 goto ProcessNextMessage;
4032 if (!hwnd.nc_expose_pending) {
4033 goto ProcessNextMessage;
4036 switch (hwnd.border_style) {
4037 case FormBorderStyle.Fixed3D: {
4040 g = Graphics.FromHwnd(hwnd.whole_window);
4041 if (hwnd.border_static)
4042 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4044 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4049 case FormBorderStyle.FixedSingle: {
4052 g = Graphics.FromHwnd(hwnd.whole_window);
4053 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4058 #if DriverDebugExtra
4059 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);
4062 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4063 Region region = new Region (rect);
4064 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4065 msg.message = Msg.WM_NCPAINT;
4066 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4067 msg.refobject = region;
4070 #if DriverDebugExtra
4071 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);
4073 if (Caret.Visible == true) {
4074 Caret.Paused = true;
4078 if (Caret.Visible == true) {
4080 Caret.Paused = false;
4082 msg.message = Msg.WM_PAINT;
4086 case XEventName.DestroyNotify: {
4088 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4089 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4091 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4092 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4093 CleanupCachedWindows (hwnd);
4095 #if DriverDebugDestroy
4096 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4099 msg.hwnd = hwnd.client_window;
4100 msg.message=Msg.WM_DESTROY;
4103 goto ProcessNextMessage;
4109 case XEventName.ClientMessage: {
4110 if (Dnd.HandleClientMessage (ref xevent)) {
4111 goto ProcessNextMessage;
4114 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4115 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4116 goto ProcessNextMessage;
4119 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4120 msg.message = Msg.WM_MOUSEHOVER;
4121 msg.wParam = GetMousewParam(0);
4122 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4126 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4127 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4128 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4129 msg.wParam = xevent.ClientMessageEvent.ptr3;
4130 msg.lParam = xevent.ClientMessageEvent.ptr4;
4131 if (msg.message == (Msg)Msg.WM_QUIT)
4137 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
4138 #if DriverDebugXEmbed
4139 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4142 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4143 XSizeHints hints = new XSizeHints();
4146 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4148 hwnd.width = hints.max_width;
4149 hwnd.height = hints.max_height;
4150 hwnd.ClientRect = Rectangle.Empty;
4151 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4155 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4156 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4157 msg.message = Msg.WM_CLOSE;
4161 // We should not get this, but I'll leave the code in case we need it in the future
4162 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4163 goto ProcessNextMessage;
4166 goto ProcessNextMessage;
4170 goto ProcessNextMessage;
4177 internal override bool GetText(IntPtr handle, out string text) {
4184 IntPtr prop = IntPtr.Zero;
4186 XGetWindowProperty(DisplayHandle, handle,
4187 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4188 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4190 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4191 text = Marshal.PtrToStringUni (prop, (int)nitems);
4196 // fallback on the non-_NET property
4199 textptr = IntPtr.Zero;
4201 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4202 if (textptr != IntPtr.Zero) {
4203 text = Marshal.PtrToStringAnsi(textptr);
4214 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) {
4217 hwnd = Hwnd.ObjectFromHandle(handle);
4223 height = hwnd.height;
4225 PerformNCCalc(hwnd);
4227 client_width = hwnd.ClientRect.Width;
4228 client_height = hwnd.ClientRect.Height;
4233 // Should we throw an exception or fail silently?
4234 // throw new ArgumentException("Called with an invalid window handle", "handle");
4244 internal override FormWindowState GetWindowState(IntPtr handle) {
4247 hwnd = Hwnd.ObjectFromHandle(handle);
4249 if (hwnd.cached_window_state == (FormWindowState)(-1))
4250 hwnd.cached_window_state = UpdateWindowState (handle);
4252 return hwnd.cached_window_state;
4255 private FormWindowState UpdateWindowState (IntPtr handle) {
4260 IntPtr prop = IntPtr.Zero;
4264 XWindowAttributes attributes;
4267 hwnd = Hwnd.ObjectFromHandle(handle);
4271 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);
4272 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4273 for (int i = 0; i < (long)nitems; i++) {
4274 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4275 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4277 } else if (atom == _NET_WM_STATE_HIDDEN) {
4285 return FormWindowState.Minimized;
4286 } else if (maximized == 2) {
4287 return FormWindowState.Maximized;
4290 attributes = new XWindowAttributes();
4291 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4292 if (attributes.map_state == MapState.IsUnmapped) {
4293 return (FormWindowState)(-1);
4297 return FormWindowState.Normal;
4300 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4302 GrabConfined = Grab.Confined;
4303 GrabArea = Grab.Area;
4306 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4308 IntPtr confine_to_window;
4310 confine_to_window = IntPtr.Zero;
4312 if (confine_to_handle != IntPtr.Zero) {
4313 XWindowAttributes attributes = new XWindowAttributes();
4315 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4318 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4320 Grab.Area.X = attributes.x;
4321 Grab.Area.Y = attributes.y;
4322 Grab.Area.Width = attributes.width;
4323 Grab.Area.Height = attributes.height;
4324 Grab.Confined = true;
4325 confine_to_window = hwnd.client_window;
4330 hwnd = Hwnd.ObjectFromHandle(handle);
4333 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4334 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4335 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4336 EventMask.LeaveWindowMask,
4337 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4341 internal override void UngrabWindow(IntPtr hwnd) {
4343 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4344 XFlush(DisplayHandle);
4346 WindowUngrabbed (hwnd);
4349 private void WindowUngrabbed (IntPtr hwnd) {
4350 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4352 Grab.Hwnd = IntPtr.Zero;
4353 Grab.Confined = false;
4356 // lparam should be the handle to the window gaining the mouse capture,
4357 // but X doesn't seem to give us that information.
4358 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4359 // X will send a NotifyUngrab, but since it comes late sometimes we're
4360 // calling WindowUngrabbed directly from UngrabWindow in order to send
4361 // this WM right away.
4362 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4366 internal override void HandleException(Exception e) {
4367 StackTrace st = new StackTrace(e, true);
4368 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4369 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4372 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4375 hwnd = Hwnd.ObjectFromHandle(handle);
4378 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4380 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4384 internal override void InvalidateNC (IntPtr handle) {
4387 hwnd = Hwnd.ObjectFromHandle(handle);
4389 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4392 internal override bool IsEnabled(IntPtr handle) {
4393 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4394 return (hwnd != null && hwnd.Enabled);
4397 internal override bool IsVisible(IntPtr handle) {
4398 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4399 return (hwnd != null && hwnd.visible);
4402 internal override void KillTimer(Timer timer) {
4403 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4405 if (queue == null) {
4406 // This isn't really an error, MS doesn't start the timer if
4407 // it has no assosciated queue
4410 queue.timer_list.Remove (timer);
4413 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4419 hwnd = Hwnd.ObjectFromHandle(handle);
4422 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4429 internal override void OverrideCursor(IntPtr cursor)
4431 if (Grab.Hwnd != IntPtr.Zero) {
4432 XChangeActivePointerGrab (DisplayHandle,
4433 EventMask.ButtonMotionMask |
4434 EventMask.PointerMotionMask |
4435 EventMask.ButtonPressMask |
4436 EventMask.ButtonReleaseMask,
4437 cursor, IntPtr.Zero);
4441 OverrideCursorHandle = cursor;
4444 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4445 PaintEventArgs paint_event;
4448 hwnd = Hwnd.ObjectFromHandle(handle);
4450 if (Caret.Visible == true) {
4451 Caret.Paused = true;
4458 dc = Graphics.FromHwnd (hwnd.client_window);
4460 Region clip_region = new Region ();
4461 clip_region.MakeEmpty();
4463 foreach (Rectangle r in hwnd.ClipRectangles) {
4464 clip_region.Union (r);
4467 if (hwnd.UserClip != null) {
4468 clip_region.Intersect(hwnd.UserClip);
4471 dc.Clip = clip_region;
4472 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4473 hwnd.expose_pending = false;
4475 hwnd.ClearInvalidArea();
4477 hwnd.drawing_stack.Push (paint_event);
4478 hwnd.drawing_stack.Push (dc);
4482 dc = Graphics.FromHwnd (hwnd.whole_window);
4484 if (!hwnd.nc_invalid.IsEmpty) {
4485 dc.SetClip (hwnd.nc_invalid);
4486 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4488 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4490 hwnd.nc_expose_pending = false;
4492 hwnd.ClearNcInvalidArea ();
4494 hwnd.drawing_stack.Push (paint_event);
4495 hwnd.drawing_stack.Push (dc);
4501 internal override void PaintEventEnd(IntPtr handle, bool client) {
4504 hwnd = Hwnd.ObjectFromHandle(handle);
4506 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4510 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4511 pe.SetGraphics (null);
4514 if (Caret.Visible == true) {
4516 Caret.Paused = false;
4520 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4521 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4522 XEventQueue queue = (XEventQueue) queue_id;
4525 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4526 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4530 if (queue.Count > 0) {
4533 // Only call UpdateMessageQueue if real events are pending
4534 // otherwise we go to sleep on the socket
4535 if (XPending(DisplayHandle) != 0) {
4536 UpdateMessageQueue((XEventQueue)queue_id);
4538 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4543 CheckTimers(queue.timer_list, DateTime.UtcNow);
4548 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4551 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4552 XEvent xevent = new XEvent ();
4553 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4555 xevent.type = XEventName.ClientMessage;
4556 xevent.ClientMessageEvent.display = DisplayHandle;
4559 xevent.ClientMessageEvent.window = hwnd.whole_window;
4561 xevent.ClientMessageEvent.window = IntPtr.Zero;
4564 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4565 xevent.ClientMessageEvent.format = 32;
4566 xevent.ClientMessageEvent.ptr1 = handle;
4567 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4568 xevent.ClientMessageEvent.ptr3 = wparam;
4569 xevent.ClientMessageEvent.ptr4 = lparam;
4571 hwnd.Queue.EnqueueLocked (xevent);
4576 internal override void PostQuitMessage(int exitCode) {
4577 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4578 XFlush(DisplayHandle);
4581 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4586 internal override void RequestNCRecalc(IntPtr handle) {
4589 hwnd = Hwnd.ObjectFromHandle(handle);
4595 PerformNCCalc(hwnd);
4596 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4597 InvalidateNC(handle);
4600 internal override void ResetMouseHover(IntPtr handle) {
4603 hwnd = Hwnd.ObjectFromHandle(handle);
4608 HoverState.Timer.Enabled = true;
4609 HoverState.X = mouse_position.X;
4610 HoverState.Y = mouse_position.Y;
4611 HoverState.Window = handle;
4615 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4621 hwnd = Hwnd.ObjectFromHandle(handle);
4624 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4631 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4637 hwnd = Hwnd.ObjectFromHandle(handle);
4640 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4647 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4650 XGCValues gc_values;
4652 hwnd = Hwnd.ObjectFromHandle(handle);
4654 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4656 /* We have an invalid area in the window we're scrolling.
4657 Adjust our stored invalid rectangle to to match the scrolled amount */
4672 if (area.Contains (hwnd.Invalid))
4673 hwnd.ClearInvalidArea ();
4674 hwnd.AddInvalidArea(r);
4677 gc_values = new XGCValues();
4679 if (with_children) {
4680 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4683 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4691 height = area.Height - YAmount;
4692 dest_y = area.Y + YAmount;
4695 src_y = area.Y - YAmount;
4696 height = area.Height + YAmount;
4702 width = area.Width - XAmount;
4703 dest_x = area.X + XAmount;
4706 src_x = area.X - XAmount;
4707 width = area.Width + XAmount;
4711 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4713 // Generate an expose for the area exposed by the horizontal scroll
4714 // We don't use AddExpose since we're
4716 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4717 } else if (XAmount < 0) {
4718 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4721 // Generate an expose for the area exposed by the vertical scroll
4723 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4724 } else if (YAmount < 0) {
4725 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4727 XFreeGC(DisplayHandle, gc);
4730 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4734 hwnd = Hwnd.GetObjectFromWindow(handle);
4736 rect = hwnd.ClientRect;
4739 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4742 internal override void SendAsyncMethod (AsyncMethodData method) {
4744 XEvent xevent = new XEvent ();
4746 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4748 xevent.type = XEventName.ClientMessage;
4749 xevent.ClientMessageEvent.display = DisplayHandle;
4750 xevent.ClientMessageEvent.window = method.Handle;
4751 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4752 xevent.ClientMessageEvent.format = 32;
4753 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4755 hwnd.Queue.EnqueueLocked (xevent);
4760 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4762 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4765 h = Hwnd.ObjectFromHandle(hwnd);
4767 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4768 AsyncMethodResult result;
4769 AsyncMethodData data;
4771 result = new AsyncMethodResult ();
4772 data = new AsyncMethodData ();
4775 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4776 data.Args = new object[] { hwnd, message, wParam, lParam };
4777 data.Result = result;
4779 SendAsyncMethod (data);
4780 #if DriverDebug || DriverDebugThreads
4781 Console.WriteLine ("Sending {0} message across.", message);
4786 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4789 internal override int SendInput(IntPtr handle, Queue keys) {
4790 if (handle == IntPtr.Zero)
4793 int count = keys.Count;
4794 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4796 while (keys.Count > 0) {
4798 MSG msg = (MSG)keys.Dequeue();
4800 XEvent xevent = new XEvent ();
4802 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4803 xevent.KeyEvent.display = DisplayHandle;
4806 xevent.KeyEvent.window = hwnd.whole_window;
4808 xevent.KeyEvent.window = IntPtr.Zero;
4811 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4813 hwnd.Queue.EnqueueLocked (xevent);
4818 internal override void SetAllowDrop (IntPtr handle, bool value)
4820 // We allow drop on all windows
4823 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4824 DragDropEffects allowed_effects)
4826 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4829 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4831 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4834 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4835 Form form = Control.FromHandle (handle) as Form;
4836 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4837 border_style == FormBorderStyle.SizableToolWindow)) {
4838 form.window_manager = new ToolWindowManager (form);
4841 RequestNCRecalc(handle);
4844 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4845 if (Caret.Hwnd == handle) {
4852 if (Caret.Visible == true) {
4854 Caret.Timer.Start();
4859 internal override void SetClipRegion(IntPtr handle, Region region) {
4862 hwnd = Hwnd.ObjectFromHandle(handle);
4867 hwnd.UserClip = region;
4868 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4871 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4874 if (OverrideCursorHandle == IntPtr.Zero) {
4875 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4879 LastCursorHandle = cursor;
4880 LastCursorWindow = handle;
4882 hwnd = Hwnd.ObjectFromHandle(handle);
4884 if (cursor != IntPtr.Zero) {
4885 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4887 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4889 XFlush(DisplayHandle);
4894 hwnd = Hwnd.ObjectFromHandle(handle);
4896 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4900 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4901 out int root_x, out int root_y, out int child_x, out int child_y,
4904 /* this code was written with the help of
4905 glance at gdk. I never would have realized we
4906 needed a loop in order to traverse down in the
4907 hierarchy. I would have assumed you'd get the
4908 most deeply nested child and have to do
4909 XQueryTree to move back up the hierarchy..
4910 stupid me, of course. */
4913 XGrabServer (display);
4915 XQueryPointer(display, w, out root, out c,
4916 out root_x, out root_y, out child_x, out child_y,
4922 IntPtr child_last = IntPtr.Zero;
4923 while (c != IntPtr.Zero) {
4925 XQueryPointer(display, c, out root, out c,
4926 out root_x, out root_y, out child_x, out child_y,
4929 XUngrabServer (display);
4935 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4936 if (handle == IntPtr.Zero) {
4939 int root_x, root_y, child_x, child_y, mask;
4942 * QueryPointer before warping
4943 * because if the warp is on
4944 * the RootWindow, the x/y are
4945 * relative to the current
4948 QueryPointer (DisplayHandle, RootWindow,
4951 out root_x, out root_y,
4952 out child_x, out child_y,
4955 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4957 XFlush (DisplayHandle);
4959 /* then we need to a
4960 * QueryPointer after warping
4961 * to manually generate a
4962 * motion event for the window
4965 QueryPointer (DisplayHandle, RootWindow,
4968 out root_x, out root_y,
4969 out child_x, out child_y,
4972 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4973 if (child_hwnd == null) {
4977 XEvent xevent = new XEvent ();
4979 xevent.type = XEventName.MotionNotify;
4980 xevent.MotionEvent.display = DisplayHandle;
4981 xevent.MotionEvent.window = child_hwnd.client_window;
4982 xevent.MotionEvent.root = RootWindow;
4983 xevent.MotionEvent.x = child_x;
4984 xevent.MotionEvent.y = child_y;
4985 xevent.MotionEvent.x_root = root_x;
4986 xevent.MotionEvent.y_root = root_y;
4987 xevent.MotionEvent.state = mask;
4989 child_hwnd.Queue.EnqueueLocked (xevent);
4994 hwnd = Hwnd.ObjectFromHandle(handle);
4996 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5001 internal override void SetFocus(IntPtr handle) {
5003 IntPtr prev_focus_window;
5005 hwnd = Hwnd.ObjectFromHandle(handle);
5007 if (hwnd.client_window == FocusWindow) {
5011 prev_focus_window = FocusWindow;
5012 FocusWindow = hwnd.client_window;
5014 if (prev_focus_window != IntPtr.Zero) {
5015 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5017 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5019 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5022 internal override void SetIcon(IntPtr handle, Icon icon) {
5025 hwnd = Hwnd.ObjectFromHandle(handle);
5027 SetIcon(hwnd, icon);
5031 internal override void SetMenu(IntPtr handle, Menu menu) {
5034 hwnd = Hwnd.ObjectFromHandle(handle);
5037 RequestNCRecalc(handle);
5040 internal override void SetModal(IntPtr handle, bool Modal) {
5042 ModalWindows.Push(handle);
5044 if (ModalWindows.Contains(handle)) {
5047 if (ModalWindows.Count > 0) {
5048 Activate((IntPtr)ModalWindows.Peek());
5052 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5053 Control ctrl = Control.FromHandle (handle);
5054 SetWMStyles (hwnd, ctrl.GetCreateParams ());
5057 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5060 hwnd = Hwnd.ObjectFromHandle(handle);
5061 hwnd.parent = Hwnd.ObjectFromHandle(parent);
5064 #if DriverDebug || DriverDebugParent
5065 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5067 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5073 internal override void SetTimer (Timer timer) {
5074 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5076 if (queue == null) {
5077 // This isn't really an error, MS doesn't start the timer if
5078 // it has no assosciated queue
5081 queue.timer_list.Add (timer);
5085 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5087 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5091 int[] atoms = new int[8];
5092 atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5093 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5097 XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5103 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5107 hwnd = Hwnd.ObjectFromHandle(handle);
5109 if (handle_owner != IntPtr.Zero) {
5110 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5116 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5117 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5119 if (hwnd_owner != null) {
5120 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5122 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5127 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5133 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5137 hwnd = Hwnd.ObjectFromHandle(handle);
5138 hwnd.visible = visible;
5142 MapWindow(hwnd, WindowType.Both);
5144 if (Control.FromHandle(handle) is Form) {
5147 s = ((Form)Control.FromHandle(handle)).WindowState;
5150 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5151 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5155 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5158 UnmapWindow(hwnd, WindowType.Both);
5164 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5169 hwnd = Hwnd.ObjectFromHandle(handle);
5174 hints = new XSizeHints();
5176 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5177 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5178 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5179 hints.min_width = min.Width;
5180 hints.min_height = min.Height;
5183 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5184 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5185 hints.max_width = max.Width;
5186 hints.max_height = max.Height;
5189 if (hints.flags != IntPtr.Zero) {
5190 // The Metacity team has decided that they won't care about this when clicking the maximize icon,
5191 // they will maximize the window to fill the screen/parent no matter what.
5192 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5193 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5196 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5197 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5198 hints.x = maximized.X;
5199 hints.y = maximized.Y;
5200 hints.width = maximized.Width;
5201 hints.height = maximized.Height;
5203 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5204 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5209 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5212 hwnd = Hwnd.ObjectFromHandle(handle);
5218 // Win32 automatically changes negative width/height to 0.
5224 // X requires a sanity check for width & height; otherwise it dies
5225 if (hwnd.zero_sized && width > 0 && height > 0) {
5227 MapWindow(hwnd, WindowType.Whole);
5229 hwnd.zero_sized = false;
5232 if ((width < 1) || (height < 1)) {
5233 hwnd.zero_sized = true;
5234 UnmapWindow(hwnd, WindowType.Whole);
5237 // Save a server roundtrip (and prevent a feedback loop)
5238 if ((hwnd.x == x) && (hwnd.y == y) &&
5239 (hwnd.width == width) && (hwnd.height == height)) {
5243 if (!hwnd.zero_sized) {
5248 hwnd.height = height;
5249 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5251 if (hwnd.fixed_size) {
5252 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5256 Control ctrl = Control.FromHandle (handle);
5257 Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams ());
5258 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5259 PerformNCCalc(hwnd);
5263 // Update our position/size immediately, so
5264 // that future calls to SetWindowPos aren't
5265 // kept from calling XMoveResizeWindow (by the
5266 // "Save a server roundtrip" block above).
5270 hwnd.height = height;
5271 hwnd.ClientRect = Rectangle.Empty;
5274 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5275 FormWindowState current_state;
5278 hwnd = Hwnd.ObjectFromHandle(handle);
5280 current_state = GetWindowState(handle);
5282 if (current_state == state) {
5287 case FormWindowState.Normal: {
5289 if (current_state == FormWindowState.Minimized) {
5290 MapWindow(hwnd, WindowType.Both);
5291 } else if (current_state == FormWindowState.Maximized) {
5292 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5299 case FormWindowState.Minimized: {
5301 if (current_state == FormWindowState.Maximized) {
5302 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5304 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5309 case FormWindowState.Maximized: {
5311 if (current_state == FormWindowState.Minimized) {
5312 MapWindow(hwnd, WindowType.Both);
5315 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5323 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5326 hwnd = Hwnd.ObjectFromHandle(handle);
5327 SetHwndStyles(hwnd, cp);
5328 SetWMStyles(hwnd, cp);
5331 internal override double GetWindowTransparency(IntPtr handle)
5336 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5340 hwnd = Hwnd.ObjectFromHandle(handle);
5346 hwnd.opacity = (uint)(0xffffffff * transparency);
5347 opacity = (IntPtr)((int)hwnd.opacity);
5349 IntPtr w = hwnd.whole_window;
5350 if (hwnd.reparented)
5351 w = XGetParent (hwnd.whole_window);
5352 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5355 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5356 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5364 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5367 } else if (!bottom) {
5368 Hwnd after_hwnd = null;
5370 if (after_handle != IntPtr.Zero) {
5371 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5374 XWindowChanges values = new XWindowChanges();
5376 if (after_hwnd == null) {
5377 // Work around metacity 'issues'
5381 atoms[0] = unixtime();
5382 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5384 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5385 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5387 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5390 values.sibling = after_hwnd.whole_window;
5391 values.stack_mode = StackMode.Below;
5394 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5399 XLowerWindow(DisplayHandle, hwnd.whole_window);
5406 internal override void ShowCursor(bool show) {
5407 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5410 internal override object StartLoop(Thread thread) {
5411 XEventQueue q = ThreadQueue(thread);
5415 internal override TransparencySupport SupportsTransparency() {
5416 // We need to check if the x compositing manager is running
5417 return TransparencySupport.Set;
5420 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5421 GetSystrayManagerWindow();
5423 if (SystrayMgrWindow != IntPtr.Zero) {
5424 XSizeHints size_hints;
5427 hwnd = Hwnd.ObjectFromHandle(handle);
5429 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5433 if (hwnd.client_window != hwnd.whole_window) {
5434 XDestroyWindow(DisplayHandle, hwnd.client_window);
5435 hwnd.client_window = hwnd.whole_window;
5437 /* by virtue of the way the tests are ordered when determining if it's PAINT
5438 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5439 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5440 there's a pending expose). */
5441 if (hwnd.nc_expose_pending) {
5442 hwnd.nc_expose_pending = false;
5443 if (!hwnd.expose_pending)
5444 hwnd.Queue.Paint.Remove (hwnd);
5448 size_hints = new XSizeHints();
5450 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5452 size_hints.min_width = 24;
5453 size_hints.min_height = 24;
5454 size_hints.max_width = 24;
5455 size_hints.max_height = 24;
5456 size_hints.base_width = 24;
5457 size_hints.base_height = 24;
5459 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5461 int[] atoms = new int[2];
5462 atoms [0] = 1; // Version 1
5463 atoms [1] = 1; // we want to be mapped
5465 // This line cost me 3 days...
5466 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5468 // Need to pick some reasonable defaults
5470 tt.AutomaticDelay = 350;
5471 tt.InitialDelay = 250;
5472 tt.ReshowDelay = 250;
5473 tt.ShowAlways = true;
5475 if ((tip != null) && (tip != string.Empty)) {
5476 tt.SetToolTip(Control.FromHandle(handle), tip);
5482 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5490 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5493 control = Control.FromHandle(handle);
5494 if (control != null && tt != null) {
5495 tt.SetToolTip(control, tip);
5503 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5505 #if GTKSOCKET_SUPPORTS_REPARENTING
5508 hwnd = Hwnd.ObjectFromHandle(handle);
5510 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5511 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5512 * 2. The client can reparent its window out of the embedder window.
5513 * 3. The client can destroy its window.
5515 * this call to SetParent is case 2, but in
5516 * the spec it also mentions that gtk doesn't
5517 * support this at present. Looking at HEAD
5518 * gtksocket-x11.c jives with this statement.
5520 * so we can't reparent. we have to destroy.
5522 SetParent(hwnd.whole_window, FosterParent);
5524 Control control = Control.FromHandle(handle);
5525 if (control is NotifyIcon.NotifyIconWindow)
5526 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5529 // The caller can now re-dock it later...
5537 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5539 ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5540 SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
5544 internal override bool Text(IntPtr handle, string text) {
5547 hwnd = Hwnd.ObjectFromHandle(handle);
5550 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5551 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5553 // XXX this has problems with UTF8.
5554 // we need to either use the actual
5555 // text if it's latin-1, or convert it
5556 // to compound text if it's in a
5557 // different charset.
5558 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5563 internal override bool TranslateMessage(ref MSG msg) {
5564 return Keyboard.TranslateMessage (ref msg);
5567 internal override void UpdateWindow(IntPtr handle) {
5570 hwnd = Hwnd.ObjectFromHandle(handle);
5572 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5576 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5577 hwnd.Queue.Paint.Remove(hwnd);
5580 internal override void CreateOffscreenDrawable (IntPtr handle,
5581 int width, int height,
5582 out object offscreen_drawable)
5585 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5587 XGetGeometry (DisplayHandle, handle,
5589 out x_out, out y_out,
5590 out width_out, out height_out,
5591 out border_width_out, out depth_out);
5593 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5595 offscreen_drawable = pixmap;
5599 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5601 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5604 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5606 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5609 internal override void BlitFromOffscreen (IntPtr dest_handle,
5611 object offscreen_drawable,
5612 Graphics offscreen_dc,
5615 XGCValues gc_values;
5618 gc_values = new XGCValues();
5620 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5622 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5623 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5625 XFreeGC (DisplayHandle, gc);
5628 #endregion // Public Static Methods
5631 internal override event EventHandler Idle;
5632 #endregion // Events
5635 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5636 internal extern static IntPtr XOpenDisplay(IntPtr display);
5637 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5638 internal extern static int XCloseDisplay(IntPtr display);
5639 [DllImport ("libX11", EntryPoint="XSynchronize")]
5640 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5642 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5643 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);
5644 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5645 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5646 [DllImport ("libX11", EntryPoint="XMapWindow")]
5647 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5648 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5649 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5650 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5651 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5652 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5653 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5654 [DllImport ("libX11", EntryPoint="XRootWindow")]
5655 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5656 [DllImport ("libX11", EntryPoint="XNextEvent")]
5657 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5658 [DllImport ("libX11")]
5659 internal extern static int XConnectionNumber (IntPtr diplay);
5660 [DllImport ("libX11")]
5661 internal extern static int XPending (IntPtr diplay);
5662 [DllImport ("libX11", EntryPoint="XSelectInput")]
5663 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5665 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5666 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5668 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5669 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5670 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5671 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5673 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5674 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5676 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5677 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5679 [DllImport ("libX11", EntryPoint="XFlush")]
5680 internal extern static int XFlush(IntPtr display);
5682 [DllImport ("libX11", EntryPoint="XSetWMName")]
5683 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5685 [DllImport ("libX11", EntryPoint="XStoreName")]
5686 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5688 [DllImport ("libX11", EntryPoint="XFetchName")]
5689 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5691 [DllImport ("libX11", EntryPoint="XSendEvent")]
5692 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5694 [DllImport ("libX11", EntryPoint="XQueryTree")]
5695 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);
5697 [DllImport ("libX11", EntryPoint="XFree")]
5698 internal extern static int XFree(IntPtr data);
5700 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5701 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5703 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5704 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5706 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5707 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5709 [DllImport ("libX11", EntryPoint="XInternAtom")]
5710 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5712 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5713 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5715 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5716 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5718 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5719 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);
5721 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5722 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5724 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5725 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);
5727 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5728 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);
5730 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5731 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);
5733 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5734 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);
5736 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5737 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);
5739 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5740 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);
5742 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5743 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);
5745 [DllImport ("libX11", EntryPoint="XClearWindow")]
5746 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5748 [DllImport ("libX11", EntryPoint="XClearArea")]
5749 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5752 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5753 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5755 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5756 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5758 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5759 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5761 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5762 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5764 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5765 internal extern static int XDefaultScreen(IntPtr display);
5767 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5768 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5770 [DllImport ("libX11", EntryPoint="XLookupColor")]
5771 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5773 [DllImport ("libX11", EntryPoint="XAllocColor")]
5774 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5776 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5777 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5779 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5780 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5782 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5783 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5785 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5786 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5788 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5789 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5791 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5792 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5794 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5795 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5797 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5798 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5800 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5801 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5803 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5804 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5807 [DllImport ("libX11", EntryPoint="XCreateGC")]
5808 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5810 [DllImport ("libX11", EntryPoint="XFreeGC")]
5811 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5813 [DllImport ("libX11", EntryPoint="XSetFunction")]
5814 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5816 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5817 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5819 [DllImport ("libX11", EntryPoint="XDrawLine")]
5820 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5822 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5823 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5825 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5826 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5828 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5829 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5831 [DllImport ("libX11", EntryPoint="XCopyArea")]
5832 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);
5834 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5835 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);
5837 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5838 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5840 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5841 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5843 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5844 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5846 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5847 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5849 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5850 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5852 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5853 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5855 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5856 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);
5858 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5859 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5861 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5862 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5864 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5865 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5867 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5868 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5870 [DllImport ("libX11", EntryPoint="XQueryExtension")]
5871 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
5873 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5874 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5876 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5877 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5879 [DllImport ("libX11", EntryPoint="XGrabServer")]
5880 internal extern static void XGrabServer(IntPtr display);
5882 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5883 internal extern static void XUngrabServer(IntPtr display);
5885 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5886 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5888 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5889 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5891 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5892 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5894 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5895 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5897 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5898 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5900 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5901 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5903 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5904 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5906 [DllImport ("libX11", EntryPoint="XInitThreads")]
5907 internal extern static int XInitThreads();
5909 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5910 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5912 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5913 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5915 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5916 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5918 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5919 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5921 [DllImport ("libX11", EntryPoint="XSetForeground")]
5922 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5924 [DllImport ("libX11", EntryPoint="XSetBackground")]
5925 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5927 [DllImport ("libX11", EntryPoint="XBell")]
5928 internal extern static int XBell(IntPtr display, int percent);
5930 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5931 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5933 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5934 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5936 [DllImport ("libX11")]
5937 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5939 [DllImport ("libX11")]
5940 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);