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
50 using System.ComponentModel;
51 using System.Collections;
52 using System.Diagnostics;
54 using System.Drawing.Drawing2D;
55 using System.Drawing.Imaging;
58 using System.Net.Sockets;
59 using System.Reflection;
60 using System.Runtime.InteropServices;
62 using System.Threading;
64 // Only do the poll when building with mono for now
66 using Mono.Unix.Native;
70 namespace System.Windows.Forms {
71 internal class XplatUIX11 : XplatUIDriver {
72 #region Local Variables
74 static volatile XplatUIX11 Instance;
75 private static int RefCount;
76 private static object XlibLock; // Our locking object
77 private static bool themes_enabled;
80 private static IntPtr DisplayHandle; // X11 handle to display
81 private static int ScreenNo; // Screen number used
82 private static IntPtr DefaultColormap; // Colormap for screen
83 private static IntPtr CustomVisual; // Visual for window creation
84 private static IntPtr CustomColormap; // Colormap for window creation
85 private static IntPtr RootWindow; // Handle of the root window for the screen/display
86 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
87 private static XErrorHandler ErrorHandler; // Error handler delegate
88 private static bool ErrorExceptions; // Throw exceptions on X errors
91 private static IntPtr ClipMagic;
92 private static ClipboardStruct Clipboard; // Our clipboard
95 private static IntPtr PostAtom; // PostMessage atom
96 private static IntPtr AsyncAtom; // Support for async messages
99 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
101 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static X11Keyboard Keyboard; //
104 private static X11Dnd Dnd;
105 private static Socket listen; //
106 private static Socket wake; //
107 private static Socket wake_receive; //
108 private static byte[] network_buffer; //
109 private static bool detectable_key_auto_repeat;
112 private static IntPtr ActiveWindow; // Handle of the active window
113 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
116 private static Stack ModalWindows; // Stack of our modal windows
119 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
122 private static IntPtr LastCursorWindow; // The last window we set the cursor on
123 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
124 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
127 private static CaretStruct Caret; //
130 private static IntPtr WM_PROTOCOLS;
131 private static IntPtr WM_DELETE_WINDOW;
132 private static IntPtr WM_TAKE_FOCUS;
133 private static IntPtr _NET_SUPPORTED;
134 private static IntPtr _NET_CLIENT_LIST;
135 private static IntPtr _NET_NUMBER_OF_DESKTOPS;
136 private static IntPtr _NET_DESKTOP_GEOMETRY;
137 private static IntPtr _NET_DESKTOP_VIEWPORT;
138 private static IntPtr _NET_CURRENT_DESKTOP;
139 private static IntPtr _NET_DESKTOP_NAMES;
140 private static IntPtr _NET_ACTIVE_WINDOW;
141 private static IntPtr _NET_WORKAREA;
142 private static IntPtr _NET_SUPPORTING_WM_CHECK;
143 private static IntPtr _NET_VIRTUAL_ROOTS;
144 private static IntPtr _NET_DESKTOP_LAYOUT;
145 private static IntPtr _NET_SHOWING_DESKTOP;
146 private static IntPtr _NET_CLOSE_WINDOW;
147 private static IntPtr _NET_MOVERESIZE_WINDOW;
148 private static IntPtr _NET_WM_MOVERESIZE;
149 private static IntPtr _NET_RESTACK_WINDOW;
150 private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
151 private static IntPtr _NET_WM_NAME;
152 private static IntPtr _NET_WM_VISIBLE_NAME;
153 private static IntPtr _NET_WM_ICON_NAME;
154 private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
155 private static IntPtr _NET_WM_DESKTOP;
156 private static IntPtr _NET_WM_WINDOW_TYPE;
157 private static IntPtr _NET_WM_STATE;
158 private static IntPtr _NET_WM_ALLOWED_ACTIONS;
159 private static IntPtr _NET_WM_STRUT;
160 private static IntPtr _NET_WM_STRUT_PARTIAL;
161 private static IntPtr _NET_WM_ICON_GEOMETRY;
162 private static IntPtr _NET_WM_ICON;
163 private static IntPtr _NET_WM_PID;
164 private static IntPtr _NET_WM_HANDLED_ICONS;
165 private static IntPtr _NET_WM_USER_TIME;
166 private static IntPtr _NET_FRAME_EXTENTS;
167 private static IntPtr _NET_WM_PING;
168 private static IntPtr _NET_WM_SYNC_REQUEST;
169 private static IntPtr _NET_SYSTEM_TRAY_S;
170 private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
171 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
172 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
173 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
174 private static IntPtr _XEMBED;
175 private static IntPtr _XEMBED_INFO;
176 private static IntPtr _MOTIF_WM_HINTS;
177 private static IntPtr _NET_WM_STATE_NO_TASKBAR;
178 private static IntPtr _NET_WM_STATE_ABOVE;
179 private static IntPtr _NET_WM_STATE_MODAL;
180 private static IntPtr _NET_WM_STATE_HIDDEN;
181 private static IntPtr _NET_WM_CONTEXT_HELP;
182 private static IntPtr _NET_WM_WINDOW_OPACITY;
183 private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
184 private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
185 private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
186 private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
187 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
188 private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
189 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
190 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
191 private static IntPtr CLIPBOARD;
192 private static IntPtr PRIMARY;
193 private static IntPtr DIB;
194 private static IntPtr OEMTEXT;
195 private static IntPtr UNICODETEXT;
196 private static IntPtr TARGETS;
198 // mouse hover message generation
199 private static HoverStruct HoverState; //
201 // double click message generation
202 private static ClickStruct ClickPending; //
204 // Support for mouse grab
205 private static GrabStruct Grab; //
208 private static Point MousePosition; // Last position of mouse, in screen coords
209 internal static MouseButtons MouseState; // Last state of mouse buttons
212 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
214 const EventMask SelectInputMask = EventMask.ButtonPressMask |
215 EventMask.ButtonReleaseMask |
216 EventMask.KeyPressMask |
217 EventMask.KeyReleaseMask |
218 EventMask.EnterWindowMask |
219 EventMask.LeaveWindowMask |
220 EventMask.ExposureMask |
221 EventMask.FocusChangeMask |
222 EventMask.PointerMotionMask |
223 EventMask.VisibilityChangeMask |
224 EventMask.SubstructureNotifyMask |
225 EventMask.StructureNotifyMask;
227 static readonly object lockobj = new object ();
229 #endregion // Local Variables
231 private XplatUIX11() {
232 // Handle singleton stuff first
235 // Now regular initialization
236 XlibLock = new object ();
237 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
240 ErrorExceptions = false;
242 // X11 Initialization
243 SetDisplay(XOpenDisplay(IntPtr.Zero));
244 X11DesktopColors.Initialize();
247 // Disable keyboard autorepeat
249 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
250 detectable_key_auto_repeat = true;
252 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
253 detectable_key_auto_repeat = false;
256 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
257 ErrorHandler = new XErrorHandler(HandleError);
258 XSetErrorHandler(ErrorHandler);
262 // Remove our display handle from S.D
263 Graphics.FromHdcInternal (IntPtr.Zero);
266 #endregion // Constructors
268 #region Singleton Specific Code
269 public static XplatUIX11 GetInstance() {
271 if (Instance == null) {
272 Instance=new XplatUIX11();
279 public int Reference {
286 #region Internal Properties
287 internal static IntPtr Display {
289 return DisplayHandle;
293 XplatUIX11.GetInstance().SetDisplay(value);
297 internal static int Screen {
307 internal static IntPtr RootWindowHandle {
317 internal static IntPtr Visual {
323 CustomVisual = value;
327 internal static IntPtr ColorMap {
329 return CustomColormap;
333 CustomColormap = value;
338 #region XExceptionClass
339 internal class XException : ApplicationException {
343 XRequest RequestCode;
347 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
348 this.Display = Display;
349 this.ResourceID = ResourceID;
350 this.Serial = Serial;
351 this.RequestCode = RequestCode;
352 this.ErrorCode = ErrorCode;
353 this.MinorCode = MinorCode;
356 public override string Message {
358 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
362 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
371 sb = new StringBuilder(160);
372 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
373 x_error_text = sb.ToString();
374 hwnd = Hwnd.ObjectFromHandle(ResourceID);
376 hwnd_text = hwnd.ToString();
377 c = Control.FromHandle(hwnd.Handle);
379 control_text = c.ToString();
381 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
384 hwnd_text = "<null>";
385 control_text = "<null>";
389 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);
393 #endregion // XExceptionClass
395 #region Internal Methods
396 internal void SetDisplay(IntPtr display_handle) {
397 if (display_handle != IntPtr.Zero) {
400 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
401 hwnd = Hwnd.ObjectFromHandle(FosterParent);
402 XDestroyWindow(DisplayHandle, FosterParent);
406 if (DisplayHandle != IntPtr.Zero) {
407 XCloseDisplay(DisplayHandle);
410 DisplayHandle=display_handle;
412 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
413 // been hacked to do this for us.
414 Graphics.FromHdcInternal (DisplayHandle);
417 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
418 XSynchronize(DisplayHandle, true);
421 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
422 ErrorExceptions = true;
426 ScreenNo = XDefaultScreen(DisplayHandle);
427 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
428 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
430 // Create the foster parent
431 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
432 if (FosterParent==IntPtr.Zero) {
433 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
437 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
438 hwnd.WholeWindow = FosterParent;
439 hwnd.ClientWindow = FosterParent;
441 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
443 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
444 hwnd.whole_window = RootWindow;
445 hwnd.ClientWindow = RootWindow;
447 // For sleeping on the X11 socket
448 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
449 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
453 // To wake up when a timer is ready
454 network_buffer = new byte[10];
456 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
457 wake.Connect(listen.LocalEndPoint);
458 wake_receive = listen.Accept();
461 pollfds = new Pollfd [2];
462 pollfds [0] = new Pollfd ();
463 pollfds [0].fd = XConnectionNumber (DisplayHandle);
464 pollfds [0].events = PollEvents.POLLIN;
466 pollfds [1] = new Pollfd ();
467 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
468 pollfds [1].events = PollEvents.POLLIN;
471 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
472 Dnd = new X11Dnd (DisplayHandle);
474 DoubleClickInterval = 500;
476 HoverState.Interval = 500;
477 HoverState.Timer = new Timer();
478 HoverState.Timer.Enabled = false;
479 HoverState.Timer.Interval = HoverState.Interval;
480 HoverState.Timer.Tick += new EventHandler(MouseHover);
481 HoverState.Size = new Size(4, 4);
485 ActiveWindow = IntPtr.Zero;
486 FocusWindow = IntPtr.Zero;
487 ModalWindows = new Stack(3);
489 MouseState = MouseButtons.None;
490 MousePosition = new Point(0, 0);
492 Caret.Timer = new Timer();
493 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
494 Caret.Timer.Tick += new EventHandler(CaretCallback);
498 // Grab atom changes off the root window to catch certain WM events
499 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
501 // Handle any upcoming errors
502 ErrorHandler = new XErrorHandler(HandleError);
503 XSetErrorHandler(ErrorHandler);
505 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
509 internal static void Where() {
510 Console.WriteLine("Here: {0}\n", WhereString());
513 internal static string WhereString() {
521 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
522 unknown = Locale.GetText("<unknown method>");
523 sb = new StringBuilder();
524 stack = new StackTrace(true);
526 for (int i = 0; i < stack.FrameCount; i++) {
527 frame = stack.GetFrame(i);
530 method = frame.GetMethod();
531 if (method != null) {
533 sb.AppendFormat(frame.ToString());
535 if (frame.GetFileLineNumber() != 0) {
536 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
538 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
544 return sb.ToString();
546 #endregion // Internal Methods
548 #region Private Methods
549 private int unixtime() {
550 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
552 return (int) t.TotalSeconds;
555 private static void SetupAtoms() {
556 WM_PROTOCOLS = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
557 WM_DELETE_WINDOW = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
558 WM_TAKE_FOCUS = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
560 _NET_SUPPORTED = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
561 _NET_CLIENT_LIST = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
562 _NET_NUMBER_OF_DESKTOPS = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
563 _NET_DESKTOP_GEOMETRY = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
564 _NET_DESKTOP_VIEWPORT = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
565 _NET_CURRENT_DESKTOP = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
566 _NET_DESKTOP_NAMES = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
567 _NET_ACTIVE_WINDOW = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
568 _NET_WORKAREA = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
569 _NET_SUPPORTING_WM_CHECK = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
570 _NET_VIRTUAL_ROOTS = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
571 _NET_DESKTOP_LAYOUT = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
572 _NET_SHOWING_DESKTOP = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
574 _NET_CLOSE_WINDOW = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
575 _NET_MOVERESIZE_WINDOW = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
576 _NET_WM_MOVERESIZE = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
577 _NET_RESTACK_WINDOW = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
578 _NET_REQUEST_FRAME_EXTENTS = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
580 _NET_WM_NAME = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
581 _NET_WM_VISIBLE_NAME = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
582 _NET_WM_ICON_NAME = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
583 _NET_WM_VISIBLE_ICON_NAME = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
584 _NET_WM_DESKTOP = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
585 _NET_WM_WINDOW_TYPE = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
586 _NET_WM_STATE = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
587 _NET_WM_ALLOWED_ACTIONS = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
588 _NET_WM_STRUT = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
589 _NET_WM_STRUT_PARTIAL = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
590 _NET_WM_ICON_GEOMETRY = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
591 _NET_WM_ICON = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
592 _NET_WM_PID = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
593 _NET_WM_HANDLED_ICONS = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
594 _NET_WM_USER_TIME = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
595 _NET_FRAME_EXTENTS = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
597 _NET_WM_PING = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
598 _NET_WM_SYNC_REQUEST = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
600 _NET_SYSTEM_TRAY_S = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
601 _NET_SYSTEM_TRAY_OPCODE = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
602 _NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
604 _NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
605 _NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
606 _NET_WM_STATE_HIDDEN = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
608 _XEMBED = XInternAtom(DisplayHandle, "_XEMBED", false);
609 _XEMBED_INFO = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
611 _MOTIF_WM_HINTS = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
613 _NET_WM_STATE_NO_TASKBAR = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
614 _NET_WM_STATE_ABOVE = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
615 _NET_WM_STATE_MODAL = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
616 _NET_WM_CONTEXT_HELP = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
617 _NET_WM_WINDOW_OPACITY = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
619 _NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DESKTOP", false);
620 _NET_WM_WINDOW_TYPE_DOCK = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DOCK", false);
621 _NET_WM_WINDOW_TYPE_TOOLBAR = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_TOOLBAR", false);
622 _NET_WM_WINDOW_TYPE_MENU = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_MENU", false);
623 _NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_UTILITY", false);
624 _NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DIALOG", false);
625 _NET_WM_WINDOW_TYPE_SPLASH = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_SPLASH", false);
626 _NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_NORMAL", false);
629 CLIPBOARD = XInternAtom (DisplayHandle, "CLIPBOARD", false);
630 PRIMARY = XInternAtom (DisplayHandle, "PRIMARY", false);
631 DIB = (IntPtr)Atom.XA_PIXMAP;
632 OEMTEXT = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
633 UNICODETEXT = XInternAtom(DisplayHandle, "UTF8_STRING", false);
634 TARGETS = XInternAtom(DisplayHandle, "TARGETS", false);
637 AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
638 PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
639 HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
642 private void GetSystrayManagerWindow() {
643 XGrabServer(DisplayHandle);
644 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
645 XUngrabServer(DisplayHandle);
646 XFlush(DisplayHandle);
649 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
653 xev.ClientMessageEvent.type = XEventName.ClientMessage;
654 xev.ClientMessageEvent.send_event = true;
655 xev.ClientMessageEvent.window = window;
656 xev.ClientMessageEvent.message_type = message_type;
657 xev.ClientMessageEvent.format = 32;
658 xev.ClientMessageEvent.ptr1 = l0;
659 xev.ClientMessageEvent.ptr2 = l1;
660 xev.ClientMessageEvent.ptr3 = l2;
661 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
664 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
668 xev.ClientMessageEvent.type = XEventName.ClientMessage;
669 xev.ClientMessageEvent.send_event = true;
670 xev.ClientMessageEvent.window = window;
671 xev.ClientMessageEvent.message_type = message_type;
672 xev.ClientMessageEvent.format = 32;
673 xev.ClientMessageEvent.ptr1 = l0;
674 xev.ClientMessageEvent.ptr2 = l1;
675 xev.ClientMessageEvent.ptr3 = l2;
676 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
679 bool StyleSet (int s, WindowStyles ws)
681 return (s & (int)ws) == (int)ws;
684 bool ExStyleSet (int ex, WindowExStyles exws)
686 return (ex & (int)exws) == (int)exws;
689 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
691 // Only MDI windows get caption_heights
693 tool_caption_height = 19;
695 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
696 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
697 border_style = FormBorderStyle.Fixed3D;
698 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
699 border_style = FormBorderStyle.None;
701 border_style = FormBorderStyle.FixedSingle;
703 title_style = TitleStyle.None;
705 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
708 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
709 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
710 title_style = TitleStyle.Tool;
712 title_style = TitleStyle.Normal;
716 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
717 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
718 border_style = (FormBorderStyle) 0xFFFF;
720 border_style = FormBorderStyle.None;
725 title_style = TitleStyle.None;
726 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
727 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
728 title_style = TitleStyle.Tool;
730 title_style = TitleStyle.Normal;
734 border_style = FormBorderStyle.None;
736 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
737 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
738 border_style = FormBorderStyle.SizableToolWindow;
740 border_style = FormBorderStyle.Sizable;
743 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
744 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
745 border_style = FormBorderStyle.Fixed3D;
746 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
747 border_style = FormBorderStyle.FixedDialog;
748 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
749 border_style = FormBorderStyle.FixedToolWindow;
750 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
751 border_style = FormBorderStyle.FixedSingle;
754 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
755 border_style = FormBorderStyle.FixedSingle;
762 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
763 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
766 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
767 MotifWmHints mwmHints;
768 MotifFunctions functions;
769 MotifDecorations decorations;
772 Rectangle client_rect;
774 // Child windows don't need WM window styles
775 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
780 mwmHints = new MotifWmHints();
784 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
785 mwmHints.functions = (IntPtr)0;
786 mwmHints.decorations = (IntPtr)0;
788 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
789 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
790 /* tool windows get no window manager
791 decorations, and neither do windows
792 which lack CAPTION/BORDER/DLGFRAME
796 /* just because the window doesn't get any decorations doesn't
797 mean we should disable the functions. for instance, without
798 MotifFunctions.Maximize, changing the windowstate to Maximized
799 is ignored by metacity. */
800 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
803 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
804 functions |= MotifFunctions.Move;
805 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
808 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
809 functions |= MotifFunctions.Move | MotifFunctions.Resize;
810 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
813 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
814 functions |= MotifFunctions.Minimize;
815 decorations |= MotifDecorations.Minimize;
818 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
819 functions |= MotifFunctions.Maximize;
820 decorations |= MotifDecorations.Maximize;
823 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
824 functions |= MotifFunctions.Resize;
825 decorations |= MotifDecorations.ResizeH;
828 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
829 decorations |= MotifDecorations.Border;
832 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
833 decorations |= MotifDecorations.Border;
836 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
837 decorations |= MotifDecorations.Border;
840 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
841 functions |= MotifFunctions.Close;
844 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
845 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
846 if (cp.Caption == "") {
847 functions &= ~MotifFunctions.Move;
848 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
853 if ((functions & MotifFunctions.Resize) == 0) {
854 hwnd.fixed_size = true;
855 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));
857 hwnd.fixed_size = false;
860 mwmHints.functions = (IntPtr)functions;
861 mwmHints.decorations = (IntPtr)decorations;
863 client_rect = hwnd.ClientRect;
865 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
866 // and get those windows in front of their parents
867 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
868 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
869 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
870 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
873 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
874 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
875 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
876 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
878 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
879 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
880 // XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
882 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
883 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
885 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
890 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
891 atoms[atom_count++] = _NET_WM_STATE_NO_TASKBAR.ToInt32();
893 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
896 IntPtr[] atom_ptrs = new IntPtr[2];
897 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
898 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
899 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
902 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
906 private void SetIcon(Hwnd hwnd, Icon icon) {
912 bitmap = icon.ToBitmap();
914 size = bitmap.Width * bitmap.Height + 2;
915 data = new IntPtr[size];
917 data[index++] = (IntPtr)bitmap.Width;
918 data[index++] = (IntPtr)bitmap.Height;
920 for (int y = 0; y < bitmap.Height; y++) {
921 for (int x = 0; x < bitmap.Width; x++) {
922 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
926 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
929 private IntPtr ImageToPixmap(Image image) {
933 private void WakeupMain () {
934 wake.Send (new byte [] { 0xFF });
937 private XEventQueue ThreadQueue(Thread thread) {
940 queue = (XEventQueue)MessageQueues[thread];
942 queue = new XEventQueue(thread);
943 MessageQueues[thread] = queue;
949 private void TranslatePropertyToClipboard(IntPtr property) {
954 IntPtr prop = IntPtr.Zero;
956 Clipboard.Item = null;
958 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);
960 if ((long)nitems > 0) {
961 if (property == (IntPtr)Atom.XA_STRING) {
962 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
963 } else if (property == (IntPtr)Atom.XA_BITMAP) {
964 // FIXME - convert bitmap to image
965 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
966 // FIXME - convert pixmap to image
967 } else if (property == OEMTEXT) {
968 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
969 } else if (property == UNICODETEXT) {
970 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
977 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
979 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
983 // Keep the invalid area as small as needed
984 if ((x + width) > hwnd.width) {
985 width = hwnd.width - x;
988 if ((y + height) > hwnd.height) {
989 height = hwnd.height - y;
993 hwnd.AddInvalidArea(x, y, width, height);
994 if (!hwnd.expose_pending) {
995 if (!hwnd.nc_expose_pending) {
996 hwnd.Queue.Paint.Enqueue(hwnd);
998 hwnd.expose_pending = true;
1001 hwnd.AddNcInvalidArea (x, y, width, height);
1003 if (!hwnd.nc_expose_pending) {
1004 if (!hwnd.expose_pending) {
1005 hwnd.Queue.Paint.Enqueue(hwnd);
1007 hwnd.nc_expose_pending = true;
1012 private void InvalidateWholeWindow(IntPtr handle) {
1015 hwnd = Hwnd.ObjectFromHandle(handle);
1017 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
1020 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
1023 hwnd = Hwnd.ObjectFromHandle(handle);
1025 AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
1028 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
1034 hwnd = Hwnd.ObjectFromHandle(handle);
1037 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1044 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
1065 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
1066 if (win == window) {
1072 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
1076 if (children != IntPtr.Zero) {
1080 } while (win != root);
1085 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
1088 private void FrameExtents(IntPtr window, out int left, out int top) {
1093 IntPtr prop = IntPtr.Zero;
1095 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);
1096 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1097 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1098 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1099 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1100 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1106 if (prop != IntPtr.Zero) {
1112 private void AddConfigureNotify (XEvent xevent) {
1115 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1122 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1123 if (!hwnd.reparented) {
1124 hwnd.x = xevent.ConfigureEvent.x;
1125 hwnd.y = xevent.ConfigureEvent.y;
1127 // This sucks ass, part 1
1128 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1129 // no standard way of getting our adjustment.
1130 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1131 // Several other WMs do their decorations different yet again and we fail to deal
1132 // with that, since I couldn't find any frigging commonality between them.
1133 // The only sane WM seems to be KDE
1135 if (!xevent.ConfigureEvent.send_event) {
1138 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1140 // This is a synthetic event, coordinates are in root space
1141 hwnd.x = xevent.ConfigureEvent.x;
1142 hwnd.y = xevent.ConfigureEvent.y;
1143 if (hwnd.whacky_wm) {
1147 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1148 hwnd.x -= frame_left;
1149 hwnd.y -= frame_top;
1153 hwnd.width = xevent.ConfigureEvent.width;
1154 hwnd.height = xevent.ConfigureEvent.height;
1155 hwnd.ClientRect = Rectangle.Empty;
1157 if (!hwnd.configure_pending) {
1158 hwnd.Queue.Enqueue(xevent);
1159 hwnd.configure_pending = true;
1162 // We drop configure events for Client windows
1165 private void ShowCaret() {
1166 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1172 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1176 private void HideCaret() {
1177 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1183 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1187 private int NextTimeout (ArrayList timers, DateTime now) {
1188 int timeout = Int32.MaxValue;
1190 foreach (Timer timer in timers) {
1191 int next = (int) (timer.Expires - now).TotalMilliseconds;
1193 return 0; // Have a timer that has already expired
1196 if (next < timeout) {
1200 if (timeout < Timer.Minimum) {
1201 timeout = Timer.Minimum;
1209 private void CheckTimers (ArrayList timers, DateTime now) {
1212 count = timers.Count;
1217 for (int i = 0; i < timers.Count; i++) {
1220 timer = (Timer) timers [i];
1222 if (timer.Enabled && timer.Expires <= now) {
1229 private void MapWindow(Hwnd hwnd, WindowType windows) {
1231 if ((windows & WindowType.Whole) != 0) {
1232 XMapWindow(DisplayHandle, hwnd.whole_window);
1234 if ((windows & WindowType.Client) != 0) {
1235 XMapWindow(DisplayHandle, hwnd.client_window);
1239 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1240 hwnd.mapped = false;
1241 if ((windows & WindowType.Whole) != 0) {
1242 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1244 if ((windows & WindowType.Client) != 0) {
1245 XUnmapWindow(DisplayHandle, hwnd.client_window);
1249 private void UpdateMessageQueue (XEventQueue queue) {
1254 now = DateTime.UtcNow;
1257 pending = XPending (DisplayHandle);
1261 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1262 Idle (this, EventArgs.Empty);
1266 pending = XPending (DisplayHandle);
1273 if (queue != null) {
1274 if (queue.Paint.Count > 0)
1277 timeout = NextTimeout (queue.timer_list, now);
1282 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1283 // Clean out buffer, so we're not busy-looping on the same data
1284 if (pollfds[1].revents != 0) {
1285 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1289 pending = XPending (DisplayHandle);
1295 CheckTimers (queue.timer_list, now);
1298 XEvent xevent = new XEvent ();
1301 if (XPending (DisplayHandle) == 0)
1304 XNextEvent (DisplayHandle, ref xevent);
1306 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1307 if (XFilterEvent(ref xevent, FosterParent)) {
1313 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1315 if (xevent.type == XEventName.Expose) {
1320 switch (xevent.type) {
1321 case XEventName.Expose:
1322 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1325 case XEventName.SelectionClear: {
1326 // Should we do something?
1330 case XEventName.SelectionRequest: {
1331 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1335 sel_event = new XEvent();
1336 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1337 sel_event.SelectionEvent.send_event = true;
1338 sel_event.SelectionEvent.display = DisplayHandle;
1339 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1340 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1341 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1342 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1343 sel_event.SelectionEvent.property = IntPtr.Zero;
1345 // Seems that some apps support asking for supported types
1346 if (xevent.SelectionEvent.target == TARGETS) {
1353 if (Clipboard.Item is String) {
1354 atoms[atom_count++] = (int)Atom.XA_STRING;
1355 atoms[atom_count++] = (int)OEMTEXT;
1356 atoms[atom_count++] = (int)UNICODETEXT;
1357 } else if (Clipboard.Item is Image) {
1358 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1359 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1361 // FIXME - handle other types
1364 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1365 } else if (Clipboard.Item is string) {
1371 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1374 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1375 buffer = Marshal.AllocHGlobal(bytes.Length);
1376 buflen = bytes.Length;
1378 for (int i = 0; i < buflen; i++) {
1379 Marshal.WriteByte(buffer, i, bytes[i]);
1381 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1382 // FIXME - this should encode into ISO2022
1383 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1384 while (Marshal.ReadByte(buffer, buflen) != 0) {
1387 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1388 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1389 while (Marshal.ReadByte(buffer, buflen) != 0) {
1393 buffer = IntPtr.Zero;
1396 if (buffer != IntPtr.Zero) {
1397 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1398 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1399 Marshal.FreeHGlobal(buffer);
1401 } else if (Clipboard.Item is Image) {
1402 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1403 // FIXME - convert image and store as property
1404 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1405 // FIXME - convert image and store as property
1409 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1413 case XEventName.SelectionNotify: {
1414 if (Clipboard.Enumerating) {
1415 Clipboard.Enumerating = false;
1416 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1417 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1418 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1419 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1420 #if DriverDebugExtra
1421 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1425 } else if (Clipboard.Retrieving) {
1426 Clipboard.Retrieving = false;
1427 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1428 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1430 Clipboard.Item = null;
1433 Dnd.HandleSelectionNotifyEvent (ref xevent);
1438 case XEventName.MapNotify: {
1439 if (hwnd.client_window == xevent.MapEvent.window) {
1445 case XEventName.UnmapNotify: {
1446 if (hwnd.client_window == xevent.MapEvent.window) {
1447 hwnd.mapped = false;
1452 case XEventName.KeyRelease:
1453 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1454 XEvent nextevent = new XEvent ();
1456 XPeekEvent (DisplayHandle, ref nextevent);
1458 if (nextevent.type == XEventName.KeyPress &&
1459 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1460 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1464 goto case XEventName.KeyPress;
1466 case XEventName.MotionNotify: {
1469 if (hwnd.Queue.Count > 0) {
1470 peek = hwnd.Queue.Peek();
1471 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1475 goto case XEventName.KeyPress;
1478 case XEventName.KeyPress:
1479 case XEventName.ButtonPress:
1480 case XEventName.ButtonRelease:
1481 case XEventName.EnterNotify:
1482 case XEventName.LeaveNotify:
1483 case XEventName.CreateNotify:
1484 case XEventName.DestroyNotify:
1485 case XEventName.FocusIn:
1486 case XEventName.FocusOut:
1487 case XEventName.ClientMessage:
1488 case XEventName.ReparentNotify:
1489 hwnd.Queue.Enqueue (xevent);
1492 case XEventName.ConfigureNotify:
1493 AddConfigureNotify(xevent);
1496 case XEventName.PropertyNotify:
1497 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1502 IntPtr prop = IntPtr.Zero;
1503 IntPtr prev_active;;
1505 prev_active = ActiveWindow;
1506 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);
1507 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1508 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1511 if (prev_active != ActiveWindow) {
1512 if (prev_active != IntPtr.Zero) {
1513 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1515 if (ActiveWindow != IntPtr.Zero) {
1516 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1519 if (ModalWindows.Count == 0) {
1522 // Modality handling, if we are modal and the new active window is one
1523 // of ours but not the modal one, switch back to the modal window
1525 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1526 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1527 Activate((IntPtr)ModalWindows.Peek());
1540 private IntPtr GetMousewParam(int Delta) {
1543 if ((MouseState & MouseButtons.Left) != 0) {
1544 result |= (int)MsgButtons.MK_LBUTTON;
1547 if ((MouseState & MouseButtons.Middle) != 0) {
1548 result |= (int)MsgButtons.MK_MBUTTON;
1551 if ((MouseState & MouseButtons.Right) != 0) {
1552 result |= (int)MsgButtons.MK_RBUTTON;
1555 Keys mods = ModifierKeys;
1556 if ((mods & Keys.Control) != 0) {
1557 result |= (int)MsgButtons.MK_CONTROL;
1560 if ((mods & Keys.Shift) != 0) {
1561 result |= (int)MsgButtons.MK_SHIFT;
1564 result |= Delta << 16;
1566 return (IntPtr)result;
1568 private IntPtr XGetParent(IntPtr handle) {
1575 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1578 if (Children!=IntPtr.Zero) {
1586 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1587 if (ErrorExceptions) {
1588 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1590 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), WhereString());
1595 private void SendWMDestroyMessages(Control c) {
1601 controls = c.child_controls.GetAllControls ();
1603 if (c.IsHandleCreated && !c.IsDisposed) {
1604 #if DriverDebugDestroy
1605 Console.WriteLine("Destroying {0}, child of {1}", XplatUI.Window(c.Handle), (c.Parent != null) ? XplatUI.Window(c.Parent.Handle) : "<none>");
1608 hwnd = Hwnd.ObjectFromHandle(c.Handle);
1609 CleanupCachedWindows (hwnd);
1610 SendMessage(c.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1613 for (i = 0; i < controls.Length; i++) {
1614 if (controls[i].IsHandleCreated) {
1615 /* set all the children hwnd's to zombies so all events will
1616 be ignored (except DestroyNotify) until their X windows are
1618 hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
1621 SendWMDestroyMessages(controls[i]);
1626 void CleanupCachedWindows (Hwnd hwnd)
1628 if (ActiveWindow == hwnd.Handle) {
1629 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1630 ActiveWindow = IntPtr.Zero;
1633 if (FocusWindow == hwnd.Handle) {
1634 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1635 FocusWindow = IntPtr.Zero;
1638 DestroyCaret (hwnd.Handle);
1641 private void PerformNCCalc(Hwnd hwnd) {
1642 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1646 rect = hwnd.DefaultClientRect;
1648 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1649 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1651 ncp.rgrc1.left = rect.Left;
1652 ncp.rgrc1.top = rect.Top;
1653 ncp.rgrc1.right = rect.Right;
1654 ncp.rgrc1.bottom = rect.Bottom;
1656 Marshal.StructureToPtr(ncp, ptr, true);
1657 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1658 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1659 Marshal.FreeHGlobal(ptr);
1661 // FIXME - debug this with Menus
1663 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1664 hwnd.ClientRect = rect;
1667 if ((rect.Width < 1) || (rect.Height < 1)) {
1668 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1670 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1674 #endregion // Private Methods
1677 private void MouseHover(object sender, EventArgs e) {
1681 HoverState.Timer.Enabled = false;
1683 if (HoverState.Window != IntPtr.Zero) {
1684 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1686 xevent = new XEvent ();
1688 xevent.type = XEventName.ClientMessage;
1689 xevent.ClientMessageEvent.display = DisplayHandle;
1690 xevent.ClientMessageEvent.window = HoverState.Window;
1691 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1692 xevent.ClientMessageEvent.format = 32;
1693 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1695 hwnd.Queue.EnqueueLocked (xevent);
1702 private void CaretCallback(object sender, EventArgs e) {
1706 Caret.On = !Caret.On;
1708 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1710 #endregion // Callbacks
1712 #region Public Properties
1714 internal override int Caption {
1720 internal override Size CursorSize {
1725 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1726 return new Size(x, y);
1728 return new Size(16, 16);
1733 internal override bool DragFullWindows {
1739 internal override Size DragSize {
1741 return new Size(4, 4);
1745 internal override Size FrameBorderSize {
1747 throw new NotImplementedException();
1751 internal override Size IconSize {
1757 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1761 current = (long)list;
1764 size = new XIconSize();
1766 for (int i = 0; i < count; i++) {
1767 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1768 current += Marshal.SizeOf(size);
1770 // Look for our preferred size
1771 if (size.min_width == 32) {
1773 return new Size(32, 32);
1776 if (size.max_width == 32) {
1778 return new Size(32, 32);
1781 if (size.min_width < 32 && size.max_width > 32) {
1784 // check if we can fit one
1786 while (x < size.max_width) {
1787 x += size.width_inc;
1790 return new Size(32, 32);
1795 if (largest < size.max_width) {
1796 largest = size.max_width;
1800 // We didn't find a match or we wouldn't be here
1801 return new Size(largest, largest);
1804 return new Size(32, 32);
1809 internal override int KeyboardSpeed {
1812 // A lot harder: need to do:
1813 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1814 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1815 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1817 // And from that we can tell the repetition rate
1819 // Notice, the values must map to:
1820 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1826 internal override int KeyboardDelay {
1829 // Return values must range from 0 to 4, 0 meaning 250ms,
1830 // and 4 meaning 1000 ms.
1832 return 1; // ie, 500 ms
1836 internal override Size MaxWindowTrackSize {
1838 return new Size (WorkingArea.Width, WorkingArea.Height);
1842 internal override Size MinimizedWindowSize {
1844 return new Size(1, 1);
1848 internal override Size MinimizedWindowSpacingSize {
1850 return new Size(1, 1);
1854 internal override Size MinimumWindowSize {
1856 return new Size(1, 1);
1860 internal override Size MinWindowTrackSize {
1862 return new Size(1, 1);
1866 internal override Keys ModifierKeys {
1868 return Keyboard.ModifierKeys;
1872 internal override Size SmallIconSize {
1878 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1882 current = (long)list;
1885 size = new XIconSize();
1887 for (int i = 0; i < count; i++) {
1888 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1889 current += Marshal.SizeOf(size);
1891 // Look for our preferred size
1892 if (size.min_width == 16) {
1894 return new Size(16, 16);
1897 if (size.max_width == 16) {
1899 return new Size(16, 16);
1902 if (size.min_width < 16 && size.max_width > 16) {
1905 // check if we can fit one
1907 while (x < size.max_width) {
1908 x += size.width_inc;
1911 return new Size(16, 16);
1916 if (smallest == 0 || smallest > size.min_width) {
1917 smallest = size.min_width;
1921 // We didn't find a match or we wouldn't be here
1922 return new Size(smallest, smallest);
1925 return new Size(16, 16);
1930 internal override int MouseButtonCount {
1936 internal override bool MouseButtonsSwapped {
1938 return false; // FIXME - how to detect?
1942 internal override Size MouseHoverSize {
1944 return new Size (1, 1);
1948 internal override int MouseHoverTime {
1950 return HoverState.Interval;
1956 internal override bool MouseWheelPresent {
1958 return true; // FIXME - how to detect?
1962 internal override Rectangle VirtualScreen {
1968 internal override Rectangle WorkingArea {
1974 IntPtr prop = IntPtr.Zero;
1977 int current_desktop;
1981 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);
1982 if ((long)nitems < 1) {
1986 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
1989 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);
1990 if ((long)nitems < 4 * current_desktop) {
1994 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
1995 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
1996 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
1997 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2000 return new Rectangle(x, y, width, height);
2003 XWindowAttributes attributes=new XWindowAttributes();
2006 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2009 return new Rectangle(0, 0, attributes.width, attributes.height);
2013 internal override bool ThemesEnabled {
2015 return XplatUIX11.themes_enabled;
2020 #endregion // Public properties
2022 #region Public Static Methods
2023 internal override IntPtr InitializeDriver() {
2025 if (DisplayHandle==IntPtr.Zero) {
2026 SetDisplay(XOpenDisplay(IntPtr.Zero));
2032 internal override void ShutdownDriver(IntPtr token) {
2034 if (DisplayHandle!=IntPtr.Zero) {
2035 XCloseDisplay(DisplayHandle);
2036 DisplayHandle=IntPtr.Zero;
2041 internal override void EnableThemes() {
2042 themes_enabled = true;
2046 internal override void Activate(IntPtr handle) {
2049 hwnd = Hwnd.ObjectFromHandle(handle);
2051 if (hwnd != null) lock (XlibLock) {
2052 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
2053 //XRaiseWindow(DisplayHandle, handle);
2058 internal override void AudibleAlert() {
2059 XBell(DisplayHandle, 0);
2064 internal override void CaretVisible(IntPtr handle, bool visible) {
2065 if (Caret.Hwnd == handle) {
2067 if (!Caret.Visible) {
2068 Caret.Visible = true;
2070 Caret.Timer.Start();
2073 Caret.Visible = false;
2080 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2081 FormBorderStyle border_style;
2082 TitleStyle title_style;
2084 int tool_caption_height;
2086 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2087 out caption_height, out tool_caption_height);
2089 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2090 caption_height, tool_caption_height,
2095 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2101 hwnd = Hwnd.ObjectFromHandle(handle);
2104 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2111 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2112 DataFormats.Format f;
2115 f = DataFormats.Format.List;
2117 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2121 Clipboard.Formats = new ArrayList();
2124 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2126 Clipboard.Enumerating = true;
2127 while (Clipboard.Enumerating) {
2128 UpdateMessageQueue(null);
2133 result = new int[Clipboard.Formats.Count];
2135 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2136 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2139 Clipboard.Formats = null;
2143 internal override void ClipboardClose(IntPtr handle) {
2144 if (handle != ClipMagic) {
2145 throw new ArgumentException("handle is not a valid clipboard handle");
2150 internal override int ClipboardGetID(IntPtr handle, string format) {
2151 if (handle != ClipMagic) {
2152 throw new ArgumentException("handle is not a valid clipboard handle");
2155 if (format == "Text" ) return (int)Atom.XA_STRING;
2156 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2157 //else if (format == "MetaFilePict" ) return 3;
2158 //else if (format == "SymbolicLink" ) return 4;
2159 //else if (format == "DataInterchangeFormat" ) return 5;
2160 //else if (format == "Tiff" ) return 6;
2161 else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
2162 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2163 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2164 //else if (format == "PenData" ) return 10;
2165 //else if (format == "RiffAudio" ) return 11;
2166 //else if (format == "WaveAudio" ) return 12;
2167 else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
2168 //else if (format == "EnhancedMetafile" ) return 14;
2169 //else if (format == "FileDrop" ) return 15;
2170 //else if (format == "Locale" ) return 16;
2172 return XInternAtom(DisplayHandle, format, false).ToInt32();
2175 internal override IntPtr ClipboardOpen(bool primary_selection) {
2176 if (!primary_selection)
2177 ClipMagic = CLIPBOARD;
2179 ClipMagic = PRIMARY;
2183 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2184 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2186 Clipboard.Retrieving = true;
2187 while (Clipboard.Retrieving) {
2188 UpdateMessageQueue(null);
2191 return Clipboard.Item;
2194 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2195 Clipboard.Item = obj;
2196 Clipboard.Type = type;
2197 Clipboard.Converter = converter;
2200 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2202 // Clearing the selection
2203 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2207 internal override void CreateCaret(IntPtr handle, int width, int height) {
2208 XGCValues gc_values;
2211 hwnd = Hwnd.ObjectFromHandle(handle);
2213 if (Caret.Hwnd != IntPtr.Zero) {
2214 DestroyCaret(Caret.Hwnd);
2217 Caret.Hwnd = handle;
2218 Caret.Window = hwnd.client_window;
2219 Caret.Width = width;
2220 Caret.Height = height;
2221 Caret.Visible = false;
2224 gc_values = new XGCValues();
2225 gc_values.line_width = width;
2227 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2228 if (Caret.gc == IntPtr.Zero) {
2229 Caret.Hwnd = IntPtr.Zero;
2233 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2236 internal override IntPtr CreateWindow(CreateParams cp) {
2237 XSetWindowAttributes Attributes;
2243 IntPtr ParentHandle;
2245 IntPtr ClientWindow;
2246 Rectangle ClientRect;
2247 SetWindowValuemask ValueMask;
2252 Attributes = new XSetWindowAttributes();
2258 if (Width<1) Width=1;
2259 if (Height<1) Height=1;
2261 if (cp.Parent != IntPtr.Zero) {
2262 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2264 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2265 // We need to use our foster parent window until this poor child gets it's parent assigned
2266 ParentHandle=FosterParent;
2267 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2268 ParentHandle=RootWindow;
2270 // Default position on screen, if window manager doesn't place us somewhere else
2273 ParentHandle=RootWindow;
2277 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2279 Attributes.bit_gravity = Gravity.NorthWestGravity;
2280 Attributes.win_gravity = Gravity.NorthWestGravity;
2282 // Save what's under the toolwindow
2283 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2284 Attributes.save_under = true;
2285 ValueMask |= SetWindowValuemask.SaveUnder;
2289 // If we're a popup without caption we override the WM
2290 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2291 Attributes.override_redirect = true;
2292 ValueMask |= SetWindowValuemask.OverrideRedirect;
2298 hwnd.height = Height;
2299 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2301 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2302 hwnd.enabled = false;
2305 ClientRect = hwnd.ClientRect;
2306 ClientWindow = IntPtr.Zero;
2309 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2310 if (WholeWindow != IntPtr.Zero) {
2311 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2313 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2314 ValueMask = SetWindowValuemask.ColorMap;
2315 Attributes.colormap = CustomColormap;
2317 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);
2321 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2322 throw new Exception("Could not create X11 windows");
2325 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2326 hwnd.WholeWindow = WholeWindow;
2327 hwnd.ClientWindow = ClientWindow;
2329 #if DriverDebug || DriverDebugCreate
2330 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);
2333 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2334 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2337 hints = new XSizeHints();
2340 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2341 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2346 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)SelectInputMask));
2347 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2349 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2350 MapWindow(hwnd, WindowType.Both);
2351 hwnd.visible = true;
2355 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2357 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2358 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2360 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2361 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
2362 // XSetTransientForHint (DisplayHandle, hwnd.whole_window, FosterParent);
2365 SetWMStyles(hwnd, cp);
2367 // set the group leader
2368 XWMHints wm_hints = new XWMHints ();
2370 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2371 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2372 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2374 if (ParentHandle != RootWindow) {
2375 wm_hints.window_group = hwnd.whole_window;
2377 wm_hints.window_group = ParentHandle;
2381 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2384 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2385 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2386 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2387 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2390 // for now make all windows dnd enabled
2391 Dnd.SetAllowDrop (hwnd, true);
2393 // Set caption/window title
2394 Text(hwnd.Handle, cp.Caption);
2399 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2400 CreateParams create_params = new CreateParams();
2402 create_params.Caption = "";
2403 create_params.X = X;
2404 create_params.Y = Y;
2405 create_params.Width = Width;
2406 create_params.Height = Height;
2408 create_params.ClassName=XplatUI.DefaultClassName;
2409 create_params.ClassStyle = 0;
2410 create_params.ExStyle=0;
2411 create_params.Parent=IntPtr.Zero;
2412 create_params.Param=0;
2414 return CreateWindow(create_params);
2417 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2419 Bitmap cursor_bitmap;
2427 IntPtr cursor_pixmap;
2434 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2438 // Win32 only allows creation cursors of a certain size
2439 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2440 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2441 cursor_mask = new Bitmap(mask, new Size(width, height));
2443 cursor_bitmap = bitmap;
2447 width = cursor_bitmap.Width;
2448 height = cursor_bitmap.Height;
2450 cursor_bits = new Byte[(width / 8) * height];
2451 mask_bits = new Byte[(width / 8) * height];
2453 for (int y = 0; y < height; y++) {
2454 for (int x = 0; x < width; x++) {
2455 c_pixel = cursor_bitmap.GetPixel(x, y);
2456 m_pixel = cursor_mask.GetPixel(x, y);
2458 and = c_pixel == cursor_pixel;
2459 xor = m_pixel == mask_pixel;
2463 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2464 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2465 } else if (and && !xor) {
2467 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2468 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2470 } else if (and && !xor) {
2472 } else if (and && xor) {
2475 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2476 // we want both to be 0 so nothing to be done
2477 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2478 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2484 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2485 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2489 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2490 fg.red = (ushort)65535;
2491 fg.green = (ushort)65535;
2492 fg.blue = (ushort)65535;
2494 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2496 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2498 XFreePixmap(DisplayHandle, cursor_pixmap);
2499 XFreePixmap(DisplayHandle, mask_pixmap);
2504 internal override IntPtr DefineStdCursor(StdCursor id) {
2505 CursorFontShape shape;
2508 // FIXME - define missing shapes
2511 case StdCursor.AppStarting: {
2512 shape = CursorFontShape.XC_watch;
2516 case StdCursor.Arrow: {
2517 shape = CursorFontShape.XC_top_left_arrow;
2521 case StdCursor.Cross: {
2522 shape = CursorFontShape.XC_crosshair;
2526 case StdCursor.Default: {
2527 shape = CursorFontShape.XC_top_left_arrow;
2531 case StdCursor.Hand: {
2532 shape = CursorFontShape.XC_hand1;
2536 case StdCursor.Help: {
2537 shape = CursorFontShape.XC_question_arrow;
2541 case StdCursor.HSplit: {
2542 shape = CursorFontShape.XC_sb_v_double_arrow;
2546 case StdCursor.IBeam: {
2547 shape = CursorFontShape.XC_xterm;
2551 case StdCursor.No: {
2552 shape = CursorFontShape.XC_circle;
2556 case StdCursor.NoMove2D: {
2557 shape = CursorFontShape.XC_fleur;
2561 case StdCursor.NoMoveHoriz: {
2562 shape = CursorFontShape.XC_fleur;
2566 case StdCursor.NoMoveVert: {
2567 shape = CursorFontShape.XC_fleur;
2571 case StdCursor.PanEast: {
2572 shape = CursorFontShape.XC_fleur;
2576 case StdCursor.PanNE: {
2577 shape = CursorFontShape.XC_fleur;
2581 case StdCursor.PanNorth: {
2582 shape = CursorFontShape.XC_fleur;
2586 case StdCursor.PanNW: {
2587 shape = CursorFontShape.XC_fleur;
2591 case StdCursor.PanSE: {
2592 shape = CursorFontShape.XC_fleur;
2596 case StdCursor.PanSouth: {
2597 shape = CursorFontShape.XC_fleur;
2601 case StdCursor.PanSW: {
2602 shape = CursorFontShape.XC_fleur;
2606 case StdCursor.PanWest: {
2607 shape = CursorFontShape.XC_sizing;
2611 case StdCursor.SizeAll: {
2612 shape = CursorFontShape.XC_fleur;
2616 case StdCursor.SizeNESW: {
2617 shape = CursorFontShape.XC_top_right_corner;
2621 case StdCursor.SizeNS: {
2622 shape = CursorFontShape.XC_sb_v_double_arrow;
2626 case StdCursor.SizeNWSE: {
2627 shape = CursorFontShape.XC_top_left_corner;
2631 case StdCursor.SizeWE: {
2632 shape = CursorFontShape.XC_sb_h_double_arrow;
2636 case StdCursor.UpArrow: {
2637 shape = CursorFontShape.XC_center_ptr;
2641 case StdCursor.VSplit: {
2642 shape = CursorFontShape.XC_sb_h_double_arrow;
2646 case StdCursor.WaitCursor: {
2647 shape = CursorFontShape.XC_watch;
2657 cursor = XCreateFontCursor(DisplayHandle, shape);
2662 internal override IntPtr DefWndProc(ref Message msg) {
2663 switch ((Msg)msg.Msg) {
2664 case Msg.WM_PAINT: {
2667 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2669 hwnd.expose_pending = false;
2675 case Msg.WM_NCPAINT: {
2678 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2680 hwnd.nc_expose_pending = false;
2686 case Msg.WM_CONTEXTMENU: {
2689 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2691 if ((hwnd != null) && (hwnd.parent != null)) {
2692 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2697 case Msg.WM_MOUSEWHEEL: {
2700 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2702 if ((hwnd != null) && (hwnd.parent != null)) {
2703 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2704 if (msg.Result == IntPtr.Zero) {
2711 case Msg.WM_SETCURSOR: {
2714 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2716 break; // not sure how this happens, but it does
2718 // Pass to parent window first
2719 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2721 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2724 if (msg.Result == IntPtr.Zero) {
2727 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2728 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2729 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2730 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2731 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2732 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2735 handle = Cursors.Default.handle;
2738 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2739 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2740 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2741 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2742 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2743 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2746 case HitTest.HTGROWBOX:
2747 case HitTest.HTSIZE:
2748 case HitTest.HTZOOM:
2749 case HitTest.HTVSCROLL:
2750 case HitTest.HTSYSMENU:
2751 case HitTest.HTREDUCE:
2752 case HitTest.HTNOWHERE:
2753 case HitTest.HTMAXBUTTON:
2754 case HitTest.HTMINBUTTON:
2755 case HitTest.HTMENU:
2756 case HitTest.HSCROLL:
2757 case HitTest.HTBOTTOM:
2758 case HitTest.HTCAPTION:
2759 case HitTest.HTCLIENT:
2760 case HitTest.HTCLOSE:
2762 default: handle = Cursors.Default.handle; break;
2764 SetCursor(msg.HWnd, handle);
2772 internal override void DestroyCaret(IntPtr handle) {
2773 if (Caret.Hwnd == handle) {
2774 if (Caret.Visible == true) {
2777 if (Caret.gc != IntPtr.Zero) {
2778 XFreeGC(DisplayHandle, Caret.gc);
2779 Caret.gc = IntPtr.Zero;
2781 Caret.Hwnd = IntPtr.Zero;
2782 Caret.Visible = false;
2787 internal override void DestroyCursor(IntPtr cursor) {
2789 XFreeCursor(DisplayHandle, cursor);
2793 internal override void DestroyWindow(IntPtr handle) {
2796 hwnd = Hwnd.ObjectFromHandle(handle);
2799 #if DriverDebug || DriverDebugDestroy
2800 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2805 #if DriverDebug || DriverDebugDestroy
2806 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2809 CleanupCachedWindows (hwnd);
2811 SendWMDestroyMessages(Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle));
2814 if (hwnd.whole_window != IntPtr.Zero) {
2815 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2817 else if (hwnd.client_window != IntPtr.Zero) {
2818 XDestroyWindow(DisplayHandle, hwnd.client_window);
2825 internal override IntPtr DispatchMessage(ref MSG msg) {
2826 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2829 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2831 XGCValues gc_values;
2834 hwnd = Hwnd.ObjectFromHandle(handle);
2836 gc_values = new XGCValues();
2838 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2839 gc_values.line_width = line_width;
2840 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2842 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2843 //mask = foreground ^ background;
2844 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2845 //XSetBackground(DisplayHandle, gc, background);
2846 //XSetFunction(DisplayHandle, gc, GXxor);
2847 //XSetPlaneMask(DisplayHandle, gc, mask);
2850 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2855 control = Control.FromHandle(handle);
2857 XColor xcolor = new XColor();
2859 xcolor.red = (ushort)(control.ForeColor.R * 257);
2860 xcolor.green = (ushort)(control.ForeColor.G * 257);
2861 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2862 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2863 foreground = (uint)xcolor.pixel.ToInt32();
2865 xcolor.red = (ushort)(control.BackColor.R * 257);
2866 xcolor.green = (ushort)(control.BackColor.G * 257);
2867 xcolor.blue = (ushort)(control.BackColor.B * 257);
2868 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2869 background = (uint)xcolor.pixel.ToInt32();
2871 uint mask = foreground ^ background;
2873 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2874 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2875 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2876 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2878 if ((rect.Width > 0) && (rect.Height > 0)) {
2879 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2881 if (rect.Width > 0) {
2882 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2884 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2887 XFreeGC(DisplayHandle, gc);
2890 internal override void DoEvents() {
2891 MSG msg = new MSG ();
2894 if (OverrideCursorHandle != IntPtr.Zero) {
2895 OverrideCursorHandle = IntPtr.Zero;
2898 queue = ThreadQueue(Thread.CurrentThread);
2900 queue.DispatchIdle = false;
2902 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2903 TranslateMessage (ref msg);
2904 DispatchMessage (ref msg);
2907 queue.DispatchIdle = true;
2910 internal override void EnableWindow(IntPtr handle, bool Enable) {
2913 hwnd = Hwnd.ObjectFromHandle(handle);
2915 hwnd.Enabled = Enable;
2919 internal override void EndLoop(Thread thread) {
2920 // This is where we one day will shut down the loop for the thread
2924 internal override IntPtr GetActive() {
2929 IntPtr prop = IntPtr.Zero;
2930 IntPtr active = IntPtr.Zero;
2932 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);
2933 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2934 active = (IntPtr)Marshal.ReadInt32(prop);
2938 if (active != IntPtr.Zero) {
2941 hwnd = Hwnd.GetObjectFromWindow(active);
2943 active = hwnd.Handle;
2945 active = IntPtr.Zero;
2951 internal override Region GetClipRegion(IntPtr handle) {
2954 hwnd = Hwnd.ObjectFromHandle(handle);
2956 return hwnd.UserClip;
2962 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2969 internal override void GetDisplaySize(out Size size) {
2970 XWindowAttributes attributes=new XWindowAttributes();
2973 // FIXME - use _NET_WM messages instead?
2974 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2977 size = new Size(attributes.width, attributes.height);
2980 internal override SizeF GetAutoScaleSize(Font font) {
2983 string magic_string = "The quick brown fox jumped over the lazy dog.";
2984 double magic_number = 44.549996948242189;
2986 g = Graphics.FromHwnd(FosterParent);
2988 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2989 return new SizeF(width, font.Height);
2992 internal override IntPtr GetParent(IntPtr handle) {
2995 hwnd = Hwnd.ObjectFromHandle(handle);
2996 if (hwnd != null && hwnd.parent != null) {
2997 return hwnd.parent.Handle;
3002 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3012 if (handle != IntPtr.Zero) {
3013 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3015 use_handle = RootWindow;
3019 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3022 if (handle != IntPtr.Zero) {
3031 internal override IntPtr GetFocus() {
3036 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3037 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3040 internal override Point GetMenuOrigin(IntPtr handle) {
3043 hwnd = Hwnd.ObjectFromHandle(handle);
3046 return hwnd.MenuOrigin;
3051 [MonoTODO("Implement filtering")]
3052 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3059 if (((XEventQueue)queue_id).Count > 0) {
3060 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3062 UpdateMessageQueue ((XEventQueue)queue_id);
3064 if (((XEventQueue)queue_id).Count > 0) {
3065 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3066 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3067 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3069 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3070 msg.hwnd= IntPtr.Zero;
3071 msg.message = Msg.WM_ENTERIDLE;
3075 // We reset ourselves so GetMessage can be called again
3076 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3082 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3084 // Handle messages for windows that are already or are about to be destroyed.
3086 // We need to make sure we only allow DestroyNotify events through for zombie
3087 // hwnds, since much of the event handling code makes requests using the hwnd's
3088 // client_window, and that'll result in BadWindow errors if there's some lag
3089 // between the XDestroyWindow call and the DestroyNotify event.
3090 if (hwnd == null || (hwnd.zombie && xevent.type != XEventName.DestroyNotify)) {
3092 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3094 goto ProcessNextMessage;
3097 if (hwnd.client_window == xevent.AnyEvent.window) {
3099 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3102 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3105 msg.hwnd = hwnd.Handle;
3108 // If you add a new event to this switch make sure to add it in
3109 // UpdateMessage also unless it is not coming through the X event system.
3111 switch(xevent.type) {
3112 case XEventName.KeyPress: {
3113 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3117 case XEventName.KeyRelease: {
3118 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3122 case XEventName.ButtonPress: {
3123 switch(xevent.ButtonEvent.button) {
3125 MouseState |= MouseButtons.Left;
3127 msg.message = Msg.WM_LBUTTONDOWN;
3129 msg.message = Msg.WM_NCLBUTTONDOWN;
3130 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3132 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3133 msg.wParam=GetMousewParam(0);
3138 MouseState |= MouseButtons.Middle;
3140 msg.message = Msg.WM_MBUTTONDOWN;
3142 msg.message = Msg.WM_NCMBUTTONDOWN;
3143 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3145 msg.wParam=GetMousewParam(0);
3150 MouseState |= MouseButtons.Right;
3152 msg.message = Msg.WM_RBUTTONDOWN;
3154 msg.message = Msg.WM_NCRBUTTONDOWN;
3155 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3157 msg.wParam=GetMousewParam(0);
3162 msg.hwnd = FocusWindow;
3163 msg.message=Msg.WM_MOUSEWHEEL;
3164 msg.wParam=GetMousewParam(120);
3169 msg.hwnd = FocusWindow;
3170 msg.message=Msg.WM_MOUSEWHEEL;
3171 msg.wParam=GetMousewParam(-120);
3177 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3178 MousePosition.X = xevent.ButtonEvent.x;
3179 MousePosition.Y = xevent.ButtonEvent.y;
3181 if (!hwnd.Enabled) {
3184 msg.hwnd = hwnd.EnabledHwnd;
3185 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);
3186 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3189 if (Grab.Hwnd != IntPtr.Zero) {
3190 msg.hwnd = Grab.Hwnd;
3193 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3194 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3195 switch(xevent.ButtonEvent.button) {
3197 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3202 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3207 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3211 ClickPending.Pending = false;
3213 ClickPending.Pending = true;
3214 ClickPending.Hwnd = msg.hwnd;
3215 ClickPending.Message = msg.message;
3216 ClickPending.wParam = msg.wParam;
3217 ClickPending.lParam = msg.lParam;
3218 ClickPending.Time = (long)xevent.ButtonEvent.time;
3224 case XEventName.ButtonRelease: {
3226 Dnd.HandleButtonRelease (ref xevent);
3230 switch(xevent.ButtonEvent.button) {
3232 MouseState &= ~MouseButtons.Left;
3234 msg.message = Msg.WM_LBUTTONUP;
3236 msg.message = Msg.WM_NCLBUTTONUP;
3237 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3239 msg.wParam=GetMousewParam(0);
3244 MouseState &= ~MouseButtons.Middle;
3246 msg.message = Msg.WM_MBUTTONUP;
3248 msg.message = Msg.WM_NCMBUTTONUP;
3249 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3251 msg.wParam=GetMousewParam(0);
3256 MouseState &= ~MouseButtons.Right;
3258 msg.message = Msg.WM_RBUTTONUP;
3260 msg.message = Msg.WM_NCRBUTTONUP;
3261 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3263 msg.wParam=GetMousewParam(0);
3268 goto ProcessNextMessage;
3272 goto ProcessNextMessage;
3276 if (!hwnd.Enabled) {
3279 msg.hwnd = hwnd.EnabledHwnd;
3280 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);
3281 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3284 if (Grab.Hwnd != IntPtr.Zero) {
3285 msg.hwnd = Grab.Hwnd;
3288 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3289 MousePosition.X = xevent.ButtonEvent.x;
3290 MousePosition.Y = xevent.ButtonEvent.y;
3294 case XEventName.MotionNotify: {
3296 #if DriverDebugExtra
3297 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);
3300 if (Dnd.HandleMotionNotify (ref xevent))
3301 goto ProcessNextMessage;
3302 if (Grab.Hwnd != IntPtr.Zero) {
3303 msg.hwnd = Grab.Hwnd;
3305 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3308 msg.message = Msg.WM_MOUSEMOVE;
3309 msg.wParam = GetMousewParam(0);
3310 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3312 if (!hwnd.Enabled) {
3315 msg.hwnd = hwnd.EnabledHwnd;
3316 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);
3317 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3320 MousePosition.X = xevent.MotionEvent.x;
3321 MousePosition.Y = xevent.MotionEvent.y;
3323 if ((HoverState.Timer.Enabled) &&
3324 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3325 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3326 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3327 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3328 HoverState.Timer.Stop();
3329 HoverState.Timer.Start();
3330 HoverState.X = MousePosition.X;
3331 HoverState.Y = MousePosition.Y;
3341 #if DriverDebugExtra
3342 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);
3344 msg.message = Msg.WM_NCMOUSEMOVE;
3346 if (!hwnd.Enabled) {
3347 msg.hwnd = hwnd.EnabledHwnd;
3348 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);
3349 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3352 // The hit test is sent in screen coordinates
3353 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3354 xevent.MotionEvent.x, xevent.MotionEvent.y,
3355 out screen_x, out screen_y, out dummy);
3357 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3358 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3359 IntPtr.Zero, msg.lParam).ToInt32 ();
3360 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3362 MousePosition.X = xevent.MotionEvent.x;
3363 MousePosition.Y = xevent.MotionEvent.y;
3369 case XEventName.EnterNotify: {
3370 if (!hwnd.Enabled) {
3371 goto ProcessNextMessage;
3373 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3374 goto ProcessNextMessage;
3376 msg.message = Msg.WM_MOUSE_ENTER;
3377 HoverState.X = xevent.CrossingEvent.x;
3378 HoverState.Y = xevent.CrossingEvent.y;
3379 HoverState.Timer.Enabled = true;
3380 HoverState.Window = xevent.CrossingEvent.window;
3384 case XEventName.LeaveNotify: {
3385 if (!hwnd.Enabled) {
3386 goto ProcessNextMessage;
3388 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3389 goto ProcessNextMessage;
3391 msg.message=Msg.WM_MOUSE_LEAVE;
3392 HoverState.Timer.Enabled = false;
3393 HoverState.Window = IntPtr.Zero;
3398 case XEventName.CreateNotify: {
3399 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3400 msg.message = WM_CREATE;
3401 // Set up CreateStruct
3403 goto ProcessNextMessage;
3410 case XEventName.ReparentNotify: {
3411 if (hwnd.parent == null) { // Toplevel
3412 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3413 // We need to adjust x/y
3414 // This sucks ass, part 2
3415 // Every WM does the reparenting of toplevel windows different, so there's
3416 // no standard way of getting our adjustment considering frames/decorations
3417 // The code below is needed for metacity. KDE doesn't works just fine without this
3425 hwnd.Reparented = true;
3427 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);
3428 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3429 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3432 hwnd.whacky_wm = true;
3435 if (hwnd.opacity != 0xffffffff) {
3438 opacity = (IntPtr)(Int32)hwnd.opacity;
3439 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3441 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3442 goto ProcessNextMessage;
3444 hwnd.Reparented = false;
3445 goto ProcessNextMessage;
3448 goto ProcessNextMessage;
3451 case XEventName.ConfigureNotify: {
3452 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3453 #if DriverDebugExtra
3454 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);
3456 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3457 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3458 hwnd.configure_pending = false;
3460 // We need to adjust our client window to track the resize of whole_window
3461 PerformNCCalc(hwnd);
3464 goto ProcessNextMessage;
3467 case XEventName.FocusIn: {
3468 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3469 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3470 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3471 // about it having focus again
3472 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3473 goto ProcessNextMessage;
3476 if (FocusWindow == IntPtr.Zero) {
3477 Control c = Control.FromHandle (hwnd.client_window);
3479 goto ProcessNextMessage;
3480 Form form = c.FindForm ();
3482 goto ProcessNextMessage;
3483 ActiveWindow = form.Handle;
3484 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3485 goto ProcessNextMessage;
3487 Keyboard.FocusIn(FocusWindow);
3488 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3489 goto ProcessNextMessage;
3492 case XEventName.FocusOut: {
3493 // Se the comment for our FocusIn handler
3494 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3495 goto ProcessNextMessage;
3497 Keyboard.FocusOut(FocusWindow);
3499 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3500 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3503 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3504 goto ProcessNextMessage;
3507 case XEventName.Expose: {
3508 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3510 hwnd.expose_pending = false;
3512 hwnd.nc_expose_pending = false;
3514 goto ProcessNextMessage;
3518 if (!hwnd.expose_pending) {
3519 goto ProcessNextMessage;
3522 if (!hwnd.nc_expose_pending) {
3523 goto ProcessNextMessage;
3526 switch (hwnd.border_style) {
3527 case FormBorderStyle.Fixed3D: {
3530 g = Graphics.FromHwnd(hwnd.whole_window);
3531 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3536 case FormBorderStyle.FixedSingle: {
3539 g = Graphics.FromHwnd(hwnd.whole_window);
3540 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3545 #if DriverDebugExtra
3546 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);
3549 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3550 Region region = new Region (rect);
3551 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3552 msg.message = Msg.WM_NCPAINT;
3553 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3556 #if DriverDebugExtra
3557 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);
3559 if (Caret.Visible == true) {
3560 Caret.Paused = true;
3564 if (Caret.Visible == true) {
3566 Caret.Paused = false;
3568 msg.message = Msg.WM_PAINT;
3572 case XEventName.DestroyNotify: {
3574 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3575 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3577 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3578 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3579 CleanupCachedWindows (hwnd);
3581 #if DriverDebugDestroy
3582 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3585 msg.hwnd = hwnd.client_window;
3586 msg.message=Msg.WM_DESTROY;
3590 Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
3593 goto ProcessNextMessage;
3599 case XEventName.ClientMessage: {
3600 if (Dnd.HandleClientMessage (ref xevent)) {
3601 goto ProcessNextMessage;
3604 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3605 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3606 goto ProcessNextMessage;
3609 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3610 msg.message = Msg.WM_MOUSEHOVER;
3611 msg.wParam = GetMousewParam(0);
3612 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3616 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3617 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3618 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3619 msg.wParam = xevent.ClientMessageEvent.ptr3;
3620 msg.lParam = xevent.ClientMessageEvent.ptr4;
3625 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3626 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3631 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3632 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3633 msg.message = Msg.WM_CLOSE;
3637 // We should not get this, but I'll leave the code in case we need it in the future
3638 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3639 goto ProcessNextMessage;
3642 goto ProcessNextMessage;
3645 case XEventName.TimerNotify: {
3646 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3647 goto ProcessNextMessage;
3651 goto ProcessNextMessage;
3658 internal override bool GetText(IntPtr handle, out string text) {
3661 textptr = IntPtr.Zero;
3664 // FIXME - use _NET properties
3665 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3667 if (textptr != IntPtr.Zero) {
3668 text = Marshal.PtrToStringAnsi(textptr);
3677 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) {
3680 hwnd = Hwnd.ObjectFromHandle(handle);
3686 height = hwnd.height;
3688 PerformNCCalc(hwnd);
3690 client_width = hwnd.ClientRect.Width;
3691 client_height = hwnd.ClientRect.Height;
3696 // Should we throw an exception or fail silently?
3697 // throw new ArgumentException("Called with an invalid window handle", "handle");
3707 internal override FormWindowState GetWindowState(IntPtr handle) {
3712 IntPtr prop = IntPtr.Zero;
3716 XWindowAttributes attributes;
3719 hwnd = Hwnd.ObjectFromHandle(handle);
3723 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);
3724 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3725 for (int i = 0; i < (long)nitems; i++) {
3726 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3727 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3729 } else if (atom == _NET_WM_STATE_HIDDEN) {
3737 return FormWindowState.Minimized;
3738 } else if (maximized == 2) {
3739 return FormWindowState.Maximized;
3742 attributes = new XWindowAttributes();
3743 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3744 if (attributes.map_state == MapState.IsUnmapped) {
3745 throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
3749 return FormWindowState.Normal;
3752 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3754 GrabConfined = Grab.Confined;
3755 GrabArea = Grab.Area;
3758 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3760 IntPtr confine_to_window;
3762 confine_to_window = IntPtr.Zero;
3764 if (confine_to_handle != IntPtr.Zero) {
3765 XWindowAttributes attributes = new XWindowAttributes();
3767 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3770 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3772 Grab.Area.X = attributes.x;
3773 Grab.Area.Y = attributes.y;
3774 Grab.Area.Width = attributes.width;
3775 Grab.Area.Height = attributes.height;
3776 Grab.Confined = true;
3777 confine_to_window = hwnd.client_window;
3782 hwnd = Hwnd.ObjectFromHandle(handle);
3785 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3786 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3787 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3788 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3792 internal override void UngrabWindow(IntPtr hwnd) {
3794 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3795 XFlush(DisplayHandle);
3797 Grab.Hwnd = IntPtr.Zero;
3798 Grab.Confined = false;
3801 internal override void HandleException(Exception e) {
3802 StackTrace st = new StackTrace(e, true);
3803 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3804 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3807 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3810 hwnd = Hwnd.ObjectFromHandle(handle);
3813 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3815 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3819 internal override bool IsEnabled(IntPtr handle) {
3820 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3821 return (hwnd != null && hwnd.Enabled);
3824 internal override bool IsVisible(IntPtr handle) {
3825 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3826 return (hwnd != null && hwnd.visible);
3829 internal override void KillTimer(Timer timer) {
3830 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3832 if (queue == null) {
3833 // This isn't really an error, MS doesn't start the timer if
3834 // it has no assosciated queue
3837 queue.timer_list.Remove (timer);
3840 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3846 hwnd = Hwnd.ObjectFromHandle(handle);
3849 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3856 internal override void OverrideCursor(IntPtr cursor) {
3857 OverrideCursorHandle = cursor;
3860 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3861 PaintEventArgs paint_event;
3864 hwnd = Hwnd.ObjectFromHandle(handle);
3866 if (Caret.Visible == true) {
3867 Caret.Paused = true;
3873 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3875 // Protected against illegal cross-thread painting
3877 if (hwnd.client_dc != null) {
3881 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3885 Region clip_region = new Region ();
3886 clip_region.MakeEmpty();
3888 foreach (Rectangle r in hwnd.ClipRectangles) {
3889 clip_region.Union (r);
3892 if (hwnd.UserClip != null) {
3893 clip_region.Intersect(hwnd.UserClip);
3896 hwnd.client_dc.Clip = clip_region;
3897 paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.Invalid);
3898 hwnd.expose_pending = false;
3900 hwnd.ClearInvalidArea();
3904 hwnd.non_client_dc = Graphics.FromHwnd (hwnd.whole_window);
3906 if (!hwnd.nc_invalid.IsEmpty) {
3907 hwnd.non_client_dc.SetClip (hwnd.nc_invalid);
3908 paint_event = new PaintEventArgs(hwnd.non_client_dc, hwnd.nc_invalid);
3910 paint_event = new PaintEventArgs(hwnd.non_client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3912 hwnd.nc_expose_pending = false;
3914 hwnd.ClearNcInvalidArea ();
3920 internal override void PaintEventEnd(IntPtr handle, bool client) {
3923 hwnd = Hwnd.ObjectFromHandle(handle);
3927 hwnd.client_dc.Flush();
3928 hwnd.client_dc.Dispose();
3929 hwnd.client_dc = null;
3932 hwnd.client_dc.Flush();
3933 hwnd.client_dc.Dispose();
3934 hwnd.client_dc = null;
3938 hwnd.non_client_dc.Flush ();
3939 hwnd.non_client_dc.Dispose ();
3940 hwnd.non_client_dc = null;
3944 if (Caret.Visible == true) {
3946 Caret.Paused = false;
3950 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3951 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3952 XEventQueue queue = (XEventQueue) queue_id;
3955 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3956 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3960 if (queue.Count > 0) {
3963 // Only call UpdateMessageQueue if real events are pending
3964 // otherwise we go to sleep on the socket
3965 if (XPending(DisplayHandle) != 0) {
3966 UpdateMessageQueue((XEventQueue)queue_id);
3968 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3973 CheckTimers(queue.timer_list, DateTime.UtcNow);
3978 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
3981 // FIXME - I think this should just enqueue directly
3982 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3983 XEvent xevent = new XEvent ();
3984 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
3986 xevent.type = XEventName.ClientMessage;
3987 xevent.ClientMessageEvent.display = DisplayHandle;
3990 xevent.ClientMessageEvent.window = hwnd.whole_window;
3992 xevent.ClientMessageEvent.window = IntPtr.Zero;
3995 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
3996 xevent.ClientMessageEvent.format = 32;
3997 xevent.ClientMessageEvent.ptr1 = handle;
3998 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
3999 xevent.ClientMessageEvent.ptr3 = wparam;
4000 xevent.ClientMessageEvent.ptr4 = lparam;
4002 hwnd.Queue.Enqueue (xevent);
4007 internal override void PostQuitMessage(int exitCode) {
4009 XFlush(DisplayHandle);
4010 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4013 internal override void RequestNCRecalc(IntPtr handle) {
4016 hwnd = Hwnd.ObjectFromHandle(handle);
4022 PerformNCCalc(hwnd);
4023 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4024 InvalidateWholeWindow(handle);
4027 internal override void ResetMouseHover(IntPtr handle) {
4030 hwnd = Hwnd.ObjectFromHandle(handle);
4035 HoverState.Timer.Enabled = true;
4036 HoverState.X = MousePosition.X;
4037 HoverState.Y = MousePosition.Y;
4038 HoverState.Window = handle;
4042 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4048 hwnd = Hwnd.ObjectFromHandle(handle);
4051 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4058 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4064 hwnd = Hwnd.ObjectFromHandle(handle);
4067 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4074 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4077 XGCValues gc_values;
4080 hwnd = Hwnd.ObjectFromHandle(handle);
4083 if (r != Rectangle.Empty) {
4084 /* We have an invalid area in the window we're scrolling.
4085 Adjust our stored invalid rectangle to to match the scrolled amount */
4100 hwnd.ClearInvalidArea();
4101 hwnd.AddInvalidArea(r);
4104 gc_values = new XGCValues();
4106 if (with_children) {
4107 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4110 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4118 height = area.Height - YAmount;
4119 dest_y = area.Y + YAmount;
4122 src_y = area.Y - YAmount;
4123 height = area.Height + YAmount;
4129 width = area.Width - XAmount;
4130 dest_x = area.X + XAmount;
4133 src_x = area.X - XAmount;
4134 width = area.Width + XAmount;
4138 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4140 // Generate an expose for the area exposed by the horizontal scroll
4141 // We don't use AddExpose since we're
4143 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4144 } else if (XAmount < 0) {
4145 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4148 // Generate an expose for the area exposed by the vertical scroll
4150 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4151 } else if (YAmount < 0) {
4152 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4154 XFreeGC(DisplayHandle, gc);
4157 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4161 hwnd = Hwnd.GetObjectFromWindow(handle);
4163 rect = hwnd.ClientRect;
4166 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4169 internal override void SendAsyncMethod (AsyncMethodData method) {
4171 XEvent xevent = new XEvent ();
4173 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4175 xevent.type = XEventName.ClientMessage;
4176 xevent.ClientMessageEvent.display = DisplayHandle;
4177 xevent.ClientMessageEvent.window = method.Handle;
4178 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4179 xevent.ClientMessageEvent.format = 32;
4180 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4182 hwnd.Queue.EnqueueLocked (xevent);
4187 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4189 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4192 h = Hwnd.ObjectFromHandle(hwnd);
4194 if (h.queue != ThreadQueue (Thread.CurrentThread)) {
4195 AsyncMethodResult result;
4196 AsyncMethodData data;
4198 result = new AsyncMethodResult ();
4199 data = new AsyncMethodData ();
4202 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4203 data.Args = new object[] { hwnd, message, wParam, lParam };
4204 data.Result = result;
4206 SendAsyncMethod (data);
4207 #if DriverDebug || DriverDebugParent
4208 Console.WriteLine ("Sending {0} message across.", message);
4213 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4216 internal override void SetAllowDrop (IntPtr handle, bool value)
4218 // We allow drop on all windows
4221 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4222 DragDropEffects allowed_effects)
4224 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4227 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4229 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4232 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4235 hwnd = Hwnd.ObjectFromHandle(handle);
4237 Form form = Control.FromHandle (handle) as Form;
4238 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4239 border_style == FormBorderStyle.SizableToolWindow)) {
4240 form.window_manager = new InternalWindowManager (form);
4243 hwnd.border_style = border_style;
4244 RequestNCRecalc(handle);
4247 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4248 if (Caret.Hwnd == handle) {
4255 if (Caret.Visible == true) {
4257 Caret.Timer.Start();
4262 internal override void SetClipRegion(IntPtr handle, Region region) {
4265 hwnd = Hwnd.ObjectFromHandle(handle);
4270 hwnd.UserClip = region;
4271 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4274 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4277 if (OverrideCursorHandle == IntPtr.Zero) {
4278 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4282 LastCursorHandle = cursor;
4283 LastCursorWindow = handle;
4285 hwnd = Hwnd.ObjectFromHandle(handle);
4287 if (cursor != IntPtr.Zero) {
4288 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4290 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4292 XFlush(DisplayHandle);
4297 hwnd = Hwnd.ObjectFromHandle(handle);
4299 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4303 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4304 out int root_x, out int root_y, out int child_x, out int child_y,
4307 /* this code was written with the help of
4308 glance at gdk. I never would have realized we
4309 needed a loop in order to traverse down in the
4310 hierarchy. I would have assumed you'd get the
4311 most deeply nested child and have to do
4312 XQueryTree to move back up the hierarchy..
4313 stupid me, of course. */
4316 XGrabServer (display);
4318 XQueryPointer(display, w, out root, out c,
4319 out root_x, out root_y, out child_x, out child_y,
4325 IntPtr child_last = IntPtr.Zero;
4326 while (c != IntPtr.Zero) {
4328 XQueryPointer(display, c, out root, out c,
4329 out root_x, out root_y, out child_x, out child_y,
4332 XUngrabServer (display);
4337 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4338 if (handle == IntPtr.Zero) {
4341 int root_x, root_y, child_x, child_y, mask;
4344 * QueryPointer before warping
4345 * because if the warp is on
4346 * the RootWindow, the x/y are
4347 * relative to the current
4350 QueryPointer (DisplayHandle, RootWindow,
4353 out root_x, out root_y,
4354 out child_x, out child_y,
4357 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4359 XFlush (DisplayHandle);
4361 /* then we need to a
4362 * QueryPointer after warping
4363 * to manually generate a
4364 * motion event for the window
4367 QueryPointer (DisplayHandle, RootWindow,
4370 out root_x, out root_y,
4371 out child_x, out child_y,
4374 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4375 if (child_hwnd == null) {
4379 Control c = Control.FromHandle (child_hwnd.Handle);
4381 XEvent xevent = new XEvent ();
4383 xevent.type = XEventName.MotionNotify;
4384 xevent.MotionEvent.display = DisplayHandle;
4385 xevent.MotionEvent.window = child_hwnd.client_window;
4386 xevent.MotionEvent.root = RootWindow;
4387 xevent.MotionEvent.x = child_x;
4388 xevent.MotionEvent.y = child_y;
4389 xevent.MotionEvent.x_root = root_x;
4390 xevent.MotionEvent.y_root = root_y;
4391 xevent.MotionEvent.state = mask;
4393 child_hwnd.Queue.Enqueue (xevent);
4398 hwnd = Hwnd.ObjectFromHandle(handle);
4400 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4405 internal override void SetFocus(IntPtr handle) {
4407 IntPtr prev_focus_window;
4409 hwnd = Hwnd.ObjectFromHandle(handle);
4411 if (hwnd.client_window == FocusWindow) {
4415 prev_focus_window = FocusWindow;
4416 FocusWindow = hwnd.client_window;
4418 if (prev_focus_window != IntPtr.Zero) {
4419 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4421 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4423 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4426 internal override void SetIcon(IntPtr handle, Icon icon) {
4429 hwnd = Hwnd.ObjectFromHandle(handle);
4431 SetIcon(hwnd, icon);
4435 internal override void SetMenu(IntPtr handle, Menu menu) {
4438 hwnd = Hwnd.ObjectFromHandle(handle);
4441 RequestNCRecalc(handle);
4444 internal override void SetModal(IntPtr handle, bool Modal) {
4446 ModalWindows.Push(handle);
4448 if (ModalWindows.Contains(handle)) {
4451 if (ModalWindows.Count > 0) {
4452 Activate((IntPtr)ModalWindows.Peek());
4457 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4460 hwnd = Hwnd.ObjectFromHandle(handle);
4461 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4464 #if DriverDebug || DriverDebugParent
4465 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4467 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4473 internal override void SetTimer (Timer timer) {
4474 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4476 if (queue == null) {
4477 // This isn't really an error, MS doesn't start the timer if
4478 // it has no assosciated queue
4481 queue.timer_list.Add (timer);
4485 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4489 hwnd = Hwnd.ObjectFromHandle(handle);
4491 if (handle_owner != IntPtr.Zero) {
4492 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4503 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4504 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4506 if (hwnd_owner != null) {
4507 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4509 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4514 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4520 internal override bool SetVisible(IntPtr handle, bool visible) {
4523 hwnd = Hwnd.ObjectFromHandle(handle);
4524 hwnd.visible = visible;
4528 if (Control.FromHandle(handle) is Form) {
4531 s = ((Form)Control.FromHandle(handle)).WindowState;
4533 MapWindow(hwnd, WindowType.Both);
4536 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4537 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4541 MapWindow(hwnd, WindowType.Both);
4543 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4545 UnmapWindow(hwnd, WindowType.Whole);
4551 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4556 hwnd = Hwnd.ObjectFromHandle(handle);
4561 hints = new XSizeHints();
4563 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4564 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4565 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4566 hints.min_width = min.Width;
4567 hints.min_height = min.Height;
4570 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4571 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4572 hints.max_width = max.Width;
4573 hints.max_height = max.Height;
4576 if (hints.flags != IntPtr.Zero) {
4577 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4580 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4581 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4582 hints.x = maximized.X;
4583 hints.y = maximized.Y;
4584 hints.width = maximized.Width;
4585 hints.height = maximized.Height;
4587 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4588 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4593 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4596 hwnd = Hwnd.ObjectFromHandle(handle);
4602 // X requires a sanity check for width & height; otherwise it dies
4603 if (hwnd.zero_sized && width > 0 && height > 0) {
4605 MapWindow(hwnd, WindowType.Whole);
4607 hwnd.zero_sized = false;
4610 if ((width < 1) || (height < 1)) {
4611 hwnd.zero_sized = true;
4612 UnmapWindow(hwnd, WindowType.Whole);
4615 // Save a server roundtrip (and prevent a feedback loop)
4616 if ((hwnd.x == x) && (hwnd.y == y) &&
4617 (hwnd.width == width) && (hwnd.height == height)) {
4621 if (!hwnd.zero_sized) {
4626 hwnd.height = height;
4627 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4629 if (hwnd.fixed_size) {
4630 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4634 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4635 PerformNCCalc(hwnd);
4639 // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
4641 hwnd.height = height;
4644 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4645 FormWindowState current_state;
4648 hwnd = Hwnd.ObjectFromHandle(handle);
4651 current_state = GetWindowState(handle);
4653 catch (NotSupportedException) {
4654 current_state = (FormWindowState)(-1);
4657 if (current_state == state) {
4662 case FormWindowState.Normal: {
4664 if (current_state == FormWindowState.Minimized) {
4665 MapWindow(hwnd, WindowType.Both);
4666 } else if (current_state == FormWindowState.Maximized) {
4667 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4674 case FormWindowState.Minimized: {
4676 if (current_state == FormWindowState.Maximized) {
4677 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4679 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4684 case FormWindowState.Maximized: {
4686 if (current_state == FormWindowState.Minimized) {
4687 MapWindow(hwnd, WindowType.Both);
4690 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4698 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4701 hwnd = Hwnd.ObjectFromHandle(handle);
4702 SetHwndStyles(hwnd, cp);
4703 SetWMStyles(hwnd, cp);
4706 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4710 hwnd = Hwnd.ObjectFromHandle(handle);
4716 hwnd.opacity = (uint)(0xffffffff * transparency);
4717 opacity = (IntPtr)((int)hwnd.opacity);
4719 if (hwnd.reparented) {
4720 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4724 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4725 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4733 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4736 } else if (!bottom) {
4737 Hwnd after_hwnd = null;
4739 if (after_handle != IntPtr.Zero) {
4740 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4743 XWindowChanges values = new XWindowChanges();
4745 if (after_hwnd == null) {
4746 // Work around metacity 'issues'
4750 atoms[0] = unixtime();
4751 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4753 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4754 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
4756 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4759 values.sibling = after_hwnd.whole_window;
4760 values.stack_mode = StackMode.Below;
4763 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4768 XLowerWindow(DisplayHandle, hwnd.whole_window);
4775 internal override void ShowCursor(bool show) {
4776 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4779 internal override object StartLoop(Thread thread) {
4780 return (Object) ThreadQueue(thread);
4783 internal override bool SupportsTransparency() {
4784 // We need to check if the x compositing manager is running
4788 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4789 GetSystrayManagerWindow();
4791 if (SystrayMgrWindow != IntPtr.Zero) {
4792 XSizeHints size_hints;
4796 hwnd = Hwnd.ObjectFromHandle(handle);
4798 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4802 if (hwnd.client_window != hwnd.whole_window) {
4803 XDestroyWindow(DisplayHandle, hwnd.client_window);
4804 hwnd.client_window = hwnd.whole_window;
4807 size_hints = new XSizeHints();
4809 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints, out dummy);
4810 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4811 size_hints.min_width = icon.Width;
4812 size_hints.min_height = icon.Height;
4814 size_hints.max_width = icon.Width;
4815 size_hints.max_height = icon.Height;
4817 size_hints.base_width = icon.Width;
4818 size_hints.base_height = icon.Height;
4819 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4821 int[] atoms = new int[2];
4822 atoms [0] = 1; // Version 1
4823 atoms [1] = 1; // we want to be mapped
4825 // This line cost me 3 days...
4826 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4828 // Need to pick some reasonable defaults
4830 tt.AutomaticDelay = 100;
4831 tt.InitialDelay = 250;
4832 tt.ReshowDelay = 250;
4833 tt.ShowAlways = true;
4835 if ((tip != null) && (tip != string.Empty)) {
4836 tt.SetToolTip(Control.FromHandle(handle), tip);
4842 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4850 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4853 control = Control.FromHandle(handle);
4854 if (control != null && tt != null) {
4855 tt.SetToolTip(control, tip);
4863 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4865 #if GTKSOCKET_SUPPORTS_REPARENTING
4868 hwnd = Hwnd.ObjectFromHandle(handle);
4870 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4871 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4872 * 2. The client can reparent its window out of the embedder window.
4873 * 3. The client can destroy its window.
4875 * this call to SetParent is case 2, but in
4876 * the spec it also mentions that gtk doesn't
4877 * support this at present. Looking at HEAD
4878 * gtksocket-x11.c jives with this statement.
4880 * so we can't reparent. we have to destroy.
4882 SetParent(hwnd.whole_window, FosterParent);
4884 Control control = Control.FromHandle(handle);
4885 if (control is NotifyIcon.NotifyIconWindow)
4886 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
4889 // The caller can now re-dock it later...
4896 internal override bool Text(IntPtr handle, string text) {
4898 // FIXME - use _NET properties
4899 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4904 internal override bool TranslateMessage(ref MSG msg) {
4905 return Keyboard.TranslateMessage (ref msg);
4908 internal override void UpdateWindow(IntPtr handle) {
4911 hwnd = Hwnd.ObjectFromHandle(handle);
4913 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
4917 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4918 hwnd.Queue.Paint.Remove(hwnd);
4921 #endregion // Public Static Methods
4924 internal override event EventHandler Idle;
4925 #endregion // Events
4928 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4929 internal extern static IntPtr XOpenDisplay(IntPtr display);
4930 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4931 internal extern static int XCloseDisplay(IntPtr display);
4932 [DllImport ("libX11", EntryPoint="XSynchronize")]
4933 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4935 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4936 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);
4937 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4938 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4939 [DllImport ("libX11", EntryPoint="XMapWindow")]
4940 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4941 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4942 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4943 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4944 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4945 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4946 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4947 [DllImport ("libX11", EntryPoint="XRootWindow")]
4948 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4949 [DllImport ("libX11", EntryPoint="XNextEvent")]
4950 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4951 [DllImport ("libX11")]
4952 internal extern static int XConnectionNumber (IntPtr diplay);
4953 [DllImport ("libX11")]
4954 internal extern static int XPending (IntPtr diplay);
4955 [DllImport ("libX11", EntryPoint="XSelectInput")]
4956 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4958 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4959 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4961 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4962 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4963 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4964 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4966 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4967 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4969 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4970 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4972 [DllImport ("libX11", EntryPoint="XFlush")]
4973 internal extern static int XFlush(IntPtr display);
4975 [DllImport ("libX11", EntryPoint="XSetWMName")]
4976 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4978 [DllImport ("libX11", EntryPoint="XStoreName")]
4979 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
4981 [DllImport ("libX11", EntryPoint="XFetchName")]
4982 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
4984 [DllImport ("libX11", EntryPoint="XSendEvent")]
4985 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
4987 [DllImport ("libX11", EntryPoint="XQueryTree")]
4988 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);
4990 [DllImport ("libX11", EntryPoint="XFree")]
4991 internal extern static int XFree(IntPtr data);
4993 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
4994 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
4996 [DllImport ("libX11", EntryPoint="XLowerWindow")]
4997 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
4999 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5000 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5002 [DllImport ("libX11", EntryPoint="XInternAtom")]
5003 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5005 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5006 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5008 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5009 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);
5011 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5012 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5014 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5015 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);
5017 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5018 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);
5020 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5021 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);
5023 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5024 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);
5026 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5027 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);
5029 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5030 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);
5032 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5033 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);
5035 [DllImport ("libX11", EntryPoint="XClearWindow")]
5036 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5038 [DllImport ("libX11", EntryPoint="XClearArea")]
5039 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5042 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5043 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5045 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5046 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5048 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5049 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5051 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5052 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5054 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5055 internal extern static int XDefaultScreen(IntPtr display);
5057 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5058 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5060 [DllImport ("libX11", EntryPoint="XLookupColor")]
5061 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5063 [DllImport ("libX11", EntryPoint="XAllocColor")]
5064 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5066 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5067 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5069 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5070 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5072 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5073 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5075 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5076 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5078 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5079 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5081 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5082 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5084 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5085 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5087 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5088 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5090 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5091 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5093 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5094 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5096 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5097 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5100 [DllImport ("libX11", EntryPoint="XCreateGC")]
5101 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5103 [DllImport ("libX11", EntryPoint="XFreeGC")]
5104 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5106 [DllImport ("libX11", EntryPoint="XSetFunction")]
5107 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5109 [DllImport ("libX11", EntryPoint="XDrawLine")]
5110 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5112 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5113 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5115 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5116 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5118 [DllImport ("libX11", EntryPoint="XCopyArea")]
5119 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);
5121 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5122 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);
5124 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5125 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5127 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5128 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5130 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5131 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5133 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5134 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5136 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5137 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5139 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5140 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5142 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5143 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);
5145 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5146 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5148 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5149 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5151 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5152 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5154 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5155 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5157 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5158 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5160 [DllImport ("libX11", EntryPoint="XGrabServer")]
5161 internal extern static void XGrabServer(IntPtr display);
5163 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5164 internal extern static void XUngrabServer(IntPtr display);
5166 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5167 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5169 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5170 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5172 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5173 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5175 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5176 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5178 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5179 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5181 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5182 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5184 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5185 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5187 [DllImport ("libX11", EntryPoint="XInitThreads")]
5188 internal extern static int XInitThreads();
5190 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5191 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5193 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5194 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5196 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5197 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5199 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5200 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5202 [DllImport ("libX11", EntryPoint="XSetForeground")]
5203 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5205 [DllImport ("libX11", EntryPoint="XSetBackground")]
5206 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5208 [DllImport ("libX11", EntryPoint="XBell")]
5209 internal extern static int XBell(IntPtr display, int percent);
5211 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5212 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5214 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5215 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5217 [DllImport ("libX11")]
5218 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5220 [DllImport ("libX11")]
5221 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);