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
92 private static IntPtr ClipMagic;
93 private static ClipboardStruct Clipboard; // Our clipboard
96 private static IntPtr PostAtom; // PostMessage atom
97 private static IntPtr AsyncAtom; // Support for async messages
100 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
102 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static bool wake_waiting;
104 private static object wake_waiting_lock = new object ();
106 private static X11Keyboard Keyboard; //
107 private static X11Dnd Dnd;
108 private static Socket listen; //
109 private static Socket wake; //
110 private static Socket wake_receive; //
111 private static byte[] network_buffer; //
112 private static bool detectable_key_auto_repeat;
115 private static IntPtr ActiveWindow; // Handle of the active window
116 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
119 private static Stack ModalWindows; // Stack of our modal windows
122 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
125 private static IntPtr LastCursorWindow; // The last window we set the cursor on
126 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
127 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
130 private static CaretStruct Caret; //
133 private static IntPtr WM_PROTOCOLS;
134 private static IntPtr WM_DELETE_WINDOW;
135 private static IntPtr WM_TAKE_FOCUS;
136 //private static IntPtr _NET_SUPPORTED;
137 //private static IntPtr _NET_CLIENT_LIST;
138 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
139 //private static IntPtr _NET_DESKTOP_GEOMETRY;
140 //private static IntPtr _NET_DESKTOP_VIEWPORT;
141 private static IntPtr _NET_CURRENT_DESKTOP;
142 //private static IntPtr _NET_DESKTOP_NAMES;
143 private static IntPtr _NET_ACTIVE_WINDOW;
144 private static IntPtr _NET_WORKAREA;
145 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
146 //private static IntPtr _NET_VIRTUAL_ROOTS;
147 //private static IntPtr _NET_DESKTOP_LAYOUT;
148 //private static IntPtr _NET_SHOWING_DESKTOP;
149 //private static IntPtr _NET_CLOSE_WINDOW;
150 //private static IntPtr _NET_MOVERESIZE_WINDOW;
151 //private static IntPtr _NET_WM_MOVERESIZE;
152 //private static IntPtr _NET_RESTACK_WINDOW;
153 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
154 private static IntPtr _NET_WM_NAME;
155 //private static IntPtr _NET_WM_VISIBLE_NAME;
156 //private static IntPtr _NET_WM_ICON_NAME;
157 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
158 //private static IntPtr _NET_WM_DESKTOP;
159 private static IntPtr _NET_WM_WINDOW_TYPE;
160 private static IntPtr _NET_WM_STATE;
161 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
162 //private static IntPtr _NET_WM_STRUT;
163 //private static IntPtr _NET_WM_STRUT_PARTIAL;
164 //private static IntPtr _NET_WM_ICON_GEOMETRY;
165 private static IntPtr _NET_WM_ICON;
166 //private static IntPtr _NET_WM_PID;
167 //private static IntPtr _NET_WM_HANDLED_ICONS;
168 private static IntPtr _NET_WM_USER_TIME;
169 private static IntPtr _NET_FRAME_EXTENTS;
170 //private static IntPtr _NET_WM_PING;
171 //private static IntPtr _NET_WM_SYNC_REQUEST;
172 private static IntPtr _NET_SYSTEM_TRAY_S;
173 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
174 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
175 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
176 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
177 private static IntPtr _XEMBED;
178 private static IntPtr _XEMBED_INFO;
179 private static IntPtr _MOTIF_WM_HINTS;
180 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
181 //private static IntPtr _NET_WM_STATE_ABOVE;
182 //private static IntPtr _NET_WM_STATE_MODAL;
183 private static IntPtr _NET_WM_STATE_HIDDEN;
184 private static IntPtr _NET_WM_CONTEXT_HELP;
185 private static IntPtr _NET_WM_WINDOW_OPACITY;
186 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
187 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
188 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
189 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
190 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
191 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
192 //private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
193 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
194 private static IntPtr CLIPBOARD;
195 private static IntPtr PRIMARY;
196 //private static IntPtr DIB;
197 private static IntPtr OEMTEXT;
198 private static IntPtr UNICODETEXT;
199 private static IntPtr TARGETS;
201 // mouse hover message generation
202 private static HoverStruct HoverState; //
204 // double click message generation
205 private static ClickStruct ClickPending; //
207 // Support for mouse grab
208 private static GrabStruct Grab; //
211 Point mouse_position; // Last position of mouse, in screen coords
212 internal static MouseButtons MouseState; // Last state of mouse buttons
215 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
217 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
218 EventMask.ButtonReleaseMask |
219 EventMask.KeyPressMask |
220 EventMask.KeyReleaseMask |
221 EventMask.EnterWindowMask |
222 EventMask.LeaveWindowMask |
223 EventMask.ExposureMask |
224 EventMask.FocusChangeMask |
225 EventMask.PointerMotionMask |
226 EventMask.SubstructureNotifyMask);
228 static readonly object lockobj = new object ();
230 #endregion // Local Variables
232 private XplatUIX11() {
233 // Handle singleton stuff first
236 // Now regular initialization
237 XlibLock = new object ();
238 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
241 ErrorExceptions = false;
243 // X11 Initialization
244 SetDisplay(XOpenDisplay(IntPtr.Zero));
245 X11DesktopColors.Initialize();
248 // Disable keyboard autorepeat
250 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
251 detectable_key_auto_repeat = true;
253 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
254 detectable_key_auto_repeat = false;
257 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
258 ErrorHandler = new XErrorHandler(HandleError);
259 XSetErrorHandler(ErrorHandler);
263 // Remove our display handle from S.D
264 Graphics.FromHdcInternal (IntPtr.Zero);
267 #endregion // Constructors
269 #region Singleton Specific Code
270 public static XplatUIX11 GetInstance() {
272 if (Instance == null) {
273 Instance=new XplatUIX11();
280 public int Reference {
287 #region Internal Properties
288 internal static IntPtr Display {
290 return DisplayHandle;
294 XplatUIX11.GetInstance().SetDisplay(value);
298 internal static int Screen {
308 internal static IntPtr RootWindowHandle {
318 internal static IntPtr Visual {
324 CustomVisual = value;
328 internal static IntPtr ColorMap {
330 return CustomColormap;
334 CustomColormap = value;
339 #region XExceptionClass
340 internal class XException : ApplicationException {
344 XRequest RequestCode;
348 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
349 this.Display = Display;
350 this.ResourceID = ResourceID;
351 this.Serial = Serial;
352 this.RequestCode = RequestCode;
353 this.ErrorCode = ErrorCode;
354 this.MinorCode = MinorCode;
357 public override string Message {
359 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
363 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
372 sb = new StringBuilder(160);
373 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
374 x_error_text = sb.ToString();
375 hwnd = Hwnd.ObjectFromHandle(ResourceID);
377 hwnd_text = hwnd.ToString();
378 c = Control.FromHandle(hwnd.Handle);
380 control_text = c.ToString();
382 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
385 hwnd_text = "<null>";
386 control_text = "<null>";
390 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, RequestCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
394 #endregion // XExceptionClass
396 #region Internal Methods
397 internal void SetDisplay(IntPtr display_handle) {
398 if (display_handle != IntPtr.Zero) {
401 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
402 hwnd = Hwnd.ObjectFromHandle(FosterParent);
403 XDestroyWindow(DisplayHandle, FosterParent);
407 if (DisplayHandle != IntPtr.Zero) {
408 XCloseDisplay(DisplayHandle);
411 DisplayHandle=display_handle;
413 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
414 // been hacked to do this for us.
415 Graphics.FromHdcInternal (DisplayHandle);
418 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
419 XSynchronize(DisplayHandle, true);
422 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
423 ErrorExceptions = true;
427 ScreenNo = XDefaultScreen(DisplayHandle);
428 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
429 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
431 // Create the foster parent
432 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
433 if (FosterParent==IntPtr.Zero) {
434 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
438 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
439 hwnd.WholeWindow = FosterParent;
440 hwnd.ClientWindow = FosterParent;
442 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
444 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
445 hwnd.whole_window = RootWindow;
446 hwnd.ClientWindow = RootWindow;
448 // For sleeping on the X11 socket
449 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
450 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
454 // To wake up when a timer is ready
455 network_buffer = new byte[10];
457 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
458 wake.Connect(listen.LocalEndPoint);
459 wake_receive = listen.Accept();
462 pollfds = new Pollfd [2];
463 pollfds [0] = new Pollfd ();
464 pollfds [0].fd = XConnectionNumber (DisplayHandle);
465 pollfds [0].events = PollEvents.POLLIN;
467 pollfds [1] = new Pollfd ();
468 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
469 pollfds [1].events = PollEvents.POLLIN;
472 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
473 Dnd = new X11Dnd (DisplayHandle, Keyboard);
475 DoubleClickInterval = 500;
477 HoverState.Interval = 500;
478 HoverState.Timer = new Timer();
479 HoverState.Timer.Enabled = false;
480 HoverState.Timer.Interval = HoverState.Interval;
481 HoverState.Timer.Tick += new EventHandler(MouseHover);
482 HoverState.Size = new Size(4, 4);
486 ActiveWindow = IntPtr.Zero;
487 FocusWindow = IntPtr.Zero;
488 ModalWindows = new Stack(3);
490 MouseState = MouseButtons.None;
491 mouse_position = new Point(0, 0);
493 Caret.Timer = new Timer();
494 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
495 Caret.Timer.Tick += new EventHandler(CaretCallback);
499 // Grab atom changes off the root window to catch certain WM events
500 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
502 // Handle any upcoming errors
503 ErrorHandler = new XErrorHandler(HandleError);
504 XSetErrorHandler(ErrorHandler);
506 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
509 #endregion // Internal Methods
511 #region Private Methods
512 private int unixtime() {
513 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
515 return (int) t.TotalSeconds;
518 private static void SetupAtoms() {
519 // make sure this array stays in sync with the statements below
520 string [] atom_names = new string[] {
525 //"_NET_CLIENT_LIST",
526 //"_NET_NUMBER_OF_DESKTOPS",
527 //"_NET_DESKTOP_GEOMETRY",
528 //"_NET_DESKTOP_VIEWPORT",
529 "_NET_CURRENT_DESKTOP",
530 //"_NET_DESKTOP_NAMES",
531 "_NET_ACTIVE_WINDOW",
533 //"_NET_SUPPORTING_WM_CHECK",
534 //"_NET_VIRTUAL_ROOTS",
535 //"_NET_DESKTOP_LAYOUT",
536 //"_NET_SHOWING_DESKTOP",
537 //"_NET_CLOSE_WINDOW",
538 //"_NET_MOVERESIZE_WINDOW",
539 //"_NET_WM_MOVERESIZE",
540 //"_NET_RESTACK_WINDOW",
541 //"_NET_REQUEST_FRAME_EXTENTS",
543 //"_NET_WM_VISIBLE_NAME",
544 //"_NET_WM_ICON_NAME",
545 //"_NET_WM_VISIBLE_ICON_NAME",
547 "_NET_WM_WINDOW_TYPE",
549 //"_NET_WM_ALLOWED_ACTIONS",
551 //"_NET_WM_STRUT_PARTIAL",
552 //"_NET_WM_ICON_GEOMETRY",
555 //"_NET_WM_HANDLED_ICONS",
557 "_NET_FRAME_EXTENTS",
559 //"_NET_WM_SYNC_REQUEST",
560 "_NET_SYSTEM_TRAY_OPCODE",
561 //"_NET_SYSTEM_TRAY_ORIENTATION",
562 "_NET_WM_STATE_MAXIMIZED_HORZ",
563 "_NET_WM_STATE_MAXIMIZED_VERT",
564 "_NET_WM_STATE_HIDDEN",
568 "_NET_WM_STATE_SKIP_TASKBAR",
569 //"_NET_WM_STATE_ABOVE",
570 //"_NET_WM_STATE_MODAL",
571 "_NET_WM_CONTEXT_HELP",
572 "_NET_WM_WINDOW_OPACITY",
573 //"_NET_WM_WINDOW_TYPE_DESKTOP",
574 //"_NET_WM_WINDOW_TYPE_DOCK",
575 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
576 //"_NET_WM_WINDOW_TYPE_MENU",
577 "_NET_WM_WINDOW_TYPE_UTILITY",
578 //"_NET_WM_WINDOW_TYPE_DIALOG",
579 //"_NET_WM_WINDOW_TYPE_SPLASH",
580 "_NET_WM_WINDOW_TYPE_NORMAL",
587 "_SWF_PostMessageAtom",
590 IntPtr[] atoms = new IntPtr [atom_names.Length];;
592 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
595 WM_PROTOCOLS = atoms [off++];
596 WM_DELETE_WINDOW = atoms [off++];
597 WM_TAKE_FOCUS = atoms [off++];
598 //_NET_SUPPORTED = atoms [off++];
599 //_NET_CLIENT_LIST = atoms [off++];
600 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
601 //_NET_DESKTOP_GEOMETRY = atoms [off++];
602 //_NET_DESKTOP_VIEWPORT = atoms [off++];
603 _NET_CURRENT_DESKTOP = atoms [off++];
604 //_NET_DESKTOP_NAMES = atoms [off++];
605 _NET_ACTIVE_WINDOW = atoms [off++];
606 _NET_WORKAREA = atoms [off++];
607 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
608 //_NET_VIRTUAL_ROOTS = atoms [off++];
609 //_NET_DESKTOP_LAYOUT = atoms [off++];
610 //_NET_SHOWING_DESKTOP = atoms [off++];
611 //_NET_CLOSE_WINDOW = atoms [off++];
612 //_NET_MOVERESIZE_WINDOW = atoms [off++];
613 //_NET_WM_MOVERESIZE = atoms [off++];
614 //_NET_RESTACK_WINDOW = atoms [off++];
615 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
616 _NET_WM_NAME = atoms [off++];
617 //_NET_WM_VISIBLE_NAME = atoms [off++];
618 //_NET_WM_ICON_NAME = atoms [off++];
619 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
620 //_NET_WM_DESKTOP = atoms [off++];
621 _NET_WM_WINDOW_TYPE = atoms [off++];
622 _NET_WM_STATE = atoms [off++];
623 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
624 //_NET_WM_STRUT = atoms [off++];
625 //_NET_WM_STRUT_PARTIAL = atoms [off++];
626 //_NET_WM_ICON_GEOMETRY = atoms [off++];
627 _NET_WM_ICON = atoms [off++];
628 //_NET_WM_PID = atoms [off++];
629 //_NET_WM_HANDLED_ICONS = atoms [off++];
630 _NET_WM_USER_TIME = atoms [off++];
631 _NET_FRAME_EXTENTS = atoms [off++];
632 //_NET_WM_PING = atoms [off++];
633 //_NET_WM_SYNC_REQUEST = atoms [off++];
634 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
635 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
636 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
637 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
638 _NET_WM_STATE_HIDDEN = atoms [off++];
639 _XEMBED = atoms [off++];
640 _XEMBED_INFO = atoms [off++];
641 _MOTIF_WM_HINTS = atoms [off++];
642 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
643 //_NET_WM_STATE_ABOVE = atoms [off++];
644 //_NET_WM_STATE_MODAL = atoms [off++];
645 _NET_WM_CONTEXT_HELP = atoms [off++];
646 _NET_WM_WINDOW_OPACITY = atoms [off++];
647 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
648 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
649 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
650 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
651 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
652 //_NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
653 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
654 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
655 CLIPBOARD = atoms [off++];
656 PRIMARY = atoms [off++];
657 OEMTEXT = atoms [off++];
658 UNICODETEXT = atoms [off++];
659 TARGETS = atoms [off++];
660 AsyncAtom = atoms [off++];
661 PostAtom = atoms [off++];
662 HoverState.Atom = atoms [off++];
664 //DIB = (IntPtr)Atom.XA_PIXMAP;
665 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
668 private void GetSystrayManagerWindow() {
669 XGrabServer(DisplayHandle);
670 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
671 XUngrabServer(DisplayHandle);
672 XFlush(DisplayHandle);
675 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
679 xev.ClientMessageEvent.type = XEventName.ClientMessage;
680 xev.ClientMessageEvent.send_event = true;
681 xev.ClientMessageEvent.window = window;
682 xev.ClientMessageEvent.message_type = message_type;
683 xev.ClientMessageEvent.format = 32;
684 xev.ClientMessageEvent.ptr1 = l0;
685 xev.ClientMessageEvent.ptr2 = l1;
686 xev.ClientMessageEvent.ptr3 = l2;
687 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
690 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
694 xev.ClientMessageEvent.type = XEventName.ClientMessage;
695 xev.ClientMessageEvent.send_event = true;
696 xev.ClientMessageEvent.window = window;
697 xev.ClientMessageEvent.message_type = message_type;
698 xev.ClientMessageEvent.format = 32;
699 xev.ClientMessageEvent.ptr1 = l0;
700 xev.ClientMessageEvent.ptr2 = l1;
701 xev.ClientMessageEvent.ptr3 = l2;
702 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
705 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
706 // WM_CREATE and WM_DESTROY causes
707 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
711 if (child == IntPtr.Zero) {
715 hwnd = Hwnd.GetObjectFromWindow (child);
721 if (hwnd.Handle == IntPtr.Zero) {
725 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
729 if (hwnd.Parent == null) {
733 if (hwnd.Parent.Handle == IntPtr.Zero) {
737 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
738 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
740 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
743 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
746 bool StyleSet (int s, WindowStyles ws)
748 return (s & (int)ws) == (int)ws;
751 bool ExStyleSet (int ex, WindowExStyles exws)
753 return (ex & (int)exws) == (int)exws;
756 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) {
759 tool_caption_height = 19;
760 border_static = false;
762 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
763 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
764 border_style = FormBorderStyle.Fixed3D;
765 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
766 border_style = FormBorderStyle.Fixed3D;
767 border_static = true;
768 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
769 border_style = FormBorderStyle.None;
771 border_style = FormBorderStyle.FixedSingle;
773 title_style = TitleStyle.None;
775 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
777 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
778 title_style = TitleStyle.Tool;
780 title_style = TitleStyle.Normal;
784 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
787 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
788 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
789 border_style = (FormBorderStyle) 0xFFFF;
791 border_style = FormBorderStyle.None;
796 title_style = TitleStyle.None;
797 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
798 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
799 title_style = TitleStyle.Tool;
801 title_style = TitleStyle.Normal;
805 border_style = FormBorderStyle.None;
807 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
808 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
809 border_style = FormBorderStyle.SizableToolWindow;
811 border_style = FormBorderStyle.Sizable;
814 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
815 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
816 border_style = FormBorderStyle.Fixed3D;
817 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
818 border_style = FormBorderStyle.Fixed3D;
819 border_static = true;
820 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
821 border_style = FormBorderStyle.FixedDialog;
822 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
823 border_style = FormBorderStyle.FixedToolWindow;
824 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
825 border_style = FormBorderStyle.FixedSingle;
828 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
829 border_style = FormBorderStyle.FixedSingle;
836 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
837 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);
840 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
841 MotifWmHints mwmHints;
842 MotifFunctions functions;
843 MotifDecorations decorations;
846 Rectangle client_rect;
848 // Windows we manage ourselves don't need WM window styles.
849 if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
854 mwmHints = new MotifWmHints();
858 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
859 mwmHints.functions = (IntPtr)0;
860 mwmHints.decorations = (IntPtr)0;
862 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
863 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
864 /* tool windows get no window manager
865 decorations, and neither do windows
866 which lack CAPTION/BORDER/DLGFRAME
870 /* just because the window doesn't get any decorations doesn't
871 mean we should disable the functions. for instance, without
872 MotifFunctions.Maximize, changing the windowstate to Maximized
873 is ignored by metacity. */
874 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
877 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
878 functions |= MotifFunctions.Move;
879 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
882 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
883 functions |= MotifFunctions.Move | MotifFunctions.Resize;
884 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
887 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
888 functions |= MotifFunctions.Minimize;
889 decorations |= MotifDecorations.Minimize;
892 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
893 functions |= MotifFunctions.Maximize;
894 decorations |= MotifDecorations.Maximize;
897 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
898 functions |= MotifFunctions.Resize;
899 decorations |= MotifDecorations.ResizeH;
902 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
903 decorations |= MotifDecorations.Border;
906 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
907 decorations |= MotifDecorations.Border;
910 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
911 decorations |= MotifDecorations.Border;
914 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
915 functions |= MotifFunctions.Close;
918 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
919 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
920 if (cp.Caption == "") {
921 functions &= ~MotifFunctions.Move;
922 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
927 if ((functions & MotifFunctions.Resize) == 0) {
928 hwnd.fixed_size = true;
929 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));
931 hwnd.fixed_size = false;
934 mwmHints.functions = (IntPtr)functions;
935 mwmHints.decorations = (IntPtr)decorations;
937 FormWindowState current_state = GetWindowState (hwnd.Handle);
938 if (current_state == (FormWindowState)(-1))
939 current_state = FormWindowState.Normal;
941 client_rect = hwnd.ClientRect;
945 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
946 // and get those windows in front of their parents
947 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
948 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
949 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
950 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
952 Form f = Control.FromHandle(hwnd.Handle) as Form;
953 if (f != null && !hwnd.reparented) {
954 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
955 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
956 if (owner_hwnd != null)
957 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
958 owner_hwnd.whole_window);
963 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
964 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
965 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
966 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
968 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
969 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
970 /* this line keeps the window from showing up in gnome's taskbar */
971 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
973 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
974 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
976 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
979 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
980 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
982 /* we need to add these atoms in the
983 * event we're maximized, since we're
984 * replacing the existing
985 * _NET_WM_STATE here. If we don't
986 * add them, future calls to
987 * GetWindowState will return Normal
988 * for a window which is maximized. */
989 if (current_state == FormWindowState.Maximized) {
990 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
991 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
993 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
996 IntPtr[] atom_ptrs = new IntPtr[2];
997 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
998 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
999 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1002 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1006 private void SetIcon(Hwnd hwnd, Icon icon)
1011 // This really needs to do whatever it
1012 // takes to remove the window manager
1013 // menu, not just delete the ICON
1014 // property. This will cause metacity
1015 // to use the "no icon set" icon, and
1016 // we'll still have an icon.
1017 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1025 bitmap = icon.ToBitmap();
1027 size = bitmap.Width * bitmap.Height + 2;
1028 data = new IntPtr[size];
1030 data[index++] = (IntPtr)bitmap.Width;
1031 data[index++] = (IntPtr)bitmap.Height;
1033 for (int y = 0; y < bitmap.Height; y++) {
1034 for (int x = 0; x < bitmap.Width; x++) {
1035 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1039 XChangeProperty (DisplayHandle, hwnd.whole_window,
1040 _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1041 PropertyMode.Replace, data, size);
1045 private void WakeupMain () {
1046 wake.Send (new byte [] { 0xFF });
1049 private XEventQueue ThreadQueue(Thread thread) {
1052 queue = (XEventQueue)MessageQueues[thread];
1053 if (queue == null) {
1054 queue = new XEventQueue(thread);
1055 MessageQueues[thread] = queue;
1061 private void TranslatePropertyToClipboard(IntPtr property) {
1066 IntPtr prop = IntPtr.Zero;
1068 Clipboard.Item = null;
1070 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);
1072 if ((long)nitems > 0) {
1073 if (property == (IntPtr)Atom.XA_STRING) {
1074 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1075 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1076 // FIXME - convert bitmap to image
1077 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1078 // FIXME - convert pixmap to image
1079 } else if (property == OEMTEXT) {
1080 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1081 } else if (property == UNICODETEXT) {
1082 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1089 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1091 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1095 // Keep the invalid area as small as needed
1096 if ((x + width) > hwnd.width) {
1097 width = hwnd.width - x;
1100 if ((y + height) > hwnd.height) {
1101 height = hwnd.height - y;
1105 hwnd.AddInvalidArea(x, y, width, height);
1106 if (!hwnd.expose_pending) {
1107 if (!hwnd.nc_expose_pending) {
1108 hwnd.Queue.Paint.Enqueue(hwnd);
1110 hwnd.expose_pending = true;
1113 hwnd.AddNcInvalidArea (x, y, width, height);
1115 if (!hwnd.nc_expose_pending) {
1116 if (!hwnd.expose_pending) {
1117 hwnd.Queue.Paint.Enqueue(hwnd);
1119 hwnd.nc_expose_pending = true;
1124 private void FrameExtents(IntPtr window, out int left, out int top) {
1129 IntPtr prop = IntPtr.Zero;
1131 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);
1132 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1133 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1134 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1135 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1136 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1142 if (prop != IntPtr.Zero) {
1148 private void AddConfigureNotify (XEvent xevent) {
1151 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1158 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1159 if (!hwnd.reparented) {
1160 hwnd.x = xevent.ConfigureEvent.x;
1161 hwnd.y = xevent.ConfigureEvent.y;
1163 // This sucks ass, part 1
1164 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1165 // no standard way of getting our adjustment.
1166 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1167 // Several other WMs do their decorations different yet again and we fail to deal
1168 // with that, since I couldn't find any frigging commonality between them.
1169 // The only sane WM seems to be KDE
1171 if (!xevent.ConfigureEvent.send_event) {
1174 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1176 // This is a synthetic event, coordinates are in root space
1177 hwnd.x = xevent.ConfigureEvent.x;
1178 hwnd.y = xevent.ConfigureEvent.y;
1179 if (hwnd.whacky_wm) {
1183 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1184 hwnd.x -= frame_left;
1185 hwnd.y -= frame_top;
1190 // XXX this sucks. this isn't thread safe
1191 hwnd.width = xevent.ConfigureEvent.width;
1192 hwnd.height = xevent.ConfigureEvent.height;
1193 hwnd.ClientRect = Rectangle.Empty;
1195 lock (hwnd.configure_lock) {
1196 if (!hwnd.configure_pending) {
1197 hwnd.Queue.EnqueueLocked (xevent);
1198 hwnd.configure_pending = true;
1202 // We drop configure events for Client windows
1205 private void ShowCaret() {
1206 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1212 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1216 private void HideCaret() {
1217 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1223 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1227 private int NextTimeout (ArrayList timers, DateTime now) {
1228 int timeout = Int32.MaxValue;
1230 foreach (Timer timer in timers) {
1231 int next = (int) (timer.Expires - now).TotalMilliseconds;
1233 return 0; // Have a timer that has already expired
1236 if (next < timeout) {
1240 if (timeout < Timer.Minimum) {
1241 timeout = Timer.Minimum;
1249 private void CheckTimers (ArrayList timers, DateTime now) {
1252 count = timers.Count;
1257 for (int i = 0; i < timers.Count; i++) {
1260 timer = (Timer) timers [i];
1262 if (timer.Enabled && timer.Expires <= now) {
1269 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1270 MSG msg = new MSG ();
1273 queue = ThreadQueue(Thread.CurrentThread);
1275 queue.DispatchIdle = false;
1279 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1280 if ((Msg)msg.message == Msg.WM_QUIT) {
1281 PostQuitMessage (0);
1285 if ((msg.hwnd == hwnd.Handle) &&
1286 ((Msg)msg.message == message || (Msg)msg.message == Msg.WM_DESTROY))
1288 TranslateMessage (ref msg);
1289 DispatchMessage (ref msg);
1294 queue.DispatchIdle = true;
1298 private void MapWindow(Hwnd hwnd, WindowType windows) {
1300 bool need_to_wait = false;
1302 if ((windows & WindowType.Whole) != 0) {
1303 XMapWindow(DisplayHandle, hwnd.whole_window);
1305 if ((windows & WindowType.Client) != 0) {
1306 XMapWindow(DisplayHandle, hwnd.client_window);
1308 need_to_wait = true;
1313 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1314 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1318 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1320 bool need_to_wait = false;
1322 if ((windows & WindowType.Client) != 0) {
1323 XUnmapWindow(DisplayHandle, hwnd.client_window);
1325 need_to_wait = true;
1327 if ((windows & WindowType.Whole) != 0) {
1328 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1331 hwnd.mapped = false;
1333 if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
1334 WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1338 private void UpdateMessageQueue (XEventQueue queue) {
1343 now = DateTime.UtcNow;
1346 pending = XPending (DisplayHandle);
1350 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1351 Idle (this, EventArgs.Empty);
1355 pending = XPending (DisplayHandle);
1362 if (queue != null) {
1363 if (queue.Paint.Count > 0)
1366 timeout = NextTimeout (queue.timer_list, now);
1371 int length = pollfds.Length - 1;
1372 lock (wake_waiting_lock) {
1373 if (wake_waiting == false) {
1375 wake_waiting = true;
1379 Syscall.poll (pollfds, (uint)length, timeout);
1380 // Clean out buffer, so we're not busy-looping on the same data
1381 if (length == pollfds.Length) {
1382 if (pollfds[1].revents != 0)
1383 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1384 lock (wake_waiting_lock) {
1385 wake_waiting = false;
1390 pending = XPending (DisplayHandle);
1396 CheckTimers (queue.timer_list, now);
1399 XEvent xevent = new XEvent ();
1402 if (XPending (DisplayHandle) == 0)
1405 XNextEvent (DisplayHandle, ref xevent);
1407 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1408 if (XFilterEvent(ref xevent, FosterParent)) {
1414 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1418 switch (xevent.type) {
1419 case XEventName.Expose:
1420 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1423 case XEventName.SelectionClear: {
1424 // Should we do something?
1428 case XEventName.SelectionRequest: {
1429 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1433 sel_event = new XEvent();
1434 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1435 sel_event.SelectionEvent.send_event = true;
1436 sel_event.SelectionEvent.display = DisplayHandle;
1437 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1438 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1439 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1440 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1441 sel_event.SelectionEvent.property = IntPtr.Zero;
1443 // Seems that some apps support asking for supported types
1444 if (xevent.SelectionEvent.target == TARGETS) {
1451 if (Clipboard.Item is String) {
1452 atoms[atom_count++] = (int)Atom.XA_STRING;
1453 atoms[atom_count++] = (int)OEMTEXT;
1454 atoms[atom_count++] = (int)UNICODETEXT;
1455 } else if (Clipboard.Item is Image) {
1456 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1457 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1459 // FIXME - handle other types
1462 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1463 } else if (Clipboard.Item is string) {
1469 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1472 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1473 buffer = Marshal.AllocHGlobal(bytes.Length);
1474 buflen = bytes.Length;
1476 for (int i = 0; i < buflen; i++) {
1477 Marshal.WriteByte(buffer, i, bytes[i]);
1479 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1480 // FIXME - this should encode into ISO2022
1481 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1482 while (Marshal.ReadByte(buffer, buflen) != 0) {
1485 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1486 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1487 while (Marshal.ReadByte(buffer, buflen) != 0) {
1491 buffer = IntPtr.Zero;
1494 if (buffer != IntPtr.Zero) {
1495 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1496 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1497 Marshal.FreeHGlobal(buffer);
1499 } else if (Clipboard.Item is Image) {
1500 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1501 // FIXME - convert image and store as property
1502 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1503 // FIXME - convert image and store as property
1507 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1511 case XEventName.SelectionNotify: {
1512 if (Clipboard.Enumerating) {
1513 Clipboard.Enumerating = false;
1514 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1515 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1516 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1517 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1518 #if DriverDebugExtra
1519 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1523 } else if (Clipboard.Retrieving) {
1524 Clipboard.Retrieving = false;
1525 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1526 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1528 Clipboard.Item = null;
1531 Dnd.HandleSelectionNotifyEvent (ref xevent);
1536 case XEventName.KeyRelease:
1537 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1538 XEvent nextevent = new XEvent ();
1540 XPeekEvent (DisplayHandle, ref nextevent);
1542 if (nextevent.type == XEventName.KeyPress &&
1543 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1544 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1548 goto case XEventName.KeyPress;
1550 case XEventName.MotionNotify: {
1553 /* we can't do motion compression across threads, so just punt if we don't match up */
1554 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1555 peek = hwnd.Queue.Peek();
1556 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1560 goto case XEventName.KeyPress;
1563 case XEventName.KeyPress:
1564 case XEventName.ButtonPress:
1565 case XEventName.ButtonRelease:
1566 case XEventName.EnterNotify:
1567 case XEventName.LeaveNotify:
1568 case XEventName.CreateNotify:
1569 case XEventName.DestroyNotify:
1570 case XEventName.FocusIn:
1571 case XEventName.FocusOut:
1572 case XEventName.ClientMessage:
1573 case XEventName.ReparentNotify:
1574 case XEventName.MapNotify:
1575 case XEventName.UnmapNotify:
1576 hwnd.Queue.EnqueueLocked (xevent);
1579 case XEventName.ConfigureNotify:
1580 AddConfigureNotify(xevent);
1583 case XEventName.PropertyNotify:
1584 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1589 IntPtr prop = IntPtr.Zero;
1592 prev_active = ActiveWindow;
1593 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);
1594 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1595 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1598 if (prev_active != ActiveWindow) {
1599 if (prev_active != IntPtr.Zero) {
1600 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1602 if (ActiveWindow != IntPtr.Zero) {
1603 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1606 if (ModalWindows.Count == 0) {
1609 // Modality handling, if we are modal and the new active window is one
1610 // of ours but not the modal one, switch back to the modal window
1612 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1613 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1614 Activate((IntPtr)ModalWindows.Peek());
1627 private IntPtr GetMousewParam(int Delta) {
1630 if ((MouseState & MouseButtons.Left) != 0) {
1631 result |= (int)MsgButtons.MK_LBUTTON;
1634 if ((MouseState & MouseButtons.Middle) != 0) {
1635 result |= (int)MsgButtons.MK_MBUTTON;
1638 if ((MouseState & MouseButtons.Right) != 0) {
1639 result |= (int)MsgButtons.MK_RBUTTON;
1642 Keys mods = ModifierKeys;
1643 if ((mods & Keys.Control) != 0) {
1644 result |= (int)MsgButtons.MK_CONTROL;
1647 if ((mods & Keys.Shift) != 0) {
1648 result |= (int)MsgButtons.MK_SHIFT;
1651 result |= Delta << 16;
1653 return (IntPtr)result;
1655 private IntPtr XGetParent(IntPtr handle) {
1662 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1665 if (Children!=IntPtr.Zero) {
1673 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1674 if (ErrorExceptions) {
1675 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1677 Console.WriteLine("X11 Error encountered: {0}{1}\n", XException.GetMessage(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), Environment.StackTrace);
1682 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1685 Control[] controls = c.Controls.GetAllControls ();
1687 if (c.IsHandleCreated && !c.IsDisposed) {
1688 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1690 #if DriverDebug || DriverDebugDestroy
1691 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1692 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1696 CleanupCachedWindows (hwnd);
1700 for (int i = 0; i < controls.Length; i ++) {
1701 AccumulateDestroyedHandles (controls[i], list);
1707 void CleanupCachedWindows (Hwnd hwnd)
1709 if (ActiveWindow == hwnd.Handle) {
1710 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1711 ActiveWindow = IntPtr.Zero;
1714 if (FocusWindow == hwnd.Handle) {
1715 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1716 FocusWindow = IntPtr.Zero;
1719 if (Grab.Hwnd == hwnd.Handle) {
1720 Grab.Hwnd = IntPtr.Zero;
1721 Grab.Confined = false;
1724 DestroyCaret (hwnd.Handle);
1727 private void PerformNCCalc(Hwnd hwnd) {
1728 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1732 rect = hwnd.DefaultClientRect;
1734 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1735 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1737 ncp.rgrc1.left = rect.Left;
1738 ncp.rgrc1.top = rect.Top;
1739 ncp.rgrc1.right = rect.Right;
1740 ncp.rgrc1.bottom = rect.Bottom;
1742 Marshal.StructureToPtr(ncp, ptr, true);
1743 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1744 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1745 Marshal.FreeHGlobal(ptr);
1747 // FIXME - debug this with Menus
1749 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1750 hwnd.ClientRect = rect;
1753 if ((rect.Width < 1) || (rect.Height < 1)) {
1754 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1756 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1760 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1762 #endregion // Private Methods
1765 private void MouseHover(object sender, EventArgs e) {
1769 HoverState.Timer.Enabled = false;
1771 if (HoverState.Window != IntPtr.Zero) {
1772 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1774 xevent = new XEvent ();
1776 xevent.type = XEventName.ClientMessage;
1777 xevent.ClientMessageEvent.display = DisplayHandle;
1778 xevent.ClientMessageEvent.window = HoverState.Window;
1779 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1780 xevent.ClientMessageEvent.format = 32;
1781 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1783 hwnd.Queue.EnqueueLocked (xevent);
1790 private void CaretCallback(object sender, EventArgs e) {
1794 Caret.On = !Caret.On;
1796 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1798 #endregion // Callbacks
1800 #region Public Properties
1802 internal override int Caption {
1808 internal override Size CursorSize {
1813 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1814 return new Size(x, y);
1816 return new Size(16, 16);
1821 internal override bool DragFullWindows {
1827 internal override Size DragSize {
1829 return new Size(4, 4);
1833 internal override Size FrameBorderSize {
1835 return new Size (4, 4);
1839 internal override Size IconSize {
1845 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1849 current = (long)list;
1852 size = new XIconSize();
1854 for (int i = 0; i < count; i++) {
1855 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1856 current += Marshal.SizeOf(size);
1858 // Look for our preferred size
1859 if (size.min_width == 32) {
1861 return new Size(32, 32);
1864 if (size.max_width == 32) {
1866 return new Size(32, 32);
1869 if (size.min_width < 32 && size.max_width > 32) {
1872 // check if we can fit one
1874 while (x < size.max_width) {
1875 x += size.width_inc;
1878 return new Size(32, 32);
1883 if (largest < size.max_width) {
1884 largest = size.max_width;
1888 // We didn't find a match or we wouldn't be here
1889 return new Size(largest, largest);
1892 return new Size(32, 32);
1897 internal override int KeyboardSpeed {
1900 // A lot harder: need to do:
1901 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1902 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1903 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1905 // And from that we can tell the repetition rate
1907 // Notice, the values must map to:
1908 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1914 internal override int KeyboardDelay {
1917 // Return values must range from 0 to 4, 0 meaning 250ms,
1918 // and 4 meaning 1000 ms.
1920 return 1; // ie, 500 ms
1924 internal override Size MaxWindowTrackSize {
1926 return new Size (WorkingArea.Width, WorkingArea.Height);
1930 internal override Size MinimizedWindowSize {
1932 return new Size(1, 1);
1936 internal override Size MinimizedWindowSpacingSize {
1938 return new Size(1, 1);
1942 internal override Size MinimumWindowSize {
1944 return new Size(1, 1);
1948 internal override Size MinWindowTrackSize {
1950 return new Size(1, 1);
1954 internal override Keys ModifierKeys {
1956 return Keyboard.ModifierKeys;
1960 internal override Size SmallIconSize {
1966 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1970 current = (long)list;
1973 size = new XIconSize();
1975 for (int i = 0; i < count; i++) {
1976 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1977 current += Marshal.SizeOf(size);
1979 // Look for our preferred size
1980 if (size.min_width == 16) {
1982 return new Size(16, 16);
1985 if (size.max_width == 16) {
1987 return new Size(16, 16);
1990 if (size.min_width < 16 && size.max_width > 16) {
1993 // check if we can fit one
1995 while (x < size.max_width) {
1996 x += size.width_inc;
1999 return new Size(16, 16);
2004 if (smallest == 0 || smallest > size.min_width) {
2005 smallest = size.min_width;
2009 // We didn't find a match or we wouldn't be here
2010 return new Size(smallest, smallest);
2013 return new Size(16, 16);
2018 internal override int MouseButtonCount {
2024 internal override bool MouseButtonsSwapped {
2026 return false; // FIXME - how to detect?
2030 internal override Point MousePosition {
2032 return mouse_position;
2036 internal override Size MouseHoverSize {
2038 return new Size (1, 1);
2042 internal override int MouseHoverTime {
2044 return HoverState.Interval;
2050 internal override bool MouseWheelPresent {
2052 return true; // FIXME - how to detect?
2056 internal override Rectangle VirtualScreen {
2062 internal override Rectangle WorkingArea {
2068 IntPtr prop = IntPtr.Zero;
2071 int current_desktop;
2075 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);
2076 if ((long)nitems < 1) {
2080 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2083 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);
2084 if ((long)nitems < 4 * current_desktop) {
2088 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2089 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2090 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2091 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2094 return new Rectangle(x, y, width, height);
2097 XWindowAttributes attributes=new XWindowAttributes();
2100 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2103 return new Rectangle(0, 0, attributes.width, attributes.height);
2107 internal override bool ThemesEnabled {
2109 return XplatUIX11.themes_enabled;
2114 #endregion // Public properties
2116 #region Public Static Methods
2117 internal override IntPtr InitializeDriver() {
2119 if (DisplayHandle==IntPtr.Zero) {
2120 SetDisplay(XOpenDisplay(IntPtr.Zero));
2126 internal override void ShutdownDriver(IntPtr token) {
2128 if (DisplayHandle!=IntPtr.Zero) {
2129 XCloseDisplay(DisplayHandle);
2130 DisplayHandle=IntPtr.Zero;
2135 internal override void EnableThemes() {
2136 themes_enabled = true;
2140 internal override void Activate(IntPtr handle) {
2143 hwnd = Hwnd.ObjectFromHandle(handle);
2147 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2148 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2151 // XRaiseWindow(DisplayHandle, handle);
2157 internal override void AudibleAlert() {
2158 XBell(DisplayHandle, 0);
2163 internal override void CaretVisible(IntPtr handle, bool visible) {
2164 if (Caret.Hwnd == handle) {
2166 if (!Caret.Visible) {
2167 Caret.Visible = true;
2169 Caret.Timer.Start();
2172 Caret.Visible = false;
2179 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2180 FormBorderStyle border_style;
2181 TitleStyle title_style;
2184 int tool_caption_height;
2186 DeriveStyles(Style, ExStyle, out border_style, out border_static, out title_style,
2187 out caption_height, out tool_caption_height);
2189 WindowRect = Hwnd.GetWindowRectangle(border_style, border_static, menu, title_style,
2190 caption_height, tool_caption_height,
2195 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2201 hwnd = Hwnd.ObjectFromHandle(handle);
2204 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2211 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2212 DataFormats.Format f;
2215 f = DataFormats.Format.List;
2217 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2221 Clipboard.Formats = new ArrayList();
2224 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2226 Clipboard.Enumerating = true;
2227 while (Clipboard.Enumerating) {
2228 UpdateMessageQueue(null);
2233 result = new int[Clipboard.Formats.Count];
2235 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2236 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2239 Clipboard.Formats = null;
2243 internal override void ClipboardClose(IntPtr handle) {
2244 if (handle != ClipMagic) {
2245 throw new ArgumentException("handle is not a valid clipboard handle");
2250 internal override int ClipboardGetID(IntPtr handle, string format) {
2251 if (handle != ClipMagic) {
2252 throw new ArgumentException("handle is not a valid clipboard handle");
2255 if (format == "Text" ) return (int)Atom.XA_STRING;
2256 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2257 //else if (format == "MetaFilePict" ) return 3;
2258 //else if (format == "SymbolicLink" ) return 4;
2259 //else if (format == "DataInterchangeFormat" ) return 5;
2260 //else if (format == "Tiff" ) return 6;
2261 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2262 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2263 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2264 //else if (format == "PenData" ) return 10;
2265 //else if (format == "RiffAudio" ) return 11;
2266 //else if (format == "WaveAudio" ) return 12;
2267 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2268 //else if (format == "EnhancedMetafile" ) return 14;
2269 //else if (format == "FileDrop" ) return 15;
2270 //else if (format == "Locale" ) return 16;
2272 return XInternAtom(DisplayHandle, format, false).ToInt32();
2275 internal override IntPtr ClipboardOpen(bool primary_selection) {
2276 if (!primary_selection)
2277 ClipMagic = CLIPBOARD;
2279 ClipMagic = PRIMARY;
2283 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2284 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2286 Clipboard.Retrieving = true;
2287 while (Clipboard.Retrieving) {
2288 UpdateMessageQueue(null);
2291 return Clipboard.Item;
2294 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2295 Clipboard.Item = obj;
2296 Clipboard.Type = type;
2297 Clipboard.Converter = converter;
2300 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2302 // Clearing the selection
2303 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2307 internal override void CreateCaret (IntPtr handle, int width, int height)
2309 XGCValues gc_values;
2312 hwnd = Hwnd.ObjectFromHandle(handle);
2314 if (Caret.Hwnd != IntPtr.Zero) {
2315 DestroyCaret(Caret.Hwnd);
2318 Caret.Hwnd = handle;
2319 Caret.Window = hwnd.client_window;
2320 Caret.Width = width;
2321 Caret.Height = height;
2322 Caret.Visible = false;
2325 gc_values = new XGCValues();
2326 gc_values.line_width = width;
2328 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2329 if (Caret.gc == IntPtr.Zero) {
2330 Caret.Hwnd = IntPtr.Zero;
2334 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2337 internal override IntPtr CreateWindow (CreateParams cp)
2339 XSetWindowAttributes Attributes;
2345 IntPtr ParentHandle;
2347 IntPtr ClientWindow;
2348 Rectangle ClientRect;
2349 SetWindowValuemask ValueMask;
2354 Attributes = new XSetWindowAttributes();
2360 if (Width<1) Width=1;
2361 if (Height<1) Height=1;
2363 if (cp.Parent != IntPtr.Zero) {
2364 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2366 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2367 // We need to use our foster parent window until this poor child gets it's parent assigned
2368 ParentHandle=FosterParent;
2369 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2370 ParentHandle=RootWindow;
2372 // Default position on screen, if window manager doesn't place us somewhere else
2375 ParentHandle=RootWindow;
2379 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2381 Attributes.bit_gravity = Gravity.NorthWestGravity;
2382 Attributes.win_gravity = Gravity.NorthWestGravity;
2384 // Save what's under the toolwindow
2385 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2386 Attributes.save_under = true;
2387 ValueMask |= SetWindowValuemask.SaveUnder;
2391 // If we're a popup without caption we override the WM
2392 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2393 Attributes.override_redirect = true;
2394 ValueMask |= SetWindowValuemask.OverrideRedirect;
2400 hwnd.height = Height;
2401 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2402 hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
2404 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2405 hwnd.enabled = false;
2408 ClientRect = hwnd.ClientRect;
2409 ClientWindow = IntPtr.Zero;
2412 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2413 if (WholeWindow != IntPtr.Zero) {
2414 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2416 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2417 ValueMask = SetWindowValuemask.ColorMap;
2418 Attributes.colormap = CustomColormap;
2420 ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
2424 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2425 throw new Exception("Could not create X11 windows");
2428 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2429 hwnd.WholeWindow = WholeWindow;
2430 hwnd.ClientWindow = ClientWindow;
2432 #if DriverDebug || DriverDebugCreate
2433 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);
2436 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2437 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2440 hints = new XSizeHints();
2443 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2444 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2449 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2450 if (hwnd.whole_window != hwnd.client_window)
2451 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2454 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2456 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2457 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2459 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2462 SetWMStyles(hwnd, cp);
2464 // set the group leader
2465 XWMHints wm_hints = new XWMHints ();
2467 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2468 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2469 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2471 if (ParentHandle != RootWindow) {
2472 wm_hints.window_group = hwnd.whole_window;
2474 wm_hints.window_group = ParentHandle;
2478 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2481 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2482 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2483 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2484 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2487 // for now make all windows dnd enabled
2488 Dnd.SetAllowDrop (hwnd, true);
2490 // Set caption/window title
2491 Text(hwnd.Handle, cp.Caption);
2493 SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2494 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2496 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2497 hwnd.visible = true;
2498 MapWindow(hwnd, WindowType.Both);
2499 if (!(Control.FromHandle(hwnd.Handle) is Form))
2500 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2506 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2507 CreateParams create_params = new CreateParams();
2509 create_params.Caption = "";
2510 create_params.X = X;
2511 create_params.Y = Y;
2512 create_params.Width = Width;
2513 create_params.Height = Height;
2515 create_params.ClassName=XplatUI.DefaultClassName;
2516 create_params.ClassStyle = 0;
2517 create_params.ExStyle=0;
2518 create_params.Parent=IntPtr.Zero;
2519 create_params.Param=0;
2521 return CreateWindow(create_params);
2524 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2526 Bitmap cursor_bitmap;
2534 IntPtr cursor_pixmap;
2541 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2545 // Win32 only allows creation cursors of a certain size
2546 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2547 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2548 cursor_mask = new Bitmap(mask, new Size(width, height));
2550 cursor_bitmap = bitmap;
2554 width = cursor_bitmap.Width;
2555 height = cursor_bitmap.Height;
2557 cursor_bits = new Byte[(width / 8) * height];
2558 mask_bits = new Byte[(width / 8) * height];
2560 for (int y = 0; y < height; y++) {
2561 for (int x = 0; x < width; x++) {
2562 c_pixel = cursor_bitmap.GetPixel(x, y);
2563 m_pixel = cursor_mask.GetPixel(x, y);
2565 and = c_pixel == cursor_pixel;
2566 xor = m_pixel == mask_pixel;
2570 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2571 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2572 } else if (and && !xor) {
2574 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2575 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2577 } else if (and && !xor) {
2579 } else if (and && xor) {
2582 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2583 // we want both to be 0 so nothing to be done
2584 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2585 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2591 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2592 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2596 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2597 fg.red = (ushort)65535;
2598 fg.green = (ushort)65535;
2599 fg.blue = (ushort)65535;
2601 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2603 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2605 XFreePixmap(DisplayHandle, cursor_pixmap);
2606 XFreePixmap(DisplayHandle, mask_pixmap);
2611 internal override IntPtr DefineStdCursor(StdCursor id) {
2612 CursorFontShape shape;
2615 // FIXME - define missing shapes
2618 case StdCursor.AppStarting: {
2619 shape = CursorFontShape.XC_watch;
2623 case StdCursor.Arrow: {
2624 shape = CursorFontShape.XC_top_left_arrow;
2628 case StdCursor.Cross: {
2629 shape = CursorFontShape.XC_crosshair;
2633 case StdCursor.Default: {
2634 shape = CursorFontShape.XC_top_left_arrow;
2638 case StdCursor.Hand: {
2639 shape = CursorFontShape.XC_hand1;
2643 case StdCursor.Help: {
2644 shape = CursorFontShape.XC_question_arrow;
2648 case StdCursor.HSplit: {
2649 shape = CursorFontShape.XC_sb_v_double_arrow;
2653 case StdCursor.IBeam: {
2654 shape = CursorFontShape.XC_xterm;
2658 case StdCursor.No: {
2659 shape = CursorFontShape.XC_circle;
2663 case StdCursor.NoMove2D: {
2664 shape = CursorFontShape.XC_fleur;
2668 case StdCursor.NoMoveHoriz: {
2669 shape = CursorFontShape.XC_fleur;
2673 case StdCursor.NoMoveVert: {
2674 shape = CursorFontShape.XC_fleur;
2678 case StdCursor.PanEast: {
2679 shape = CursorFontShape.XC_fleur;
2683 case StdCursor.PanNE: {
2684 shape = CursorFontShape.XC_fleur;
2688 case StdCursor.PanNorth: {
2689 shape = CursorFontShape.XC_fleur;
2693 case StdCursor.PanNW: {
2694 shape = CursorFontShape.XC_fleur;
2698 case StdCursor.PanSE: {
2699 shape = CursorFontShape.XC_fleur;
2703 case StdCursor.PanSouth: {
2704 shape = CursorFontShape.XC_fleur;
2708 case StdCursor.PanSW: {
2709 shape = CursorFontShape.XC_fleur;
2713 case StdCursor.PanWest: {
2714 shape = CursorFontShape.XC_sizing;
2718 case StdCursor.SizeAll: {
2719 shape = CursorFontShape.XC_fleur;
2723 case StdCursor.SizeNESW: {
2724 shape = CursorFontShape.XC_top_right_corner;
2728 case StdCursor.SizeNS: {
2729 shape = CursorFontShape.XC_sb_v_double_arrow;
2733 case StdCursor.SizeNWSE: {
2734 shape = CursorFontShape.XC_top_left_corner;
2738 case StdCursor.SizeWE: {
2739 shape = CursorFontShape.XC_sb_h_double_arrow;
2743 case StdCursor.UpArrow: {
2744 shape = CursorFontShape.XC_center_ptr;
2748 case StdCursor.VSplit: {
2749 shape = CursorFontShape.XC_sb_h_double_arrow;
2753 case StdCursor.WaitCursor: {
2754 shape = CursorFontShape.XC_watch;
2764 cursor = XCreateFontCursor(DisplayHandle, shape);
2769 internal override IntPtr DefWndProc(ref Message msg) {
2770 switch ((Msg)msg.Msg) {
2771 case Msg.WM_PAINT: {
2774 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2776 hwnd.expose_pending = false;
2782 case Msg.WM_NCPAINT: {
2785 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2787 hwnd.nc_expose_pending = false;
2793 case Msg.WM_CONTEXTMENU: {
2796 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2798 if ((hwnd != null) && (hwnd.parent != null)) {
2799 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2804 case Msg.WM_MOUSEWHEEL: {
2807 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2809 if ((hwnd != null) && (hwnd.parent != null)) {
2810 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2811 if (msg.Result == IntPtr.Zero) {
2818 case Msg.WM_SETCURSOR: {
2821 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2823 break; // not sure how this happens, but it does
2825 // Pass to parent window first
2826 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2828 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2831 if (msg.Result == IntPtr.Zero) {
2834 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2835 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2836 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2837 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2838 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2839 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2842 handle = Cursors.Default.handle;
2845 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2846 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2847 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2848 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2849 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2850 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2853 case HitTest.HTGROWBOX:
2854 case HitTest.HTSIZE:
2855 case HitTest.HTZOOM:
2856 case HitTest.HTVSCROLL:
2857 case HitTest.HTSYSMENU:
2858 case HitTest.HTREDUCE:
2859 case HitTest.HTNOWHERE:
2860 case HitTest.HTMAXBUTTON:
2861 case HitTest.HTMINBUTTON:
2862 case HitTest.HTMENU:
2863 case HitTest.HSCROLL:
2864 case HitTest.HTBOTTOM:
2865 case HitTest.HTCAPTION:
2866 case HitTest.HTCLIENT:
2867 case HitTest.HTCLOSE:
2869 default: handle = Cursors.Default.handle; break;
2871 SetCursor(msg.HWnd, handle);
2879 internal override void DestroyCaret(IntPtr handle) {
2880 if (Caret.Hwnd == handle) {
2881 if (Caret.Visible) {
2885 if (Caret.gc != IntPtr.Zero) {
2886 XFreeGC(DisplayHandle, Caret.gc);
2887 Caret.gc = IntPtr.Zero;
2889 Caret.Hwnd = IntPtr.Zero;
2890 Caret.Visible = false;
2895 internal override void DestroyCursor(IntPtr cursor) {
2897 XFreeCursor(DisplayHandle, cursor);
2901 internal override void DestroyWindow(IntPtr handle) {
2904 hwnd = Hwnd.ObjectFromHandle(handle);
2907 #if DriverDebug || DriverDebugDestroy
2908 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2913 #if DriverDebug || DriverDebugDestroy
2914 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2917 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
2919 CleanupCachedWindows (hwnd);
2921 ArrayList windows = new ArrayList ();
2923 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2926 if (hwnd.whole_window != IntPtr.Zero) {
2927 #if DriverDebug || DriverDebugDestroy
2928 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2930 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2932 else if (hwnd.client_window != IntPtr.Zero) {
2933 #if DriverDebug || DriverDebugDestroy
2934 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2936 XDestroyWindow(DisplayHandle, hwnd.client_window);
2941 foreach (Hwnd h in windows) {
2942 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2946 internal override IntPtr DispatchMessage(ref MSG msg) {
2947 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2950 IntPtr GetReversibleScreenGC (Color backColor)
2952 XGCValues gc_values;
2956 XColor xcolor = new XColor();
2957 xcolor.red = (ushort)(backColor.R * 257);
2958 xcolor.green = (ushort)(backColor.G * 257);
2959 xcolor.blue = (ushort)(backColor.B * 257);
2960 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2961 pixel = (uint)xcolor.pixel.ToInt32();
2964 gc_values = new XGCValues();
2966 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2967 gc_values.foreground = (IntPtr)pixel;
2969 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
2970 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
2971 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2976 IntPtr GetReversibleControlGC (Control control, int line_width)
2978 XGCValues gc_values;
2981 gc_values = new XGCValues();
2983 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2984 gc_values.line_width = line_width;
2985 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2987 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2988 //mask = foreground ^ background;
2989 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2990 //XSetBackground(DisplayHandle, gc, background);
2991 //XSetFunction(DisplayHandle, gc, GXxor);
2992 //XSetPlaneMask(DisplayHandle, gc, mask);
2995 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2999 XColor xcolor = new XColor();
3001 xcolor.red = (ushort)(control.ForeColor.R * 257);
3002 xcolor.green = (ushort)(control.ForeColor.G * 257);
3003 xcolor.blue = (ushort)(control.ForeColor.B * 257);
3004 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3005 foreground = (uint)xcolor.pixel.ToInt32();
3007 xcolor.red = (ushort)(control.BackColor.R * 257);
3008 xcolor.green = (ushort)(control.BackColor.G * 257);
3009 xcolor.blue = (ushort)(control.BackColor.B * 257);
3010 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3011 background = (uint)xcolor.pixel.ToInt32();
3013 uint mask = foreground ^ background;
3015 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3016 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3017 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
3018 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
3023 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3025 IntPtr gc = GetReversibleScreenGC (backColor);
3027 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3029 XFreeGC(DisplayHandle, gc);
3032 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3034 IntPtr gc = GetReversibleScreenGC (backColor);
3036 if (rectangle.Width < 0) {
3037 rectangle.X += rectangle.Width;
3038 rectangle.Width = -rectangle.Width;
3040 if (rectangle.Height < 0) {
3041 rectangle.Y += rectangle.Height;
3042 rectangle.Height = -rectangle.Height;
3046 GCLineStyle line_style = GCLineStyle.LineSolid;
3047 GCCapStyle cap_style = GCCapStyle.CapButt;
3048 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3051 case FrameStyle.Dashed:
3052 line_style = GCLineStyle.LineOnOffDash;
3054 case FrameStyle.Thick:
3059 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3061 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3063 XFreeGC(DisplayHandle, gc);
3066 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3068 IntPtr gc = GetReversibleScreenGC (backColor);
3070 if (rectangle.Width < 0) {
3071 rectangle.X += rectangle.Width;
3072 rectangle.Width = -rectangle.Width;
3074 if (rectangle.Height < 0) {
3075 rectangle.Y += rectangle.Height;
3076 rectangle.Height = -rectangle.Height;
3078 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3080 XFreeGC(DisplayHandle, gc);
3083 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3085 Control control = Control.FromHandle(handle);
3087 gc = GetReversibleControlGC (control, line_width);
3089 if ((rect.Width > 0) && (rect.Height > 0)) {
3090 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3092 if (rect.Width > 0) {
3093 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3095 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3098 XFreeGC(DisplayHandle, gc);
3101 internal override void DoEvents() {
3102 MSG msg = new MSG ();
3105 if (OverrideCursorHandle != IntPtr.Zero) {
3106 OverrideCursorHandle = IntPtr.Zero;
3109 queue = ThreadQueue(Thread.CurrentThread);
3111 queue.DispatchIdle = false;
3113 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3114 TranslateMessage (ref msg);
3115 DispatchMessage (ref msg);
3118 queue.DispatchIdle = true;
3121 internal override void EnableWindow(IntPtr handle, bool Enable) {
3124 hwnd = Hwnd.ObjectFromHandle(handle);
3126 hwnd.Enabled = Enable;
3130 internal override void EndLoop(Thread thread) {
3131 // This is where we one day will shut down the loop for the thread
3134 internal override IntPtr GetActive() {
3139 IntPtr prop = IntPtr.Zero;
3140 IntPtr active = IntPtr.Zero;
3142 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);
3143 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3144 active = (IntPtr)Marshal.ReadInt32(prop);
3148 if (active != IntPtr.Zero) {
3151 hwnd = Hwnd.GetObjectFromWindow(active);
3153 active = hwnd.Handle;
3155 active = IntPtr.Zero;
3161 internal override Region GetClipRegion(IntPtr handle) {
3164 hwnd = Hwnd.ObjectFromHandle(handle);
3166 return hwnd.UserClip;
3172 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3179 internal override void GetDisplaySize(out Size size) {
3180 XWindowAttributes attributes=new XWindowAttributes();
3183 // FIXME - use _NET_WM messages instead?
3184 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3187 size = new Size(attributes.width, attributes.height);
3190 internal override SizeF GetAutoScaleSize(Font font) {
3193 string magic_string = "The quick brown fox jumped over the lazy dog.";
3194 double magic_number = 44.549996948242189;
3196 g = Graphics.FromHwnd(FosterParent);
3198 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3199 return new SizeF(width, font.Height);
3202 internal override IntPtr GetParent(IntPtr handle) {
3205 hwnd = Hwnd.ObjectFromHandle(handle);
3206 if (hwnd != null && hwnd.parent != null) {
3207 return hwnd.parent.Handle;
3212 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3222 if (handle != IntPtr.Zero) {
3223 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3225 use_handle = RootWindow;
3229 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3232 if (handle != IntPtr.Zero) {
3241 internal override IntPtr GetFocus() {
3246 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3247 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3250 internal override Point GetMenuOrigin(IntPtr handle) {
3253 hwnd = Hwnd.ObjectFromHandle(handle);
3256 return hwnd.MenuOrigin;
3261 [MonoTODO("Implement filtering")]
3262 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3269 if (((XEventQueue)queue_id).Count > 0) {
3270 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3272 UpdateMessageQueue ((XEventQueue)queue_id);
3274 if (((XEventQueue)queue_id).Count > 0) {
3275 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3276 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3277 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3279 msg.hwnd= IntPtr.Zero;
3280 msg.message = Msg.WM_ENTERIDLE;
3285 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3287 // Handle messages for windows that are already or are about to be destroyed.
3289 // we need a special block for this because unless we remove the hwnd from the paint
3290 // queue it will always stay there (since we don't handle the expose), and we'll
3291 // effectively loop infinitely trying to repaint a non-existant window.
3292 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3293 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3294 hwnd.Queue.Paint.Remove (hwnd);
3295 goto ProcessNextMessage;
3298 // We need to make sure we only allow DestroyNotify events through for zombie
3299 // hwnds, since much of the event handling code makes requests using the hwnd's
3300 // client_window, and that'll result in BadWindow errors if there's some lag
3301 // between the XDestroyWindow call and the DestroyNotify event.
3302 if (hwnd == null || hwnd.zombie) {
3303 #if DriverDebug || DriverDebugDestroy
3304 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3306 goto ProcessNextMessage;
3309 if (hwnd.client_window == xevent.AnyEvent.window) {
3311 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3314 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3317 msg.hwnd = hwnd.Handle;
3320 // If you add a new event to this switch make sure to add it in
3321 // UpdateMessage also unless it is not coming through the X event system.
3323 switch(xevent.type) {
3324 case XEventName.KeyPress: {
3326 Dnd.HandleKeyPress (ref xevent);
3327 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3331 case XEventName.KeyRelease: {
3332 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3336 case XEventName.ButtonPress: {
3337 switch(xevent.ButtonEvent.button) {
3339 MouseState |= MouseButtons.Left;
3341 msg.message = Msg.WM_LBUTTONDOWN;
3343 msg.message = Msg.WM_NCLBUTTONDOWN;
3344 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3346 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3347 msg.wParam=GetMousewParam(0);
3352 MouseState |= MouseButtons.Middle;
3354 msg.message = Msg.WM_MBUTTONDOWN;
3356 msg.message = Msg.WM_NCMBUTTONDOWN;
3357 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3359 msg.wParam=GetMousewParam(0);
3364 MouseState |= MouseButtons.Right;
3366 msg.message = Msg.WM_RBUTTONDOWN;
3368 msg.message = Msg.WM_NCRBUTTONDOWN;
3369 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3371 msg.wParam=GetMousewParam(0);
3376 msg.hwnd = FocusWindow;
3377 msg.message=Msg.WM_MOUSEWHEEL;
3378 msg.wParam=GetMousewParam(120);
3383 msg.hwnd = FocusWindow;
3384 msg.message=Msg.WM_MOUSEWHEEL;
3385 msg.wParam=GetMousewParam(-120);
3391 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3392 mouse_position.X = xevent.ButtonEvent.x;
3393 mouse_position.Y = xevent.ButtonEvent.y;
3395 if (!hwnd.Enabled) {
3398 msg.hwnd = hwnd.EnabledHwnd;
3399 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);
3400 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3403 if (Grab.Hwnd != IntPtr.Zero) {
3404 msg.hwnd = Grab.Hwnd;
3407 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3408 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3409 switch(xevent.ButtonEvent.button) {
3411 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3416 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3421 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3425 ClickPending.Pending = false;
3427 ClickPending.Pending = true;
3428 ClickPending.Hwnd = msg.hwnd;
3429 ClickPending.Message = msg.message;
3430 ClickPending.wParam = msg.wParam;
3431 ClickPending.lParam = msg.lParam;
3432 ClickPending.Time = (long)xevent.ButtonEvent.time;
3435 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN)
3436 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3441 case XEventName.ButtonRelease: {
3443 if (Dnd.HandleButtonRelease (ref xevent)) {
3446 // Allow the LBUTTONUP message to get through
3449 switch(xevent.ButtonEvent.button) {
3452 msg.message = Msg.WM_LBUTTONUP;
3454 msg.message = Msg.WM_NCLBUTTONUP;
3455 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3457 MouseState &= ~MouseButtons.Left;
3458 msg.wParam=GetMousewParam(0);
3464 msg.message = Msg.WM_MBUTTONUP;
3466 msg.message = Msg.WM_NCMBUTTONUP;
3467 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3469 MouseState &= ~MouseButtons.Middle;
3470 msg.wParam=GetMousewParam(0);
3476 msg.message = Msg.WM_RBUTTONUP;
3478 msg.message = Msg.WM_NCRBUTTONUP;
3479 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3481 MouseState &= ~MouseButtons.Right;
3482 msg.wParam=GetMousewParam(0);
3487 goto ProcessNextMessage;
3491 goto ProcessNextMessage;
3495 if (!hwnd.Enabled) {
3498 msg.hwnd = hwnd.EnabledHwnd;
3499 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);
3500 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3503 if (Grab.Hwnd != IntPtr.Zero) {
3504 msg.hwnd = Grab.Hwnd;
3507 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3508 mouse_position.X = xevent.ButtonEvent.x;
3509 mouse_position.Y = xevent.ButtonEvent.y;
3513 case XEventName.MotionNotify: {
3515 #if DriverDebugExtra
3516 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);
3519 if (Dnd.HandleMotionNotify (ref xevent))
3520 goto ProcessNextMessage;
3521 if (Grab.Hwnd != IntPtr.Zero) {
3522 msg.hwnd = Grab.Hwnd;
3524 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3527 msg.message = Msg.WM_MOUSEMOVE;
3528 msg.wParam = GetMousewParam(0);
3529 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3531 if (!hwnd.Enabled) {
3534 msg.hwnd = hwnd.EnabledHwnd;
3535 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);
3536 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3539 mouse_position.X = xevent.MotionEvent.x;
3540 mouse_position.Y = xevent.MotionEvent.y;
3542 if ((HoverState.Timer.Enabled) &&
3543 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3544 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3545 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3546 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3547 HoverState.Timer.Stop();
3548 HoverState.Timer.Start();
3549 HoverState.X = mouse_position.X;
3550 HoverState.Y = mouse_position.Y;
3560 #if DriverDebugExtra
3561 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);
3563 msg.message = Msg.WM_NCMOUSEMOVE;
3565 if (!hwnd.Enabled) {
3566 msg.hwnd = hwnd.EnabledHwnd;
3567 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);
3568 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3571 // The hit test is sent in screen coordinates
3572 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3573 xevent.MotionEvent.x, xevent.MotionEvent.y,
3574 out screen_x, out screen_y, out dummy);
3576 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3577 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3578 IntPtr.Zero, msg.lParam).ToInt32 ();
3579 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3581 mouse_position.X = xevent.MotionEvent.x;
3582 mouse_position.Y = xevent.MotionEvent.y;
3588 case XEventName.EnterNotify: {
3589 if (!hwnd.Enabled) {
3590 goto ProcessNextMessage;
3592 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3593 goto ProcessNextMessage;
3595 msg.message = Msg.WM_MOUSE_ENTER;
3596 HoverState.X = xevent.CrossingEvent.x;
3597 HoverState.Y = xevent.CrossingEvent.y;
3598 HoverState.Timer.Enabled = true;
3599 HoverState.Window = xevent.CrossingEvent.window;
3603 case XEventName.LeaveNotify: {
3604 if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
3605 WindowUngrabbed (hwnd.Handle);
3606 goto ProcessNextMessage;
3608 if (!hwnd.Enabled) {
3609 goto ProcessNextMessage;
3611 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3612 goto ProcessNextMessage;
3614 msg.message=Msg.WM_MOUSE_LEAVE;
3615 HoverState.Timer.Enabled = false;
3616 HoverState.Window = IntPtr.Zero;
3621 case XEventName.CreateNotify: {
3622 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3623 msg.message = WM_CREATE;
3624 // Set up CreateStruct
3626 goto ProcessNextMessage;
3633 case XEventName.ReparentNotify: {
3634 if (hwnd.parent == null) { // Toplevel
3635 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3636 // We need to adjust x/y
3637 // This sucks ass, part 2
3638 // Every WM does the reparenting of toplevel windows different, so there's
3639 // no standard way of getting our adjustment considering frames/decorations
3640 // The code below is needed for metacity. KDE doesn't works just fine without this
3648 hwnd.Reparented = true;
3650 XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out new_x, out new_y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
3651 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3652 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3655 hwnd.whacky_wm = true;
3658 if (hwnd.opacity != 0xffffffff) {
3661 opacity = (IntPtr)(Int32)hwnd.opacity;
3662 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3664 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3665 goto ProcessNextMessage;
3667 hwnd.Reparented = false;
3668 goto ProcessNextMessage;
3671 goto ProcessNextMessage;
3674 case XEventName.ConfigureNotify: {
3675 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3676 #if DriverDebugExtra
3677 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);
3679 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3680 lock (hwnd.configure_lock) {
3681 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3682 hwnd.configure_pending = false;
3685 // We need to adjust our client window to track the resize of whole_window
3686 if (hwnd.whole_window != hwnd.client_window)
3687 PerformNCCalc(hwnd);
3690 goto ProcessNextMessage;
3693 case XEventName.FocusIn: {
3694 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3695 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3696 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3697 // about it having focus again
3698 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3699 goto ProcessNextMessage;
3702 if (FocusWindow == IntPtr.Zero) {
3703 Control c = Control.FromHandle (hwnd.client_window);
3705 goto ProcessNextMessage;
3706 Form form = c.FindForm ();
3708 goto ProcessNextMessage;
3709 if (ActiveWindow != form.Handle) {
3710 ActiveWindow = form.Handle;
3711 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3713 goto ProcessNextMessage;
3715 Keyboard.FocusIn(FocusWindow);
3716 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3717 goto ProcessNextMessage;
3720 case XEventName.FocusOut: {
3721 // Se the comment for our FocusIn handler
3722 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3723 goto ProcessNextMessage;
3725 Keyboard.FocusOut(FocusWindow);
3727 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3728 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3731 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3732 goto ProcessNextMessage;
3735 case XEventName.MapNotify: {
3736 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3738 msg.message = Msg.WM_SHOWWINDOW;
3739 msg.wParam = (IntPtr) 1;
3740 // XXX we're missing the lParam..
3743 goto ProcessNextMessage;
3746 case XEventName.UnmapNotify: {
3747 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3748 hwnd.mapped = false;
3749 msg.message = Msg.WM_SHOWWINDOW;
3750 msg.wParam = (IntPtr) 0;
3751 // XXX we're missing the lParam..
3754 goto ProcessNextMessage;
3757 case XEventName.Expose: {
3760 hwnd.expose_pending = false;
3762 hwnd.nc_expose_pending = false;
3764 goto ProcessNextMessage;
3768 if (!hwnd.expose_pending) {
3769 goto ProcessNextMessage;
3772 if (!hwnd.nc_expose_pending) {
3773 goto ProcessNextMessage;
3776 switch (hwnd.border_style) {
3777 case FormBorderStyle.Fixed3D: {
3780 g = Graphics.FromHwnd(hwnd.whole_window);
3781 if (hwnd.border_static)
3782 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
3784 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3789 case FormBorderStyle.FixedSingle: {
3792 g = Graphics.FromHwnd(hwnd.whole_window);
3793 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3798 #if DriverDebugExtra
3799 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);
3802 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3803 Region region = new Region (rect);
3804 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3805 msg.message = Msg.WM_NCPAINT;
3806 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3807 msg.refobject = region;
3810 #if DriverDebugExtra
3811 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);
3813 if (Caret.Visible == true) {
3814 Caret.Paused = true;
3818 if (Caret.Visible == true) {
3820 Caret.Paused = false;
3822 msg.message = Msg.WM_PAINT;
3826 case XEventName.DestroyNotify: {
3828 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3829 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3831 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3832 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3833 CleanupCachedWindows (hwnd);
3835 #if DriverDebugDestroy
3836 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3839 msg.hwnd = hwnd.client_window;
3840 msg.message=Msg.WM_DESTROY;
3843 goto ProcessNextMessage;
3849 case XEventName.ClientMessage: {
3850 if (Dnd.HandleClientMessage (ref xevent)) {
3851 goto ProcessNextMessage;
3854 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3855 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3856 goto ProcessNextMessage;
3859 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3860 msg.message = Msg.WM_MOUSEHOVER;
3861 msg.wParam = GetMousewParam(0);
3862 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3866 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3867 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3868 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3869 msg.wParam = xevent.ClientMessageEvent.ptr3;
3870 msg.lParam = xevent.ClientMessageEvent.ptr4;
3871 if (msg.message == (Msg)Msg.WM_QUIT)
3877 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3878 #if DriverDebugXEmbed
3879 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3882 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3883 XSizeHints hints = new XSizeHints();
3886 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3888 hwnd.width = hints.max_width;
3889 hwnd.height = hints.max_height;
3890 hwnd.ClientRect = Rectangle.Empty;
3891 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3895 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3896 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3897 msg.message = Msg.WM_CLOSE;
3901 // We should not get this, but I'll leave the code in case we need it in the future
3902 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3903 goto ProcessNextMessage;
3906 goto ProcessNextMessage;
3910 goto ProcessNextMessage;
3917 internal override bool GetText(IntPtr handle, out string text) {
3924 IntPtr prop = IntPtr.Zero;
3926 XGetWindowProperty(DisplayHandle, handle,
3927 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
3928 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3930 if ((long)nitems > 0 && prop != IntPtr.Zero) {
3931 text = Marshal.PtrToStringUni (prop, (int)nitems);
3936 // fallback on the non-_NET property
3939 textptr = IntPtr.Zero;
3941 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3942 if (textptr != IntPtr.Zero) {
3943 text = Marshal.PtrToStringAnsi(textptr);
3954 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) {
3957 hwnd = Hwnd.ObjectFromHandle(handle);
3963 height = hwnd.height;
3965 PerformNCCalc(hwnd);
3967 client_width = hwnd.ClientRect.Width;
3968 client_height = hwnd.ClientRect.Height;
3973 // Should we throw an exception or fail silently?
3974 // throw new ArgumentException("Called with an invalid window handle", "handle");
3984 internal override FormWindowState GetWindowState(IntPtr handle) {
3989 IntPtr prop = IntPtr.Zero;
3993 XWindowAttributes attributes;
3996 hwnd = Hwnd.ObjectFromHandle(handle);
4000 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);
4001 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4002 for (int i = 0; i < (long)nitems; i++) {
4003 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4004 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4006 } else if (atom == _NET_WM_STATE_HIDDEN) {
4014 return FormWindowState.Minimized;
4015 } else if (maximized == 2) {
4016 return FormWindowState.Maximized;
4019 attributes = new XWindowAttributes();
4020 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4021 if (attributes.map_state == MapState.IsUnmapped) {
4022 return (FormWindowState)(-1);
4026 return FormWindowState.Normal;
4029 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4031 GrabConfined = Grab.Confined;
4032 GrabArea = Grab.Area;
4035 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4037 IntPtr confine_to_window;
4039 confine_to_window = IntPtr.Zero;
4041 if (confine_to_handle != IntPtr.Zero) {
4042 XWindowAttributes attributes = new XWindowAttributes();
4044 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4047 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4049 Grab.Area.X = attributes.x;
4050 Grab.Area.Y = attributes.y;
4051 Grab.Area.Width = attributes.width;
4052 Grab.Area.Height = attributes.height;
4053 Grab.Confined = true;
4054 confine_to_window = hwnd.client_window;
4059 hwnd = Hwnd.ObjectFromHandle(handle);
4062 XGrabPointer(DisplayHandle, hwnd.client_window, false,
4063 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4064 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
4065 EventMask.LeaveWindowMask,
4066 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4070 internal override void UngrabWindow(IntPtr hwnd) {
4072 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4073 XFlush(DisplayHandle);
4075 WindowUngrabbed (hwnd);
4078 private void WindowUngrabbed (IntPtr hwnd) {
4079 bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4081 Grab.Hwnd = IntPtr.Zero;
4082 Grab.Confined = false;
4085 // lparam should be the handle to the window gaining the mouse capture,
4086 // but X doesn't seem to give us that information.
4087 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4088 // X will send a NotifyUngrab, but since it comes late sometimes we're
4089 // calling WindowUngrabbed directly from UngrabWindow in order to send
4090 // this WM right away.
4091 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4095 internal override void HandleException(Exception e) {
4096 StackTrace st = new StackTrace(e, true);
4097 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4098 Console.WriteLine("{0}{1}", e.Message, st.ToString());
4101 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4104 hwnd = Hwnd.ObjectFromHandle(handle);
4107 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4109 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4113 internal override void InvalidateNC (IntPtr handle) {
4116 hwnd = Hwnd.ObjectFromHandle(handle);
4118 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4121 internal override bool IsEnabled(IntPtr handle) {
4122 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4123 return (hwnd != null && hwnd.Enabled);
4126 internal override bool IsVisible(IntPtr handle) {
4127 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4128 return (hwnd != null && hwnd.visible);
4131 internal override void KillTimer(Timer timer) {
4132 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4134 if (queue == null) {
4135 // This isn't really an error, MS doesn't start the timer if
4136 // it has no assosciated queue
4139 queue.timer_list.Remove (timer);
4142 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4148 hwnd = Hwnd.ObjectFromHandle(handle);
4151 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4158 internal override void OverrideCursor(IntPtr cursor)
4160 if (Grab.Hwnd != IntPtr.Zero) {
4161 XChangeActivePointerGrab (DisplayHandle,
4162 EventMask.ButtonMotionMask |
4163 EventMask.PointerMotionMask |
4164 EventMask.ButtonPressMask |
4165 EventMask.ButtonReleaseMask,
4166 cursor, IntPtr.Zero);
4170 OverrideCursorHandle = cursor;
4173 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4174 PaintEventArgs paint_event;
4177 hwnd = Hwnd.ObjectFromHandle(handle);
4179 if (Caret.Visible == true) {
4180 Caret.Paused = true;
4187 dc = Graphics.FromHwnd (hwnd.client_window);
4189 Region clip_region = new Region ();
4190 clip_region.MakeEmpty();
4192 foreach (Rectangle r in hwnd.ClipRectangles) {
4193 clip_region.Union (r);
4196 if (hwnd.UserClip != null) {
4197 clip_region.Intersect(hwnd.UserClip);
4200 dc.Clip = clip_region;
4201 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4202 hwnd.expose_pending = false;
4204 hwnd.ClearInvalidArea();
4206 hwnd.drawing_stack.Push (paint_event);
4207 hwnd.drawing_stack.Push (dc);
4211 dc = Graphics.FromHwnd (hwnd.whole_window);
4213 if (!hwnd.nc_invalid.IsEmpty) {
4214 dc.SetClip (hwnd.nc_invalid);
4215 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4217 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4219 hwnd.nc_expose_pending = false;
4221 hwnd.ClearNcInvalidArea ();
4223 hwnd.drawing_stack.Push (paint_event);
4224 hwnd.drawing_stack.Push (dc);
4230 internal override void PaintEventEnd(IntPtr handle, bool client) {
4233 hwnd = Hwnd.ObjectFromHandle(handle);
4235 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4239 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4240 pe.SetGraphics (null);
4243 if (Caret.Visible == true) {
4245 Caret.Paused = false;
4249 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4250 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4251 XEventQueue queue = (XEventQueue) queue_id;
4254 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4255 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4259 if (queue.Count > 0) {
4262 // Only call UpdateMessageQueue if real events are pending
4263 // otherwise we go to sleep on the socket
4264 if (XPending(DisplayHandle) != 0) {
4265 UpdateMessageQueue((XEventQueue)queue_id);
4267 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4272 CheckTimers(queue.timer_list, DateTime.UtcNow);
4277 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4280 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4281 XEvent xevent = new XEvent ();
4282 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4284 xevent.type = XEventName.ClientMessage;
4285 xevent.ClientMessageEvent.display = DisplayHandle;
4288 xevent.ClientMessageEvent.window = hwnd.whole_window;
4290 xevent.ClientMessageEvent.window = IntPtr.Zero;
4293 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4294 xevent.ClientMessageEvent.format = 32;
4295 xevent.ClientMessageEvent.ptr1 = handle;
4296 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4297 xevent.ClientMessageEvent.ptr3 = wparam;
4298 xevent.ClientMessageEvent.ptr4 = lparam;
4300 hwnd.Queue.EnqueueLocked (xevent);
4305 internal override void PostQuitMessage(int exitCode) {
4306 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4307 XFlush(DisplayHandle);
4310 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4315 internal override void RequestNCRecalc(IntPtr handle) {
4318 hwnd = Hwnd.ObjectFromHandle(handle);
4324 PerformNCCalc(hwnd);
4325 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4326 InvalidateNC(handle);
4329 internal override void ResetMouseHover(IntPtr handle) {
4332 hwnd = Hwnd.ObjectFromHandle(handle);
4337 HoverState.Timer.Enabled = true;
4338 HoverState.X = mouse_position.X;
4339 HoverState.Y = mouse_position.Y;
4340 HoverState.Window = handle;
4344 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4350 hwnd = Hwnd.ObjectFromHandle(handle);
4353 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4360 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4366 hwnd = Hwnd.ObjectFromHandle(handle);
4369 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4376 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4379 XGCValues gc_values;
4381 hwnd = Hwnd.ObjectFromHandle(handle);
4383 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4385 /* We have an invalid area in the window we're scrolling.
4386 Adjust our stored invalid rectangle to to match the scrolled amount */
4401 if (area.Contains (hwnd.Invalid))
4402 hwnd.ClearInvalidArea ();
4403 hwnd.AddInvalidArea(r);
4406 gc_values = new XGCValues();
4408 if (with_children) {
4409 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4412 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4420 height = area.Height - YAmount;
4421 dest_y = area.Y + YAmount;
4424 src_y = area.Y - YAmount;
4425 height = area.Height + YAmount;
4431 width = area.Width - XAmount;
4432 dest_x = area.X + XAmount;
4435 src_x = area.X - XAmount;
4436 width = area.Width + XAmount;
4440 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4442 // Generate an expose for the area exposed by the horizontal scroll
4443 // We don't use AddExpose since we're
4445 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4446 } else if (XAmount < 0) {
4447 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4450 // Generate an expose for the area exposed by the vertical scroll
4452 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4453 } else if (YAmount < 0) {
4454 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4456 XFreeGC(DisplayHandle, gc);
4459 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4463 hwnd = Hwnd.GetObjectFromWindow(handle);
4465 rect = hwnd.ClientRect;
4468 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4471 internal override void SendAsyncMethod (AsyncMethodData method) {
4473 XEvent xevent = new XEvent ();
4475 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4477 xevent.type = XEventName.ClientMessage;
4478 xevent.ClientMessageEvent.display = DisplayHandle;
4479 xevent.ClientMessageEvent.window = method.Handle;
4480 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4481 xevent.ClientMessageEvent.format = 32;
4482 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4484 hwnd.Queue.EnqueueLocked (xevent);
4489 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4491 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4494 h = Hwnd.ObjectFromHandle(hwnd);
4496 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4497 AsyncMethodResult result;
4498 AsyncMethodData data;
4500 result = new AsyncMethodResult ();
4501 data = new AsyncMethodData ();
4504 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4505 data.Args = new object[] { hwnd, message, wParam, lParam };
4506 data.Result = result;
4508 SendAsyncMethod (data);
4509 #if DriverDebug || DriverDebugThreads
4510 Console.WriteLine ("Sending {0} message across.", message);
4515 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4518 internal override int SendInput(IntPtr handle, Queue keys) {
4519 if (handle == IntPtr.Zero)
4522 int count = keys.Count;
4523 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4525 while (keys.Count > 0) {
4527 MSG msg = (MSG)keys.Dequeue();
4529 XEvent xevent = new XEvent ();
4531 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4532 xevent.KeyEvent.display = DisplayHandle;
4535 xevent.KeyEvent.window = hwnd.whole_window;
4537 xevent.KeyEvent.window = IntPtr.Zero;
4540 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4542 hwnd.Queue.EnqueueLocked (xevent);
4547 internal override void SetAllowDrop (IntPtr handle, bool value)
4549 // We allow drop on all windows
4552 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4553 DragDropEffects allowed_effects)
4555 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4558 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4560 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4563 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4564 Form form = Control.FromHandle (handle) as Form;
4565 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4566 border_style == FormBorderStyle.SizableToolWindow)) {
4567 form.window_manager = new ToolWindowManager (form);
4570 RequestNCRecalc(handle);
4573 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4574 if (Caret.Hwnd == handle) {
4581 if (Caret.Visible == true) {
4583 Caret.Timer.Start();
4588 internal override void SetClipRegion(IntPtr handle, Region region) {
4591 hwnd = Hwnd.ObjectFromHandle(handle);
4596 hwnd.UserClip = region;
4597 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4600 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4603 if (OverrideCursorHandle == IntPtr.Zero) {
4604 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4608 LastCursorHandle = cursor;
4609 LastCursorWindow = handle;
4611 hwnd = Hwnd.ObjectFromHandle(handle);
4613 if (cursor != IntPtr.Zero) {
4614 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4616 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4618 XFlush(DisplayHandle);
4623 hwnd = Hwnd.ObjectFromHandle(handle);
4625 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4629 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4630 out int root_x, out int root_y, out int child_x, out int child_y,
4633 /* this code was written with the help of
4634 glance at gdk. I never would have realized we
4635 needed a loop in order to traverse down in the
4636 hierarchy. I would have assumed you'd get the
4637 most deeply nested child and have to do
4638 XQueryTree to move back up the hierarchy..
4639 stupid me, of course. */
4642 XGrabServer (display);
4644 XQueryPointer(display, w, out root, out c,
4645 out root_x, out root_y, out child_x, out child_y,
4651 IntPtr child_last = IntPtr.Zero;
4652 while (c != IntPtr.Zero) {
4654 XQueryPointer(display, c, out root, out c,
4655 out root_x, out root_y, out child_x, out child_y,
4658 XUngrabServer (display);
4664 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4665 if (handle == IntPtr.Zero) {
4668 int root_x, root_y, child_x, child_y, mask;
4671 * QueryPointer before warping
4672 * because if the warp is on
4673 * the RootWindow, the x/y are
4674 * relative to the current
4677 QueryPointer (DisplayHandle, RootWindow,
4680 out root_x, out root_y,
4681 out child_x, out child_y,
4684 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4686 XFlush (DisplayHandle);
4688 /* then we need to a
4689 * QueryPointer after warping
4690 * to manually generate a
4691 * motion event for the window
4694 QueryPointer (DisplayHandle, RootWindow,
4697 out root_x, out root_y,
4698 out child_x, out child_y,
4701 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4702 if (child_hwnd == null) {
4706 XEvent xevent = new XEvent ();
4708 xevent.type = XEventName.MotionNotify;
4709 xevent.MotionEvent.display = DisplayHandle;
4710 xevent.MotionEvent.window = child_hwnd.client_window;
4711 xevent.MotionEvent.root = RootWindow;
4712 xevent.MotionEvent.x = child_x;
4713 xevent.MotionEvent.y = child_y;
4714 xevent.MotionEvent.x_root = root_x;
4715 xevent.MotionEvent.y_root = root_y;
4716 xevent.MotionEvent.state = mask;
4718 child_hwnd.Queue.EnqueueLocked (xevent);
4723 hwnd = Hwnd.ObjectFromHandle(handle);
4725 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4730 internal override void SetFocus(IntPtr handle) {
4732 IntPtr prev_focus_window;
4734 hwnd = Hwnd.ObjectFromHandle(handle);
4736 if (hwnd.client_window == FocusWindow) {
4740 prev_focus_window = FocusWindow;
4741 FocusWindow = hwnd.client_window;
4743 if (prev_focus_window != IntPtr.Zero) {
4744 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4746 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4748 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4751 internal override void SetIcon(IntPtr handle, Icon icon) {
4754 hwnd = Hwnd.ObjectFromHandle(handle);
4756 SetIcon(hwnd, icon);
4760 internal override void SetMenu(IntPtr handle, Menu menu) {
4763 hwnd = Hwnd.ObjectFromHandle(handle);
4766 RequestNCRecalc(handle);
4769 internal override void SetModal(IntPtr handle, bool Modal) {
4771 ModalWindows.Push(handle);
4773 if (ModalWindows.Contains(handle)) {
4776 if (ModalWindows.Count > 0) {
4777 Activate((IntPtr)ModalWindows.Peek());
4782 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4785 hwnd = Hwnd.ObjectFromHandle(handle);
4786 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4789 #if DriverDebug || DriverDebugParent
4790 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4792 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4798 internal override void SetTimer (Timer timer) {
4799 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4801 if (queue == null) {
4802 // This isn't really an error, MS doesn't start the timer if
4803 // it has no assosciated queue
4806 queue.timer_list.Add (timer);
4810 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4814 hwnd = Hwnd.ObjectFromHandle(handle);
4816 if (handle_owner != IntPtr.Zero) {
4817 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4828 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4829 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4831 if (hwnd_owner != null) {
4832 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4834 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4839 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4845 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
4849 hwnd = Hwnd.ObjectFromHandle(handle);
4850 hwnd.visible = visible;
4854 MapWindow(hwnd, WindowType.Both);
4856 if (Control.FromHandle(handle) is Form) {
4859 s = ((Form)Control.FromHandle(handle)).WindowState;
4862 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4863 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4867 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4870 UnmapWindow(hwnd, WindowType.Both);
4876 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4881 hwnd = Hwnd.ObjectFromHandle(handle);
4886 hints = new XSizeHints();
4888 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4889 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4890 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4891 hints.min_width = min.Width;
4892 hints.min_height = min.Height;
4895 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4896 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4897 hints.max_width = max.Width;
4898 hints.max_height = max.Height;
4901 if (hints.flags != IntPtr.Zero) {
4902 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4905 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4906 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4907 hints.x = maximized.X;
4908 hints.y = maximized.Y;
4909 hints.width = maximized.Width;
4910 hints.height = maximized.Height;
4912 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4913 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4918 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4921 hwnd = Hwnd.ObjectFromHandle(handle);
4927 // Win32 automatically changes negative width/height to 0.
4933 // X requires a sanity check for width & height; otherwise it dies
4934 if (hwnd.zero_sized && width > 0 && height > 0) {
4936 MapWindow(hwnd, WindowType.Whole);
4938 hwnd.zero_sized = false;
4941 if ((width < 1) || (height < 1)) {
4942 hwnd.zero_sized = true;
4943 UnmapWindow(hwnd, WindowType.Whole);
4946 // Save a server roundtrip (and prevent a feedback loop)
4947 if ((hwnd.x == x) && (hwnd.y == y) &&
4948 (hwnd.width == width) && (hwnd.height == height)) {
4952 if (!hwnd.zero_sized) {
4957 hwnd.height = height;
4958 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4960 if (hwnd.fixed_size) {
4961 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4965 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4966 PerformNCCalc(hwnd);
4970 // Update our position/size immediately, so
4971 // that future calls to SetWindowPos aren't
4972 // kept from calling XMoveResizeWindow (by the
4973 // "Save a server roundtrip" block above).
4977 hwnd.height = height;
4978 hwnd.ClientRect = Rectangle.Empty;
4981 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4982 FormWindowState current_state;
4985 hwnd = Hwnd.ObjectFromHandle(handle);
4987 current_state = GetWindowState(handle);
4989 if (current_state == state) {
4994 case FormWindowState.Normal: {
4996 if (current_state == FormWindowState.Minimized) {
4997 MapWindow(hwnd, WindowType.Both);
4998 } else if (current_state == FormWindowState.Maximized) {
4999 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5006 case FormWindowState.Minimized: {
5008 if (current_state == FormWindowState.Maximized) {
5009 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5011 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5016 case FormWindowState.Maximized: {
5018 if (current_state == FormWindowState.Minimized) {
5019 MapWindow(hwnd, WindowType.Both);
5022 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5030 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5033 hwnd = Hwnd.ObjectFromHandle(handle);
5034 SetHwndStyles(hwnd, cp);
5035 SetWMStyles(hwnd, cp);
5038 internal override double GetWindowTransparency(IntPtr handle)
5043 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5047 hwnd = Hwnd.ObjectFromHandle(handle);
5053 hwnd.opacity = (uint)(0xffffffff * transparency);
5054 opacity = (IntPtr)((int)hwnd.opacity);
5056 IntPtr w = hwnd.whole_window;
5057 if (hwnd.reparented)
5058 w = XGetParent (hwnd.whole_window);
5059 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5062 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5063 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5071 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5074 } else if (!bottom) {
5075 Hwnd after_hwnd = null;
5077 if (after_handle != IntPtr.Zero) {
5078 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5081 XWindowChanges values = new XWindowChanges();
5083 if (after_hwnd == null) {
5084 // Work around metacity 'issues'
5088 atoms[0] = unixtime();
5089 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5091 XRaiseWindow(DisplayHandle, hwnd.whole_window);
5092 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5094 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5097 values.sibling = after_hwnd.whole_window;
5098 values.stack_mode = StackMode.Below;
5101 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5106 XLowerWindow(DisplayHandle, hwnd.whole_window);
5113 internal override void ShowCursor(bool show) {
5114 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5117 internal override object StartLoop(Thread thread) {
5118 XEventQueue q = ThreadQueue(thread);
5122 internal override TransparencySupport SupportsTransparency() {
5123 // We need to check if the x compositing manager is running
5124 return TransparencySupport.Set;
5127 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5128 GetSystrayManagerWindow();
5130 if (SystrayMgrWindow != IntPtr.Zero) {
5131 XSizeHints size_hints;
5134 hwnd = Hwnd.ObjectFromHandle(handle);
5136 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5140 if (hwnd.client_window != hwnd.whole_window) {
5141 XDestroyWindow(DisplayHandle, hwnd.client_window);
5142 hwnd.client_window = hwnd.whole_window;
5144 /* by virtue of the way the tests are ordered when determining if it's PAINT
5145 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5146 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5147 there's a pending expose). */
5148 if (hwnd.nc_expose_pending) {
5149 hwnd.nc_expose_pending = false;
5150 if (!hwnd.expose_pending)
5151 hwnd.Queue.Paint.Remove (hwnd);
5155 size_hints = new XSizeHints();
5157 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5159 size_hints.min_width = 24;
5160 size_hints.min_height = 24;
5161 size_hints.max_width = 24;
5162 size_hints.max_height = 24;
5163 size_hints.base_width = 24;
5164 size_hints.base_height = 24;
5166 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5168 int[] atoms = new int[2];
5169 atoms [0] = 1; // Version 1
5170 atoms [1] = 1; // we want to be mapped
5172 // This line cost me 3 days...
5173 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5175 // Need to pick some reasonable defaults
5177 tt.AutomaticDelay = 100;
5178 tt.InitialDelay = 250;
5179 tt.ReshowDelay = 250;
5180 tt.ShowAlways = true;
5182 if ((tip != null) && (tip != string.Empty)) {
5183 tt.SetToolTip(Control.FromHandle(handle), tip);
5189 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5197 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5200 control = Control.FromHandle(handle);
5201 if (control != null && tt != null) {
5202 tt.SetToolTip(control, tip);
5210 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5212 #if GTKSOCKET_SUPPORTS_REPARENTING
5215 hwnd = Hwnd.ObjectFromHandle(handle);
5217 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5218 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5219 * 2. The client can reparent its window out of the embedder window.
5220 * 3. The client can destroy its window.
5222 * this call to SetParent is case 2, but in
5223 * the spec it also mentions that gtk doesn't
5224 * support this at present. Looking at HEAD
5225 * gtksocket-x11.c jives with this statement.
5227 * so we can't reparent. we have to destroy.
5229 SetParent(hwnd.whole_window, FosterParent);
5231 Control control = Control.FromHandle(handle);
5232 if (control is NotifyIcon.NotifyIconWindow)
5233 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5236 // The caller can now re-dock it later...
5243 internal override bool Text(IntPtr handle, string text) {
5246 hwnd = Hwnd.ObjectFromHandle(handle);
5249 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5250 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5252 // XXX this has problems with UTF8.
5253 // we need to either use the actual
5254 // text if it's latin-1, or convert it
5255 // to compound text if it's in a
5256 // different charset.
5257 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5262 internal override bool TranslateMessage(ref MSG msg) {
5263 return Keyboard.TranslateMessage (ref msg);
5266 internal override void UpdateWindow(IntPtr handle) {
5269 hwnd = Hwnd.ObjectFromHandle(handle);
5271 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5275 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5276 hwnd.Queue.Paint.Remove(hwnd);
5279 internal override void CreateOffscreenDrawable (IntPtr handle,
5280 int width, int height,
5281 out object offscreen_drawable)
5284 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5286 XGetGeometry (DisplayHandle, handle,
5288 out x_out, out y_out,
5289 out width_out, out height_out,
5290 out border_width_out, out depth_out);
5292 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5294 offscreen_drawable = pixmap;
5298 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5300 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5303 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5305 return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5308 internal override void BlitFromOffscreen (IntPtr dest_handle,
5310 object offscreen_drawable,
5311 Graphics offscreen_dc,
5314 XGCValues gc_values;
5317 gc_values = new XGCValues();
5319 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5321 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5322 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5324 XFreeGC (DisplayHandle, gc);
5327 #endregion // Public Static Methods
5330 internal override event EventHandler Idle;
5331 #endregion // Events
5334 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5335 internal extern static IntPtr XOpenDisplay(IntPtr display);
5336 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5337 internal extern static int XCloseDisplay(IntPtr display);
5338 [DllImport ("libX11", EntryPoint="XSynchronize")]
5339 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5341 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5342 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);
5343 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5344 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5345 [DllImport ("libX11", EntryPoint="XMapWindow")]
5346 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5347 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5348 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5349 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5350 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5351 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5352 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5353 [DllImport ("libX11", EntryPoint="XRootWindow")]
5354 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5355 [DllImport ("libX11", EntryPoint="XNextEvent")]
5356 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5357 [DllImport ("libX11")]
5358 internal extern static int XConnectionNumber (IntPtr diplay);
5359 [DllImport ("libX11")]
5360 internal extern static int XPending (IntPtr diplay);
5361 [DllImport ("libX11", EntryPoint="XSelectInput")]
5362 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5364 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5365 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5367 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5368 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5369 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5370 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5372 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5373 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5375 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5376 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5378 [DllImport ("libX11", EntryPoint="XFlush")]
5379 internal extern static int XFlush(IntPtr display);
5381 [DllImport ("libX11", EntryPoint="XSetWMName")]
5382 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5384 [DllImport ("libX11", EntryPoint="XStoreName")]
5385 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5387 [DllImport ("libX11", EntryPoint="XFetchName")]
5388 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5390 [DllImport ("libX11", EntryPoint="XSendEvent")]
5391 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5393 [DllImport ("libX11", EntryPoint="XQueryTree")]
5394 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);
5396 [DllImport ("libX11", EntryPoint="XFree")]
5397 internal extern static int XFree(IntPtr data);
5399 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5400 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5402 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5403 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5405 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5406 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5408 [DllImport ("libX11", EntryPoint="XInternAtom")]
5409 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5411 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5412 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5414 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5415 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5417 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5418 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);
5420 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5421 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5423 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5424 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);
5426 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5427 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);
5429 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5430 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);
5432 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5433 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);
5435 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5436 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);
5438 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5439 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);
5441 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5442 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);
5444 [DllImport ("libX11", EntryPoint="XClearWindow")]
5445 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5447 [DllImport ("libX11", EntryPoint="XClearArea")]
5448 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5451 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5452 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5454 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5455 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5457 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5458 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5460 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5461 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5463 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5464 internal extern static int XDefaultScreen(IntPtr display);
5466 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5467 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5469 [DllImport ("libX11", EntryPoint="XLookupColor")]
5470 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5472 [DllImport ("libX11", EntryPoint="XAllocColor")]
5473 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5475 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5476 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5478 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5479 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5481 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5482 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5484 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5485 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5487 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5488 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5490 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5491 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5493 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5494 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5496 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5497 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5499 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5500 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5502 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5503 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5505 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5506 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5509 [DllImport ("libX11", EntryPoint="XCreateGC")]
5510 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5512 [DllImport ("libX11", EntryPoint="XFreeGC")]
5513 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5515 [DllImport ("libX11", EntryPoint="XSetFunction")]
5516 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5518 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5519 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5521 [DllImport ("libX11", EntryPoint="XDrawLine")]
5522 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5524 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5525 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5527 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5528 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5530 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5531 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5533 [DllImport ("libX11", EntryPoint="XCopyArea")]
5534 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);
5536 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5537 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);
5539 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5540 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5542 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5543 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5545 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5546 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5548 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5549 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5551 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5552 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5554 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5555 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5557 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5558 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);
5560 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5561 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5563 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5564 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5566 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5567 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5569 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5570 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5572 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5573 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5575 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5576 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5578 [DllImport ("libX11", EntryPoint="XGrabServer")]
5579 internal extern static void XGrabServer(IntPtr display);
5581 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5582 internal extern static void XUngrabServer(IntPtr display);
5584 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5585 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5587 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5588 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5590 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5591 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5593 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5594 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5596 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5597 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5599 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5600 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5602 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5603 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5605 [DllImport ("libX11", EntryPoint="XInitThreads")]
5606 internal extern static int XInitThreads();
5608 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5609 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5611 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5612 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5614 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5615 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5617 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5618 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5620 [DllImport ("libX11", EntryPoint="XSetForeground")]
5621 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5623 [DllImport ("libX11", EntryPoint="XSetBackground")]
5624 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5626 [DllImport ("libX11", EntryPoint="XBell")]
5627 internal extern static int XBell(IntPtr display, int percent);
5629 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5630 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5632 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5633 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5635 [DllImport ("libX11")]
5636 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5638 [DllImport ("libX11")]
5639 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);