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) {
712 //Console.WriteLine ("Child is zero");
716 hwnd = Hwnd.GetObjectFromWindow (child);
722 if (hwnd.Handle == IntPtr.Zero) {
723 //Console.WriteLine ("Child's Handle is zero");
727 if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
731 if (hwnd.Parent == null) {
735 if (hwnd.Parent.Handle == IntPtr.Zero) {
739 if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
740 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
742 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
745 SendParentNotify (hwnd.Parent.Handle, cause, x, y);
748 bool StyleSet (int s, WindowStyles ws)
750 return (s & (int)ws) == (int)ws;
753 bool ExStyleSet (int ex, WindowExStyles exws)
755 return (ex & (int)exws) == (int)exws;
758 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
760 // Only MDI windows get caption_heights
762 tool_caption_height = 19;
764 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
765 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
766 border_style = FormBorderStyle.Fixed3D;
767 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
768 border_style = FormBorderStyle.None;
770 border_style = FormBorderStyle.FixedSingle;
772 title_style = TitleStyle.None;
774 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
777 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
778 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
779 title_style = TitleStyle.Tool;
781 title_style = TitleStyle.Normal;
785 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
786 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
787 border_style = (FormBorderStyle) 0xFFFF;
789 border_style = FormBorderStyle.None;
794 title_style = TitleStyle.None;
795 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
796 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
797 title_style = TitleStyle.Tool;
799 title_style = TitleStyle.Normal;
803 border_style = FormBorderStyle.None;
805 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
806 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
807 border_style = FormBorderStyle.SizableToolWindow;
809 border_style = FormBorderStyle.Sizable;
812 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
813 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
814 border_style = FormBorderStyle.Fixed3D;
815 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
816 border_style = FormBorderStyle.FixedDialog;
817 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
818 border_style = FormBorderStyle.FixedToolWindow;
819 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
820 border_style = FormBorderStyle.FixedSingle;
823 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
824 border_style = FormBorderStyle.FixedSingle;
831 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
832 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
835 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
836 MotifWmHints mwmHints;
837 MotifFunctions functions;
838 MotifDecorations decorations;
841 Rectangle client_rect;
843 // Child windows don't need WM window styles
844 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
849 mwmHints = new MotifWmHints();
853 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
854 mwmHints.functions = (IntPtr)0;
855 mwmHints.decorations = (IntPtr)0;
857 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
858 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
859 /* tool windows get no window manager
860 decorations, and neither do windows
861 which lack CAPTION/BORDER/DLGFRAME
865 /* just because the window doesn't get any decorations doesn't
866 mean we should disable the functions. for instance, without
867 MotifFunctions.Maximize, changing the windowstate to Maximized
868 is ignored by metacity. */
869 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
872 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
873 functions |= MotifFunctions.Move;
874 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
877 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
878 functions |= MotifFunctions.Move | MotifFunctions.Resize;
879 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
882 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
883 functions |= MotifFunctions.Minimize;
884 decorations |= MotifDecorations.Minimize;
887 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
888 functions |= MotifFunctions.Maximize;
889 decorations |= MotifDecorations.Maximize;
892 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
893 functions |= MotifFunctions.Resize;
894 decorations |= MotifDecorations.ResizeH;
897 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
898 decorations |= MotifDecorations.Border;
901 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
902 decorations |= MotifDecorations.Border;
905 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
906 decorations |= MotifDecorations.Border;
909 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
910 functions |= MotifFunctions.Close;
913 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
914 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
915 if (cp.Caption == "") {
916 functions &= ~MotifFunctions.Move;
917 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
922 if ((functions & MotifFunctions.Resize) == 0) {
923 hwnd.fixed_size = true;
924 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));
926 hwnd.fixed_size = false;
929 mwmHints.functions = (IntPtr)functions;
930 mwmHints.decorations = (IntPtr)decorations;
932 FormWindowState current_state = GetWindowState (hwnd.Handle);
933 if (current_state == (FormWindowState)(-1))
934 current_state = FormWindowState.Normal;
936 client_rect = hwnd.ClientRect;
940 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
941 // and get those windows in front of their parents
942 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
943 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
944 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
945 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
947 Form f = Control.FromHandle(hwnd.Handle) as Form;
948 if (f != null && !hwnd.reparented) {
949 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
950 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
951 if (owner_hwnd != null)
952 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
953 owner_hwnd.whole_window);
958 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
959 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
960 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
961 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
963 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
964 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
965 /* this line keeps the window from showing up in gnome's taskbar */
966 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
968 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
969 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
971 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
974 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
975 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
977 /* we need to add these atoms in the
978 * event we're maximized, since we're
979 * replacing the existing
980 * _NET_WM_STATE here. If we don't
981 * add them, future calls to
982 * GetWindowState will return Normal
983 * for a window which is maximized. */
984 if (current_state == FormWindowState.Maximized) {
985 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
986 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
988 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
991 IntPtr[] atom_ptrs = new IntPtr[2];
992 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
993 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
994 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
997 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1001 private void SetIcon(Hwnd hwnd, Icon icon) {
1007 bitmap = icon.ToBitmap();
1009 size = bitmap.Width * bitmap.Height + 2;
1010 data = new IntPtr[size];
1012 data[index++] = (IntPtr)bitmap.Width;
1013 data[index++] = (IntPtr)bitmap.Height;
1015 for (int y = 0; y < bitmap.Height; y++) {
1016 for (int x = 0; x < bitmap.Width; x++) {
1017 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
1021 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
1024 private void WakeupMain () {
1025 wake.Send (new byte [] { 0xFF });
1028 private XEventQueue ThreadQueue(Thread thread) {
1031 queue = (XEventQueue)MessageQueues[thread];
1032 if (queue == null) {
1033 queue = new XEventQueue(thread);
1034 MessageQueues[thread] = queue;
1040 private void TranslatePropertyToClipboard(IntPtr property) {
1045 IntPtr prop = IntPtr.Zero;
1047 Clipboard.Item = null;
1049 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);
1051 if ((long)nitems > 0) {
1052 if (property == (IntPtr)Atom.XA_STRING) {
1053 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1054 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1055 // FIXME - convert bitmap to image
1056 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1057 // FIXME - convert pixmap to image
1058 } else if (property == OEMTEXT) {
1059 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1060 } else if (property == UNICODETEXT) {
1061 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1068 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1070 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1074 // Keep the invalid area as small as needed
1075 if ((x + width) > hwnd.width) {
1076 width = hwnd.width - x;
1079 if ((y + height) > hwnd.height) {
1080 height = hwnd.height - y;
1084 hwnd.AddInvalidArea(x, y, width, height);
1085 if (!hwnd.expose_pending) {
1086 if (!hwnd.nc_expose_pending) {
1087 hwnd.Queue.Paint.Enqueue(hwnd);
1089 hwnd.expose_pending = true;
1092 hwnd.AddNcInvalidArea (x, y, width, height);
1094 if (!hwnd.nc_expose_pending) {
1095 if (!hwnd.expose_pending) {
1096 hwnd.Queue.Paint.Enqueue(hwnd);
1098 hwnd.nc_expose_pending = true;
1103 private void FrameExtents(IntPtr window, out int left, out int top) {
1108 IntPtr prop = IntPtr.Zero;
1110 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);
1111 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1112 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1113 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1114 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1115 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1121 if (prop != IntPtr.Zero) {
1127 private void AddConfigureNotify (XEvent xevent) {
1130 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1137 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1138 if (!hwnd.reparented) {
1139 hwnd.x = xevent.ConfigureEvent.x;
1140 hwnd.y = xevent.ConfigureEvent.y;
1142 // This sucks ass, part 1
1143 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1144 // no standard way of getting our adjustment.
1145 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1146 // Several other WMs do their decorations different yet again and we fail to deal
1147 // with that, since I couldn't find any frigging commonality between them.
1148 // The only sane WM seems to be KDE
1150 if (!xevent.ConfigureEvent.send_event) {
1153 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1155 // This is a synthetic event, coordinates are in root space
1156 hwnd.x = xevent.ConfigureEvent.x;
1157 hwnd.y = xevent.ConfigureEvent.y;
1158 if (hwnd.whacky_wm) {
1162 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1163 hwnd.x -= frame_left;
1164 hwnd.y -= frame_top;
1169 // XXX this sucks. this isn't thread safe
1170 hwnd.width = xevent.ConfigureEvent.width;
1171 hwnd.height = xevent.ConfigureEvent.height;
1172 hwnd.ClientRect = Rectangle.Empty;
1174 lock (hwnd.configure_lock) {
1175 if (!hwnd.configure_pending) {
1176 hwnd.Queue.EnqueueLocked (xevent);
1177 hwnd.configure_pending = true;
1181 // We drop configure events for Client windows
1184 private void ShowCaret() {
1185 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1191 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1195 private void HideCaret() {
1196 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1202 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1206 private int NextTimeout (ArrayList timers, DateTime now) {
1207 int timeout = Int32.MaxValue;
1209 foreach (Timer timer in timers) {
1210 int next = (int) (timer.Expires - now).TotalMilliseconds;
1212 return 0; // Have a timer that has already expired
1215 if (next < timeout) {
1219 if (timeout < Timer.Minimum) {
1220 timeout = Timer.Minimum;
1228 private void CheckTimers (ArrayList timers, DateTime now) {
1231 count = timers.Count;
1236 for (int i = 0; i < timers.Count; i++) {
1239 timer = (Timer) timers [i];
1241 if (timer.Enabled && timer.Expires <= now) {
1248 private void MapWindow(Hwnd hwnd, WindowType windows) {
1250 if ((windows & WindowType.Whole) != 0) {
1251 XMapWindow(DisplayHandle, hwnd.whole_window);
1253 if ((windows & WindowType.Client) != 0) {
1254 XMapWindow(DisplayHandle, hwnd.client_window);
1258 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1259 hwnd.mapped = false;
1260 if ((windows & WindowType.Whole) != 0) {
1261 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1263 if ((windows & WindowType.Client) != 0) {
1264 XUnmapWindow(DisplayHandle, hwnd.client_window);
1268 private void UpdateMessageQueue (XEventQueue queue) {
1273 now = DateTime.UtcNow;
1276 pending = XPending (DisplayHandle);
1280 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1281 Idle (this, EventArgs.Empty);
1285 pending = XPending (DisplayHandle);
1292 if (queue != null) {
1293 if (queue.Paint.Count > 0)
1296 timeout = NextTimeout (queue.timer_list, now);
1301 int length = pollfds.Length - 1;
1302 lock (wake_waiting_lock) {
1303 if (wake_waiting == false) {
1305 wake_waiting = true;
1309 Syscall.poll (pollfds, (uint)length, timeout);
1310 // Clean out buffer, so we're not busy-looping on the same data
1311 if (pollfds[1].revents != 0) {
1312 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1313 wake_waiting = false;
1317 pending = XPending (DisplayHandle);
1323 CheckTimers (queue.timer_list, now);
1326 XEvent xevent = new XEvent ();
1329 if (XPending (DisplayHandle) == 0)
1332 XNextEvent (DisplayHandle, ref xevent);
1334 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1335 if (XFilterEvent(ref xevent, FosterParent)) {
1341 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1345 switch (xevent.type) {
1346 case XEventName.Expose:
1347 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1350 case XEventName.SelectionClear: {
1351 // Should we do something?
1355 case XEventName.SelectionRequest: {
1356 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1360 sel_event = new XEvent();
1361 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1362 sel_event.SelectionEvent.send_event = true;
1363 sel_event.SelectionEvent.display = DisplayHandle;
1364 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1365 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1366 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1367 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1368 sel_event.SelectionEvent.property = IntPtr.Zero;
1370 // Seems that some apps support asking for supported types
1371 if (xevent.SelectionEvent.target == TARGETS) {
1378 if (Clipboard.Item is String) {
1379 atoms[atom_count++] = (int)Atom.XA_STRING;
1380 atoms[atom_count++] = (int)OEMTEXT;
1381 atoms[atom_count++] = (int)UNICODETEXT;
1382 } else if (Clipboard.Item is Image) {
1383 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1384 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1386 // FIXME - handle other types
1389 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1390 } else if (Clipboard.Item is string) {
1396 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1399 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1400 buffer = Marshal.AllocHGlobal(bytes.Length);
1401 buflen = bytes.Length;
1403 for (int i = 0; i < buflen; i++) {
1404 Marshal.WriteByte(buffer, i, bytes[i]);
1406 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1407 // FIXME - this should encode into ISO2022
1408 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1409 while (Marshal.ReadByte(buffer, buflen) != 0) {
1412 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1413 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1414 while (Marshal.ReadByte(buffer, buflen) != 0) {
1418 buffer = IntPtr.Zero;
1421 if (buffer != IntPtr.Zero) {
1422 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1423 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1424 Marshal.FreeHGlobal(buffer);
1426 } else if (Clipboard.Item is Image) {
1427 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1428 // FIXME - convert image and store as property
1429 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1430 // FIXME - convert image and store as property
1434 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1438 case XEventName.SelectionNotify: {
1439 if (Clipboard.Enumerating) {
1440 Clipboard.Enumerating = false;
1441 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1442 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1443 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1444 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1445 #if DriverDebugExtra
1446 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1450 } else if (Clipboard.Retrieving) {
1451 Clipboard.Retrieving = false;
1452 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1453 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1455 Clipboard.Item = null;
1458 Dnd.HandleSelectionNotifyEvent (ref xevent);
1463 case XEventName.MapNotify: {
1464 if (hwnd.client_window == xevent.MapEvent.window) {
1470 case XEventName.UnmapNotify: {
1471 if (hwnd.client_window == xevent.MapEvent.window) {
1472 hwnd.mapped = false;
1477 case XEventName.KeyRelease:
1478 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1479 XEvent nextevent = new XEvent ();
1481 XPeekEvent (DisplayHandle, ref nextevent);
1483 if (nextevent.type == XEventName.KeyPress &&
1484 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1485 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1489 goto case XEventName.KeyPress;
1491 case XEventName.MotionNotify: {
1494 /* we can't do motion compression across threads, so just punt if we don't match up */
1495 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1496 peek = hwnd.Queue.Peek();
1497 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1501 goto case XEventName.KeyPress;
1504 case XEventName.KeyPress:
1505 case XEventName.ButtonPress:
1506 case XEventName.ButtonRelease:
1507 case XEventName.EnterNotify:
1508 case XEventName.LeaveNotify:
1509 case XEventName.CreateNotify:
1510 case XEventName.DestroyNotify:
1511 case XEventName.FocusIn:
1512 case XEventName.FocusOut:
1513 case XEventName.ClientMessage:
1514 case XEventName.ReparentNotify:
1515 hwnd.Queue.EnqueueLocked (xevent);
1518 case XEventName.ConfigureNotify:
1519 AddConfigureNotify(xevent);
1522 case XEventName.PropertyNotify:
1523 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1528 IntPtr prop = IntPtr.Zero;
1531 prev_active = ActiveWindow;
1532 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);
1533 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1534 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1537 if (prev_active != ActiveWindow) {
1538 if (prev_active != IntPtr.Zero) {
1539 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1541 if (ActiveWindow != IntPtr.Zero) {
1542 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1545 if (ModalWindows.Count == 0) {
1548 // Modality handling, if we are modal and the new active window is one
1549 // of ours but not the modal one, switch back to the modal window
1551 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1552 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1553 Activate((IntPtr)ModalWindows.Peek());
1566 private IntPtr GetMousewParam(int Delta) {
1569 if ((MouseState & MouseButtons.Left) != 0) {
1570 result |= (int)MsgButtons.MK_LBUTTON;
1573 if ((MouseState & MouseButtons.Middle) != 0) {
1574 result |= (int)MsgButtons.MK_MBUTTON;
1577 if ((MouseState & MouseButtons.Right) != 0) {
1578 result |= (int)MsgButtons.MK_RBUTTON;
1581 Keys mods = ModifierKeys;
1582 if ((mods & Keys.Control) != 0) {
1583 result |= (int)MsgButtons.MK_CONTROL;
1586 if ((mods & Keys.Shift) != 0) {
1587 result |= (int)MsgButtons.MK_SHIFT;
1590 result |= Delta << 16;
1592 return (IntPtr)result;
1594 private IntPtr XGetParent(IntPtr handle) {
1601 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1604 if (Children!=IntPtr.Zero) {
1612 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1613 if (ErrorExceptions) {
1614 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1616 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);
1621 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1624 Control[] controls = c.Controls.GetAllControls ();
1626 if (c.IsHandleCreated && !c.IsDisposed) {
1627 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1629 #if DriverDebug || DriverDebugDestroy
1630 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1631 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1635 CleanupCachedWindows (hwnd);
1639 for (int i = 0; i < controls.Length; i ++) {
1640 AccumulateDestroyedHandles (controls[i], list);
1646 void CleanupCachedWindows (Hwnd hwnd)
1648 if (ActiveWindow == hwnd.Handle) {
1649 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1650 ActiveWindow = IntPtr.Zero;
1653 if (FocusWindow == hwnd.Handle) {
1654 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1655 FocusWindow = IntPtr.Zero;
1658 if (Grab.Hwnd == hwnd.Handle) {
1659 Grab.Hwnd = IntPtr.Zero;
1660 Grab.Confined = false;
1663 DestroyCaret (hwnd.Handle);
1666 private void PerformNCCalc(Hwnd hwnd) {
1667 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1671 rect = hwnd.DefaultClientRect;
1673 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1674 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1676 ncp.rgrc1.left = rect.Left;
1677 ncp.rgrc1.top = rect.Top;
1678 ncp.rgrc1.right = rect.Right;
1679 ncp.rgrc1.bottom = rect.Bottom;
1681 Marshal.StructureToPtr(ncp, ptr, true);
1682 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1683 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1684 Marshal.FreeHGlobal(ptr);
1686 // FIXME - debug this with Menus
1688 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1689 hwnd.ClientRect = rect;
1692 if ((rect.Width < 1) || (rect.Height < 1)) {
1693 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1695 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1699 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1701 #endregion // Private Methods
1704 private void MouseHover(object sender, EventArgs e) {
1708 HoverState.Timer.Enabled = false;
1710 if (HoverState.Window != IntPtr.Zero) {
1711 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1713 xevent = new XEvent ();
1715 xevent.type = XEventName.ClientMessage;
1716 xevent.ClientMessageEvent.display = DisplayHandle;
1717 xevent.ClientMessageEvent.window = HoverState.Window;
1718 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1719 xevent.ClientMessageEvent.format = 32;
1720 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1722 hwnd.Queue.EnqueueLocked (xevent);
1729 private void CaretCallback(object sender, EventArgs e) {
1733 Caret.On = !Caret.On;
1735 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1737 #endregion // Callbacks
1739 #region Public Properties
1741 internal override int Caption {
1747 internal override Size CursorSize {
1752 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1753 return new Size(x, y);
1755 return new Size(16, 16);
1760 internal override bool DragFullWindows {
1766 internal override Size DragSize {
1768 return new Size(4, 4);
1772 internal override Size FrameBorderSize {
1774 throw new NotImplementedException();
1778 internal override Size IconSize {
1784 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1788 current = (long)list;
1791 size = new XIconSize();
1793 for (int i = 0; i < count; i++) {
1794 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1795 current += Marshal.SizeOf(size);
1797 // Look for our preferred size
1798 if (size.min_width == 32) {
1800 return new Size(32, 32);
1803 if (size.max_width == 32) {
1805 return new Size(32, 32);
1808 if (size.min_width < 32 && size.max_width > 32) {
1811 // check if we can fit one
1813 while (x < size.max_width) {
1814 x += size.width_inc;
1817 return new Size(32, 32);
1822 if (largest < size.max_width) {
1823 largest = size.max_width;
1827 // We didn't find a match or we wouldn't be here
1828 return new Size(largest, largest);
1831 return new Size(32, 32);
1836 internal override int KeyboardSpeed {
1839 // A lot harder: need to do:
1840 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1841 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1842 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1844 // And from that we can tell the repetition rate
1846 // Notice, the values must map to:
1847 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1853 internal override int KeyboardDelay {
1856 // Return values must range from 0 to 4, 0 meaning 250ms,
1857 // and 4 meaning 1000 ms.
1859 return 1; // ie, 500 ms
1863 internal override Size MaxWindowTrackSize {
1865 return new Size (WorkingArea.Width, WorkingArea.Height);
1869 internal override Size MinimizedWindowSize {
1871 return new Size(1, 1);
1875 internal override Size MinimizedWindowSpacingSize {
1877 return new Size(1, 1);
1881 internal override Size MinimumWindowSize {
1883 return new Size(1, 1);
1887 internal override Size MinWindowTrackSize {
1889 return new Size(1, 1);
1893 internal override Keys ModifierKeys {
1895 return Keyboard.ModifierKeys;
1899 internal override Size SmallIconSize {
1905 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1909 current = (long)list;
1912 size = new XIconSize();
1914 for (int i = 0; i < count; i++) {
1915 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1916 current += Marshal.SizeOf(size);
1918 // Look for our preferred size
1919 if (size.min_width == 16) {
1921 return new Size(16, 16);
1924 if (size.max_width == 16) {
1926 return new Size(16, 16);
1929 if (size.min_width < 16 && size.max_width > 16) {
1932 // check if we can fit one
1934 while (x < size.max_width) {
1935 x += size.width_inc;
1938 return new Size(16, 16);
1943 if (smallest == 0 || smallest > size.min_width) {
1944 smallest = size.min_width;
1948 // We didn't find a match or we wouldn't be here
1949 return new Size(smallest, smallest);
1952 return new Size(16, 16);
1957 internal override int MouseButtonCount {
1963 internal override bool MouseButtonsSwapped {
1965 return false; // FIXME - how to detect?
1969 internal override Point MousePosition {
1971 return mouse_position;
1975 internal override Size MouseHoverSize {
1977 return new Size (1, 1);
1981 internal override int MouseHoverTime {
1983 return HoverState.Interval;
1989 internal override bool MouseWheelPresent {
1991 return true; // FIXME - how to detect?
1995 internal override Rectangle VirtualScreen {
2001 internal override Rectangle WorkingArea {
2007 IntPtr prop = IntPtr.Zero;
2010 int current_desktop;
2014 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);
2015 if ((long)nitems < 1) {
2019 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2022 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);
2023 if ((long)nitems < 4 * current_desktop) {
2027 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2028 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2029 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2030 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2033 return new Rectangle(x, y, width, height);
2036 XWindowAttributes attributes=new XWindowAttributes();
2039 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2042 return new Rectangle(0, 0, attributes.width, attributes.height);
2046 internal override bool ThemesEnabled {
2048 return XplatUIX11.themes_enabled;
2053 #endregion // Public properties
2055 #region Public Static Methods
2056 internal override IntPtr InitializeDriver() {
2058 if (DisplayHandle==IntPtr.Zero) {
2059 SetDisplay(XOpenDisplay(IntPtr.Zero));
2065 internal override void ShutdownDriver(IntPtr token) {
2067 if (DisplayHandle!=IntPtr.Zero) {
2068 XCloseDisplay(DisplayHandle);
2069 DisplayHandle=IntPtr.Zero;
2074 internal override void EnableThemes() {
2075 themes_enabled = true;
2079 internal override void Activate(IntPtr handle) {
2082 hwnd = Hwnd.ObjectFromHandle(handle);
2086 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2087 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2090 // XRaiseWindow(DisplayHandle, handle);
2096 internal override void AudibleAlert() {
2097 XBell(DisplayHandle, 0);
2102 internal override void CaretVisible(IntPtr handle, bool visible) {
2103 if (Caret.Hwnd == handle) {
2105 if (!Caret.Visible) {
2106 Caret.Visible = true;
2108 Caret.Timer.Start();
2111 Caret.Visible = false;
2118 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2119 FormBorderStyle border_style;
2120 TitleStyle title_style;
2122 int tool_caption_height;
2124 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2125 out caption_height, out tool_caption_height);
2127 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2128 caption_height, tool_caption_height,
2133 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2139 hwnd = Hwnd.ObjectFromHandle(handle);
2142 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2149 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2150 DataFormats.Format f;
2153 f = DataFormats.Format.List;
2155 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2159 Clipboard.Formats = new ArrayList();
2162 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2164 Clipboard.Enumerating = true;
2165 while (Clipboard.Enumerating) {
2166 UpdateMessageQueue(null);
2171 result = new int[Clipboard.Formats.Count];
2173 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2174 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2177 Clipboard.Formats = null;
2181 internal override void ClipboardClose(IntPtr handle) {
2182 if (handle != ClipMagic) {
2183 throw new ArgumentException("handle is not a valid clipboard handle");
2188 internal override int ClipboardGetID(IntPtr handle, string format) {
2189 if (handle != ClipMagic) {
2190 throw new ArgumentException("handle is not a valid clipboard handle");
2193 if (format == "Text" ) return (int)Atom.XA_STRING;
2194 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2195 //else if (format == "MetaFilePict" ) return 3;
2196 //else if (format == "SymbolicLink" ) return 4;
2197 //else if (format == "DataInterchangeFormat" ) return 5;
2198 //else if (format == "Tiff" ) return 6;
2199 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2200 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2201 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2202 //else if (format == "PenData" ) return 10;
2203 //else if (format == "RiffAudio" ) return 11;
2204 //else if (format == "WaveAudio" ) return 12;
2205 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2206 //else if (format == "EnhancedMetafile" ) return 14;
2207 //else if (format == "FileDrop" ) return 15;
2208 //else if (format == "Locale" ) return 16;
2210 return XInternAtom(DisplayHandle, format, false).ToInt32();
2213 internal override IntPtr ClipboardOpen(bool primary_selection) {
2214 if (!primary_selection)
2215 ClipMagic = CLIPBOARD;
2217 ClipMagic = PRIMARY;
2221 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2222 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2224 Clipboard.Retrieving = true;
2225 while (Clipboard.Retrieving) {
2226 UpdateMessageQueue(null);
2229 return Clipboard.Item;
2232 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2233 Clipboard.Item = obj;
2234 Clipboard.Type = type;
2235 Clipboard.Converter = converter;
2238 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2240 // Clearing the selection
2241 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2245 internal override void CreateCaret(IntPtr handle, int width, int height) {
2246 XGCValues gc_values;
2249 hwnd = Hwnd.ObjectFromHandle(handle);
2251 if (Caret.Hwnd != IntPtr.Zero) {
2252 DestroyCaret(Caret.Hwnd);
2255 Caret.Hwnd = handle;
2256 Caret.Window = hwnd.client_window;
2257 Caret.Width = width;
2258 Caret.Height = height;
2259 Caret.Visible = false;
2262 gc_values = new XGCValues();
2263 gc_values.line_width = width;
2265 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2266 if (Caret.gc == IntPtr.Zero) {
2267 Caret.Hwnd = IntPtr.Zero;
2271 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2274 internal override IntPtr CreateWindow(CreateParams cp) {
2275 XSetWindowAttributes Attributes;
2281 IntPtr ParentHandle;
2283 IntPtr ClientWindow;
2284 Rectangle ClientRect;
2285 SetWindowValuemask ValueMask;
2290 Attributes = new XSetWindowAttributes();
2296 if (Width<1) Width=1;
2297 if (Height<1) Height=1;
2299 if (cp.Parent != IntPtr.Zero) {
2300 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2302 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2303 // We need to use our foster parent window until this poor child gets it's parent assigned
2304 ParentHandle=FosterParent;
2305 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2306 ParentHandle=RootWindow;
2308 // Default position on screen, if window manager doesn't place us somewhere else
2311 ParentHandle=RootWindow;
2315 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2317 Attributes.bit_gravity = Gravity.NorthWestGravity;
2318 Attributes.win_gravity = Gravity.NorthWestGravity;
2320 // Save what's under the toolwindow
2321 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2322 Attributes.save_under = true;
2323 ValueMask |= SetWindowValuemask.SaveUnder;
2327 // If we're a popup without caption we override the WM
2328 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2329 Attributes.override_redirect = true;
2330 ValueMask |= SetWindowValuemask.OverrideRedirect;
2336 hwnd.height = Height;
2337 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2338 hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
2340 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2341 hwnd.enabled = false;
2344 ClientRect = hwnd.ClientRect;
2345 ClientWindow = IntPtr.Zero;
2348 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2349 if (WholeWindow != IntPtr.Zero) {
2350 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2352 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2353 ValueMask = SetWindowValuemask.ColorMap;
2354 Attributes.colormap = CustomColormap;
2356 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);
2360 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2361 throw new Exception("Could not create X11 windows");
2364 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2365 hwnd.WholeWindow = WholeWindow;
2366 hwnd.ClientWindow = ClientWindow;
2368 #if DriverDebug || DriverDebugCreate
2369 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);
2372 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2373 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2376 hints = new XSizeHints();
2379 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2380 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2385 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2386 if (hwnd.whole_window != hwnd.client_window)
2387 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2389 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2390 MapWindow(hwnd, WindowType.Both);
2391 hwnd.visible = true;
2395 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2397 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2398 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2400 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2403 SetWMStyles(hwnd, cp);
2405 // set the group leader
2406 XWMHints wm_hints = new XWMHints ();
2408 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2409 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2410 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2412 if (ParentHandle != RootWindow) {
2413 wm_hints.window_group = hwnd.whole_window;
2415 wm_hints.window_group = ParentHandle;
2419 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2422 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2423 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2424 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2425 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2428 // for now make all windows dnd enabled
2429 Dnd.SetAllowDrop (hwnd, true);
2431 // Set caption/window title
2432 Text(hwnd.Handle, cp.Caption);
2434 SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2439 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2440 CreateParams create_params = new CreateParams();
2442 create_params.Caption = "";
2443 create_params.X = X;
2444 create_params.Y = Y;
2445 create_params.Width = Width;
2446 create_params.Height = Height;
2448 create_params.ClassName=XplatUI.DefaultClassName;
2449 create_params.ClassStyle = 0;
2450 create_params.ExStyle=0;
2451 create_params.Parent=IntPtr.Zero;
2452 create_params.Param=0;
2454 return CreateWindow(create_params);
2457 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2459 Bitmap cursor_bitmap;
2467 IntPtr cursor_pixmap;
2474 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2478 // Win32 only allows creation cursors of a certain size
2479 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2480 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2481 cursor_mask = new Bitmap(mask, new Size(width, height));
2483 cursor_bitmap = bitmap;
2487 width = cursor_bitmap.Width;
2488 height = cursor_bitmap.Height;
2490 cursor_bits = new Byte[(width / 8) * height];
2491 mask_bits = new Byte[(width / 8) * height];
2493 for (int y = 0; y < height; y++) {
2494 for (int x = 0; x < width; x++) {
2495 c_pixel = cursor_bitmap.GetPixel(x, y);
2496 m_pixel = cursor_mask.GetPixel(x, y);
2498 and = c_pixel == cursor_pixel;
2499 xor = m_pixel == mask_pixel;
2503 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2504 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2505 } else if (and && !xor) {
2507 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2508 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2510 } else if (and && !xor) {
2512 } else if (and && xor) {
2515 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2516 // we want both to be 0 so nothing to be done
2517 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2518 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2524 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2525 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2529 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2530 fg.red = (ushort)65535;
2531 fg.green = (ushort)65535;
2532 fg.blue = (ushort)65535;
2534 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2536 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2538 XFreePixmap(DisplayHandle, cursor_pixmap);
2539 XFreePixmap(DisplayHandle, mask_pixmap);
2544 internal override IntPtr DefineStdCursor(StdCursor id) {
2545 CursorFontShape shape;
2548 // FIXME - define missing shapes
2551 case StdCursor.AppStarting: {
2552 shape = CursorFontShape.XC_watch;
2556 case StdCursor.Arrow: {
2557 shape = CursorFontShape.XC_top_left_arrow;
2561 case StdCursor.Cross: {
2562 shape = CursorFontShape.XC_crosshair;
2566 case StdCursor.Default: {
2567 shape = CursorFontShape.XC_top_left_arrow;
2571 case StdCursor.Hand: {
2572 shape = CursorFontShape.XC_hand1;
2576 case StdCursor.Help: {
2577 shape = CursorFontShape.XC_question_arrow;
2581 case StdCursor.HSplit: {
2582 shape = CursorFontShape.XC_sb_v_double_arrow;
2586 case StdCursor.IBeam: {
2587 shape = CursorFontShape.XC_xterm;
2591 case StdCursor.No: {
2592 shape = CursorFontShape.XC_circle;
2596 case StdCursor.NoMove2D: {
2597 shape = CursorFontShape.XC_fleur;
2601 case StdCursor.NoMoveHoriz: {
2602 shape = CursorFontShape.XC_fleur;
2606 case StdCursor.NoMoveVert: {
2607 shape = CursorFontShape.XC_fleur;
2611 case StdCursor.PanEast: {
2612 shape = CursorFontShape.XC_fleur;
2616 case StdCursor.PanNE: {
2617 shape = CursorFontShape.XC_fleur;
2621 case StdCursor.PanNorth: {
2622 shape = CursorFontShape.XC_fleur;
2626 case StdCursor.PanNW: {
2627 shape = CursorFontShape.XC_fleur;
2631 case StdCursor.PanSE: {
2632 shape = CursorFontShape.XC_fleur;
2636 case StdCursor.PanSouth: {
2637 shape = CursorFontShape.XC_fleur;
2641 case StdCursor.PanSW: {
2642 shape = CursorFontShape.XC_fleur;
2646 case StdCursor.PanWest: {
2647 shape = CursorFontShape.XC_sizing;
2651 case StdCursor.SizeAll: {
2652 shape = CursorFontShape.XC_fleur;
2656 case StdCursor.SizeNESW: {
2657 shape = CursorFontShape.XC_top_right_corner;
2661 case StdCursor.SizeNS: {
2662 shape = CursorFontShape.XC_sb_v_double_arrow;
2666 case StdCursor.SizeNWSE: {
2667 shape = CursorFontShape.XC_top_left_corner;
2671 case StdCursor.SizeWE: {
2672 shape = CursorFontShape.XC_sb_h_double_arrow;
2676 case StdCursor.UpArrow: {
2677 shape = CursorFontShape.XC_center_ptr;
2681 case StdCursor.VSplit: {
2682 shape = CursorFontShape.XC_sb_h_double_arrow;
2686 case StdCursor.WaitCursor: {
2687 shape = CursorFontShape.XC_watch;
2697 cursor = XCreateFontCursor(DisplayHandle, shape);
2702 internal override IntPtr DefWndProc(ref Message msg) {
2703 switch ((Msg)msg.Msg) {
2704 case Msg.WM_PAINT: {
2707 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2709 hwnd.expose_pending = false;
2715 case Msg.WM_NCPAINT: {
2718 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2720 hwnd.nc_expose_pending = false;
2726 case Msg.WM_CONTEXTMENU: {
2729 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2731 if ((hwnd != null) && (hwnd.parent != null)) {
2732 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2737 case Msg.WM_MOUSEWHEEL: {
2740 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2742 if ((hwnd != null) && (hwnd.parent != null)) {
2743 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2744 if (msg.Result == IntPtr.Zero) {
2751 case Msg.WM_SETCURSOR: {
2754 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2756 break; // not sure how this happens, but it does
2758 // Pass to parent window first
2759 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2761 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2764 if (msg.Result == IntPtr.Zero) {
2767 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2768 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2769 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2770 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2771 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2772 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2775 handle = Cursors.Default.handle;
2778 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2779 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2780 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2781 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2782 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2783 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2786 case HitTest.HTGROWBOX:
2787 case HitTest.HTSIZE:
2788 case HitTest.HTZOOM:
2789 case HitTest.HTVSCROLL:
2790 case HitTest.HTSYSMENU:
2791 case HitTest.HTREDUCE:
2792 case HitTest.HTNOWHERE:
2793 case HitTest.HTMAXBUTTON:
2794 case HitTest.HTMINBUTTON:
2795 case HitTest.HTMENU:
2796 case HitTest.HSCROLL:
2797 case HitTest.HTBOTTOM:
2798 case HitTest.HTCAPTION:
2799 case HitTest.HTCLIENT:
2800 case HitTest.HTCLOSE:
2802 default: handle = Cursors.Default.handle; break;
2804 SetCursor(msg.HWnd, handle);
2812 internal override void DestroyCaret(IntPtr handle) {
2813 if (Caret.Hwnd == handle) {
2814 if (Caret.Visible == true) {
2817 if (Caret.gc != IntPtr.Zero) {
2818 XFreeGC(DisplayHandle, Caret.gc);
2819 Caret.gc = IntPtr.Zero;
2821 Caret.Hwnd = IntPtr.Zero;
2822 Caret.Visible = false;
2827 internal override void DestroyCursor(IntPtr cursor) {
2829 XFreeCursor(DisplayHandle, cursor);
2833 internal override void DestroyWindow(IntPtr handle) {
2836 hwnd = Hwnd.ObjectFromHandle(handle);
2839 #if DriverDebug || DriverDebugDestroy
2840 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2845 #if DriverDebug || DriverDebugDestroy
2846 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2849 SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
2851 CleanupCachedWindows (hwnd);
2853 ArrayList windows = new ArrayList ();
2855 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2858 if (hwnd.whole_window != IntPtr.Zero) {
2859 #if DriverDebug || DriverDebugDestroy
2860 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2862 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2864 else if (hwnd.client_window != IntPtr.Zero) {
2865 #if DriverDebug || DriverDebugDestroy
2866 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2868 XDestroyWindow(DisplayHandle, hwnd.client_window);
2873 foreach (Hwnd h in windows) {
2874 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2878 internal override IntPtr DispatchMessage(ref MSG msg) {
2879 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2882 IntPtr GetReversibleScreenGC (Color backColor)
2884 XGCValues gc_values;
2888 XColor xcolor = new XColor();
2889 xcolor.red = (ushort)(backColor.R * 257);
2890 xcolor.green = (ushort)(backColor.G * 257);
2891 xcolor.blue = (ushort)(backColor.B * 257);
2892 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2893 pixel = (uint)xcolor.pixel.ToInt32();
2896 gc_values = new XGCValues();
2898 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2899 gc_values.foreground = (IntPtr)pixel;
2901 gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
2902 XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
2903 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2908 IntPtr GetReversibleControlGC (Control control, int line_width)
2910 XGCValues gc_values;
2913 gc_values = new XGCValues();
2915 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2916 gc_values.line_width = line_width;
2917 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2919 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2920 //mask = foreground ^ background;
2921 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2922 //XSetBackground(DisplayHandle, gc, background);
2923 //XSetFunction(DisplayHandle, gc, GXxor);
2924 //XSetPlaneMask(DisplayHandle, gc, mask);
2927 gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2931 XColor xcolor = new XColor();
2933 xcolor.red = (ushort)(control.ForeColor.R * 257);
2934 xcolor.green = (ushort)(control.ForeColor.G * 257);
2935 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2936 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2937 foreground = (uint)xcolor.pixel.ToInt32();
2939 xcolor.red = (ushort)(control.BackColor.R * 257);
2940 xcolor.green = (ushort)(control.BackColor.G * 257);
2941 xcolor.blue = (ushort)(control.BackColor.B * 257);
2942 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2943 background = (uint)xcolor.pixel.ToInt32();
2945 uint mask = foreground ^ background;
2947 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2948 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2949 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2950 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2955 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
2957 IntPtr gc = GetReversibleScreenGC (backColor);
2959 XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
2961 XFreeGC(DisplayHandle, gc);
2964 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
2966 IntPtr gc = GetReversibleScreenGC (backColor);
2968 if (rectangle.Width < 0) {
2969 rectangle.X += rectangle.Width;
2970 rectangle.Width = -rectangle.Width;
2972 if (rectangle.Height < 0) {
2973 rectangle.Y += rectangle.Height;
2974 rectangle.Height = -rectangle.Height;
2978 GCLineStyle line_style = GCLineStyle.LineSolid;
2979 GCCapStyle cap_style = GCCapStyle.CapButt;
2980 GCJoinStyle join_style = GCJoinStyle.JoinMiter;
2983 case FrameStyle.Dashed:
2984 line_style = GCLineStyle.LineOnOffDash;
2986 case FrameStyle.Thick:
2991 XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
2993 XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
2995 XFreeGC(DisplayHandle, gc);
2998 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
3000 IntPtr gc = GetReversibleScreenGC (backColor);
3002 if (rectangle.Width < 0) {
3003 rectangle.X += rectangle.Width;
3004 rectangle.Width = -rectangle.Width;
3006 if (rectangle.Height < 0) {
3007 rectangle.Y += rectangle.Height;
3008 rectangle.Height = -rectangle.Height;
3010 XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3012 XFreeGC(DisplayHandle, gc);
3015 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
3017 Control control = Control.FromHandle(handle);
3019 gc = GetReversibleControlGC (control, line_width);
3021 if ((rect.Width > 0) && (rect.Height > 0)) {
3022 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3024 if (rect.Width > 0) {
3025 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3027 XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3030 XFreeGC(DisplayHandle, gc);
3033 internal override void DoEvents() {
3034 MSG msg = new MSG ();
3037 if (OverrideCursorHandle != IntPtr.Zero) {
3038 OverrideCursorHandle = IntPtr.Zero;
3041 queue = ThreadQueue(Thread.CurrentThread);
3043 queue.DispatchIdle = false;
3045 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3046 TranslateMessage (ref msg);
3047 DispatchMessage (ref msg);
3050 queue.DispatchIdle = true;
3053 internal override void EnableWindow(IntPtr handle, bool Enable) {
3056 hwnd = Hwnd.ObjectFromHandle(handle);
3058 hwnd.Enabled = Enable;
3062 internal override void EndLoop(Thread thread) {
3063 // This is where we one day will shut down the loop for the thread
3067 internal override IntPtr GetActive() {
3072 IntPtr prop = IntPtr.Zero;
3073 IntPtr active = IntPtr.Zero;
3075 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);
3076 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3077 active = (IntPtr)Marshal.ReadInt32(prop);
3081 if (active != IntPtr.Zero) {
3084 hwnd = Hwnd.GetObjectFromWindow(active);
3086 active = hwnd.Handle;
3088 active = IntPtr.Zero;
3094 internal override Region GetClipRegion(IntPtr handle) {
3097 hwnd = Hwnd.ObjectFromHandle(handle);
3099 return hwnd.UserClip;
3105 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3112 internal override void GetDisplaySize(out Size size) {
3113 XWindowAttributes attributes=new XWindowAttributes();
3116 // FIXME - use _NET_WM messages instead?
3117 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3120 size = new Size(attributes.width, attributes.height);
3123 internal override SizeF GetAutoScaleSize(Font font) {
3126 string magic_string = "The quick brown fox jumped over the lazy dog.";
3127 double magic_number = 44.549996948242189;
3129 g = Graphics.FromHwnd(FosterParent);
3131 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3132 return new SizeF(width, font.Height);
3135 internal override IntPtr GetParent(IntPtr handle) {
3138 hwnd = Hwnd.ObjectFromHandle(handle);
3139 if (hwnd != null && hwnd.parent != null) {
3140 return hwnd.parent.Handle;
3145 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3155 if (handle != IntPtr.Zero) {
3156 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3158 use_handle = RootWindow;
3162 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3165 if (handle != IntPtr.Zero) {
3174 internal override IntPtr GetFocus() {
3179 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3180 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3183 internal override Point GetMenuOrigin(IntPtr handle) {
3186 hwnd = Hwnd.ObjectFromHandle(handle);
3189 return hwnd.MenuOrigin;
3194 [MonoTODO("Implement filtering")]
3195 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3202 if (((XEventQueue)queue_id).Count > 0) {
3203 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3205 UpdateMessageQueue ((XEventQueue)queue_id);
3207 if (((XEventQueue)queue_id).Count > 0) {
3208 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3209 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3210 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3212 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3213 msg.hwnd= IntPtr.Zero;
3214 msg.message = Msg.WM_ENTERIDLE;
3218 // We reset ourselves so GetMessage can be called again
3219 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3225 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3227 // Handle messages for windows that are already or are about to be destroyed.
3229 // we need a special block for this because unless we remove the hwnd from the paint
3230 // queue it will always stay there (since we don't handle the expose), and we'll
3231 // effectively loop infinitely trying to repaint a non-existant window.
3232 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3233 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3234 hwnd.Queue.Paint.Remove (hwnd);
3235 goto ProcessNextMessage;
3238 // We need to make sure we only allow DestroyNotify events through for zombie
3239 // hwnds, since much of the event handling code makes requests using the hwnd's
3240 // client_window, and that'll result in BadWindow errors if there's some lag
3241 // between the XDestroyWindow call and the DestroyNotify event.
3242 if (hwnd == null || hwnd.zombie) {
3243 #if DriverDebug || DriverDebugDestroy
3244 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3246 goto ProcessNextMessage;
3249 if (hwnd.client_window == xevent.AnyEvent.window) {
3251 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3254 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3257 msg.hwnd = hwnd.Handle;
3260 // If you add a new event to this switch make sure to add it in
3261 // UpdateMessage also unless it is not coming through the X event system.
3263 switch(xevent.type) {
3264 case XEventName.KeyPress: {
3265 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3269 case XEventName.KeyRelease: {
3270 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3274 case XEventName.ButtonPress: {
3275 switch(xevent.ButtonEvent.button) {
3277 MouseState |= MouseButtons.Left;
3279 msg.message = Msg.WM_LBUTTONDOWN;
3281 msg.message = Msg.WM_NCLBUTTONDOWN;
3282 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3284 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3285 msg.wParam=GetMousewParam(0);
3290 MouseState |= MouseButtons.Middle;
3292 msg.message = Msg.WM_MBUTTONDOWN;
3294 msg.message = Msg.WM_NCMBUTTONDOWN;
3295 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3297 msg.wParam=GetMousewParam(0);
3302 MouseState |= MouseButtons.Right;
3304 msg.message = Msg.WM_RBUTTONDOWN;
3306 msg.message = Msg.WM_NCRBUTTONDOWN;
3307 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3309 msg.wParam=GetMousewParam(0);
3314 msg.hwnd = FocusWindow;
3315 msg.message=Msg.WM_MOUSEWHEEL;
3316 msg.wParam=GetMousewParam(120);
3321 msg.hwnd = FocusWindow;
3322 msg.message=Msg.WM_MOUSEWHEEL;
3323 msg.wParam=GetMousewParam(-120);
3329 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3330 mouse_position.X = xevent.ButtonEvent.x;
3331 mouse_position.Y = xevent.ButtonEvent.y;
3333 if (!hwnd.Enabled) {
3336 msg.hwnd = hwnd.EnabledHwnd;
3337 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);
3338 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3341 if (Grab.Hwnd != IntPtr.Zero) {
3342 msg.hwnd = Grab.Hwnd;
3345 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3346 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3347 switch(xevent.ButtonEvent.button) {
3349 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3354 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3359 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3363 ClickPending.Pending = false;
3365 ClickPending.Pending = true;
3366 ClickPending.Hwnd = msg.hwnd;
3367 ClickPending.Message = msg.message;
3368 ClickPending.wParam = msg.wParam;
3369 ClickPending.lParam = msg.lParam;
3370 ClickPending.Time = (long)xevent.ButtonEvent.time;
3373 if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN)
3374 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3379 case XEventName.ButtonRelease: {
3381 Dnd.HandleButtonRelease (ref xevent);
3385 switch(xevent.ButtonEvent.button) {
3388 msg.message = Msg.WM_LBUTTONUP;
3390 msg.message = Msg.WM_NCLBUTTONUP;
3391 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3393 MouseState &= ~MouseButtons.Left;
3394 msg.wParam=GetMousewParam(0);
3400 msg.message = Msg.WM_MBUTTONUP;
3402 msg.message = Msg.WM_NCMBUTTONUP;
3403 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3405 MouseState &= ~MouseButtons.Middle;
3406 msg.wParam=GetMousewParam(0);
3412 msg.message = Msg.WM_RBUTTONUP;
3414 msg.message = Msg.WM_NCRBUTTONUP;
3415 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3417 MouseState &= ~MouseButtons.Right;
3418 msg.wParam=GetMousewParam(0);
3423 goto ProcessNextMessage;
3427 goto ProcessNextMessage;
3431 if (!hwnd.Enabled) {
3434 msg.hwnd = hwnd.EnabledHwnd;
3435 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);
3436 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3439 if (Grab.Hwnd != IntPtr.Zero) {
3440 msg.hwnd = Grab.Hwnd;
3443 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3444 mouse_position.X = xevent.ButtonEvent.x;
3445 mouse_position.Y = xevent.ButtonEvent.y;
3449 case XEventName.MotionNotify: {
3451 #if DriverDebugExtra
3452 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);
3455 if (Dnd.HandleMotionNotify (ref xevent))
3456 goto ProcessNextMessage;
3457 if (Grab.Hwnd != IntPtr.Zero) {
3458 msg.hwnd = Grab.Hwnd;
3460 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3463 msg.message = Msg.WM_MOUSEMOVE;
3464 msg.wParam = GetMousewParam(0);
3465 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3467 if (!hwnd.Enabled) {
3470 msg.hwnd = hwnd.EnabledHwnd;
3471 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);
3472 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3475 mouse_position.X = xevent.MotionEvent.x;
3476 mouse_position.Y = xevent.MotionEvent.y;
3478 if ((HoverState.Timer.Enabled) &&
3479 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3480 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3481 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3482 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3483 HoverState.Timer.Stop();
3484 HoverState.Timer.Start();
3485 HoverState.X = mouse_position.X;
3486 HoverState.Y = mouse_position.Y;
3496 #if DriverDebugExtra
3497 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);
3499 msg.message = Msg.WM_NCMOUSEMOVE;
3501 if (!hwnd.Enabled) {
3502 msg.hwnd = hwnd.EnabledHwnd;
3503 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);
3504 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3507 // The hit test is sent in screen coordinates
3508 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3509 xevent.MotionEvent.x, xevent.MotionEvent.y,
3510 out screen_x, out screen_y, out dummy);
3512 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3513 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3514 IntPtr.Zero, msg.lParam).ToInt32 ();
3515 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3517 mouse_position.X = xevent.MotionEvent.x;
3518 mouse_position.Y = xevent.MotionEvent.y;
3524 case XEventName.EnterNotify: {
3525 if (!hwnd.Enabled) {
3526 goto ProcessNextMessage;
3528 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3529 goto ProcessNextMessage;
3531 msg.message = Msg.WM_MOUSE_ENTER;
3532 HoverState.X = xevent.CrossingEvent.x;
3533 HoverState.Y = xevent.CrossingEvent.y;
3534 HoverState.Timer.Enabled = true;
3535 HoverState.Window = xevent.CrossingEvent.window;
3539 case XEventName.LeaveNotify: {
3540 if (!hwnd.Enabled) {
3541 goto ProcessNextMessage;
3543 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3544 goto ProcessNextMessage;
3546 msg.message=Msg.WM_MOUSE_LEAVE;
3547 HoverState.Timer.Enabled = false;
3548 HoverState.Window = IntPtr.Zero;
3553 case XEventName.CreateNotify: {
3554 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3555 msg.message = WM_CREATE;
3556 // Set up CreateStruct
3558 goto ProcessNextMessage;
3565 case XEventName.ReparentNotify: {
3566 if (hwnd.parent == null) { // Toplevel
3567 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3568 // We need to adjust x/y
3569 // This sucks ass, part 2
3570 // Every WM does the reparenting of toplevel windows different, so there's
3571 // no standard way of getting our adjustment considering frames/decorations
3572 // The code below is needed for metacity. KDE doesn't works just fine without this
3580 hwnd.Reparented = true;
3582 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);
3583 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3584 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3587 hwnd.whacky_wm = true;
3590 if (hwnd.opacity != 0xffffffff) {
3593 opacity = (IntPtr)(Int32)hwnd.opacity;
3594 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3596 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3597 goto ProcessNextMessage;
3599 hwnd.Reparented = false;
3600 goto ProcessNextMessage;
3603 goto ProcessNextMessage;
3606 case XEventName.ConfigureNotify: {
3607 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3608 #if DriverDebugExtra
3609 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);
3611 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3612 lock (hwnd.configure_lock) {
3613 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3614 hwnd.configure_pending = false;
3617 // We need to adjust our client window to track the resize of whole_window
3618 if (hwnd.whole_window != hwnd.client_window)
3619 PerformNCCalc(hwnd);
3622 goto ProcessNextMessage;
3625 case XEventName.FocusIn: {
3626 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3627 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3628 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3629 // about it having focus again
3630 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3631 goto ProcessNextMessage;
3634 if (FocusWindow == IntPtr.Zero) {
3635 Control c = Control.FromHandle (hwnd.client_window);
3637 goto ProcessNextMessage;
3638 Form form = c.FindForm ();
3640 goto ProcessNextMessage;
3641 ActiveWindow = form.Handle;
3642 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3643 goto ProcessNextMessage;
3645 Keyboard.FocusIn(FocusWindow);
3646 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3647 goto ProcessNextMessage;
3650 case XEventName.FocusOut: {
3651 // Se the comment for our FocusIn handler
3652 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3653 goto ProcessNextMessage;
3655 Keyboard.FocusOut(FocusWindow);
3657 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3658 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3661 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3662 goto ProcessNextMessage;
3665 case XEventName.Expose: {
3666 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3668 hwnd.expose_pending = false;
3670 hwnd.nc_expose_pending = false;
3672 goto ProcessNextMessage;
3676 if (!hwnd.expose_pending) {
3677 goto ProcessNextMessage;
3680 if (!hwnd.nc_expose_pending) {
3681 goto ProcessNextMessage;
3684 switch (hwnd.border_style) {
3685 case FormBorderStyle.Fixed3D: {
3688 g = Graphics.FromHwnd(hwnd.whole_window);
3689 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3694 case FormBorderStyle.FixedSingle: {
3697 g = Graphics.FromHwnd(hwnd.whole_window);
3698 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3703 #if DriverDebugExtra
3704 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);
3707 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3708 Region region = new Region (rect);
3709 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3710 msg.message = Msg.WM_NCPAINT;
3711 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3712 msg.refobject = region;
3715 #if DriverDebugExtra
3716 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);
3718 if (Caret.Visible == true) {
3719 Caret.Paused = true;
3723 if (Caret.Visible == true) {
3725 Caret.Paused = false;
3727 msg.message = Msg.WM_PAINT;
3731 case XEventName.DestroyNotify: {
3733 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3734 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3736 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3737 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3738 CleanupCachedWindows (hwnd);
3740 #if DriverDebugDestroy
3741 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3744 msg.hwnd = hwnd.client_window;
3745 msg.message=Msg.WM_DESTROY;
3748 goto ProcessNextMessage;
3754 case XEventName.ClientMessage: {
3755 if (Dnd.HandleClientMessage (ref xevent)) {
3756 goto ProcessNextMessage;
3759 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3760 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3761 goto ProcessNextMessage;
3764 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3765 msg.message = Msg.WM_MOUSEHOVER;
3766 msg.wParam = GetMousewParam(0);
3767 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3771 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3772 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3773 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3774 msg.wParam = xevent.ClientMessageEvent.ptr3;
3775 msg.lParam = xevent.ClientMessageEvent.ptr4;
3779 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3780 #if DriverDebugXEmbed
3781 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3784 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3785 XSizeHints hints = new XSizeHints();
3788 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3790 hwnd.width = hints.max_width;
3791 hwnd.height = hints.max_height;
3792 hwnd.ClientRect = Rectangle.Empty;
3793 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3797 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3798 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3799 msg.message = Msg.WM_CLOSE;
3803 // We should not get this, but I'll leave the code in case we need it in the future
3804 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3805 goto ProcessNextMessage;
3808 goto ProcessNextMessage;
3812 goto ProcessNextMessage;
3819 internal override bool GetText(IntPtr handle, out string text) {
3826 IntPtr prop = IntPtr.Zero;
3828 XGetWindowProperty(DisplayHandle, handle,
3829 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
3830 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3832 if ((long)nitems > 0 && prop != IntPtr.Zero) {
3833 text = Marshal.PtrToStringUni (prop, (int)nitems);
3838 // fallback on the non-_NET property
3841 textptr = IntPtr.Zero;
3843 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3844 if (textptr != IntPtr.Zero) {
3845 text = Marshal.PtrToStringAnsi(textptr);
3856 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) {
3859 hwnd = Hwnd.ObjectFromHandle(handle);
3865 height = hwnd.height;
3867 PerformNCCalc(hwnd);
3869 client_width = hwnd.ClientRect.Width;
3870 client_height = hwnd.ClientRect.Height;
3875 // Should we throw an exception or fail silently?
3876 // throw new ArgumentException("Called with an invalid window handle", "handle");
3886 internal override FormWindowState GetWindowState(IntPtr handle) {
3891 IntPtr prop = IntPtr.Zero;
3895 XWindowAttributes attributes;
3898 hwnd = Hwnd.ObjectFromHandle(handle);
3902 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);
3903 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3904 for (int i = 0; i < (long)nitems; i++) {
3905 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3906 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3908 } else if (atom == _NET_WM_STATE_HIDDEN) {
3916 return FormWindowState.Minimized;
3917 } else if (maximized == 2) {
3918 return FormWindowState.Maximized;
3921 attributes = new XWindowAttributes();
3922 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3923 if (attributes.map_state == MapState.IsUnmapped) {
3924 return (FormWindowState)(-1);
3928 return FormWindowState.Normal;
3931 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3933 GrabConfined = Grab.Confined;
3934 GrabArea = Grab.Area;
3937 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3939 IntPtr confine_to_window;
3941 confine_to_window = IntPtr.Zero;
3943 if (confine_to_handle != IntPtr.Zero) {
3944 XWindowAttributes attributes = new XWindowAttributes();
3946 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3949 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3951 Grab.Area.X = attributes.x;
3952 Grab.Area.Y = attributes.y;
3953 Grab.Area.Width = attributes.width;
3954 Grab.Area.Height = attributes.height;
3955 Grab.Confined = true;
3956 confine_to_window = hwnd.client_window;
3961 hwnd = Hwnd.ObjectFromHandle(handle);
3964 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3965 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3966 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3967 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3971 internal override void UngrabWindow(IntPtr hwnd) {
3973 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3974 XFlush(DisplayHandle);
3976 Grab.Hwnd = IntPtr.Zero;
3977 Grab.Confined = false;
3980 internal override void HandleException(Exception e) {
3981 StackTrace st = new StackTrace(e, true);
3982 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3983 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3986 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3989 hwnd = Hwnd.ObjectFromHandle(handle);
3992 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3994 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3998 internal override void InvalidateNC (IntPtr handle) {
4001 hwnd = Hwnd.ObjectFromHandle(handle);
4003 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4006 internal override bool IsEnabled(IntPtr handle) {
4007 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4008 return (hwnd != null && hwnd.Enabled);
4011 internal override bool IsVisible(IntPtr handle) {
4012 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4013 return (hwnd != null && hwnd.visible);
4016 internal override void KillTimer(Timer timer) {
4017 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4019 if (queue == null) {
4020 // This isn't really an error, MS doesn't start the timer if
4021 // it has no assosciated queue
4024 queue.timer_list.Remove (timer);
4027 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4033 hwnd = Hwnd.ObjectFromHandle(handle);
4036 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4043 internal override void OverrideCursor(IntPtr cursor) {
4044 OverrideCursorHandle = cursor;
4047 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4048 PaintEventArgs paint_event;
4051 hwnd = Hwnd.ObjectFromHandle(handle);
4053 if (Caret.Visible == true) {
4054 Caret.Paused = true;
4061 dc = Graphics.FromHwnd (hwnd.client_window);
4063 Region clip_region = new Region ();
4064 clip_region.MakeEmpty();
4066 foreach (Rectangle r in hwnd.ClipRectangles) {
4067 clip_region.Union (r);
4070 if (hwnd.UserClip != null) {
4071 clip_region.Intersect(hwnd.UserClip);
4074 dc.Clip = clip_region;
4075 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4076 hwnd.expose_pending = false;
4078 hwnd.ClearInvalidArea();
4080 hwnd.drawing_stack.Push (paint_event);
4081 hwnd.drawing_stack.Push (dc);
4085 dc = Graphics.FromHwnd (hwnd.whole_window);
4087 if (!hwnd.nc_invalid.IsEmpty) {
4088 dc.SetClip (hwnd.nc_invalid);
4089 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4091 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4093 hwnd.nc_expose_pending = false;
4095 hwnd.ClearNcInvalidArea ();
4097 hwnd.drawing_stack.Push (paint_event);
4098 hwnd.drawing_stack.Push (dc);
4104 internal override void PaintEventEnd(IntPtr handle, bool client) {
4107 hwnd = Hwnd.ObjectFromHandle(handle);
4109 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4113 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4114 pe.SetGraphics (null);
4117 if (Caret.Visible == true) {
4119 Caret.Paused = false;
4123 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4124 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4125 XEventQueue queue = (XEventQueue) queue_id;
4128 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4129 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4133 if (queue.Count > 0) {
4136 // Only call UpdateMessageQueue if real events are pending
4137 // otherwise we go to sleep on the socket
4138 if (XPending(DisplayHandle) != 0) {
4139 UpdateMessageQueue((XEventQueue)queue_id);
4141 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4146 CheckTimers(queue.timer_list, DateTime.UtcNow);
4151 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4154 // FIXME - I think this should just enqueue directly
4155 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4156 XEvent xevent = new XEvent ();
4157 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4159 xevent.type = XEventName.ClientMessage;
4160 xevent.ClientMessageEvent.display = DisplayHandle;
4163 xevent.ClientMessageEvent.window = hwnd.whole_window;
4165 xevent.ClientMessageEvent.window = IntPtr.Zero;
4168 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4169 xevent.ClientMessageEvent.format = 32;
4170 xevent.ClientMessageEvent.ptr1 = handle;
4171 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4172 xevent.ClientMessageEvent.ptr3 = wparam;
4173 xevent.ClientMessageEvent.ptr4 = lparam;
4175 hwnd.Queue.EnqueueLocked (xevent);
4180 internal override void PostQuitMessage(int exitCode) {
4182 XFlush(DisplayHandle);
4183 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4186 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4191 internal override void RequestNCRecalc(IntPtr handle) {
4194 hwnd = Hwnd.ObjectFromHandle(handle);
4200 PerformNCCalc(hwnd);
4201 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4202 InvalidateNC(handle);
4205 internal override void ResetMouseHover(IntPtr handle) {
4208 hwnd = Hwnd.ObjectFromHandle(handle);
4213 HoverState.Timer.Enabled = true;
4214 HoverState.X = mouse_position.X;
4215 HoverState.Y = mouse_position.Y;
4216 HoverState.Window = handle;
4220 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4226 hwnd = Hwnd.ObjectFromHandle(handle);
4229 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4236 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4242 hwnd = Hwnd.ObjectFromHandle(handle);
4245 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4252 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4255 XGCValues gc_values;
4257 hwnd = Hwnd.ObjectFromHandle(handle);
4259 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4261 /* We have an invalid area in the window we're scrolling.
4262 Adjust our stored invalid rectangle to to match the scrolled amount */
4277 if (area.Contains (hwnd.Invalid))
4278 hwnd.ClearInvalidArea ();
4279 hwnd.AddInvalidArea(r);
4282 gc_values = new XGCValues();
4284 if (with_children) {
4285 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4288 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4296 height = area.Height - YAmount;
4297 dest_y = area.Y + YAmount;
4300 src_y = area.Y - YAmount;
4301 height = area.Height + YAmount;
4307 width = area.Width - XAmount;
4308 dest_x = area.X + XAmount;
4311 src_x = area.X - XAmount;
4312 width = area.Width + XAmount;
4316 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4318 // Generate an expose for the area exposed by the horizontal scroll
4319 // We don't use AddExpose since we're
4321 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4322 } else if (XAmount < 0) {
4323 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4326 // Generate an expose for the area exposed by the vertical scroll
4328 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4329 } else if (YAmount < 0) {
4330 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4332 XFreeGC(DisplayHandle, gc);
4335 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4339 hwnd = Hwnd.GetObjectFromWindow(handle);
4341 rect = hwnd.ClientRect;
4344 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4347 internal override void SendAsyncMethod (AsyncMethodData method) {
4349 XEvent xevent = new XEvent ();
4351 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4353 xevent.type = XEventName.ClientMessage;
4354 xevent.ClientMessageEvent.display = DisplayHandle;
4355 xevent.ClientMessageEvent.window = method.Handle;
4356 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4357 xevent.ClientMessageEvent.format = 32;
4358 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4360 hwnd.Queue.EnqueueLocked (xevent);
4365 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4367 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4370 h = Hwnd.ObjectFromHandle(hwnd);
4372 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4373 AsyncMethodResult result;
4374 AsyncMethodData data;
4376 result = new AsyncMethodResult ();
4377 data = new AsyncMethodData ();
4380 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4381 data.Args = new object[] { hwnd, message, wParam, lParam };
4382 data.Result = result;
4384 SendAsyncMethod (data);
4385 #if DriverDebug || DriverDebugThreads
4386 Console.WriteLine ("Sending {0} message across.", message);
4391 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4394 internal override void SetAllowDrop (IntPtr handle, bool value)
4396 // We allow drop on all windows
4399 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4400 DragDropEffects allowed_effects)
4402 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4405 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4407 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4410 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4413 hwnd = Hwnd.ObjectFromHandle(handle);
4415 Form form = Control.FromHandle (handle) as Form;
4416 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4417 border_style == FormBorderStyle.SizableToolWindow)) {
4418 form.window_manager = new InternalWindowManager (form);
4421 hwnd.border_style = border_style;
4422 RequestNCRecalc(handle);
4425 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4426 if (Caret.Hwnd == handle) {
4433 if (Caret.Visible == true) {
4435 Caret.Timer.Start();
4440 internal override void SetClipRegion(IntPtr handle, Region region) {
4443 hwnd = Hwnd.ObjectFromHandle(handle);
4448 hwnd.UserClip = region;
4449 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4452 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4455 if (OverrideCursorHandle == IntPtr.Zero) {
4456 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4460 LastCursorHandle = cursor;
4461 LastCursorWindow = handle;
4463 hwnd = Hwnd.ObjectFromHandle(handle);
4465 if (cursor != IntPtr.Zero) {
4466 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4468 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4470 XFlush(DisplayHandle);
4475 hwnd = Hwnd.ObjectFromHandle(handle);
4477 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4481 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4482 out int root_x, out int root_y, out int child_x, out int child_y,
4485 /* this code was written with the help of
4486 glance at gdk. I never would have realized we
4487 needed a loop in order to traverse down in the
4488 hierarchy. I would have assumed you'd get the
4489 most deeply nested child and have to do
4490 XQueryTree to move back up the hierarchy..
4491 stupid me, of course. */
4494 XGrabServer (display);
4496 XQueryPointer(display, w, out root, out c,
4497 out root_x, out root_y, out child_x, out child_y,
4503 IntPtr child_last = IntPtr.Zero;
4504 while (c != IntPtr.Zero) {
4506 XQueryPointer(display, c, out root, out c,
4507 out root_x, out root_y, out child_x, out child_y,
4510 XUngrabServer (display);
4515 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4516 if (handle == IntPtr.Zero) {
4519 int root_x, root_y, child_x, child_y, mask;
4522 * QueryPointer before warping
4523 * because if the warp is on
4524 * the RootWindow, the x/y are
4525 * relative to the current
4528 QueryPointer (DisplayHandle, RootWindow,
4531 out root_x, out root_y,
4532 out child_x, out child_y,
4535 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4537 XFlush (DisplayHandle);
4539 /* then we need to a
4540 * QueryPointer after warping
4541 * to manually generate a
4542 * motion event for the window
4545 QueryPointer (DisplayHandle, RootWindow,
4548 out root_x, out root_y,
4549 out child_x, out child_y,
4552 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4553 if (child_hwnd == null) {
4557 XEvent xevent = new XEvent ();
4559 xevent.type = XEventName.MotionNotify;
4560 xevent.MotionEvent.display = DisplayHandle;
4561 xevent.MotionEvent.window = child_hwnd.client_window;
4562 xevent.MotionEvent.root = RootWindow;
4563 xevent.MotionEvent.x = child_x;
4564 xevent.MotionEvent.y = child_y;
4565 xevent.MotionEvent.x_root = root_x;
4566 xevent.MotionEvent.y_root = root_y;
4567 xevent.MotionEvent.state = mask;
4569 child_hwnd.Queue.EnqueueLocked (xevent);
4574 hwnd = Hwnd.ObjectFromHandle(handle);
4576 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4581 internal override void SetFocus(IntPtr handle) {
4583 IntPtr prev_focus_window;
4585 hwnd = Hwnd.ObjectFromHandle(handle);
4587 if (hwnd.client_window == FocusWindow) {
4591 prev_focus_window = FocusWindow;
4592 FocusWindow = hwnd.client_window;
4594 if (prev_focus_window != IntPtr.Zero) {
4595 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4597 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4599 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4602 internal override void SetIcon(IntPtr handle, Icon icon) {
4605 hwnd = Hwnd.ObjectFromHandle(handle);
4607 SetIcon(hwnd, icon);
4611 internal override void SetMenu(IntPtr handle, Menu menu) {
4614 hwnd = Hwnd.ObjectFromHandle(handle);
4617 RequestNCRecalc(handle);
4620 internal override void SetModal(IntPtr handle, bool Modal) {
4622 ModalWindows.Push(handle);
4624 if (ModalWindows.Contains(handle)) {
4627 if (ModalWindows.Count > 0) {
4628 Activate((IntPtr)ModalWindows.Peek());
4633 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4636 hwnd = Hwnd.ObjectFromHandle(handle);
4637 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4640 #if DriverDebug || DriverDebugParent
4641 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4643 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4649 internal override void SetTimer (Timer timer) {
4650 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4652 if (queue == null) {
4653 // This isn't really an error, MS doesn't start the timer if
4654 // it has no assosciated queue
4657 queue.timer_list.Add (timer);
4661 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4665 hwnd = Hwnd.ObjectFromHandle(handle);
4667 if (handle_owner != IntPtr.Zero) {
4668 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4679 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4680 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4682 if (hwnd_owner != null) {
4683 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4685 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4690 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4696 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4699 hwnd = Hwnd.ObjectFromHandle(handle);
4700 hwnd.visible = visible;
4704 if (Control.FromHandle(handle) is Form) {
4707 s = ((Form)Control.FromHandle(handle)).WindowState;
4709 MapWindow(hwnd, WindowType.Both);
4712 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4713 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4717 MapWindow(hwnd, WindowType.Both);
4719 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4721 UnmapWindow(hwnd, WindowType.Whole);
4727 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4732 hwnd = Hwnd.ObjectFromHandle(handle);
4737 hints = new XSizeHints();
4739 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4740 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4741 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4742 hints.min_width = min.Width;
4743 hints.min_height = min.Height;
4746 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4747 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4748 hints.max_width = max.Width;
4749 hints.max_height = max.Height;
4752 if (hints.flags != IntPtr.Zero) {
4753 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4756 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4757 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4758 hints.x = maximized.X;
4759 hints.y = maximized.Y;
4760 hints.width = maximized.Width;
4761 hints.height = maximized.Height;
4763 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4764 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4769 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4772 hwnd = Hwnd.ObjectFromHandle(handle);
4778 // Win32 automatically changes negative width/height to 0.
4784 // X requires a sanity check for width & height; otherwise it dies
4785 if (hwnd.zero_sized && width > 0 && height > 0) {
4787 MapWindow(hwnd, WindowType.Whole);
4789 hwnd.zero_sized = false;
4792 if ((width < 1) || (height < 1)) {
4793 hwnd.zero_sized = true;
4794 UnmapWindow(hwnd, WindowType.Whole);
4797 // Save a server roundtrip (and prevent a feedback loop)
4798 if ((hwnd.x == x) && (hwnd.y == y) &&
4799 (hwnd.width == width) && (hwnd.height == height)) {
4803 if (!hwnd.zero_sized) {
4808 hwnd.height = height;
4809 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4811 if (hwnd.fixed_size) {
4812 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4816 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4817 PerformNCCalc(hwnd);
4821 // Update our position/size immediately, so
4822 // that future calls to SetWindowPos aren't
4823 // kept from calling XMoveResizeWindow (by the
4824 // "Save a server roundtrip" block above).
4828 hwnd.height = height;
4829 hwnd.ClientRect = Rectangle.Empty;
4832 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4833 FormWindowState current_state;
4836 hwnd = Hwnd.ObjectFromHandle(handle);
4838 current_state = GetWindowState(handle);
4840 if (current_state == state) {
4845 case FormWindowState.Normal: {
4847 if (current_state == FormWindowState.Minimized) {
4848 MapWindow(hwnd, WindowType.Both);
4849 } else if (current_state == FormWindowState.Maximized) {
4850 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4857 case FormWindowState.Minimized: {
4859 if (current_state == FormWindowState.Maximized) {
4860 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4862 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4867 case FormWindowState.Maximized: {
4869 if (current_state == FormWindowState.Minimized) {
4870 MapWindow(hwnd, WindowType.Both);
4873 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4881 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4884 hwnd = Hwnd.ObjectFromHandle(handle);
4885 SetHwndStyles(hwnd, cp);
4886 SetWMStyles(hwnd, cp);
4889 internal override double GetWindowTransparency(IntPtr handle)
4894 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4898 hwnd = Hwnd.ObjectFromHandle(handle);
4904 hwnd.opacity = (uint)(0xffffffff * transparency);
4905 opacity = (IntPtr)((int)hwnd.opacity);
4907 IntPtr w = hwnd.whole_window;
4908 if (hwnd.reparented)
4909 w = XGetParent (hwnd.whole_window);
4910 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4913 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4914 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4922 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4925 } else if (!bottom) {
4926 Hwnd after_hwnd = null;
4928 if (after_handle != IntPtr.Zero) {
4929 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4932 XWindowChanges values = new XWindowChanges();
4934 if (after_hwnd == null) {
4935 // Work around metacity 'issues'
4939 atoms[0] = unixtime();
4940 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4942 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4943 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4945 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4948 values.sibling = after_hwnd.whole_window;
4949 values.stack_mode = StackMode.Below;
4952 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4957 XLowerWindow(DisplayHandle, hwnd.whole_window);
4964 internal override void ShowCursor(bool show) {
4965 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4968 internal override object StartLoop(Thread thread) {
4969 return (Object) ThreadQueue(thread);
4972 internal override TransparencySupport SupportsTransparency() {
4973 // We need to check if the x compositing manager is running
4974 return TransparencySupport.Set;
4977 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4978 GetSystrayManagerWindow();
4980 if (SystrayMgrWindow != IntPtr.Zero) {
4981 XSizeHints size_hints;
4984 hwnd = Hwnd.ObjectFromHandle(handle);
4986 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4990 if (hwnd.client_window != hwnd.whole_window) {
4991 XDestroyWindow(DisplayHandle, hwnd.client_window);
4992 hwnd.client_window = hwnd.whole_window;
4994 /* by virtue of the way the tests are ordered when determining if it's PAINT
4995 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
4996 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4997 there's a pending expose). */
4998 if (hwnd.nc_expose_pending) {
4999 hwnd.nc_expose_pending = false;
5000 if (!hwnd.expose_pending)
5001 hwnd.Queue.Paint.Remove (hwnd);
5005 size_hints = new XSizeHints();
5007 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5009 size_hints.min_width = 24;
5010 size_hints.min_height = 24;
5011 size_hints.max_width = 24;
5012 size_hints.max_height = 24;
5013 size_hints.base_width = 24;
5014 size_hints.base_height = 24;
5016 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5018 int[] atoms = new int[2];
5019 atoms [0] = 1; // Version 1
5020 atoms [1] = 1; // we want to be mapped
5022 // This line cost me 3 days...
5023 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5025 // Need to pick some reasonable defaults
5027 tt.AutomaticDelay = 100;
5028 tt.InitialDelay = 250;
5029 tt.ReshowDelay = 250;
5030 tt.ShowAlways = true;
5032 if ((tip != null) && (tip != string.Empty)) {
5033 tt.SetToolTip(Control.FromHandle(handle), tip);
5039 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5047 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5050 control = Control.FromHandle(handle);
5051 if (control != null && tt != null) {
5052 tt.SetToolTip(control, tip);
5060 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5062 #if GTKSOCKET_SUPPORTS_REPARENTING
5065 hwnd = Hwnd.ObjectFromHandle(handle);
5067 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5068 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5069 * 2. The client can reparent its window out of the embedder window.
5070 * 3. The client can destroy its window.
5072 * this call to SetParent is case 2, but in
5073 * the spec it also mentions that gtk doesn't
5074 * support this at present. Looking at HEAD
5075 * gtksocket-x11.c jives with this statement.
5077 * so we can't reparent. we have to destroy.
5079 SetParent(hwnd.whole_window, FosterParent);
5081 Control control = Control.FromHandle(handle);
5082 if (control is NotifyIcon.NotifyIconWindow)
5083 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5086 // The caller can now re-dock it later...
5093 internal override bool Text(IntPtr handle, string text) {
5096 hwnd = Hwnd.ObjectFromHandle(handle);
5099 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5100 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5102 // XXX this has problems with UTF8.
5103 // we need to either use the actual
5104 // text if it's latin-1, or convert it
5105 // to compound text if it's in a
5106 // different charset.
5107 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5112 internal override bool TranslateMessage(ref MSG msg) {
5113 return Keyboard.TranslateMessage (ref msg);
5116 internal override void UpdateWindow(IntPtr handle) {
5119 hwnd = Hwnd.ObjectFromHandle(handle);
5121 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5125 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5126 hwnd.Queue.Paint.Remove(hwnd);
5129 internal override void CreateOffscreenDrawable (IntPtr handle,
5130 int width, int height,
5131 out object offscreen_drawable,
5132 out Graphics offscreen_dc)
5135 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5137 XGetGeometry (DisplayHandle, handle,
5139 out x_out, out y_out,
5140 out width_out, out height_out,
5141 out border_width_out, out depth_out);
5143 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5145 offscreen_drawable = pixmap;
5147 offscreen_dc = Graphics.FromHwnd (pixmap);
5150 internal override void DestroyOffscreenDrawable (object offscreen_drawable,
5151 Graphics offscreen_dc)
5153 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5154 offscreen_dc.Dispose ();
5157 internal override void BlitFromOffscreen (IntPtr dest_handle,
5159 object offscreen_drawable,
5160 Graphics offscreen_dc,
5163 XGCValues gc_values;
5166 gc_values = new XGCValues();
5168 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5170 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5171 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5173 XFreeGC (DisplayHandle, gc);
5176 #endregion // Public Static Methods
5179 internal override event EventHandler Idle;
5180 #endregion // Events
5183 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5184 internal extern static IntPtr XOpenDisplay(IntPtr display);
5185 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5186 internal extern static int XCloseDisplay(IntPtr display);
5187 [DllImport ("libX11", EntryPoint="XSynchronize")]
5188 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5190 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5191 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);
5192 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5193 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5194 [DllImport ("libX11", EntryPoint="XMapWindow")]
5195 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5196 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5197 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5198 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5199 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5200 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5201 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5202 [DllImport ("libX11", EntryPoint="XRootWindow")]
5203 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5204 [DllImport ("libX11", EntryPoint="XNextEvent")]
5205 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5206 [DllImport ("libX11")]
5207 internal extern static int XConnectionNumber (IntPtr diplay);
5208 [DllImport ("libX11")]
5209 internal extern static int XPending (IntPtr diplay);
5210 [DllImport ("libX11", EntryPoint="XSelectInput")]
5211 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5213 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5214 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5216 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5217 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5218 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5219 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5221 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5222 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5224 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5225 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5227 [DllImport ("libX11", EntryPoint="XFlush")]
5228 internal extern static int XFlush(IntPtr display);
5230 [DllImport ("libX11", EntryPoint="XSetWMName")]
5231 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5233 [DllImport ("libX11", EntryPoint="XStoreName")]
5234 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5236 [DllImport ("libX11", EntryPoint="XFetchName")]
5237 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5239 [DllImport ("libX11", EntryPoint="XSendEvent")]
5240 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5242 [DllImport ("libX11", EntryPoint="XQueryTree")]
5243 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);
5245 [DllImport ("libX11", EntryPoint="XFree")]
5246 internal extern static int XFree(IntPtr data);
5248 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5249 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5251 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5252 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5254 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5255 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5257 [DllImport ("libX11", EntryPoint="XInternAtom")]
5258 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5260 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5261 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5263 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5264 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5266 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5267 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);
5269 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5270 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5272 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5273 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);
5275 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5276 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);
5278 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5279 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);
5281 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5282 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);
5284 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5285 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);
5287 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5288 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);
5290 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5291 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);
5293 [DllImport ("libX11", EntryPoint="XClearWindow")]
5294 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5296 [DllImport ("libX11", EntryPoint="XClearArea")]
5297 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5300 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5301 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5303 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5304 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5306 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5307 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5309 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5310 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5312 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5313 internal extern static int XDefaultScreen(IntPtr display);
5315 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5316 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5318 [DllImport ("libX11", EntryPoint="XLookupColor")]
5319 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5321 [DllImport ("libX11", EntryPoint="XAllocColor")]
5322 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5324 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5325 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5327 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5328 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5330 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5331 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5333 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5334 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5336 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5337 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5339 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5340 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5342 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5343 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5345 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5346 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5348 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5349 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5351 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5352 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5354 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5355 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5358 [DllImport ("libX11", EntryPoint="XCreateGC")]
5359 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5361 [DllImport ("libX11", EntryPoint="XFreeGC")]
5362 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5364 [DllImport ("libX11", EntryPoint="XSetFunction")]
5365 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5367 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
5368 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
5370 [DllImport ("libX11", EntryPoint="XDrawLine")]
5371 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5373 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5374 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5376 [DllImport ("libX11", EntryPoint="XFillRectangle")]
5377 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5379 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5380 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5382 [DllImport ("libX11", EntryPoint="XCopyArea")]
5383 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);
5385 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5386 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);
5388 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5389 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5391 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5392 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5394 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5395 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5397 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5398 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5400 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5401 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5403 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5404 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5406 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5407 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);
5409 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5410 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5412 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5413 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5415 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5416 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5418 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5419 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5421 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5422 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5424 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5425 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5427 [DllImport ("libX11", EntryPoint="XGrabServer")]
5428 internal extern static void XGrabServer(IntPtr display);
5430 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5431 internal extern static void XUngrabServer(IntPtr display);
5433 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5434 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5436 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5437 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5439 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5440 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5442 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5443 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5445 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5446 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5448 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5449 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5451 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5452 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5454 [DllImport ("libX11", EntryPoint="XInitThreads")]
5455 internal extern static int XInitThreads();
5457 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5458 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5460 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5461 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5463 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5464 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5466 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5467 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5469 [DllImport ("libX11", EntryPoint="XSetForeground")]
5470 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5472 [DllImport ("libX11", EntryPoint="XSetBackground")]
5473 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5475 [DllImport ("libX11", EntryPoint="XBell")]
5476 internal extern static int XBell(IntPtr display, int percent);
5478 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5479 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5481 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5482 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5484 [DllImport ("libX11")]
5485 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5487 [DllImport ("libX11")]
5488 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);