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);
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 TitleStyle title_style, out int caption_height, out int tool_caption_height) {
758 // Only MDI windows get caption_heights
760 tool_caption_height = 19;
762 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
763 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
764 border_style = FormBorderStyle.Fixed3D;
765 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
766 border_style = FormBorderStyle.None;
768 border_style = FormBorderStyle.FixedSingle;
770 title_style = TitleStyle.None;
772 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
775 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
776 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
777 title_style = TitleStyle.Tool;
779 title_style = TitleStyle.Normal;
783 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
784 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
785 border_style = (FormBorderStyle) 0xFFFF;
787 border_style = FormBorderStyle.None;
792 title_style = TitleStyle.None;
793 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
794 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
795 title_style = TitleStyle.Tool;
797 title_style = TitleStyle.Normal;
801 border_style = FormBorderStyle.None;
803 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
804 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
805 border_style = FormBorderStyle.SizableToolWindow;
807 border_style = FormBorderStyle.Sizable;
810 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
811 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
812 border_style = FormBorderStyle.Fixed3D;
813 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
814 border_style = FormBorderStyle.FixedDialog;
815 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
816 border_style = FormBorderStyle.FixedToolWindow;
817 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
818 border_style = FormBorderStyle.FixedSingle;
821 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
822 border_style = FormBorderStyle.FixedSingle;
829 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
830 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
833 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
834 MotifWmHints mwmHints;
835 MotifFunctions functions;
836 MotifDecorations decorations;
839 Rectangle client_rect;
841 // Child windows don't need WM window styles
842 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
847 mwmHints = new MotifWmHints();
851 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
852 mwmHints.functions = (IntPtr)0;
853 mwmHints.decorations = (IntPtr)0;
855 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
856 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
857 /* tool windows get no window manager
858 decorations, and neither do windows
859 which lack CAPTION/BORDER/DLGFRAME
863 /* just because the window doesn't get any decorations doesn't
864 mean we should disable the functions. for instance, without
865 MotifFunctions.Maximize, changing the windowstate to Maximized
866 is ignored by metacity. */
867 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
870 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
871 functions |= MotifFunctions.Move;
872 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
875 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
876 functions |= MotifFunctions.Move | MotifFunctions.Resize;
877 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
880 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
881 functions |= MotifFunctions.Minimize;
882 decorations |= MotifDecorations.Minimize;
885 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
886 functions |= MotifFunctions.Maximize;
887 decorations |= MotifDecorations.Maximize;
890 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
891 functions |= MotifFunctions.Resize;
892 decorations |= MotifDecorations.ResizeH;
895 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
896 decorations |= MotifDecorations.Border;
899 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
900 decorations |= MotifDecorations.Border;
903 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
904 decorations |= MotifDecorations.Border;
907 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
908 functions |= MotifFunctions.Close;
911 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
912 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
913 if (cp.Caption == "") {
914 functions &= ~MotifFunctions.Move;
915 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
920 if ((functions & MotifFunctions.Resize) == 0) {
921 hwnd.fixed_size = true;
922 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));
924 hwnd.fixed_size = false;
927 mwmHints.functions = (IntPtr)functions;
928 mwmHints.decorations = (IntPtr)decorations;
930 FormWindowState current_state = GetWindowState (hwnd.Handle);
931 if (current_state == (FormWindowState)(-1))
932 current_state = FormWindowState.Normal;
934 client_rect = hwnd.ClientRect;
938 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
939 // and get those windows in front of their parents
940 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
941 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
942 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
943 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
945 Form f = Control.FromHandle(hwnd.Handle) as Form;
946 if (f != null && !hwnd.reparented) {
947 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
948 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
949 if (owner_hwnd != null)
950 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
951 owner_hwnd.whole_window);
956 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
957 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
958 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
959 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
961 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
962 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
963 /* this line keeps the window from showing up in gnome's taskbar */
964 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
966 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
967 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
969 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
972 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
973 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
975 /* we need to add these atoms in the
976 * event we're maximized, since we're
977 * replacing the existing
978 * _NET_WM_STATE here. If we don't
979 * add them, future calls to
980 * GetWindowState will return Normal
981 * for a window which is maximized. */
982 if (current_state == FormWindowState.Maximized) {
983 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
984 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
986 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
989 IntPtr[] atom_ptrs = new IntPtr[2];
990 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
991 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
992 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
995 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
999 private void SetIcon(Hwnd hwnd, Icon icon) {
1005 bitmap = icon.ToBitmap();
1007 size = bitmap.Width * bitmap.Height + 2;
1008 data = new IntPtr[size];
1010 data[index++] = (IntPtr)bitmap.Width;
1011 data[index++] = (IntPtr)bitmap.Height;
1013 for (int y = 0; y < bitmap.Height; y++) {
1014 for (int x = 0; x < bitmap.Width; x++) {
1015 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
1019 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
1022 private void WakeupMain () {
1023 wake.Send (new byte [] { 0xFF });
1026 private XEventQueue ThreadQueue(Thread thread) {
1029 queue = (XEventQueue)MessageQueues[thread];
1030 if (queue == null) {
1031 queue = new XEventQueue(thread);
1032 MessageQueues[thread] = queue;
1038 private void TranslatePropertyToClipboard(IntPtr property) {
1043 IntPtr prop = IntPtr.Zero;
1045 Clipboard.Item = null;
1047 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);
1049 if ((long)nitems > 0) {
1050 if (property == (IntPtr)Atom.XA_STRING) {
1051 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1052 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1053 // FIXME - convert bitmap to image
1054 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1055 // FIXME - convert pixmap to image
1056 } else if (property == OEMTEXT) {
1057 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1058 } else if (property == UNICODETEXT) {
1059 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1066 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1068 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1072 // Keep the invalid area as small as needed
1073 if ((x + width) > hwnd.width) {
1074 width = hwnd.width - x;
1077 if ((y + height) > hwnd.height) {
1078 height = hwnd.height - y;
1082 hwnd.AddInvalidArea(x, y, width, height);
1083 if (!hwnd.expose_pending) {
1084 if (!hwnd.nc_expose_pending) {
1085 hwnd.Queue.Paint.Enqueue(hwnd);
1087 hwnd.expose_pending = true;
1090 hwnd.AddNcInvalidArea (x, y, width, height);
1092 if (!hwnd.nc_expose_pending) {
1093 if (!hwnd.expose_pending) {
1094 hwnd.Queue.Paint.Enqueue(hwnd);
1096 hwnd.nc_expose_pending = true;
1101 private void FrameExtents(IntPtr window, out int left, out int top) {
1106 IntPtr prop = IntPtr.Zero;
1108 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);
1109 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1110 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1111 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1112 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1113 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1119 if (prop != IntPtr.Zero) {
1125 private void AddConfigureNotify (XEvent xevent) {
1128 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1135 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1136 if (!hwnd.reparented) {
1137 hwnd.x = xevent.ConfigureEvent.x;
1138 hwnd.y = xevent.ConfigureEvent.y;
1140 // This sucks ass, part 1
1141 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1142 // no standard way of getting our adjustment.
1143 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1144 // Several other WMs do their decorations different yet again and we fail to deal
1145 // with that, since I couldn't find any frigging commonality between them.
1146 // The only sane WM seems to be KDE
1148 if (!xevent.ConfigureEvent.send_event) {
1151 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1153 // This is a synthetic event, coordinates are in root space
1154 hwnd.x = xevent.ConfigureEvent.x;
1155 hwnd.y = xevent.ConfigureEvent.y;
1156 if (hwnd.whacky_wm) {
1160 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1161 hwnd.x -= frame_left;
1162 hwnd.y -= frame_top;
1167 // XXX this sucks. this isn't thread safe
1168 hwnd.width = xevent.ConfigureEvent.width;
1169 hwnd.height = xevent.ConfigureEvent.height;
1170 hwnd.ClientRect = Rectangle.Empty;
1172 lock (hwnd.configure_lock) {
1173 if (!hwnd.configure_pending) {
1174 hwnd.Queue.EnqueueLocked (xevent);
1175 hwnd.configure_pending = true;
1179 // We drop configure events for Client windows
1182 private void ShowCaret() {
1183 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1189 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1193 private void HideCaret() {
1194 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1200 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1204 private int NextTimeout (ArrayList timers, DateTime now) {
1205 int timeout = Int32.MaxValue;
1207 foreach (Timer timer in timers) {
1208 int next = (int) (timer.Expires - now).TotalMilliseconds;
1210 return 0; // Have a timer that has already expired
1213 if (next < timeout) {
1217 if (timeout < Timer.Minimum) {
1218 timeout = Timer.Minimum;
1226 private void CheckTimers (ArrayList timers, DateTime now) {
1229 count = timers.Count;
1234 for (int i = 0; i < timers.Count; i++) {
1237 timer = (Timer) timers [i];
1239 if (timer.Enabled && timer.Expires <= now) {
1246 private void MapWindow(Hwnd hwnd, WindowType windows) {
1248 if ((windows & WindowType.Whole) != 0) {
1249 XMapWindow(DisplayHandle, hwnd.whole_window);
1251 if ((windows & WindowType.Client) != 0) {
1252 XMapWindow(DisplayHandle, hwnd.client_window);
1256 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1257 hwnd.mapped = false;
1258 if ((windows & WindowType.Whole) != 0) {
1259 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1261 if ((windows & WindowType.Client) != 0) {
1262 XUnmapWindow(DisplayHandle, hwnd.client_window);
1266 private void UpdateMessageQueue (XEventQueue queue) {
1271 now = DateTime.UtcNow;
1274 pending = XPending (DisplayHandle);
1278 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1279 Idle (this, EventArgs.Empty);
1283 pending = XPending (DisplayHandle);
1290 if (queue != null) {
1291 if (queue.Paint.Count > 0)
1294 timeout = NextTimeout (queue.timer_list, now);
1299 int length = pollfds.Length - 1;
1300 lock (wake_waiting_lock) {
1301 if (wake_waiting == false) {
1303 wake_waiting = true;
1307 Syscall.poll (pollfds, (uint)length, timeout);
1308 // Clean out buffer, so we're not busy-looping on the same data
1309 if (pollfds[1].revents != 0) {
1310 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1311 wake_waiting = false;
1315 pending = XPending (DisplayHandle);
1321 CheckTimers (queue.timer_list, now);
1324 XEvent xevent = new XEvent ();
1327 if (XPending (DisplayHandle) == 0)
1330 XNextEvent (DisplayHandle, ref xevent);
1332 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1333 if (XFilterEvent(ref xevent, FosterParent)) {
1339 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1343 switch (xevent.type) {
1344 case XEventName.Expose:
1345 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1348 case XEventName.SelectionClear: {
1349 // Should we do something?
1353 case XEventName.SelectionRequest: {
1354 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1358 sel_event = new XEvent();
1359 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1360 sel_event.SelectionEvent.send_event = true;
1361 sel_event.SelectionEvent.display = DisplayHandle;
1362 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1363 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1364 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1365 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1366 sel_event.SelectionEvent.property = IntPtr.Zero;
1368 // Seems that some apps support asking for supported types
1369 if (xevent.SelectionEvent.target == TARGETS) {
1376 if (Clipboard.Item is String) {
1377 atoms[atom_count++] = (int)Atom.XA_STRING;
1378 atoms[atom_count++] = (int)OEMTEXT;
1379 atoms[atom_count++] = (int)UNICODETEXT;
1380 } else if (Clipboard.Item is Image) {
1381 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1382 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1384 // FIXME - handle other types
1387 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1388 } else if (Clipboard.Item is string) {
1394 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1397 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1398 buffer = Marshal.AllocHGlobal(bytes.Length);
1399 buflen = bytes.Length;
1401 for (int i = 0; i < buflen; i++) {
1402 Marshal.WriteByte(buffer, i, bytes[i]);
1404 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1405 // FIXME - this should encode into ISO2022
1406 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1407 while (Marshal.ReadByte(buffer, buflen) != 0) {
1410 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1411 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1412 while (Marshal.ReadByte(buffer, buflen) != 0) {
1416 buffer = IntPtr.Zero;
1419 if (buffer != IntPtr.Zero) {
1420 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1421 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1422 Marshal.FreeHGlobal(buffer);
1424 } else if (Clipboard.Item is Image) {
1425 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1426 // FIXME - convert image and store as property
1427 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1428 // FIXME - convert image and store as property
1432 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1436 case XEventName.SelectionNotify: {
1437 if (Clipboard.Enumerating) {
1438 Clipboard.Enumerating = false;
1439 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1440 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1441 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1442 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1443 #if DriverDebugExtra
1444 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1448 } else if (Clipboard.Retrieving) {
1449 Clipboard.Retrieving = false;
1450 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1451 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1453 Clipboard.Item = null;
1456 Dnd.HandleSelectionNotifyEvent (ref xevent);
1461 case XEventName.MapNotify: {
1462 if (hwnd.client_window == xevent.MapEvent.window) {
1468 case XEventName.UnmapNotify: {
1469 if (hwnd.client_window == xevent.MapEvent.window) {
1470 hwnd.mapped = false;
1475 case XEventName.KeyRelease:
1476 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1477 XEvent nextevent = new XEvent ();
1479 XPeekEvent (DisplayHandle, ref nextevent);
1481 if (nextevent.type == XEventName.KeyPress &&
1482 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1483 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1487 goto case XEventName.KeyPress;
1489 case XEventName.MotionNotify: {
1492 /* we can't do motion compression across threads, so just punt if we don't match up */
1493 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1494 peek = hwnd.Queue.Peek();
1495 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1499 goto case XEventName.KeyPress;
1502 case XEventName.KeyPress:
1503 case XEventName.ButtonPress:
1504 case XEventName.ButtonRelease:
1505 case XEventName.EnterNotify:
1506 case XEventName.LeaveNotify:
1507 case XEventName.CreateNotify:
1508 case XEventName.DestroyNotify:
1509 case XEventName.FocusIn:
1510 case XEventName.FocusOut:
1511 case XEventName.ClientMessage:
1512 case XEventName.ReparentNotify:
1513 hwnd.Queue.EnqueueLocked (xevent);
1516 case XEventName.ConfigureNotify:
1517 AddConfigureNotify(xevent);
1520 case XEventName.PropertyNotify:
1521 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1526 IntPtr prop = IntPtr.Zero;
1529 prev_active = ActiveWindow;
1530 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);
1531 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1532 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1535 if (prev_active != ActiveWindow) {
1536 if (prev_active != IntPtr.Zero) {
1537 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1539 if (ActiveWindow != IntPtr.Zero) {
1540 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1543 if (ModalWindows.Count == 0) {
1546 // Modality handling, if we are modal and the new active window is one
1547 // of ours but not the modal one, switch back to the modal window
1549 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1550 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1551 Activate((IntPtr)ModalWindows.Peek());
1564 private IntPtr GetMousewParam(int Delta) {
1567 if ((MouseState & MouseButtons.Left) != 0) {
1568 result |= (int)MsgButtons.MK_LBUTTON;
1571 if ((MouseState & MouseButtons.Middle) != 0) {
1572 result |= (int)MsgButtons.MK_MBUTTON;
1575 if ((MouseState & MouseButtons.Right) != 0) {
1576 result |= (int)MsgButtons.MK_RBUTTON;
1579 Keys mods = ModifierKeys;
1580 if ((mods & Keys.Control) != 0) {
1581 result |= (int)MsgButtons.MK_CONTROL;
1584 if ((mods & Keys.Shift) != 0) {
1585 result |= (int)MsgButtons.MK_SHIFT;
1588 result |= Delta << 16;
1590 return (IntPtr)result;
1592 private IntPtr XGetParent(IntPtr handle) {
1599 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1602 if (Children!=IntPtr.Zero) {
1610 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1611 if (ErrorExceptions) {
1612 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1614 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);
1619 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1622 Control[] controls = c.Controls.GetAllControls ();
1624 if (c.IsHandleCreated && !c.IsDisposed) {
1625 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1627 #if DriverDebug || DriverDebugDestroy
1628 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1629 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1633 CleanupCachedWindows (hwnd);
1637 for (int i = 0; i < controls.Length; i ++) {
1638 AccumulateDestroyedHandles (controls[i], list);
1644 void CleanupCachedWindows (Hwnd hwnd)
1646 if (ActiveWindow == hwnd.Handle) {
1647 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1648 ActiveWindow = IntPtr.Zero;
1651 if (FocusWindow == hwnd.Handle) {
1652 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1653 FocusWindow = IntPtr.Zero;
1656 if (Grab.Hwnd == hwnd.Handle) {
1657 Grab.Hwnd = IntPtr.Zero;
1658 Grab.Confined = false;
1661 DestroyCaret (hwnd.Handle);
1664 private void PerformNCCalc(Hwnd hwnd) {
1665 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1669 rect = hwnd.DefaultClientRect;
1671 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1672 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1674 ncp.rgrc1.left = rect.Left;
1675 ncp.rgrc1.top = rect.Top;
1676 ncp.rgrc1.right = rect.Right;
1677 ncp.rgrc1.bottom = rect.Bottom;
1679 Marshal.StructureToPtr(ncp, ptr, true);
1680 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1681 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1682 Marshal.FreeHGlobal(ptr);
1684 // FIXME - debug this with Menus
1686 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1687 hwnd.ClientRect = rect;
1690 if ((rect.Width < 1) || (rect.Height < 1)) {
1691 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1693 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1697 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1699 #endregion // Private Methods
1702 private void MouseHover(object sender, EventArgs e) {
1706 HoverState.Timer.Enabled = false;
1708 if (HoverState.Window != IntPtr.Zero) {
1709 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1711 xevent = new XEvent ();
1713 xevent.type = XEventName.ClientMessage;
1714 xevent.ClientMessageEvent.display = DisplayHandle;
1715 xevent.ClientMessageEvent.window = HoverState.Window;
1716 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1717 xevent.ClientMessageEvent.format = 32;
1718 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1720 hwnd.Queue.EnqueueLocked (xevent);
1727 private void CaretCallback(object sender, EventArgs e) {
1731 Caret.On = !Caret.On;
1733 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1735 #endregion // Callbacks
1737 #region Public Properties
1739 internal override int Caption {
1745 internal override Size CursorSize {
1750 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1751 return new Size(x, y);
1753 return new Size(16, 16);
1758 internal override bool DragFullWindows {
1764 internal override Size DragSize {
1766 return new Size(4, 4);
1770 internal override Size FrameBorderSize {
1772 throw new NotImplementedException();
1776 internal override Size IconSize {
1782 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1786 current = (long)list;
1789 size = new XIconSize();
1791 for (int i = 0; i < count; i++) {
1792 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1793 current += Marshal.SizeOf(size);
1795 // Look for our preferred size
1796 if (size.min_width == 32) {
1798 return new Size(32, 32);
1801 if (size.max_width == 32) {
1803 return new Size(32, 32);
1806 if (size.min_width < 32 && size.max_width > 32) {
1809 // check if we can fit one
1811 while (x < size.max_width) {
1812 x += size.width_inc;
1815 return new Size(32, 32);
1820 if (largest < size.max_width) {
1821 largest = size.max_width;
1825 // We didn't find a match or we wouldn't be here
1826 return new Size(largest, largest);
1829 return new Size(32, 32);
1834 internal override int KeyboardSpeed {
1837 // A lot harder: need to do:
1838 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1839 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1840 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1842 // And from that we can tell the repetition rate
1844 // Notice, the values must map to:
1845 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1851 internal override int KeyboardDelay {
1854 // Return values must range from 0 to 4, 0 meaning 250ms,
1855 // and 4 meaning 1000 ms.
1857 return 1; // ie, 500 ms
1861 internal override Size MaxWindowTrackSize {
1863 return new Size (WorkingArea.Width, WorkingArea.Height);
1867 internal override Size MinimizedWindowSize {
1869 return new Size(1, 1);
1873 internal override Size MinimizedWindowSpacingSize {
1875 return new Size(1, 1);
1879 internal override Size MinimumWindowSize {
1881 return new Size(1, 1);
1885 internal override Size MinWindowTrackSize {
1887 return new Size(1, 1);
1891 internal override Keys ModifierKeys {
1893 return Keyboard.ModifierKeys;
1897 internal override Size SmallIconSize {
1903 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1907 current = (long)list;
1910 size = new XIconSize();
1912 for (int i = 0; i < count; i++) {
1913 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1914 current += Marshal.SizeOf(size);
1916 // Look for our preferred size
1917 if (size.min_width == 16) {
1919 return new Size(16, 16);
1922 if (size.max_width == 16) {
1924 return new Size(16, 16);
1927 if (size.min_width < 16 && size.max_width > 16) {
1930 // check if we can fit one
1932 while (x < size.max_width) {
1933 x += size.width_inc;
1936 return new Size(16, 16);
1941 if (smallest == 0 || smallest > size.min_width) {
1942 smallest = size.min_width;
1946 // We didn't find a match or we wouldn't be here
1947 return new Size(smallest, smallest);
1950 return new Size(16, 16);
1955 internal override int MouseButtonCount {
1961 internal override bool MouseButtonsSwapped {
1963 return false; // FIXME - how to detect?
1967 internal override Point MousePosition {
1969 return mouse_position;
1973 internal override Size MouseHoverSize {
1975 return new Size (1, 1);
1979 internal override int MouseHoverTime {
1981 return HoverState.Interval;
1987 internal override bool MouseWheelPresent {
1989 return true; // FIXME - how to detect?
1993 internal override Rectangle VirtualScreen {
1999 internal override Rectangle WorkingArea {
2005 IntPtr prop = IntPtr.Zero;
2008 int current_desktop;
2012 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);
2013 if ((long)nitems < 1) {
2017 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2020 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);
2021 if ((long)nitems < 4 * current_desktop) {
2025 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2026 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2027 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2028 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2031 return new Rectangle(x, y, width, height);
2034 XWindowAttributes attributes=new XWindowAttributes();
2037 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2040 return new Rectangle(0, 0, attributes.width, attributes.height);
2044 internal override bool ThemesEnabled {
2046 return XplatUIX11.themes_enabled;
2051 #endregion // Public properties
2053 #region Public Static Methods
2054 internal override IntPtr InitializeDriver() {
2056 if (DisplayHandle==IntPtr.Zero) {
2057 SetDisplay(XOpenDisplay(IntPtr.Zero));
2063 internal override void ShutdownDriver(IntPtr token) {
2065 if (DisplayHandle!=IntPtr.Zero) {
2066 XCloseDisplay(DisplayHandle);
2067 DisplayHandle=IntPtr.Zero;
2072 internal override void EnableThemes() {
2073 themes_enabled = true;
2077 internal override void Activate(IntPtr handle) {
2080 hwnd = Hwnd.ObjectFromHandle(handle);
2084 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2085 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2088 // XRaiseWindow(DisplayHandle, handle);
2094 internal override void AudibleAlert() {
2095 XBell(DisplayHandle, 0);
2100 internal override void CaretVisible(IntPtr handle, bool visible) {
2101 if (Caret.Hwnd == handle) {
2103 if (!Caret.Visible) {
2104 Caret.Visible = true;
2106 Caret.Timer.Start();
2109 Caret.Visible = false;
2116 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2117 FormBorderStyle border_style;
2118 TitleStyle title_style;
2120 int tool_caption_height;
2122 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2123 out caption_height, out tool_caption_height);
2125 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2126 caption_height, tool_caption_height,
2131 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2137 hwnd = Hwnd.ObjectFromHandle(handle);
2140 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2147 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2148 DataFormats.Format f;
2151 f = DataFormats.Format.List;
2153 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2157 Clipboard.Formats = new ArrayList();
2160 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2162 Clipboard.Enumerating = true;
2163 while (Clipboard.Enumerating) {
2164 UpdateMessageQueue(null);
2169 result = new int[Clipboard.Formats.Count];
2171 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2172 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2175 Clipboard.Formats = null;
2179 internal override void ClipboardClose(IntPtr handle) {
2180 if (handle != ClipMagic) {
2181 throw new ArgumentException("handle is not a valid clipboard handle");
2186 internal override int ClipboardGetID(IntPtr handle, string format) {
2187 if (handle != ClipMagic) {
2188 throw new ArgumentException("handle is not a valid clipboard handle");
2191 if (format == "Text" ) return (int)Atom.XA_STRING;
2192 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2193 //else if (format == "MetaFilePict" ) return 3;
2194 //else if (format == "SymbolicLink" ) return 4;
2195 //else if (format == "DataInterchangeFormat" ) return 5;
2196 //else if (format == "Tiff" ) return 6;
2197 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2198 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2199 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2200 //else if (format == "PenData" ) return 10;
2201 //else if (format == "RiffAudio" ) return 11;
2202 //else if (format == "WaveAudio" ) return 12;
2203 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2204 //else if (format == "EnhancedMetafile" ) return 14;
2205 //else if (format == "FileDrop" ) return 15;
2206 //else if (format == "Locale" ) return 16;
2208 return XInternAtom(DisplayHandle, format, false).ToInt32();
2211 internal override IntPtr ClipboardOpen(bool primary_selection) {
2212 if (!primary_selection)
2213 ClipMagic = CLIPBOARD;
2215 ClipMagic = PRIMARY;
2219 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2220 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2222 Clipboard.Retrieving = true;
2223 while (Clipboard.Retrieving) {
2224 UpdateMessageQueue(null);
2227 return Clipboard.Item;
2230 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2231 Clipboard.Item = obj;
2232 Clipboard.Type = type;
2233 Clipboard.Converter = converter;
2236 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2238 // Clearing the selection
2239 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2243 internal override void CreateCaret(IntPtr handle, int width, int height) {
2244 XGCValues gc_values;
2247 hwnd = Hwnd.ObjectFromHandle(handle);
2249 if (Caret.Hwnd != IntPtr.Zero) {
2250 DestroyCaret(Caret.Hwnd);
2253 Caret.Hwnd = handle;
2254 Caret.Window = hwnd.client_window;
2255 Caret.Width = width;
2256 Caret.Height = height;
2257 Caret.Visible = false;
2260 gc_values = new XGCValues();
2261 gc_values.line_width = width;
2263 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2264 if (Caret.gc == IntPtr.Zero) {
2265 Caret.Hwnd = IntPtr.Zero;
2269 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2272 internal override IntPtr CreateWindow(CreateParams cp) {
2273 XSetWindowAttributes Attributes;
2279 IntPtr ParentHandle;
2281 IntPtr ClientWindow;
2282 Rectangle ClientRect;
2283 SetWindowValuemask ValueMask;
2288 Attributes = new XSetWindowAttributes();
2294 if (Width<1) Width=1;
2295 if (Height<1) Height=1;
2297 if (cp.Parent != IntPtr.Zero) {
2298 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2300 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2301 // We need to use our foster parent window until this poor child gets it's parent assigned
2302 ParentHandle=FosterParent;
2303 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2304 ParentHandle=RootWindow;
2306 // Default position on screen, if window manager doesn't place us somewhere else
2309 ParentHandle=RootWindow;
2313 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2315 Attributes.bit_gravity = Gravity.NorthWestGravity;
2316 Attributes.win_gravity = Gravity.NorthWestGravity;
2318 // Save what's under the toolwindow
2319 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2320 Attributes.save_under = true;
2321 ValueMask |= SetWindowValuemask.SaveUnder;
2325 // If we're a popup without caption we override the WM
2326 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2327 Attributes.override_redirect = true;
2328 ValueMask |= SetWindowValuemask.OverrideRedirect;
2334 hwnd.height = Height;
2335 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2336 hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
2338 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2339 hwnd.enabled = false;
2342 ClientRect = hwnd.ClientRect;
2343 ClientWindow = IntPtr.Zero;
2346 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2347 if (WholeWindow != IntPtr.Zero) {
2348 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2350 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2351 ValueMask = SetWindowValuemask.ColorMap;
2352 Attributes.colormap = CustomColormap;
2354 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);
2358 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2359 throw new Exception("Could not create X11 windows");
2362 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2363 hwnd.WholeWindow = WholeWindow;
2364 hwnd.ClientWindow = ClientWindow;
2366 #if DriverDebug || DriverDebugCreate
2367 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);
2370 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2371 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2374 hints = new XSizeHints();
2377 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2378 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2383 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2384 if (hwnd.whole_window != hwnd.client_window)
2385 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2387 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2388 MapWindow(hwnd, WindowType.Both);
2389 hwnd.visible = true;
2393 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2395 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2396 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2398 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2401 SetWMStyles(hwnd, cp);
2403 // set the group leader
2404 XWMHints wm_hints = new XWMHints ();
2406 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2407 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2408 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2410 if (ParentHandle != RootWindow) {
2411 wm_hints.window_group = hwnd.whole_window;
2413 wm_hints.window_group = ParentHandle;
2417 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2420 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2421 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2422 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2423 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2426 // for now make all windows dnd enabled
2427 Dnd.SetAllowDrop (hwnd, true);
2429 // Set caption/window title
2430 Text(hwnd.Handle, cp.Caption);
2432 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2437 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2438 CreateParams create_params = new CreateParams();
2440 create_params.Caption = "";
2441 create_params.X = X;
2442 create_params.Y = Y;
2443 create_params.Width = Width;
2444 create_params.Height = Height;
2446 create_params.ClassName=XplatUI.DefaultClassName;
2447 create_params.ClassStyle = 0;
2448 create_params.ExStyle=0;
2449 create_params.Parent=IntPtr.Zero;
2450 create_params.Param=0;
2452 return CreateWindow(create_params);
2455 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2457 Bitmap cursor_bitmap;
2465 IntPtr cursor_pixmap;
2472 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2476 // Win32 only allows creation cursors of a certain size
2477 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2478 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2479 cursor_mask = new Bitmap(mask, new Size(width, height));
2481 cursor_bitmap = bitmap;
2485 width = cursor_bitmap.Width;
2486 height = cursor_bitmap.Height;
2488 cursor_bits = new Byte[(width / 8) * height];
2489 mask_bits = new Byte[(width / 8) * height];
2491 for (int y = 0; y < height; y++) {
2492 for (int x = 0; x < width; x++) {
2493 c_pixel = cursor_bitmap.GetPixel(x, y);
2494 m_pixel = cursor_mask.GetPixel(x, y);
2496 and = c_pixel == cursor_pixel;
2497 xor = m_pixel == mask_pixel;
2501 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2502 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2503 } else if (and && !xor) {
2505 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2506 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2508 } else if (and && !xor) {
2510 } else if (and && xor) {
2513 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2514 // we want both to be 0 so nothing to be done
2515 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2516 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2522 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2523 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2527 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2528 fg.red = (ushort)65535;
2529 fg.green = (ushort)65535;
2530 fg.blue = (ushort)65535;
2532 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2534 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2536 XFreePixmap(DisplayHandle, cursor_pixmap);
2537 XFreePixmap(DisplayHandle, mask_pixmap);
2542 internal override IntPtr DefineStdCursor(StdCursor id) {
2543 CursorFontShape shape;
2546 // FIXME - define missing shapes
2549 case StdCursor.AppStarting: {
2550 shape = CursorFontShape.XC_watch;
2554 case StdCursor.Arrow: {
2555 shape = CursorFontShape.XC_top_left_arrow;
2559 case StdCursor.Cross: {
2560 shape = CursorFontShape.XC_crosshair;
2564 case StdCursor.Default: {
2565 shape = CursorFontShape.XC_top_left_arrow;
2569 case StdCursor.Hand: {
2570 shape = CursorFontShape.XC_hand1;
2574 case StdCursor.Help: {
2575 shape = CursorFontShape.XC_question_arrow;
2579 case StdCursor.HSplit: {
2580 shape = CursorFontShape.XC_sb_v_double_arrow;
2584 case StdCursor.IBeam: {
2585 shape = CursorFontShape.XC_xterm;
2589 case StdCursor.No: {
2590 shape = CursorFontShape.XC_circle;
2594 case StdCursor.NoMove2D: {
2595 shape = CursorFontShape.XC_fleur;
2599 case StdCursor.NoMoveHoriz: {
2600 shape = CursorFontShape.XC_fleur;
2604 case StdCursor.NoMoveVert: {
2605 shape = CursorFontShape.XC_fleur;
2609 case StdCursor.PanEast: {
2610 shape = CursorFontShape.XC_fleur;
2614 case StdCursor.PanNE: {
2615 shape = CursorFontShape.XC_fleur;
2619 case StdCursor.PanNorth: {
2620 shape = CursorFontShape.XC_fleur;
2624 case StdCursor.PanNW: {
2625 shape = CursorFontShape.XC_fleur;
2629 case StdCursor.PanSE: {
2630 shape = CursorFontShape.XC_fleur;
2634 case StdCursor.PanSouth: {
2635 shape = CursorFontShape.XC_fleur;
2639 case StdCursor.PanSW: {
2640 shape = CursorFontShape.XC_fleur;
2644 case StdCursor.PanWest: {
2645 shape = CursorFontShape.XC_sizing;
2649 case StdCursor.SizeAll: {
2650 shape = CursorFontShape.XC_fleur;
2654 case StdCursor.SizeNESW: {
2655 shape = CursorFontShape.XC_top_right_corner;
2659 case StdCursor.SizeNS: {
2660 shape = CursorFontShape.XC_sb_v_double_arrow;
2664 case StdCursor.SizeNWSE: {
2665 shape = CursorFontShape.XC_top_left_corner;
2669 case StdCursor.SizeWE: {
2670 shape = CursorFontShape.XC_sb_h_double_arrow;
2674 case StdCursor.UpArrow: {
2675 shape = CursorFontShape.XC_center_ptr;
2679 case StdCursor.VSplit: {
2680 shape = CursorFontShape.XC_sb_h_double_arrow;
2684 case StdCursor.WaitCursor: {
2685 shape = CursorFontShape.XC_watch;
2695 cursor = XCreateFontCursor(DisplayHandle, shape);
2700 internal override IntPtr DefWndProc(ref Message msg) {
2701 switch ((Msg)msg.Msg) {
2702 case Msg.WM_PAINT: {
2705 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2707 hwnd.expose_pending = false;
2713 case Msg.WM_NCPAINT: {
2716 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2718 hwnd.nc_expose_pending = false;
2724 case Msg.WM_CONTEXTMENU: {
2727 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2729 if ((hwnd != null) && (hwnd.parent != null)) {
2730 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2735 case Msg.WM_MOUSEWHEEL: {
2738 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2740 if ((hwnd != null) && (hwnd.parent != null)) {
2741 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2742 if (msg.Result == IntPtr.Zero) {
2749 case Msg.WM_SETCURSOR: {
2752 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2754 break; // not sure how this happens, but it does
2756 // Pass to parent window first
2757 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2759 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2762 if (msg.Result == IntPtr.Zero) {
2765 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2766 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2767 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2768 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2769 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2770 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2773 handle = Cursors.Default.handle;
2776 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2777 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2778 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2779 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2780 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2781 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2784 case HitTest.HTGROWBOX:
2785 case HitTest.HTSIZE:
2786 case HitTest.HTZOOM:
2787 case HitTest.HTVSCROLL:
2788 case HitTest.HTSYSMENU:
2789 case HitTest.HTREDUCE:
2790 case HitTest.HTNOWHERE:
2791 case HitTest.HTMAXBUTTON:
2792 case HitTest.HTMINBUTTON:
2793 case HitTest.HTMENU:
2794 case HitTest.HSCROLL:
2795 case HitTest.HTBOTTOM:
2796 case HitTest.HTCAPTION:
2797 case HitTest.HTCLIENT:
2798 case HitTest.HTCLOSE:
2800 default: handle = Cursors.Default.handle; break;
2802 SetCursor(msg.HWnd, handle);
2810 internal override void DestroyCaret(IntPtr handle) {
2811 if (Caret.Hwnd == handle) {
2812 if (Caret.Visible == true) {
2815 if (Caret.gc != IntPtr.Zero) {
2816 XFreeGC(DisplayHandle, Caret.gc);
2817 Caret.gc = IntPtr.Zero;
2819 Caret.Hwnd = IntPtr.Zero;
2820 Caret.Visible = false;
2825 internal override void DestroyCursor(IntPtr cursor) {
2827 XFreeCursor(DisplayHandle, cursor);
2831 internal override void DestroyWindow(IntPtr handle) {
2834 hwnd = Hwnd.ObjectFromHandle(handle);
2837 #if DriverDebug || DriverDebugDestroy
2838 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2843 #if DriverDebug || DriverDebugDestroy
2844 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2847 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
2849 CleanupCachedWindows (hwnd);
2851 ArrayList windows = new ArrayList ();
2853 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2856 if (hwnd.whole_window != IntPtr.Zero) {
2857 #if DriverDebug || DriverDebugDestroy
2858 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2860 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2862 else if (hwnd.client_window != IntPtr.Zero) {
2863 #if DriverDebug || DriverDebugDestroy
2864 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2866 XDestroyWindow(DisplayHandle, hwnd.client_window);
2871 foreach (Hwnd h in windows) {
2872 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2876 internal override IntPtr DispatchMessage(ref MSG msg) {
2877 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2880 IntPtr GetReversibleScreenGC (Color backColor)
2882 XGCValues gc_values;
2886 XColor xcolor = new XColor();
2887 xcolor.red = (ushort)(backColor.R * 257);
2888 xcolor.green = (ushort)(backColor.G * 257);
2889 xcolor.blue = (ushort)(backColor.B * 257);
2890 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2891 pixel = (uint)xcolor.pixel.ToInt32();
2894 gc_values = new XGCValues();
2896 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2897 gc_values.foreground = (IntPtr)pixel;
2899 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
2900 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
2901 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2906 IntPtr GetReversibleControlGC (Control control, int line_width)
2908 XGCValues gc_values;
2911 gc_values = new XGCValues();
2913 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2914 gc_values.line_width = line_width;
2915 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2917 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2918 //mask = foreground ^ background;
2919 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2920 //XSetBackground(DisplayHandle, gc, background);
2921 //XSetFunction(DisplayHandle, gc, GXxor);
2922 //XSetPlaneMask(DisplayHandle, gc, mask);
2925 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2929 XColor xcolor = new XColor();
2931 xcolor.red = (ushort)(control.ForeColor.R * 257);
2932 xcolor.green = (ushort)(control.ForeColor.G * 257);
2933 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2934 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2935 foreground = (uint)xcolor.pixel.ToInt32();
2937 xcolor.red = (ushort)(control.BackColor.R * 257);
2938 xcolor.green = (ushort)(control.BackColor.G * 257);
2939 xcolor.blue = (ushort)(control.BackColor.B * 257);
2940 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2941 background = (uint)xcolor.pixel.ToInt32();
2943 uint mask = foreground ^ background;
2945 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2946 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2947 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2948 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2953 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
2955 IntPtr gc = GetReversibleScreenGC (backColor);
2957 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
2959 XFreeGC(DisplayHandle, gc);
2962 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
2964 IntPtr gc = GetReversibleScreenGC (backColor);
2966 if (rectangle.Width < 0) {
2967 rectangle.X += rectangle.Width;
2968 rectangle.Width = -rectangle.Width;
2970 if (rectangle.Height < 0) {
2971 rectangle.Y += rectangle.Height;
2972 rectangle.Height = -rectangle.Height;
2976 GCLineStyle line_style = GCLineStyle.LineSolid;
2977 GCCapStyle cap_style = GCCapStyle.CapButt;
2978 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
2981 case FrameStyle.Dashed:
2982 line_style = GCLineStyle.LineOnOffDash;
2984 case FrameStyle.Thick:
2989 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
2991 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
2993 XFreeGC(DisplayHandle, gc);
2996 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
2998 IntPtr gc = GetReversibleScreenGC (backColor);
3000 if (rectangle.Width < 0) {
3001 rectangle.X += rectangle.Width;
3002 rectangle.Width = -rectangle.Width;
3004 if (rectangle.Height < 0) {
3005 rectangle.Y += rectangle.Height;
3006 rectangle.Height = -rectangle.Height;
3008 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3010 XFreeGC(DisplayHandle, gc);
3013 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3015 Control control = Control.FromHandle(handle);
3017 gc = GetReversibleControlGC (control, line_width);
3019 if ((rect.Width > 0) && (rect.Height > 0)) {
3020 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3022 if (rect.Width > 0) {
3023 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3025 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3028 XFreeGC(DisplayHandle, gc);
3031 internal override void DoEvents() {
3032 MSG msg = new MSG ();
3035 if (OverrideCursorHandle != IntPtr.Zero) {
3036 OverrideCursorHandle = IntPtr.Zero;
3039 queue = ThreadQueue(Thread.CurrentThread);
3041 queue.DispatchIdle = false;
3043 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3044 TranslateMessage (ref msg);
3045 DispatchMessage (ref msg);
3048 queue.DispatchIdle = true;
3051 internal override void EnableWindow(IntPtr handle, bool Enable) {
3054 hwnd = Hwnd.ObjectFromHandle(handle);
3056 hwnd.Enabled = Enable;
3060 internal override void EndLoop(Thread thread) {
3061 // This is where we one day will shut down the loop for the thread
3065 internal override IntPtr GetActive() {
3070 IntPtr prop = IntPtr.Zero;
3071 IntPtr active = IntPtr.Zero;
3073 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);
3074 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3075 active = (IntPtr)Marshal.ReadInt32(prop);
3079 if (active != IntPtr.Zero) {
3082 hwnd = Hwnd.GetObjectFromWindow(active);
3084 active = hwnd.Handle;
3086 active = IntPtr.Zero;
3092 internal override Region GetClipRegion(IntPtr handle) {
3095 hwnd = Hwnd.ObjectFromHandle(handle);
3097 return hwnd.UserClip;
3103 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3110 internal override void GetDisplaySize(out Size size) {
3111 XWindowAttributes attributes=new XWindowAttributes();
3114 // FIXME - use _NET_WM messages instead?
3115 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3118 size = new Size(attributes.width, attributes.height);
3121 internal override SizeF GetAutoScaleSize(Font font) {
3124 string magic_string = "The quick brown fox jumped over the lazy dog.";
3125 double magic_number = 44.549996948242189;
3127 g = Graphics.FromHwnd(FosterParent);
3129 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3130 return new SizeF(width, font.Height);
3133 internal override IntPtr GetParent(IntPtr handle) {
3136 hwnd = Hwnd.ObjectFromHandle(handle);
3137 if (hwnd != null && hwnd.parent != null) {
3138 return hwnd.parent.Handle;
3143 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3153 if (handle != IntPtr.Zero) {
3154 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3156 use_handle = RootWindow;
3160 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3163 if (handle != IntPtr.Zero) {
3172 internal override IntPtr GetFocus() {
3177 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3178 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3181 internal override Point GetMenuOrigin(IntPtr handle) {
3184 hwnd = Hwnd.ObjectFromHandle(handle);
3187 return hwnd.MenuOrigin;
3192 [MonoTODO("Implement filtering")]
3193 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3200 if (((XEventQueue)queue_id).Count > 0) {
3201 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3203 UpdateMessageQueue ((XEventQueue)queue_id);
3205 if (((XEventQueue)queue_id).Count > 0) {
3206 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3207 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3208 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3210 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3211 msg.hwnd= IntPtr.Zero;
3212 msg.message = Msg.WM_ENTERIDLE;
3216 // We reset ourselves so GetMessage can be called again
3217 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3223 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3225 // Handle messages for windows that are already or are about to be destroyed.
3227 // we need a special block for this because unless we remove the hwnd from the paint
3228 // queue it will always stay there (since we don't handle the expose), and we'll
3229 // effectively loop infinitely trying to repaint a non-existant window.
3230 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3231 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3232 hwnd.Queue.Paint.Remove (hwnd);
3233 goto ProcessNextMessage;
3236 // We need to make sure we only allow DestroyNotify events through for zombie
3237 // hwnds, since much of the event handling code makes requests using the hwnd's
3238 // client_window, and that'll result in BadWindow errors if there's some lag
3239 // between the XDestroyWindow call and the DestroyNotify event.
3240 if (hwnd == null || hwnd.zombie) {
3241 #if DriverDebug || DriverDebugDestroy
3242 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3244 goto ProcessNextMessage;
3247 if (hwnd.client_window == xevent.AnyEvent.window) {
3249 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3252 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3255 msg.hwnd = hwnd.Handle;
3258 // If you add a new event to this switch make sure to add it in
3259 // UpdateMessage also unless it is not coming through the X event system.
3261 switch(xevent.type) {
3262 case XEventName.KeyPress: {
3263 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3267 case XEventName.KeyRelease: {
3268 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3272 case XEventName.ButtonPress: {
3273 switch(xevent.ButtonEvent.button) {
3275 MouseState |= MouseButtons.Left;
3277 msg.message = Msg.WM_LBUTTONDOWN;
3279 msg.message = Msg.WM_NCLBUTTONDOWN;
3280 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3282 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3283 msg.wParam=GetMousewParam(0);
3288 MouseState |= MouseButtons.Middle;
3290 msg.message = Msg.WM_MBUTTONDOWN;
3292 msg.message = Msg.WM_NCMBUTTONDOWN;
3293 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3295 msg.wParam=GetMousewParam(0);
3300 MouseState |= MouseButtons.Right;
3302 msg.message = Msg.WM_RBUTTONDOWN;
3304 msg.message = Msg.WM_NCRBUTTONDOWN;
3305 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3307 msg.wParam=GetMousewParam(0);
3312 msg.hwnd = FocusWindow;
3313 msg.message=Msg.WM_MOUSEWHEEL;
3314 msg.wParam=GetMousewParam(120);
3319 msg.hwnd = FocusWindow;
3320 msg.message=Msg.WM_MOUSEWHEEL;
3321 msg.wParam=GetMousewParam(-120);
3327 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3328 mouse_position.X = xevent.ButtonEvent.x;
3329 mouse_position.Y = xevent.ButtonEvent.y;
3331 if (!hwnd.Enabled) {
3334 msg.hwnd = hwnd.EnabledHwnd;
3335 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);
3336 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3339 if (Grab.Hwnd != IntPtr.Zero) {
3340 msg.hwnd = Grab.Hwnd;
3343 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3344 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3345 switch(xevent.ButtonEvent.button) {
3347 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3352 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3357 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3361 ClickPending.Pending = false;
3363 ClickPending.Pending = true;
3364 ClickPending.Hwnd = msg.hwnd;
3365 ClickPending.Message = msg.message;
3366 ClickPending.wParam = msg.wParam;
3367 ClickPending.lParam = msg.lParam;
3368 ClickPending.Time = (long)xevent.ButtonEvent.time;
3371 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN)
3372 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3377 case XEventName.ButtonRelease: {
3379 Dnd.HandleButtonRelease (ref xevent);
3383 switch(xevent.ButtonEvent.button) {
3386 msg.message = Msg.WM_LBUTTONUP;
3388 msg.message = Msg.WM_NCLBUTTONUP;
3389 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3391 MouseState &= ~MouseButtons.Left;
3392 msg.wParam=GetMousewParam(0);
3398 msg.message = Msg.WM_MBUTTONUP;
3400 msg.message = Msg.WM_NCMBUTTONUP;
3401 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3403 MouseState &= ~MouseButtons.Middle;
3404 msg.wParam=GetMousewParam(0);
3410 msg.message = Msg.WM_RBUTTONUP;
3412 msg.message = Msg.WM_NCRBUTTONUP;
3413 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3415 MouseState &= ~MouseButtons.Right;
3416 msg.wParam=GetMousewParam(0);
3421 goto ProcessNextMessage;
3425 goto ProcessNextMessage;
3429 if (!hwnd.Enabled) {
3432 msg.hwnd = hwnd.EnabledHwnd;
3433 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);
3434 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3437 if (Grab.Hwnd != IntPtr.Zero) {
3438 msg.hwnd = Grab.Hwnd;
3441 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3442 mouse_position.X = xevent.ButtonEvent.x;
3443 mouse_position.Y = xevent.ButtonEvent.y;
3447 case XEventName.MotionNotify: {
3449 #if DriverDebugExtra
3450 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);
3453 if (Dnd.HandleMotionNotify (ref xevent))
3454 goto ProcessNextMessage;
3455 if (Grab.Hwnd != IntPtr.Zero) {
3456 msg.hwnd = Grab.Hwnd;
3458 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3461 msg.message = Msg.WM_MOUSEMOVE;
3462 msg.wParam = GetMousewParam(0);
3463 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3465 if (!hwnd.Enabled) {
3468 msg.hwnd = hwnd.EnabledHwnd;
3469 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);
3470 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3473 mouse_position.X = xevent.MotionEvent.x;
3474 mouse_position.Y = xevent.MotionEvent.y;
3476 if ((HoverState.Timer.Enabled) &&
3477 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3478 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3479 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3480 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3481 HoverState.Timer.Stop();
3482 HoverState.Timer.Start();
3483 HoverState.X = mouse_position.X;
3484 HoverState.Y = mouse_position.Y;
3494 #if DriverDebugExtra
3495 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);
3497 msg.message = Msg.WM_NCMOUSEMOVE;
3499 if (!hwnd.Enabled) {
3500 msg.hwnd = hwnd.EnabledHwnd;
3501 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);
3502 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3505 // The hit test is sent in screen coordinates
3506 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3507 xevent.MotionEvent.x, xevent.MotionEvent.y,
3508 out screen_x, out screen_y, out dummy);
3510 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3511 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3512 IntPtr.Zero, msg.lParam).ToInt32 ();
3513 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3515 mouse_position.X = xevent.MotionEvent.x;
3516 mouse_position.Y = xevent.MotionEvent.y;
3522 case XEventName.EnterNotify: {
3523 if (!hwnd.Enabled) {
3524 goto ProcessNextMessage;
3526 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3527 goto ProcessNextMessage;
3529 msg.message = Msg.WM_MOUSE_ENTER;
3530 HoverState.X = xevent.CrossingEvent.x;
3531 HoverState.Y = xevent.CrossingEvent.y;
3532 HoverState.Timer.Enabled = true;
3533 HoverState.Window = xevent.CrossingEvent.window;
3537 case XEventName.LeaveNotify: {
3538 if (!hwnd.Enabled) {
3539 goto ProcessNextMessage;
3541 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3542 goto ProcessNextMessage;
3544 msg.message=Msg.WM_MOUSE_LEAVE;
3545 HoverState.Timer.Enabled = false;
3546 HoverState.Window = IntPtr.Zero;
3551 case XEventName.CreateNotify: {
3552 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3553 msg.message = WM_CREATE;
3554 // Set up CreateStruct
3556 goto ProcessNextMessage;
3563 case XEventName.ReparentNotify: {
3564 if (hwnd.parent == null) { // Toplevel
3565 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3566 // We need to adjust x/y
3567 // This sucks ass, part 2
3568 // Every WM does the reparenting of toplevel windows different, so there's
3569 // no standard way of getting our adjustment considering frames/decorations
3570 // The code below is needed for metacity. KDE doesn't works just fine without this
3578 hwnd.Reparented = true;
3580 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);
3581 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3582 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3585 hwnd.whacky_wm = true;
3588 if (hwnd.opacity != 0xffffffff) {
3591 opacity = (IntPtr)(Int32)hwnd.opacity;
3592 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3594 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3595 goto ProcessNextMessage;
3597 hwnd.Reparented = false;
3598 goto ProcessNextMessage;
3601 goto ProcessNextMessage;
3604 case XEventName.ConfigureNotify: {
3605 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3606 #if DriverDebugExtra
3607 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);
3609 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3610 lock (hwnd.configure_lock) {
3611 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3612 hwnd.configure_pending = false;
3615 // We need to adjust our client window to track the resize of whole_window
3616 if (hwnd.whole_window != hwnd.client_window)
3617 PerformNCCalc(hwnd);
3620 goto ProcessNextMessage;
3623 case XEventName.FocusIn: {
3624 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3625 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3626 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3627 // about it having focus again
3628 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3629 goto ProcessNextMessage;
3632 if (FocusWindow == IntPtr.Zero) {
3633 Control c = Control.FromHandle (hwnd.client_window);
3635 goto ProcessNextMessage;
3636 Form form = c.FindForm ();
3638 goto ProcessNextMessage;
3639 ActiveWindow = form.Handle;
3640 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3641 goto ProcessNextMessage;
3643 Keyboard.FocusIn(FocusWindow);
3644 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3645 goto ProcessNextMessage;
3648 case XEventName.FocusOut: {
3649 // Se the comment for our FocusIn handler
3650 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3651 goto ProcessNextMessage;
3653 Keyboard.FocusOut(FocusWindow);
3655 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3656 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3659 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3660 goto ProcessNextMessage;
3663 case XEventName.Expose: {
3664 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3666 hwnd.expose_pending = false;
3668 hwnd.nc_expose_pending = false;
3670 goto ProcessNextMessage;
3674 if (!hwnd.expose_pending) {
3675 goto ProcessNextMessage;
3678 if (!hwnd.nc_expose_pending) {
3679 goto ProcessNextMessage;
3682 switch (hwnd.border_style) {
3683 case FormBorderStyle.Fixed3D: {
3686 g = Graphics.FromHwnd(hwnd.whole_window);
3687 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3692 case FormBorderStyle.FixedSingle: {
3695 g = Graphics.FromHwnd(hwnd.whole_window);
3696 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3701 #if DriverDebugExtra
3702 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);
3705 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3706 Region region = new Region (rect);
3707 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3708 msg.message = Msg.WM_NCPAINT;
3709 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3710 msg.refobject = region;
3713 #if DriverDebugExtra
3714 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);
3716 if (Caret.Visible == true) {
3717 Caret.Paused = true;
3721 if (Caret.Visible == true) {
3723 Caret.Paused = false;
3725 msg.message = Msg.WM_PAINT;
3729 case XEventName.DestroyNotify: {
3731 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3732 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3734 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3735 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3736 CleanupCachedWindows (hwnd);
3738 #if DriverDebugDestroy
3739 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3742 msg.hwnd = hwnd.client_window;
3743 msg.message=Msg.WM_DESTROY;
3746 goto ProcessNextMessage;
3752 case XEventName.ClientMessage: {
3753 if (Dnd.HandleClientMessage (ref xevent)) {
3754 goto ProcessNextMessage;
3757 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3758 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3759 goto ProcessNextMessage;
3762 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3763 msg.message = Msg.WM_MOUSEHOVER;
3764 msg.wParam = GetMousewParam(0);
3765 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3769 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3770 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3771 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3772 msg.wParam = xevent.ClientMessageEvent.ptr3;
3773 msg.lParam = xevent.ClientMessageEvent.ptr4;
3777 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3778 #if DriverDebugXEmbed
3779 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3782 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3783 XSizeHints hints = new XSizeHints();
3786 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3788 hwnd.width = hints.max_width;
3789 hwnd.height = hints.max_height;
3790 hwnd.ClientRect = Rectangle.Empty;
3791 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3795 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3796 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3797 msg.message = Msg.WM_CLOSE;
3801 // We should not get this, but I'll leave the code in case we need it in the future
3802 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3803 goto ProcessNextMessage;
3806 goto ProcessNextMessage;
3810 goto ProcessNextMessage;
3817 internal override bool GetText(IntPtr handle, out string text) {
3824 IntPtr prop = IntPtr.Zero;
3826 XGetWindowProperty(DisplayHandle, handle,
3827 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
3828 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3830 if ((long)nitems > 0 && prop != IntPtr.Zero) {
3831 text = Marshal.PtrToStringUni (prop, (int)nitems);
3836 // fallback on the non-_NET property
3839 textptr = IntPtr.Zero;
3841 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3842 if (textptr != IntPtr.Zero) {
3843 text = Marshal.PtrToStringAnsi(textptr);
3854 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) {
3857 hwnd = Hwnd.ObjectFromHandle(handle);
3863 height = hwnd.height;
3865 PerformNCCalc(hwnd);
3867 client_width = hwnd.ClientRect.Width;
3868 client_height = hwnd.ClientRect.Height;
3873 // Should we throw an exception or fail silently?
3874 // throw new ArgumentException("Called with an invalid window handle", "handle");
3884 internal override FormWindowState GetWindowState(IntPtr handle) {
3889 IntPtr prop = IntPtr.Zero;
3893 XWindowAttributes attributes;
3896 hwnd = Hwnd.ObjectFromHandle(handle);
3900 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);
3901 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3902 for (int i = 0; i < (long)nitems; i++) {
3903 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3904 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3906 } else if (atom == _NET_WM_STATE_HIDDEN) {
3914 return FormWindowState.Minimized;
3915 } else if (maximized == 2) {
3916 return FormWindowState.Maximized;
3919 attributes = new XWindowAttributes();
3920 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3921 if (attributes.map_state == MapState.IsUnmapped) {
3922 return (FormWindowState)(-1);
3926 return FormWindowState.Normal;
3929 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3931 GrabConfined = Grab.Confined;
3932 GrabArea = Grab.Area;
3935 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3937 IntPtr confine_to_window;
3939 confine_to_window = IntPtr.Zero;
3941 if (confine_to_handle != IntPtr.Zero) {
3942 XWindowAttributes attributes = new XWindowAttributes();
3944 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3947 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3949 Grab.Area.X = attributes.x;
3950 Grab.Area.Y = attributes.y;
3951 Grab.Area.Width = attributes.width;
3952 Grab.Area.Height = attributes.height;
3953 Grab.Confined = true;
3954 confine_to_window = hwnd.client_window;
3959 hwnd = Hwnd.ObjectFromHandle(handle);
3962 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3963 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3964 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3965 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3969 internal override void UngrabWindow(IntPtr hwnd) {
3971 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3972 XFlush(DisplayHandle);
3974 Grab.Hwnd = IntPtr.Zero;
3975 Grab.Confined = false;
3978 internal override void HandleException(Exception e) {
3979 StackTrace st = new StackTrace(e, true);
3980 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3981 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3984 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3987 hwnd = Hwnd.ObjectFromHandle(handle);
3990 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3992 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3996 internal override void InvalidateNC (IntPtr handle) {
3999 hwnd = Hwnd.ObjectFromHandle(handle);
4001 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4004 internal override bool IsEnabled(IntPtr handle) {
4005 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4006 return (hwnd != null && hwnd.Enabled);
4009 internal override bool IsVisible(IntPtr handle) {
4010 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4011 return (hwnd != null && hwnd.visible);
4014 internal override void KillTimer(Timer timer) {
4015 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4017 if (queue == null) {
4018 // This isn't really an error, MS doesn't start the timer if
4019 // it has no assosciated queue
4022 queue.timer_list.Remove (timer);
4025 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4031 hwnd = Hwnd.ObjectFromHandle(handle);
4034 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4041 internal override void OverrideCursor(IntPtr cursor) {
4042 OverrideCursorHandle = cursor;
4045 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4046 PaintEventArgs paint_event;
4049 hwnd = Hwnd.ObjectFromHandle(handle);
4051 if (Caret.Visible == true) {
4052 Caret.Paused = true;
4059 dc = Graphics.FromHwnd (hwnd.client_window);
4061 Region clip_region = new Region ();
4062 clip_region.MakeEmpty();
4064 foreach (Rectangle r in hwnd.ClipRectangles) {
4065 clip_region.Union (r);
4068 if (hwnd.UserClip != null) {
4069 clip_region.Intersect(hwnd.UserClip);
4072 dc.Clip = clip_region;
4073 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4074 hwnd.expose_pending = false;
4076 hwnd.ClearInvalidArea();
4078 hwnd.drawing_stack.Push (paint_event);
4079 hwnd.drawing_stack.Push (dc);
4083 dc = Graphics.FromHwnd (hwnd.whole_window);
4085 if (!hwnd.nc_invalid.IsEmpty) {
4086 dc.SetClip (hwnd.nc_invalid);
4087 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4089 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4091 hwnd.nc_expose_pending = false;
4093 hwnd.ClearNcInvalidArea ();
4095 hwnd.drawing_stack.Push (paint_event);
4096 hwnd.drawing_stack.Push (dc);
4102 internal override void PaintEventEnd(IntPtr handle, bool client) {
4105 hwnd = Hwnd.ObjectFromHandle(handle);
4107 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4111 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4112 pe.SetGraphics (null);
4115 if (Caret.Visible == true) {
4117 Caret.Paused = false;
4121 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4122 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4123 XEventQueue queue = (XEventQueue) queue_id;
4126 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4127 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4131 if (queue.Count > 0) {
4134 // Only call UpdateMessageQueue if real events are pending
4135 // otherwise we go to sleep on the socket
4136 if (XPending(DisplayHandle) != 0) {
4137 UpdateMessageQueue((XEventQueue)queue_id);
4139 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4144 CheckTimers(queue.timer_list, DateTime.UtcNow);
4149 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4152 // FIXME - I think this should just enqueue directly
4153 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4154 XEvent xevent = new XEvent ();
4155 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4157 xevent.type = XEventName.ClientMessage;
4158 xevent.ClientMessageEvent.display = DisplayHandle;
4161 xevent.ClientMessageEvent.window = hwnd.whole_window;
4163 xevent.ClientMessageEvent.window = IntPtr.Zero;
4166 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4167 xevent.ClientMessageEvent.format = 32;
4168 xevent.ClientMessageEvent.ptr1 = handle;
4169 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4170 xevent.ClientMessageEvent.ptr3 = wparam;
4171 xevent.ClientMessageEvent.ptr4 = lparam;
4173 hwnd.Queue.EnqueueLocked (xevent);
4178 internal override void PostQuitMessage(int exitCode) {
4180 XFlush(DisplayHandle);
4181 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4184 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4189 internal override void RequestNCRecalc(IntPtr handle) {
4192 hwnd = Hwnd.ObjectFromHandle(handle);
4198 PerformNCCalc(hwnd);
4199 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4200 InvalidateNC(handle);
4203 internal override void ResetMouseHover(IntPtr handle) {
4206 hwnd = Hwnd.ObjectFromHandle(handle);
4211 HoverState.Timer.Enabled = true;
4212 HoverState.X = mouse_position.X;
4213 HoverState.Y = mouse_position.Y;
4214 HoverState.Window = handle;
4218 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4224 hwnd = Hwnd.ObjectFromHandle(handle);
4227 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4234 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4240 hwnd = Hwnd.ObjectFromHandle(handle);
4243 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4250 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4253 XGCValues gc_values;
4255 hwnd = Hwnd.ObjectFromHandle(handle);
4257 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4259 /* We have an invalid area in the window we're scrolling.
4260 Adjust our stored invalid rectangle to to match the scrolled amount */
4275 if (area.Contains (hwnd.Invalid))
4276 hwnd.ClearInvalidArea ();
4277 hwnd.AddInvalidArea(r);
4280 gc_values = new XGCValues();
4282 if (with_children) {
4283 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4286 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4294 height = area.Height - YAmount;
4295 dest_y = area.Y + YAmount;
4298 src_y = area.Y - YAmount;
4299 height = area.Height + YAmount;
4305 width = area.Width - XAmount;
4306 dest_x = area.X + XAmount;
4309 src_x = area.X - XAmount;
4310 width = area.Width + XAmount;
4314 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4316 // Generate an expose for the area exposed by the horizontal scroll
4317 // We don't use AddExpose since we're
4319 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4320 } else if (XAmount < 0) {
4321 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4324 // Generate an expose for the area exposed by the vertical scroll
4326 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4327 } else if (YAmount < 0) {
4328 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4330 XFreeGC(DisplayHandle, gc);
4333 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4337 hwnd = Hwnd.GetObjectFromWindow(handle);
4339 rect = hwnd.ClientRect;
4342 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4345 internal override void SendAsyncMethod (AsyncMethodData method) {
4347 XEvent xevent = new XEvent ();
4349 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4351 xevent.type = XEventName.ClientMessage;
4352 xevent.ClientMessageEvent.display = DisplayHandle;
4353 xevent.ClientMessageEvent.window = method.Handle;
4354 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4355 xevent.ClientMessageEvent.format = 32;
4356 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4358 hwnd.Queue.EnqueueLocked (xevent);
4363 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4365 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4368 h = Hwnd.ObjectFromHandle(hwnd);
4370 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4371 AsyncMethodResult result;
4372 AsyncMethodData data;
4374 result = new AsyncMethodResult ();
4375 data = new AsyncMethodData ();
4378 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4379 data.Args = new object[] { hwnd, message, wParam, lParam };
4380 data.Result = result;
4382 SendAsyncMethod (data);
4383 #if DriverDebug || DriverDebugThreads
4384 Console.WriteLine ("Sending {0} message across.", message);
4389 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4392 internal override int SendInput(IntPtr handle, Queue keys) {
4393 int count = keys.Count;
4395 while (keys.Count > 0) {
4397 MSG msg = (MSG)keys.Dequeue();
4399 XEvent xevent = new XEvent ();
4400 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4402 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
4403 xevent.KeyEvent.display = DisplayHandle;
4406 xevent.KeyEvent.window = hwnd.whole_window;
4408 xevent.KeyEvent.window = IntPtr.Zero;
4411 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
4413 hwnd.Queue.EnqueueLocked (xevent);
4419 internal override void SetAllowDrop (IntPtr handle, bool value)
4421 // We allow drop on all windows
4424 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4425 DragDropEffects allowed_effects)
4427 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4430 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4432 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4435 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4438 hwnd = Hwnd.ObjectFromHandle(handle);
4440 Form form = Control.FromHandle (handle) as Form;
4441 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4442 border_style == FormBorderStyle.SizableToolWindow)) {
4443 form.window_manager = new InternalWindowManager (form);
4446 hwnd.border_style = border_style;
4447 RequestNCRecalc(handle);
4450 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4451 if (Caret.Hwnd == handle) {
4458 if (Caret.Visible == true) {
4460 Caret.Timer.Start();
4465 internal override void SetClipRegion(IntPtr handle, Region region) {
4468 hwnd = Hwnd.ObjectFromHandle(handle);
4473 hwnd.UserClip = region;
4474 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4477 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4480 if (OverrideCursorHandle == IntPtr.Zero) {
4481 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4485 LastCursorHandle = cursor;
4486 LastCursorWindow = handle;
4488 hwnd = Hwnd.ObjectFromHandle(handle);
4490 if (cursor != IntPtr.Zero) {
4491 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4493 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4495 XFlush(DisplayHandle);
4500 hwnd = Hwnd.ObjectFromHandle(handle);
4502 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4506 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4507 out int root_x, out int root_y, out int child_x, out int child_y,
4510 /* this code was written with the help of
4511 glance at gdk. I never would have realized we
4512 needed a loop in order to traverse down in the
4513 hierarchy. I would have assumed you'd get the
4514 most deeply nested child and have to do
4515 XQueryTree to move back up the hierarchy..
4516 stupid me, of course. */
4519 XGrabServer (display);
4521 XQueryPointer(display, w, out root, out c,
4522 out root_x, out root_y, out child_x, out child_y,
4528 IntPtr child_last = IntPtr.Zero;
4529 while (c != IntPtr.Zero) {
4531 XQueryPointer(display, c, out root, out c,
4532 out root_x, out root_y, out child_x, out child_y,
4535 XUngrabServer (display);
4540 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4541 if (handle == IntPtr.Zero) {
4544 int root_x, root_y, child_x, child_y, mask;
4547 * QueryPointer before warping
4548 * because if the warp is on
4549 * the RootWindow, the x/y are
4550 * relative to the current
4553 QueryPointer (DisplayHandle, RootWindow,
4556 out root_x, out root_y,
4557 out child_x, out child_y,
4560 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4562 XFlush (DisplayHandle);
4564 /* then we need to a
4565 * QueryPointer after warping
4566 * to manually generate a
4567 * motion event for the window
4570 QueryPointer (DisplayHandle, RootWindow,
4573 out root_x, out root_y,
4574 out child_x, out child_y,
4577 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4578 if (child_hwnd == null) {
4582 XEvent xevent = new XEvent ();
4584 xevent.type = XEventName.MotionNotify;
4585 xevent.MotionEvent.display = DisplayHandle;
4586 xevent.MotionEvent.window = child_hwnd.client_window;
4587 xevent.MotionEvent.root = RootWindow;
4588 xevent.MotionEvent.x = child_x;
4589 xevent.MotionEvent.y = child_y;
4590 xevent.MotionEvent.x_root = root_x;
4591 xevent.MotionEvent.y_root = root_y;
4592 xevent.MotionEvent.state = mask;
4594 child_hwnd.Queue.EnqueueLocked (xevent);
4599 hwnd = Hwnd.ObjectFromHandle(handle);
4601 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4606 internal override void SetFocus(IntPtr handle) {
4608 IntPtr prev_focus_window;
4610 hwnd = Hwnd.ObjectFromHandle(handle);
4612 if (hwnd.client_window == FocusWindow) {
4616 prev_focus_window = FocusWindow;
4617 FocusWindow = hwnd.client_window;
4619 if (prev_focus_window != IntPtr.Zero) {
4620 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4622 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4624 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4627 internal override void SetIcon(IntPtr handle, Icon icon) {
4630 hwnd = Hwnd.ObjectFromHandle(handle);
4632 SetIcon(hwnd, icon);
4636 internal override void SetMenu(IntPtr handle, Menu menu) {
4639 hwnd = Hwnd.ObjectFromHandle(handle);
4642 RequestNCRecalc(handle);
4645 internal override void SetModal(IntPtr handle, bool Modal) {
4647 ModalWindows.Push(handle);
4649 if (ModalWindows.Contains(handle)) {
4652 if (ModalWindows.Count > 0) {
4653 Activate((IntPtr)ModalWindows.Peek());
4658 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4661 hwnd = Hwnd.ObjectFromHandle(handle);
4662 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4665 #if DriverDebug || DriverDebugParent
4666 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4668 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4674 internal override void SetTimer (Timer timer) {
4675 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4677 if (queue == null) {
4678 // This isn't really an error, MS doesn't start the timer if
4679 // it has no assosciated queue
4682 queue.timer_list.Add (timer);
4686 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4690 hwnd = Hwnd.ObjectFromHandle(handle);
4692 if (handle_owner != IntPtr.Zero) {
4693 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4704 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4705 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4707 if (hwnd_owner != null) {
4708 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4710 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4715 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4721 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4724 hwnd = Hwnd.ObjectFromHandle(handle);
4725 hwnd.visible = visible;
4729 if (Control.FromHandle(handle) is Form) {
4732 s = ((Form)Control.FromHandle(handle)).WindowState;
4734 MapWindow(hwnd, WindowType.Both);
4737 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4738 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4742 MapWindow(hwnd, WindowType.Both);
4744 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4746 UnmapWindow(hwnd, WindowType.Whole);
4752 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4757 hwnd = Hwnd.ObjectFromHandle(handle);
4762 hints = new XSizeHints();
4764 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4765 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4766 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4767 hints.min_width = min.Width;
4768 hints.min_height = min.Height;
4771 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4772 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4773 hints.max_width = max.Width;
4774 hints.max_height = max.Height;
4777 if (hints.flags != IntPtr.Zero) {
4778 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4781 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4782 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4783 hints.x = maximized.X;
4784 hints.y = maximized.Y;
4785 hints.width = maximized.Width;
4786 hints.height = maximized.Height;
4788 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4789 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4794 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4797 hwnd = Hwnd.ObjectFromHandle(handle);
4803 // Win32 automatically changes negative width/height to 0.
4809 // X requires a sanity check for width & height; otherwise it dies
4810 if (hwnd.zero_sized && width > 0 && height > 0) {
4812 MapWindow(hwnd, WindowType.Whole);
4814 hwnd.zero_sized = false;
4817 if ((width < 1) || (height < 1)) {
4818 hwnd.zero_sized = true;
4819 UnmapWindow(hwnd, WindowType.Whole);
4822 // Save a server roundtrip (and prevent a feedback loop)
4823 if ((hwnd.x == x) && (hwnd.y == y) &&
4824 (hwnd.width == width) && (hwnd.height == height)) {
4828 if (!hwnd.zero_sized) {
4833 hwnd.height = height;
4834 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4836 if (hwnd.fixed_size) {
4837 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4841 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4842 PerformNCCalc(hwnd);
4846 // Update our position/size immediately, so
4847 // that future calls to SetWindowPos aren't
4848 // kept from calling XMoveResizeWindow (by the
4849 // "Save a server roundtrip" block above).
4853 hwnd.height = height;
4854 hwnd.ClientRect = Rectangle.Empty;
4857 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4858 FormWindowState current_state;
4861 hwnd = Hwnd.ObjectFromHandle(handle);
4863 current_state = GetWindowState(handle);
4865 if (current_state == state) {
4870 case FormWindowState.Normal: {
4872 if (current_state == FormWindowState.Minimized) {
4873 MapWindow(hwnd, WindowType.Both);
4874 } else if (current_state == FormWindowState.Maximized) {
4875 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4882 case FormWindowState.Minimized: {
4884 if (current_state == FormWindowState.Maximized) {
4885 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4887 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4892 case FormWindowState.Maximized: {
4894 if (current_state == FormWindowState.Minimized) {
4895 MapWindow(hwnd, WindowType.Both);
4898 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4906 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4909 hwnd = Hwnd.ObjectFromHandle(handle);
4910 SetHwndStyles(hwnd, cp);
4911 SetWMStyles(hwnd, cp);
4914 internal override double GetWindowTransparency(IntPtr handle)
4919 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4923 hwnd = Hwnd.ObjectFromHandle(handle);
4929 hwnd.opacity = (uint)(0xffffffff * transparency);
4930 opacity = (IntPtr)((int)hwnd.opacity);
4932 IntPtr w = hwnd.whole_window;
4933 if (hwnd.reparented)
4934 w = XGetParent (hwnd.whole_window);
4935 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4938 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4939 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4947 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4950 } else if (!bottom) {
4951 Hwnd after_hwnd = null;
4953 if (after_handle != IntPtr.Zero) {
4954 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4957 XWindowChanges values = new XWindowChanges();
4959 if (after_hwnd == null) {
4960 // Work around metacity 'issues'
4964 atoms[0] = unixtime();
4965 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4967 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4968 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4970 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4973 values.sibling = after_hwnd.whole_window;
4974 values.stack_mode = StackMode.Below;
4977 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4982 XLowerWindow(DisplayHandle, hwnd.whole_window);
4989 internal override void ShowCursor(bool show) {
4990 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4993 internal override object StartLoop(Thread thread) {
4994 return (Object) ThreadQueue(thread);
4997 internal override TransparencySupport SupportsTransparency() {
4998 // We need to check if the x compositing manager is running
4999 return TransparencySupport.Set;
5002 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5003 GetSystrayManagerWindow();
5005 if (SystrayMgrWindow != IntPtr.Zero) {
5006 XSizeHints size_hints;
5009 hwnd = Hwnd.ObjectFromHandle(handle);
5011 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5015 if (hwnd.client_window != hwnd.whole_window) {
5016 XDestroyWindow(DisplayHandle, hwnd.client_window);
5017 hwnd.client_window = hwnd.whole_window;
5019 /* by virtue of the way the tests are ordered when determining if it's PAINT
5020 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
5021 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5022 there's a pending expose). */
5023 if (hwnd.nc_expose_pending) {
5024 hwnd.nc_expose_pending = false;
5025 if (!hwnd.expose_pending)
5026 hwnd.Queue.Paint.Remove (hwnd);
5030 size_hints = new XSizeHints();
5032 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5034 size_hints.min_width = 24;
5035 size_hints.min_height = 24;
5036 size_hints.max_width = 24;
5037 size_hints.max_height = 24;
5038 size_hints.base_width = 24;
5039 size_hints.base_height = 24;
5041 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5043 int[] atoms = new int[2];
5044 atoms [0] = 1; // Version 1
5045 atoms [1] = 1; // we want to be mapped
5047 // This line cost me 3 days...
5048 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5050 // Need to pick some reasonable defaults
5052 tt.AutomaticDelay = 100;
5053 tt.InitialDelay = 250;
5054 tt.ReshowDelay = 250;
5055 tt.ShowAlways = true;
5057 if ((tip != null) && (tip != string.Empty)) {
5058 tt.SetToolTip(Control.FromHandle(handle), tip);
5064 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5072 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5075 control = Control.FromHandle(handle);
5076 if (control != null && tt != null) {
5077 tt.SetToolTip(control, tip);
5085 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5087 #if GTKSOCKET_SUPPORTS_REPARENTING
5090 hwnd = Hwnd.ObjectFromHandle(handle);
5092 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5093 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5094 * 2. The client can reparent its window out of the embedder window.
5095 * 3. The client can destroy its window.
5097 * this call to SetParent is case 2, but in
5098 * the spec it also mentions that gtk doesn't
5099 * support this at present. Looking at HEAD
5100 * gtksocket-x11.c jives with this statement.
5102 * so we can't reparent. we have to destroy.
5104 SetParent(hwnd.whole_window, FosterParent);
5106 Control control = Control.FromHandle(handle);
5107 if (control is NotifyIcon.NotifyIconWindow)
5108 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5111 // The caller can now re-dock it later...
5118 internal override bool Text(IntPtr handle, string text) {
5121 hwnd = Hwnd.ObjectFromHandle(handle);
5124 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5125 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5127 // XXX this has problems with UTF8.
5128 // we need to either use the actual
5129 // text if it's latin-1, or convert it
5130 // to compound text if it's in a
5131 // different charset.
5132 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5137 internal override bool TranslateMessage(ref MSG msg) {
5138 return Keyboard.TranslateMessage (ref msg);
5141 internal override void UpdateWindow(IntPtr handle) {
5144 hwnd = Hwnd.ObjectFromHandle(handle);
5146 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5150 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5151 hwnd.Queue.Paint.Remove(hwnd);
5154 internal override void CreateOffscreenDrawable (IntPtr handle,
5155 int width, int height,
5156 out object offscreen_drawable,
5157 out Graphics offscreen_dc)
5160 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5162 XGetGeometry (DisplayHandle, handle,
5164 out x_out, out y_out,
5165 out width_out, out height_out,
5166 out border_width_out, out depth_out);
5168 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5170 offscreen_drawable = pixmap;
5172 offscreen_dc = Graphics.FromHwnd (pixmap);
5175 internal override void DestroyOffscreenDrawable (object offscreen_drawable,
5176 Graphics offscreen_dc)
5178 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5179 offscreen_dc.Dispose ();
5182 internal override void BlitFromOffscreen (IntPtr dest_handle,
5184 object offscreen_drawable,
5185 Graphics offscreen_dc,
5188 XGCValues gc_values;
5191 gc_values = new XGCValues();
5193 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5195 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5196 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5198 XFreeGC (DisplayHandle, gc);
5201 #endregion // Public Static Methods
5204 internal override event EventHandler Idle;
5205 #endregion // Events
5208 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5209 internal extern static IntPtr XOpenDisplay(IntPtr display);
5210 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5211 internal extern static int XCloseDisplay(IntPtr display);
5212 [DllImport ("libX11", EntryPoint="XSynchronize")]
5213 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5215 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5216 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);
5217 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5218 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5219 [DllImport ("libX11", EntryPoint="XMapWindow")]
5220 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5221 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5222 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5223 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5224 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5225 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5226 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5227 [DllImport ("libX11", EntryPoint="XRootWindow")]
5228 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5229 [DllImport ("libX11", EntryPoint="XNextEvent")]
5230 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5231 [DllImport ("libX11")]
5232 internal extern static int XConnectionNumber (IntPtr diplay);
5233 [DllImport ("libX11")]
5234 internal extern static int XPending (IntPtr diplay);
5235 [DllImport ("libX11", EntryPoint="XSelectInput")]
5236 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5238 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5239 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5241 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5242 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5243 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5244 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5246 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5247 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5249 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5250 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5252 [DllImport ("libX11", EntryPoint="XFlush")]
5253 internal extern static int XFlush(IntPtr display);
5255 [DllImport ("libX11", EntryPoint="XSetWMName")]
5256 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5258 [DllImport ("libX11", EntryPoint="XStoreName")]
5259 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5261 [DllImport ("libX11", EntryPoint="XFetchName")]
5262 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5264 [DllImport ("libX11", EntryPoint="XSendEvent")]
5265 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5267 [DllImport ("libX11", EntryPoint="XQueryTree")]
5268 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);
5270 [DllImport ("libX11", EntryPoint="XFree")]
5271 internal extern static int XFree(IntPtr data);
5273 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5274 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5276 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5277 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5279 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5280 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5282 [DllImport ("libX11", EntryPoint="XInternAtom")]
5283 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5285 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5286 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5288 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5289 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5291 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5292 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);
5294 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5295 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5297 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5298 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);
5300 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5301 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);
5303 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5304 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);
5306 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5307 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);
5309 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5310 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);
5312 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5313 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);
5315 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5316 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);
5318 [DllImport ("libX11", EntryPoint="XClearWindow")]
5319 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5321 [DllImport ("libX11", EntryPoint="XClearArea")]
5322 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5325 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5326 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5328 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5329 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5331 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5332 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5334 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5335 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5337 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5338 internal extern static int XDefaultScreen(IntPtr display);
5340 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5341 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5343 [DllImport ("libX11", EntryPoint="XLookupColor")]
5344 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5346 [DllImport ("libX11", EntryPoint="XAllocColor")]
5347 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5349 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5350 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5352 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5353 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5355 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5356 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5358 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5359 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5361 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5362 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5364 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5365 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5367 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5368 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5370 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5371 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5373 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5374 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5376 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5377 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5379 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5380 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5383 [DllImport ("libX11", EntryPoint="XCreateGC")]
5384 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5386 [DllImport ("libX11", EntryPoint="XFreeGC")]
5387 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5389 [DllImport ("libX11", EntryPoint="XSetFunction")]
5390 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5392 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5393 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5395 [DllImport ("libX11", EntryPoint="XDrawLine")]
5396 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5398 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5399 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5401 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5402 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5404 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5405 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5407 [DllImport ("libX11", EntryPoint="XCopyArea")]
5408 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);
5410 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5411 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);
5413 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5414 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5416 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5417 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5419 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5420 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5422 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5423 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5425 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5426 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5428 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5429 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5431 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5432 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);
5434 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5435 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5437 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5438 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5440 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5441 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5443 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5444 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5446 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5447 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5449 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5450 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5452 [DllImport ("libX11", EntryPoint="XGrabServer")]
5453 internal extern static void XGrabServer(IntPtr display);
5455 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5456 internal extern static void XUngrabServer(IntPtr display);
5458 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5459 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5461 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5462 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5464 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5465 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5467 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5468 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5470 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5471 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5473 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5474 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5476 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5477 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5479 [DllImport ("libX11", EntryPoint="XInitThreads")]
5480 internal extern static int XInitThreads();
5482 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5483 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5485 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5486 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5488 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5489 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5491 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5492 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5494 [DllImport ("libX11", EntryPoint="XSetForeground")]
5495 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5497 [DllImport ("libX11", EntryPoint="XSetBackground")]
5498 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5500 [DllImport ("libX11", EntryPoint="XBell")]
5501 internal extern static int XBell(IntPtr display, int percent);
5503 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5504 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5506 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5507 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5509 [DllImport ("libX11")]
5510 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5512 [DllImport ("libX11")]
5513 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);