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.SubstructureNotifyMask);
225 static readonly object lockobj = new object ();
227 #endregion // Local Variables
229 private XplatUIX11() {
230 // Handle singleton stuff first
233 // Now regular initialization
234 XlibLock = new object ();
235 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
238 ErrorExceptions = false;
240 // X11 Initialization
241 SetDisplay(XOpenDisplay(IntPtr.Zero));
242 X11DesktopColors.Initialize();
245 // Disable keyboard autorepeat
247 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
248 detectable_key_auto_repeat = true;
250 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
251 detectable_key_auto_repeat = false;
254 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
255 ErrorHandler = new XErrorHandler(HandleError);
256 XSetErrorHandler(ErrorHandler);
260 // Remove our display handle from S.D
261 Graphics.FromHdcInternal (IntPtr.Zero);
264 #endregion // Constructors
266 #region Singleton Specific Code
267 public static XplatUIX11 GetInstance() {
269 if (Instance == null) {
270 Instance=new XplatUIX11();
277 public int Reference {
284 #region Internal Properties
285 internal static IntPtr Display {
287 return DisplayHandle;
291 XplatUIX11.GetInstance().SetDisplay(value);
295 internal static int Screen {
305 internal static IntPtr RootWindowHandle {
315 internal static IntPtr Visual {
321 CustomVisual = value;
325 internal static IntPtr ColorMap {
327 return CustomColormap;
331 CustomColormap = value;
336 #region XExceptionClass
337 internal class XException : ApplicationException {
341 XRequest RequestCode;
345 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
346 this.Display = Display;
347 this.ResourceID = ResourceID;
348 this.Serial = Serial;
349 this.RequestCode = RequestCode;
350 this.ErrorCode = ErrorCode;
351 this.MinorCode = MinorCode;
354 public override string Message {
356 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
360 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
369 sb = new StringBuilder(160);
370 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
371 x_error_text = sb.ToString();
372 hwnd = Hwnd.ObjectFromHandle(ResourceID);
374 hwnd_text = hwnd.ToString();
375 c = Control.FromHandle(hwnd.Handle);
377 control_text = c.ToString();
379 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
382 hwnd_text = "<null>";
383 control_text = "<null>";
387 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);
391 #endregion // XExceptionClass
393 #region Internal Methods
394 internal void SetDisplay(IntPtr display_handle) {
395 if (display_handle != IntPtr.Zero) {
398 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
399 hwnd = Hwnd.ObjectFromHandle(FosterParent);
400 XDestroyWindow(DisplayHandle, FosterParent);
404 if (DisplayHandle != IntPtr.Zero) {
405 XCloseDisplay(DisplayHandle);
408 DisplayHandle=display_handle;
410 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
411 // been hacked to do this for us.
412 Graphics.FromHdcInternal (DisplayHandle);
415 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
416 XSynchronize(DisplayHandle, true);
419 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
420 ErrorExceptions = true;
424 ScreenNo = XDefaultScreen(DisplayHandle);
425 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
426 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
428 // Create the foster parent
429 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
430 if (FosterParent==IntPtr.Zero) {
431 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
435 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
436 hwnd.WholeWindow = FosterParent;
437 hwnd.ClientWindow = FosterParent;
439 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
441 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
442 hwnd.whole_window = RootWindow;
443 hwnd.ClientWindow = RootWindow;
445 // For sleeping on the X11 socket
446 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
447 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
451 // To wake up when a timer is ready
452 network_buffer = new byte[10];
454 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
455 wake.Connect(listen.LocalEndPoint);
456 wake_receive = listen.Accept();
459 pollfds = new Pollfd [2];
460 pollfds [0] = new Pollfd ();
461 pollfds [0].fd = XConnectionNumber (DisplayHandle);
462 pollfds [0].events = PollEvents.POLLIN;
464 pollfds [1] = new Pollfd ();
465 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
466 pollfds [1].events = PollEvents.POLLIN;
469 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
470 Dnd = new X11Dnd (DisplayHandle);
472 DoubleClickInterval = 500;
474 HoverState.Interval = 500;
475 HoverState.Timer = new Timer();
476 HoverState.Timer.Enabled = false;
477 HoverState.Timer.Interval = HoverState.Interval;
478 HoverState.Timer.Tick += new EventHandler(MouseHover);
479 HoverState.Size = new Size(4, 4);
483 ActiveWindow = IntPtr.Zero;
484 FocusWindow = IntPtr.Zero;
485 ModalWindows = new Stack(3);
487 MouseState = MouseButtons.None;
488 MousePosition = new Point(0, 0);
490 Caret.Timer = new Timer();
491 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
492 Caret.Timer.Tick += new EventHandler(CaretCallback);
496 // Grab atom changes off the root window to catch certain WM events
497 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
499 // Handle any upcoming errors
500 ErrorHandler = new XErrorHandler(HandleError);
501 XSetErrorHandler(ErrorHandler);
503 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
507 internal static void Where() {
508 Console.WriteLine("Here: {0}\n", WhereString());
511 internal static string WhereString() {
519 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
520 unknown = Locale.GetText("<unknown method>");
521 sb = new StringBuilder();
522 stack = new StackTrace(true);
524 for (int i = 0; i < stack.FrameCount; i++) {
525 frame = stack.GetFrame(i);
528 method = frame.GetMethod();
529 if (method != null) {
531 sb.AppendFormat(frame.ToString());
533 if (frame.GetFileLineNumber() != 0) {
534 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
536 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
542 return sb.ToString();
544 #endregion // Internal Methods
546 #region Private Methods
547 private int unixtime() {
548 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
550 return (int) t.TotalSeconds;
553 private static void SetupAtoms() {
554 WM_PROTOCOLS = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
555 WM_DELETE_WINDOW = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
556 WM_TAKE_FOCUS = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
558 _NET_SUPPORTED = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
559 _NET_CLIENT_LIST = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
560 _NET_NUMBER_OF_DESKTOPS = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
561 _NET_DESKTOP_GEOMETRY = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
562 _NET_DESKTOP_VIEWPORT = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
563 _NET_CURRENT_DESKTOP = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
564 _NET_DESKTOP_NAMES = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
565 _NET_ACTIVE_WINDOW = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
566 _NET_WORKAREA = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
567 _NET_SUPPORTING_WM_CHECK = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
568 _NET_VIRTUAL_ROOTS = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
569 _NET_DESKTOP_LAYOUT = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
570 _NET_SHOWING_DESKTOP = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
572 _NET_CLOSE_WINDOW = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
573 _NET_MOVERESIZE_WINDOW = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
574 _NET_WM_MOVERESIZE = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
575 _NET_RESTACK_WINDOW = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
576 _NET_REQUEST_FRAME_EXTENTS = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
578 _NET_WM_NAME = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
579 _NET_WM_VISIBLE_NAME = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
580 _NET_WM_ICON_NAME = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
581 _NET_WM_VISIBLE_ICON_NAME = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
582 _NET_WM_DESKTOP = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
583 _NET_WM_WINDOW_TYPE = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
584 _NET_WM_STATE = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
585 _NET_WM_ALLOWED_ACTIONS = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
586 _NET_WM_STRUT = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
587 _NET_WM_STRUT_PARTIAL = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
588 _NET_WM_ICON_GEOMETRY = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
589 _NET_WM_ICON = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
590 _NET_WM_PID = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
591 _NET_WM_HANDLED_ICONS = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
592 _NET_WM_USER_TIME = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
593 _NET_FRAME_EXTENTS = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
595 _NET_WM_PING = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
596 _NET_WM_SYNC_REQUEST = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
598 _NET_SYSTEM_TRAY_S = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
599 _NET_SYSTEM_TRAY_OPCODE = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
600 _NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
602 _NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
603 _NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
604 _NET_WM_STATE_HIDDEN = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
606 _XEMBED = XInternAtom(DisplayHandle, "_XEMBED", false);
607 _XEMBED_INFO = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
609 _MOTIF_WM_HINTS = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
611 _NET_WM_STATE_NO_TASKBAR = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
612 _NET_WM_STATE_ABOVE = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
613 _NET_WM_STATE_MODAL = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
614 _NET_WM_CONTEXT_HELP = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
615 _NET_WM_WINDOW_OPACITY = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
617 _NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DESKTOP", false);
618 _NET_WM_WINDOW_TYPE_DOCK = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DOCK", false);
619 _NET_WM_WINDOW_TYPE_TOOLBAR = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_TOOLBAR", false);
620 _NET_WM_WINDOW_TYPE_MENU = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_MENU", false);
621 _NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_UTILITY", false);
622 _NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DIALOG", false);
623 _NET_WM_WINDOW_TYPE_SPLASH = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_SPLASH", false);
624 _NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_NORMAL", false);
627 CLIPBOARD = XInternAtom (DisplayHandle, "CLIPBOARD", false);
628 PRIMARY = XInternAtom (DisplayHandle, "PRIMARY", false);
629 DIB = (IntPtr)Atom.XA_PIXMAP;
630 OEMTEXT = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
631 UNICODETEXT = XInternAtom(DisplayHandle, "UTF8_STRING", false);
632 TARGETS = XInternAtom(DisplayHandle, "TARGETS", false);
635 AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
636 PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
637 HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
640 private void GetSystrayManagerWindow() {
641 XGrabServer(DisplayHandle);
642 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
643 XUngrabServer(DisplayHandle);
644 XFlush(DisplayHandle);
647 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
651 xev.ClientMessageEvent.type = XEventName.ClientMessage;
652 xev.ClientMessageEvent.send_event = true;
653 xev.ClientMessageEvent.window = window;
654 xev.ClientMessageEvent.message_type = message_type;
655 xev.ClientMessageEvent.format = 32;
656 xev.ClientMessageEvent.ptr1 = l0;
657 xev.ClientMessageEvent.ptr2 = l1;
658 xev.ClientMessageEvent.ptr3 = l2;
659 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
662 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
666 xev.ClientMessageEvent.type = XEventName.ClientMessage;
667 xev.ClientMessageEvent.send_event = true;
668 xev.ClientMessageEvent.window = window;
669 xev.ClientMessageEvent.message_type = message_type;
670 xev.ClientMessageEvent.format = 32;
671 xev.ClientMessageEvent.ptr1 = l0;
672 xev.ClientMessageEvent.ptr2 = l1;
673 xev.ClientMessageEvent.ptr3 = l2;
674 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
677 bool StyleSet (int s, WindowStyles ws)
679 return (s & (int)ws) == (int)ws;
682 bool ExStyleSet (int ex, WindowExStyles exws)
684 return (ex & (int)exws) == (int)exws;
687 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
689 // Only MDI windows get caption_heights
691 tool_caption_height = 19;
693 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
694 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
695 border_style = FormBorderStyle.Fixed3D;
696 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
697 border_style = FormBorderStyle.None;
699 border_style = FormBorderStyle.FixedSingle;
701 title_style = TitleStyle.None;
703 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
706 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
707 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
708 title_style = TitleStyle.Tool;
710 title_style = TitleStyle.Normal;
714 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
715 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
716 border_style = (FormBorderStyle) 0xFFFF;
718 border_style = FormBorderStyle.None;
723 title_style = TitleStyle.None;
724 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
725 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
726 title_style = TitleStyle.Tool;
728 title_style = TitleStyle.Normal;
732 border_style = FormBorderStyle.None;
734 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
735 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
736 border_style = FormBorderStyle.SizableToolWindow;
738 border_style = FormBorderStyle.Sizable;
741 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
742 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
743 border_style = FormBorderStyle.Fixed3D;
744 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
745 border_style = FormBorderStyle.FixedDialog;
746 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
747 border_style = FormBorderStyle.FixedToolWindow;
748 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
749 border_style = FormBorderStyle.FixedSingle;
752 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
753 border_style = FormBorderStyle.FixedSingle;
760 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
761 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
764 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
765 MotifWmHints mwmHints;
766 MotifFunctions functions;
767 MotifDecorations decorations;
770 Rectangle client_rect;
772 // Child windows don't need WM window styles
773 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
778 mwmHints = new MotifWmHints();
782 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
783 mwmHints.functions = (IntPtr)0;
784 mwmHints.decorations = (IntPtr)0;
786 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
787 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
788 /* tool windows get no window manager
789 decorations, and neither do windows
790 which lack CAPTION/BORDER/DLGFRAME
794 /* just because the window doesn't get any decorations doesn't
795 mean we should disable the functions. for instance, without
796 MotifFunctions.Maximize, changing the windowstate to Maximized
797 is ignored by metacity. */
798 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
801 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
802 functions |= MotifFunctions.Move;
803 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
806 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
807 functions |= MotifFunctions.Move | MotifFunctions.Resize;
808 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
811 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
812 functions |= MotifFunctions.Minimize;
813 decorations |= MotifDecorations.Minimize;
816 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
817 functions |= MotifFunctions.Maximize;
818 decorations |= MotifDecorations.Maximize;
821 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
822 functions |= MotifFunctions.Resize;
823 decorations |= MotifDecorations.ResizeH;
826 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
827 decorations |= MotifDecorations.Border;
830 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
831 decorations |= MotifDecorations.Border;
834 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
835 decorations |= MotifDecorations.Border;
838 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
839 functions |= MotifFunctions.Close;
842 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
843 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
844 if (cp.Caption == "") {
845 functions &= ~MotifFunctions.Move;
846 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
851 if ((functions & MotifFunctions.Resize) == 0) {
852 hwnd.fixed_size = true;
853 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));
855 hwnd.fixed_size = false;
858 mwmHints.functions = (IntPtr)functions;
859 mwmHints.decorations = (IntPtr)decorations;
861 FormWindowState current_state = FormWindowState.Normal;
863 current_state = GetWindowState (hwnd.Handle);
865 catch (NotSupportedException) {
868 client_rect = hwnd.ClientRect;
870 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
871 // and get those windows in front of their parents
872 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
873 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
874 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
875 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
878 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
879 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
880 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
881 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
883 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
884 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
885 // XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
887 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
888 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
890 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
895 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
896 atoms[atom_count++] = _NET_WM_STATE_NO_TASKBAR.ToInt32();
898 /* we need to add these atoms in the
899 * event we're maximized, since we're
900 * replacing the existing
901 * _NET_WM_STATE here. If we don't
902 * add them, future calls to
903 * GetWindowState will return Normal
904 * for a window which is maximized. */
905 if (current_state == FormWindowState.Maximized) {
906 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
907 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
909 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
912 IntPtr[] atom_ptrs = new IntPtr[2];
913 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
914 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
915 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
918 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
922 private void SetIcon(Hwnd hwnd, Icon icon) {
928 bitmap = icon.ToBitmap();
930 size = bitmap.Width * bitmap.Height + 2;
931 data = new IntPtr[size];
933 data[index++] = (IntPtr)bitmap.Width;
934 data[index++] = (IntPtr)bitmap.Height;
936 for (int y = 0; y < bitmap.Height; y++) {
937 for (int x = 0; x < bitmap.Width; x++) {
938 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
942 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
945 private IntPtr ImageToPixmap(Image image) {
949 private void WakeupMain () {
950 wake.Send (new byte [] { 0xFF });
953 private XEventQueue ThreadQueue(Thread thread) {
956 queue = (XEventQueue)MessageQueues[thread];
958 queue = new XEventQueue(thread);
959 MessageQueues[thread] = queue;
965 private void TranslatePropertyToClipboard(IntPtr property) {
970 IntPtr prop = IntPtr.Zero;
972 Clipboard.Item = null;
974 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);
976 if ((long)nitems > 0) {
977 if (property == (IntPtr)Atom.XA_STRING) {
978 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
979 } else if (property == (IntPtr)Atom.XA_BITMAP) {
980 // FIXME - convert bitmap to image
981 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
982 // FIXME - convert pixmap to image
983 } else if (property == OEMTEXT) {
984 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
985 } else if (property == UNICODETEXT) {
986 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
993 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
995 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
999 // Keep the invalid area as small as needed
1000 if ((x + width) > hwnd.width) {
1001 width = hwnd.width - x;
1004 if ((y + height) > hwnd.height) {
1005 height = hwnd.height - y;
1009 hwnd.AddInvalidArea(x, y, width, height);
1010 if (!hwnd.expose_pending) {
1011 if (!hwnd.nc_expose_pending) {
1012 hwnd.Queue.Paint.Enqueue(hwnd);
1014 hwnd.expose_pending = true;
1017 hwnd.AddNcInvalidArea (x, y, width, height);
1019 if (!hwnd.nc_expose_pending) {
1020 if (!hwnd.expose_pending) {
1021 hwnd.Queue.Paint.Enqueue(hwnd);
1023 hwnd.nc_expose_pending = true;
1028 private void InvalidateWholeWindow(IntPtr handle) {
1031 hwnd = Hwnd.ObjectFromHandle(handle);
1033 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
1036 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
1039 hwnd = Hwnd.ObjectFromHandle(handle);
1041 AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
1044 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
1050 hwnd = Hwnd.ObjectFromHandle(handle);
1053 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1060 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
1081 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
1082 if (win == window) {
1088 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
1092 if (children != IntPtr.Zero) {
1096 } while (win != root);
1101 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
1104 private void FrameExtents(IntPtr window, out int left, out int top) {
1109 IntPtr prop = IntPtr.Zero;
1111 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);
1112 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1113 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1114 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1115 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1116 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1122 if (prop != IntPtr.Zero) {
1128 private void AddConfigureNotify (XEvent xevent) {
1131 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1138 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1139 if (!hwnd.reparented) {
1140 hwnd.x = xevent.ConfigureEvent.x;
1141 hwnd.y = xevent.ConfigureEvent.y;
1143 // This sucks ass, part 1
1144 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1145 // no standard way of getting our adjustment.
1146 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1147 // Several other WMs do their decorations different yet again and we fail to deal
1148 // with that, since I couldn't find any frigging commonality between them.
1149 // The only sane WM seems to be KDE
1151 if (!xevent.ConfigureEvent.send_event) {
1154 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1156 // This is a synthetic event, coordinates are in root space
1157 hwnd.x = xevent.ConfigureEvent.x;
1158 hwnd.y = xevent.ConfigureEvent.y;
1159 if (hwnd.whacky_wm) {
1163 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1164 hwnd.x -= frame_left;
1165 hwnd.y -= frame_top;
1169 hwnd.width = xevent.ConfigureEvent.width;
1170 hwnd.height = xevent.ConfigureEvent.height;
1171 hwnd.ClientRect = Rectangle.Empty;
1173 if (!hwnd.configure_pending) {
1174 hwnd.Queue.Enqueue(xevent);
1175 hwnd.configure_pending = true;
1178 // We drop configure events for Client windows
1181 private void ShowCaret() {
1182 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1188 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1192 private void HideCaret() {
1193 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1199 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1203 private int NextTimeout (ArrayList timers, DateTime now) {
1204 int timeout = Int32.MaxValue;
1206 foreach (Timer timer in timers) {
1207 int next = (int) (timer.Expires - now).TotalMilliseconds;
1209 return 0; // Have a timer that has already expired
1212 if (next < timeout) {
1216 if (timeout < Timer.Minimum) {
1217 timeout = Timer.Minimum;
1225 private void CheckTimers (ArrayList timers, DateTime now) {
1228 count = timers.Count;
1233 for (int i = 0; i < timers.Count; i++) {
1236 timer = (Timer) timers [i];
1238 if (timer.Enabled && timer.Expires <= now) {
1245 private void MapWindow(Hwnd hwnd, WindowType windows) {
1247 if ((windows & WindowType.Whole) != 0) {
1248 XMapWindow(DisplayHandle, hwnd.whole_window);
1250 if ((windows & WindowType.Client) != 0) {
1251 XMapWindow(DisplayHandle, hwnd.client_window);
1255 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1256 hwnd.mapped = false;
1257 if ((windows & WindowType.Whole) != 0) {
1258 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1260 if ((windows & WindowType.Client) != 0) {
1261 XUnmapWindow(DisplayHandle, hwnd.client_window);
1265 private void UpdateMessageQueue (XEventQueue queue) {
1270 now = DateTime.UtcNow;
1273 pending = XPending (DisplayHandle);
1277 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1278 Idle (this, EventArgs.Empty);
1282 pending = XPending (DisplayHandle);
1289 if (queue != null) {
1290 if (queue.Paint.Count > 0)
1293 timeout = NextTimeout (queue.timer_list, now);
1298 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1299 // Clean out buffer, so we're not busy-looping on the same data
1300 if (pollfds[1].revents != 0) {
1301 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1305 pending = XPending (DisplayHandle);
1311 CheckTimers (queue.timer_list, now);
1314 XEvent xevent = new XEvent ();
1317 if (XPending (DisplayHandle) == 0)
1320 XNextEvent (DisplayHandle, ref xevent);
1322 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1323 if (XFilterEvent(ref xevent, FosterParent)) {
1329 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1331 if (xevent.type == XEventName.Expose) {
1336 switch (xevent.type) {
1337 case XEventName.Expose:
1338 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1341 case XEventName.SelectionClear: {
1342 // Should we do something?
1346 case XEventName.SelectionRequest: {
1347 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1351 sel_event = new XEvent();
1352 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1353 sel_event.SelectionEvent.send_event = true;
1354 sel_event.SelectionEvent.display = DisplayHandle;
1355 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1356 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1357 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1358 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1359 sel_event.SelectionEvent.property = IntPtr.Zero;
1361 // Seems that some apps support asking for supported types
1362 if (xevent.SelectionEvent.target == TARGETS) {
1369 if (Clipboard.Item is String) {
1370 atoms[atom_count++] = (int)Atom.XA_STRING;
1371 atoms[atom_count++] = (int)OEMTEXT;
1372 atoms[atom_count++] = (int)UNICODETEXT;
1373 } else if (Clipboard.Item is Image) {
1374 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1375 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1377 // FIXME - handle other types
1380 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1381 } else if (Clipboard.Item is string) {
1387 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1390 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1391 buffer = Marshal.AllocHGlobal(bytes.Length);
1392 buflen = bytes.Length;
1394 for (int i = 0; i < buflen; i++) {
1395 Marshal.WriteByte(buffer, i, bytes[i]);
1397 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1398 // FIXME - this should encode into ISO2022
1399 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1400 while (Marshal.ReadByte(buffer, buflen) != 0) {
1403 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1404 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1405 while (Marshal.ReadByte(buffer, buflen) != 0) {
1409 buffer = IntPtr.Zero;
1412 if (buffer != IntPtr.Zero) {
1413 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1414 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1415 Marshal.FreeHGlobal(buffer);
1417 } else if (Clipboard.Item is Image) {
1418 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1419 // FIXME - convert image and store as property
1420 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1421 // FIXME - convert image and store as property
1425 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1429 case XEventName.SelectionNotify: {
1430 if (Clipboard.Enumerating) {
1431 Clipboard.Enumerating = false;
1432 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1433 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1434 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1435 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1436 #if DriverDebugExtra
1437 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1441 } else if (Clipboard.Retrieving) {
1442 Clipboard.Retrieving = false;
1443 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1444 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1446 Clipboard.Item = null;
1449 Dnd.HandleSelectionNotifyEvent (ref xevent);
1454 case XEventName.MapNotify: {
1455 if (hwnd.client_window == xevent.MapEvent.window) {
1461 case XEventName.UnmapNotify: {
1462 if (hwnd.client_window == xevent.MapEvent.window) {
1463 hwnd.mapped = false;
1468 case XEventName.KeyRelease:
1469 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1470 XEvent nextevent = new XEvent ();
1472 XPeekEvent (DisplayHandle, ref nextevent);
1474 if (nextevent.type == XEventName.KeyPress &&
1475 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1476 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1480 goto case XEventName.KeyPress;
1482 case XEventName.MotionNotify: {
1485 if (hwnd.Queue.Count > 0) {
1486 peek = hwnd.Queue.Peek();
1487 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1491 goto case XEventName.KeyPress;
1494 case XEventName.KeyPress:
1495 case XEventName.ButtonPress:
1496 case XEventName.ButtonRelease:
1497 case XEventName.EnterNotify:
1498 case XEventName.LeaveNotify:
1499 case XEventName.CreateNotify:
1500 case XEventName.DestroyNotify:
1501 case XEventName.FocusIn:
1502 case XEventName.FocusOut:
1503 case XEventName.ClientMessage:
1504 case XEventName.ReparentNotify:
1505 hwnd.Queue.Enqueue (xevent);
1508 case XEventName.ConfigureNotify:
1509 AddConfigureNotify(xevent);
1512 case XEventName.PropertyNotify:
1513 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1518 IntPtr prop = IntPtr.Zero;
1519 IntPtr prev_active;;
1521 prev_active = ActiveWindow;
1522 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);
1523 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1524 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1527 if (prev_active != ActiveWindow) {
1528 if (prev_active != IntPtr.Zero) {
1529 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1531 if (ActiveWindow != IntPtr.Zero) {
1532 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1535 if (ModalWindows.Count == 0) {
1538 // Modality handling, if we are modal and the new active window is one
1539 // of ours but not the modal one, switch back to the modal window
1541 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1542 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1543 Activate((IntPtr)ModalWindows.Peek());
1556 private IntPtr GetMousewParam(int Delta) {
1559 if ((MouseState & MouseButtons.Left) != 0) {
1560 result |= (int)MsgButtons.MK_LBUTTON;
1563 if ((MouseState & MouseButtons.Middle) != 0) {
1564 result |= (int)MsgButtons.MK_MBUTTON;
1567 if ((MouseState & MouseButtons.Right) != 0) {
1568 result |= (int)MsgButtons.MK_RBUTTON;
1571 Keys mods = ModifierKeys;
1572 if ((mods & Keys.Control) != 0) {
1573 result |= (int)MsgButtons.MK_CONTROL;
1576 if ((mods & Keys.Shift) != 0) {
1577 result |= (int)MsgButtons.MK_SHIFT;
1580 result |= Delta << 16;
1582 return (IntPtr)result;
1584 private IntPtr XGetParent(IntPtr handle) {
1591 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1594 if (Children!=IntPtr.Zero) {
1602 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1603 if (ErrorExceptions) {
1604 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1606 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());
1611 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1614 Control[] controls = c.child_controls.GetAllControls ();
1616 if (c.IsHandleCreated && !c.IsDisposed) {
1617 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1619 list.Add (hwnd.Handle);
1620 CleanupCachedWindows (hwnd);
1624 for (int i = 0; i < controls.Length; i ++) {
1625 AccumulateDestroyedHandles (controls[i], list);
1631 private void SendWMDestroyMessages(ArrayList handles) {
1632 foreach (IntPtr handle in handles) {
1633 SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1637 void CleanupCachedWindows (Hwnd hwnd)
1639 if (ActiveWindow == hwnd.Handle) {
1640 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1641 ActiveWindow = IntPtr.Zero;
1644 if (FocusWindow == hwnd.Handle) {
1645 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1646 FocusWindow = IntPtr.Zero;
1649 DestroyCaret (hwnd.Handle);
1652 private void PerformNCCalc(Hwnd hwnd) {
1653 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1657 rect = hwnd.DefaultClientRect;
1659 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1660 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1662 ncp.rgrc1.left = rect.Left;
1663 ncp.rgrc1.top = rect.Top;
1664 ncp.rgrc1.right = rect.Right;
1665 ncp.rgrc1.bottom = rect.Bottom;
1667 Marshal.StructureToPtr(ncp, ptr, true);
1668 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1669 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1670 Marshal.FreeHGlobal(ptr);
1672 // FIXME - debug this with Menus
1674 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1675 hwnd.ClientRect = rect;
1678 if ((rect.Width < 1) || (rect.Height < 1)) {
1679 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1681 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1685 #endregion // Private Methods
1688 private void MouseHover(object sender, EventArgs e) {
1692 HoverState.Timer.Enabled = false;
1694 if (HoverState.Window != IntPtr.Zero) {
1695 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1697 xevent = new XEvent ();
1699 xevent.type = XEventName.ClientMessage;
1700 xevent.ClientMessageEvent.display = DisplayHandle;
1701 xevent.ClientMessageEvent.window = HoverState.Window;
1702 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1703 xevent.ClientMessageEvent.format = 32;
1704 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1706 hwnd.Queue.EnqueueLocked (xevent);
1713 private void CaretCallback(object sender, EventArgs e) {
1717 Caret.On = !Caret.On;
1719 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1721 #endregion // Callbacks
1723 #region Public Properties
1725 internal override int Caption {
1731 internal override Size CursorSize {
1736 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1737 return new Size(x, y);
1739 return new Size(16, 16);
1744 internal override bool DragFullWindows {
1750 internal override Size DragSize {
1752 return new Size(4, 4);
1756 internal override Size FrameBorderSize {
1758 throw new NotImplementedException();
1762 internal override Size IconSize {
1768 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1772 current = (long)list;
1775 size = new XIconSize();
1777 for (int i = 0; i < count; i++) {
1778 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1779 current += Marshal.SizeOf(size);
1781 // Look for our preferred size
1782 if (size.min_width == 32) {
1784 return new Size(32, 32);
1787 if (size.max_width == 32) {
1789 return new Size(32, 32);
1792 if (size.min_width < 32 && size.max_width > 32) {
1795 // check if we can fit one
1797 while (x < size.max_width) {
1798 x += size.width_inc;
1801 return new Size(32, 32);
1806 if (largest < size.max_width) {
1807 largest = size.max_width;
1811 // We didn't find a match or we wouldn't be here
1812 return new Size(largest, largest);
1815 return new Size(32, 32);
1820 internal override int KeyboardSpeed {
1823 // A lot harder: need to do:
1824 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1825 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1826 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1828 // And from that we can tell the repetition rate
1830 // Notice, the values must map to:
1831 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1837 internal override int KeyboardDelay {
1840 // Return values must range from 0 to 4, 0 meaning 250ms,
1841 // and 4 meaning 1000 ms.
1843 return 1; // ie, 500 ms
1847 internal override Size MaxWindowTrackSize {
1849 return new Size (WorkingArea.Width, WorkingArea.Height);
1853 internal override Size MinimizedWindowSize {
1855 return new Size(1, 1);
1859 internal override Size MinimizedWindowSpacingSize {
1861 return new Size(1, 1);
1865 internal override Size MinimumWindowSize {
1867 return new Size(1, 1);
1871 internal override Size MinWindowTrackSize {
1873 return new Size(1, 1);
1877 internal override Keys ModifierKeys {
1879 return Keyboard.ModifierKeys;
1883 internal override Size SmallIconSize {
1889 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1893 current = (long)list;
1896 size = new XIconSize();
1898 for (int i = 0; i < count; i++) {
1899 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1900 current += Marshal.SizeOf(size);
1902 // Look for our preferred size
1903 if (size.min_width == 16) {
1905 return new Size(16, 16);
1908 if (size.max_width == 16) {
1910 return new Size(16, 16);
1913 if (size.min_width < 16 && size.max_width > 16) {
1916 // check if we can fit one
1918 while (x < size.max_width) {
1919 x += size.width_inc;
1922 return new Size(16, 16);
1927 if (smallest == 0 || smallest > size.min_width) {
1928 smallest = size.min_width;
1932 // We didn't find a match or we wouldn't be here
1933 return new Size(smallest, smallest);
1936 return new Size(16, 16);
1941 internal override int MouseButtonCount {
1947 internal override bool MouseButtonsSwapped {
1949 return false; // FIXME - how to detect?
1953 internal override Size MouseHoverSize {
1955 return new Size (1, 1);
1959 internal override int MouseHoverTime {
1961 return HoverState.Interval;
1967 internal override bool MouseWheelPresent {
1969 return true; // FIXME - how to detect?
1973 internal override Rectangle VirtualScreen {
1979 internal override Rectangle WorkingArea {
1985 IntPtr prop = IntPtr.Zero;
1988 int current_desktop;
1992 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);
1993 if ((long)nitems < 1) {
1997 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2000 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);
2001 if ((long)nitems < 4 * current_desktop) {
2005 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2006 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2007 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2008 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2011 return new Rectangle(x, y, width, height);
2014 XWindowAttributes attributes=new XWindowAttributes();
2017 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2020 return new Rectangle(0, 0, attributes.width, attributes.height);
2024 internal override bool ThemesEnabled {
2026 return XplatUIX11.themes_enabled;
2031 #endregion // Public properties
2033 #region Public Static Methods
2034 internal override IntPtr InitializeDriver() {
2036 if (DisplayHandle==IntPtr.Zero) {
2037 SetDisplay(XOpenDisplay(IntPtr.Zero));
2043 internal override void ShutdownDriver(IntPtr token) {
2045 if (DisplayHandle!=IntPtr.Zero) {
2046 XCloseDisplay(DisplayHandle);
2047 DisplayHandle=IntPtr.Zero;
2052 internal override void EnableThemes() {
2053 themes_enabled = true;
2057 internal override void Activate(IntPtr handle) {
2060 hwnd = Hwnd.ObjectFromHandle(handle);
2062 if (hwnd != null) lock (XlibLock) {
2063 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
2064 //XRaiseWindow(DisplayHandle, handle);
2069 internal override void AudibleAlert() {
2070 XBell(DisplayHandle, 0);
2075 internal override void CaretVisible(IntPtr handle, bool visible) {
2076 if (Caret.Hwnd == handle) {
2078 if (!Caret.Visible) {
2079 Caret.Visible = true;
2081 Caret.Timer.Start();
2084 Caret.Visible = false;
2091 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2092 FormBorderStyle border_style;
2093 TitleStyle title_style;
2095 int tool_caption_height;
2097 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2098 out caption_height, out tool_caption_height);
2100 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2101 caption_height, tool_caption_height,
2106 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2112 hwnd = Hwnd.ObjectFromHandle(handle);
2115 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2122 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2123 DataFormats.Format f;
2126 f = DataFormats.Format.List;
2128 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2132 Clipboard.Formats = new ArrayList();
2135 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2137 Clipboard.Enumerating = true;
2138 while (Clipboard.Enumerating) {
2139 UpdateMessageQueue(null);
2144 result = new int[Clipboard.Formats.Count];
2146 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2147 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2150 Clipboard.Formats = null;
2154 internal override void ClipboardClose(IntPtr handle) {
2155 if (handle != ClipMagic) {
2156 throw new ArgumentException("handle is not a valid clipboard handle");
2161 internal override int ClipboardGetID(IntPtr handle, string format) {
2162 if (handle != ClipMagic) {
2163 throw new ArgumentException("handle is not a valid clipboard handle");
2166 if (format == "Text" ) return (int)Atom.XA_STRING;
2167 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2168 //else if (format == "MetaFilePict" ) return 3;
2169 //else if (format == "SymbolicLink" ) return 4;
2170 //else if (format == "DataInterchangeFormat" ) return 5;
2171 //else if (format == "Tiff" ) return 6;
2172 else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
2173 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2174 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2175 //else if (format == "PenData" ) return 10;
2176 //else if (format == "RiffAudio" ) return 11;
2177 //else if (format == "WaveAudio" ) return 12;
2178 else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
2179 //else if (format == "EnhancedMetafile" ) return 14;
2180 //else if (format == "FileDrop" ) return 15;
2181 //else if (format == "Locale" ) return 16;
2183 return XInternAtom(DisplayHandle, format, false).ToInt32();
2186 internal override IntPtr ClipboardOpen(bool primary_selection) {
2187 if (!primary_selection)
2188 ClipMagic = CLIPBOARD;
2190 ClipMagic = PRIMARY;
2194 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2195 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2197 Clipboard.Retrieving = true;
2198 while (Clipboard.Retrieving) {
2199 UpdateMessageQueue(null);
2202 return Clipboard.Item;
2205 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2206 Clipboard.Item = obj;
2207 Clipboard.Type = type;
2208 Clipboard.Converter = converter;
2211 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2213 // Clearing the selection
2214 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2218 internal override void CreateCaret(IntPtr handle, int width, int height) {
2219 XGCValues gc_values;
2222 hwnd = Hwnd.ObjectFromHandle(handle);
2224 if (Caret.Hwnd != IntPtr.Zero) {
2225 DestroyCaret(Caret.Hwnd);
2228 Caret.Hwnd = handle;
2229 Caret.Window = hwnd.client_window;
2230 Caret.Width = width;
2231 Caret.Height = height;
2232 Caret.Visible = false;
2235 gc_values = new XGCValues();
2236 gc_values.line_width = width;
2238 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2239 if (Caret.gc == IntPtr.Zero) {
2240 Caret.Hwnd = IntPtr.Zero;
2244 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2247 internal override IntPtr CreateWindow(CreateParams cp) {
2248 XSetWindowAttributes Attributes;
2254 IntPtr ParentHandle;
2256 IntPtr ClientWindow;
2257 Rectangle ClientRect;
2258 SetWindowValuemask ValueMask;
2263 Attributes = new XSetWindowAttributes();
2269 if (Width<1) Width=1;
2270 if (Height<1) Height=1;
2272 if (cp.Parent != IntPtr.Zero) {
2273 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2275 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2276 // We need to use our foster parent window until this poor child gets it's parent assigned
2277 ParentHandle=FosterParent;
2278 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2279 ParentHandle=RootWindow;
2281 // Default position on screen, if window manager doesn't place us somewhere else
2284 ParentHandle=RootWindow;
2288 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2290 Attributes.bit_gravity = Gravity.NorthWestGravity;
2291 Attributes.win_gravity = Gravity.NorthWestGravity;
2293 // Save what's under the toolwindow
2294 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2295 Attributes.save_under = true;
2296 ValueMask |= SetWindowValuemask.SaveUnder;
2300 // If we're a popup without caption we override the WM
2301 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2302 Attributes.override_redirect = true;
2303 ValueMask |= SetWindowValuemask.OverrideRedirect;
2309 hwnd.height = Height;
2310 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2312 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2313 hwnd.enabled = false;
2316 ClientRect = hwnd.ClientRect;
2317 ClientWindow = IntPtr.Zero;
2320 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2321 if (WholeWindow != IntPtr.Zero) {
2322 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2324 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2325 ValueMask = SetWindowValuemask.ColorMap;
2326 Attributes.colormap = CustomColormap;
2328 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);
2332 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2333 throw new Exception("Could not create X11 windows");
2336 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2337 hwnd.WholeWindow = WholeWindow;
2338 hwnd.ClientWindow = ClientWindow;
2340 #if DriverDebug || DriverDebugCreate
2341 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);
2344 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2345 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2348 hints = new XSizeHints();
2351 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2352 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2357 EventMask whole_window_mask = SelectInputMask;
2358 /* if we're a toplevel form, we want
2359 * to know about user-driven resizes.
2360 * otherwise, ignore them. */
2361 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD))
2362 whole_window_mask |= EventMask.StructureNotifyMask;
2363 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)whole_window_mask));
2364 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2366 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2367 MapWindow(hwnd, WindowType.Both);
2368 hwnd.visible = true;
2372 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2374 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2375 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2377 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2378 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
2379 // XSetTransientForHint (DisplayHandle, hwnd.whole_window, FosterParent);
2382 SetWMStyles(hwnd, cp);
2384 // set the group leader
2385 XWMHints wm_hints = new XWMHints ();
2387 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2388 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2389 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2391 if (ParentHandle != RootWindow) {
2392 wm_hints.window_group = hwnd.whole_window;
2394 wm_hints.window_group = ParentHandle;
2398 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2401 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2402 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2403 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2404 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2407 // for now make all windows dnd enabled
2408 Dnd.SetAllowDrop (hwnd, true);
2410 // Set caption/window title
2411 Text(hwnd.Handle, cp.Caption);
2416 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2417 CreateParams create_params = new CreateParams();
2419 create_params.Caption = "";
2420 create_params.X = X;
2421 create_params.Y = Y;
2422 create_params.Width = Width;
2423 create_params.Height = Height;
2425 create_params.ClassName=XplatUI.DefaultClassName;
2426 create_params.ClassStyle = 0;
2427 create_params.ExStyle=0;
2428 create_params.Parent=IntPtr.Zero;
2429 create_params.Param=0;
2431 return CreateWindow(create_params);
2434 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2436 Bitmap cursor_bitmap;
2444 IntPtr cursor_pixmap;
2451 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2455 // Win32 only allows creation cursors of a certain size
2456 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2457 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2458 cursor_mask = new Bitmap(mask, new Size(width, height));
2460 cursor_bitmap = bitmap;
2464 width = cursor_bitmap.Width;
2465 height = cursor_bitmap.Height;
2467 cursor_bits = new Byte[(width / 8) * height];
2468 mask_bits = new Byte[(width / 8) * height];
2470 for (int y = 0; y < height; y++) {
2471 for (int x = 0; x < width; x++) {
2472 c_pixel = cursor_bitmap.GetPixel(x, y);
2473 m_pixel = cursor_mask.GetPixel(x, y);
2475 and = c_pixel == cursor_pixel;
2476 xor = m_pixel == mask_pixel;
2480 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2481 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2482 } else if (and && !xor) {
2484 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2485 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2487 } else if (and && !xor) {
2489 } else if (and && xor) {
2492 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2493 // we want both to be 0 so nothing to be done
2494 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2495 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2501 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2502 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2506 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2507 fg.red = (ushort)65535;
2508 fg.green = (ushort)65535;
2509 fg.blue = (ushort)65535;
2511 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2513 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2515 XFreePixmap(DisplayHandle, cursor_pixmap);
2516 XFreePixmap(DisplayHandle, mask_pixmap);
2521 internal override IntPtr DefineStdCursor(StdCursor id) {
2522 CursorFontShape shape;
2525 // FIXME - define missing shapes
2528 case StdCursor.AppStarting: {
2529 shape = CursorFontShape.XC_watch;
2533 case StdCursor.Arrow: {
2534 shape = CursorFontShape.XC_top_left_arrow;
2538 case StdCursor.Cross: {
2539 shape = CursorFontShape.XC_crosshair;
2543 case StdCursor.Default: {
2544 shape = CursorFontShape.XC_top_left_arrow;
2548 case StdCursor.Hand: {
2549 shape = CursorFontShape.XC_hand1;
2553 case StdCursor.Help: {
2554 shape = CursorFontShape.XC_question_arrow;
2558 case StdCursor.HSplit: {
2559 shape = CursorFontShape.XC_sb_v_double_arrow;
2563 case StdCursor.IBeam: {
2564 shape = CursorFontShape.XC_xterm;
2568 case StdCursor.No: {
2569 shape = CursorFontShape.XC_circle;
2573 case StdCursor.NoMove2D: {
2574 shape = CursorFontShape.XC_fleur;
2578 case StdCursor.NoMoveHoriz: {
2579 shape = CursorFontShape.XC_fleur;
2583 case StdCursor.NoMoveVert: {
2584 shape = CursorFontShape.XC_fleur;
2588 case StdCursor.PanEast: {
2589 shape = CursorFontShape.XC_fleur;
2593 case StdCursor.PanNE: {
2594 shape = CursorFontShape.XC_fleur;
2598 case StdCursor.PanNorth: {
2599 shape = CursorFontShape.XC_fleur;
2603 case StdCursor.PanNW: {
2604 shape = CursorFontShape.XC_fleur;
2608 case StdCursor.PanSE: {
2609 shape = CursorFontShape.XC_fleur;
2613 case StdCursor.PanSouth: {
2614 shape = CursorFontShape.XC_fleur;
2618 case StdCursor.PanSW: {
2619 shape = CursorFontShape.XC_fleur;
2623 case StdCursor.PanWest: {
2624 shape = CursorFontShape.XC_sizing;
2628 case StdCursor.SizeAll: {
2629 shape = CursorFontShape.XC_fleur;
2633 case StdCursor.SizeNESW: {
2634 shape = CursorFontShape.XC_top_right_corner;
2638 case StdCursor.SizeNS: {
2639 shape = CursorFontShape.XC_sb_v_double_arrow;
2643 case StdCursor.SizeNWSE: {
2644 shape = CursorFontShape.XC_top_left_corner;
2648 case StdCursor.SizeWE: {
2649 shape = CursorFontShape.XC_sb_h_double_arrow;
2653 case StdCursor.UpArrow: {
2654 shape = CursorFontShape.XC_center_ptr;
2658 case StdCursor.VSplit: {
2659 shape = CursorFontShape.XC_sb_h_double_arrow;
2663 case StdCursor.WaitCursor: {
2664 shape = CursorFontShape.XC_watch;
2674 cursor = XCreateFontCursor(DisplayHandle, shape);
2679 internal override IntPtr DefWndProc(ref Message msg) {
2680 switch ((Msg)msg.Msg) {
2681 case Msg.WM_PAINT: {
2684 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2686 hwnd.expose_pending = false;
2692 case Msg.WM_NCPAINT: {
2695 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2697 hwnd.nc_expose_pending = false;
2703 case Msg.WM_CONTEXTMENU: {
2706 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2708 if ((hwnd != null) && (hwnd.parent != null)) {
2709 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2714 case Msg.WM_MOUSEWHEEL: {
2717 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2719 if ((hwnd != null) && (hwnd.parent != null)) {
2720 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2721 if (msg.Result == IntPtr.Zero) {
2728 case Msg.WM_SETCURSOR: {
2731 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2733 break; // not sure how this happens, but it does
2735 // Pass to parent window first
2736 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2738 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2741 if (msg.Result == IntPtr.Zero) {
2744 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2745 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2746 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2747 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2748 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2749 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2752 handle = Cursors.Default.handle;
2755 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2756 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2757 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2758 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2759 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2760 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2763 case HitTest.HTGROWBOX:
2764 case HitTest.HTSIZE:
2765 case HitTest.HTZOOM:
2766 case HitTest.HTVSCROLL:
2767 case HitTest.HTSYSMENU:
2768 case HitTest.HTREDUCE:
2769 case HitTest.HTNOWHERE:
2770 case HitTest.HTMAXBUTTON:
2771 case HitTest.HTMINBUTTON:
2772 case HitTest.HTMENU:
2773 case HitTest.HSCROLL:
2774 case HitTest.HTBOTTOM:
2775 case HitTest.HTCAPTION:
2776 case HitTest.HTCLIENT:
2777 case HitTest.HTCLOSE:
2779 default: handle = Cursors.Default.handle; break;
2781 SetCursor(msg.HWnd, handle);
2789 internal override void DestroyCaret(IntPtr handle) {
2790 if (Caret.Hwnd == handle) {
2791 if (Caret.Visible == true) {
2794 if (Caret.gc != IntPtr.Zero) {
2795 XFreeGC(DisplayHandle, Caret.gc);
2796 Caret.gc = IntPtr.Zero;
2798 Caret.Hwnd = IntPtr.Zero;
2799 Caret.Visible = false;
2804 internal override void DestroyCursor(IntPtr cursor) {
2806 XFreeCursor(DisplayHandle, cursor);
2810 internal override void DestroyWindow(IntPtr handle) {
2813 hwnd = Hwnd.ObjectFromHandle(handle);
2816 #if DriverDebug || DriverDebugDestroy
2817 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2822 #if DriverDebug || DriverDebugDestroy
2823 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2826 CleanupCachedWindows (hwnd);
2828 ArrayList windows = new ArrayList ();
2830 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2833 if (hwnd.whole_window != IntPtr.Zero) {
2834 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2836 else if (hwnd.client_window != IntPtr.Zero) {
2837 XDestroyWindow(DisplayHandle, hwnd.client_window);
2842 SendWMDestroyMessages(windows);
2847 internal override IntPtr DispatchMessage(ref MSG msg) {
2848 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2851 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2853 XGCValues gc_values;
2856 hwnd = Hwnd.ObjectFromHandle(handle);
2858 gc_values = new XGCValues();
2860 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2861 gc_values.line_width = line_width;
2862 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2864 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2865 //mask = foreground ^ background;
2866 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2867 //XSetBackground(DisplayHandle, gc, background);
2868 //XSetFunction(DisplayHandle, gc, GXxor);
2869 //XSetPlaneMask(DisplayHandle, gc, mask);
2872 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2877 control = Control.FromHandle(handle);
2879 XColor xcolor = new XColor();
2881 xcolor.red = (ushort)(control.ForeColor.R * 257);
2882 xcolor.green = (ushort)(control.ForeColor.G * 257);
2883 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2884 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2885 foreground = (uint)xcolor.pixel.ToInt32();
2887 xcolor.red = (ushort)(control.BackColor.R * 257);
2888 xcolor.green = (ushort)(control.BackColor.G * 257);
2889 xcolor.blue = (ushort)(control.BackColor.B * 257);
2890 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2891 background = (uint)xcolor.pixel.ToInt32();
2893 uint mask = foreground ^ background;
2895 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2896 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2897 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2898 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2900 if ((rect.Width > 0) && (rect.Height > 0)) {
2901 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2903 if (rect.Width > 0) {
2904 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2906 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2909 XFreeGC(DisplayHandle, gc);
2912 internal override void DoEvents() {
2913 MSG msg = new MSG ();
2916 if (OverrideCursorHandle != IntPtr.Zero) {
2917 OverrideCursorHandle = IntPtr.Zero;
2920 queue = ThreadQueue(Thread.CurrentThread);
2922 queue.DispatchIdle = false;
2924 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2925 TranslateMessage (ref msg);
2926 DispatchMessage (ref msg);
2929 queue.DispatchIdle = true;
2932 internal override void EnableWindow(IntPtr handle, bool Enable) {
2935 hwnd = Hwnd.ObjectFromHandle(handle);
2937 hwnd.Enabled = Enable;
2941 internal override void EndLoop(Thread thread) {
2942 // This is where we one day will shut down the loop for the thread
2946 internal override IntPtr GetActive() {
2951 IntPtr prop = IntPtr.Zero;
2952 IntPtr active = IntPtr.Zero;
2954 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);
2955 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2956 active = (IntPtr)Marshal.ReadInt32(prop);
2960 if (active != IntPtr.Zero) {
2963 hwnd = Hwnd.GetObjectFromWindow(active);
2965 active = hwnd.Handle;
2967 active = IntPtr.Zero;
2973 internal override Region GetClipRegion(IntPtr handle) {
2976 hwnd = Hwnd.ObjectFromHandle(handle);
2978 return hwnd.UserClip;
2984 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2991 internal override void GetDisplaySize(out Size size) {
2992 XWindowAttributes attributes=new XWindowAttributes();
2995 // FIXME - use _NET_WM messages instead?
2996 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2999 size = new Size(attributes.width, attributes.height);
3002 internal override SizeF GetAutoScaleSize(Font font) {
3005 string magic_string = "The quick brown fox jumped over the lazy dog.";
3006 double magic_number = 44.549996948242189;
3008 g = Graphics.FromHwnd(FosterParent);
3010 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3011 return new SizeF(width, font.Height);
3014 internal override IntPtr GetParent(IntPtr handle) {
3017 hwnd = Hwnd.ObjectFromHandle(handle);
3018 if (hwnd != null && hwnd.parent != null) {
3019 return hwnd.parent.Handle;
3024 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3034 if (handle != IntPtr.Zero) {
3035 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3037 use_handle = RootWindow;
3041 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3044 if (handle != IntPtr.Zero) {
3053 internal override IntPtr GetFocus() {
3058 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3059 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3062 internal override Point GetMenuOrigin(IntPtr handle) {
3065 hwnd = Hwnd.ObjectFromHandle(handle);
3068 return hwnd.MenuOrigin;
3073 [MonoTODO("Implement filtering")]
3074 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3081 if (((XEventQueue)queue_id).Count > 0) {
3082 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3084 UpdateMessageQueue ((XEventQueue)queue_id);
3086 if (((XEventQueue)queue_id).Count > 0) {
3087 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3088 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3089 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3091 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3092 msg.hwnd= IntPtr.Zero;
3093 msg.message = Msg.WM_ENTERIDLE;
3097 // We reset ourselves so GetMessage can be called again
3098 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3104 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3106 // Handle messages for windows that are already or are about to be destroyed.
3108 // we need a special block for this because unless we remove the hwnd from the paint
3109 // queue it will always stay there (since we don't handle the expose), and we'll
3110 // effectively loop infinitely trying to repaint a non-existant window.
3111 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3112 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3113 hwnd.Queue.Paint.Remove (hwnd);
3114 goto ProcessNextMessage;
3117 // We need to make sure we only allow DestroyNotify events through for zombie
3118 // hwnds, since much of the event handling code makes requests using the hwnd's
3119 // client_window, and that'll result in BadWindow errors if there's some lag
3120 // between the XDestroyWindow call and the DestroyNotify event.
3121 if (hwnd == null || (hwnd.zombie && xevent.type != XEventName.DestroyNotify)) {
3123 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3125 goto ProcessNextMessage;
3128 if (hwnd.client_window == xevent.AnyEvent.window) {
3130 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3133 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3136 msg.hwnd = hwnd.Handle;
3139 // If you add a new event to this switch make sure to add it in
3140 // UpdateMessage also unless it is not coming through the X event system.
3142 switch(xevent.type) {
3143 case XEventName.KeyPress: {
3144 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3148 case XEventName.KeyRelease: {
3149 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3153 case XEventName.ButtonPress: {
3154 switch(xevent.ButtonEvent.button) {
3156 MouseState |= MouseButtons.Left;
3158 msg.message = Msg.WM_LBUTTONDOWN;
3160 msg.message = Msg.WM_NCLBUTTONDOWN;
3161 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3163 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3164 msg.wParam=GetMousewParam(0);
3169 MouseState |= MouseButtons.Middle;
3171 msg.message = Msg.WM_MBUTTONDOWN;
3173 msg.message = Msg.WM_NCMBUTTONDOWN;
3174 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3176 msg.wParam=GetMousewParam(0);
3181 MouseState |= MouseButtons.Right;
3183 msg.message = Msg.WM_RBUTTONDOWN;
3185 msg.message = Msg.WM_NCRBUTTONDOWN;
3186 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3188 msg.wParam=GetMousewParam(0);
3193 msg.hwnd = FocusWindow;
3194 msg.message=Msg.WM_MOUSEWHEEL;
3195 msg.wParam=GetMousewParam(120);
3200 msg.hwnd = FocusWindow;
3201 msg.message=Msg.WM_MOUSEWHEEL;
3202 msg.wParam=GetMousewParam(-120);
3208 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3209 MousePosition.X = xevent.ButtonEvent.x;
3210 MousePosition.Y = xevent.ButtonEvent.y;
3212 if (!hwnd.Enabled) {
3215 msg.hwnd = hwnd.EnabledHwnd;
3216 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);
3217 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3220 if (Grab.Hwnd != IntPtr.Zero) {
3221 msg.hwnd = Grab.Hwnd;
3224 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3225 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3226 switch(xevent.ButtonEvent.button) {
3228 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3233 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3238 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3242 ClickPending.Pending = false;
3244 ClickPending.Pending = true;
3245 ClickPending.Hwnd = msg.hwnd;
3246 ClickPending.Message = msg.message;
3247 ClickPending.wParam = msg.wParam;
3248 ClickPending.lParam = msg.lParam;
3249 ClickPending.Time = (long)xevent.ButtonEvent.time;
3255 case XEventName.ButtonRelease: {
3257 Dnd.HandleButtonRelease (ref xevent);
3261 switch(xevent.ButtonEvent.button) {
3263 MouseState &= ~MouseButtons.Left;
3265 msg.message = Msg.WM_LBUTTONUP;
3267 msg.message = Msg.WM_NCLBUTTONUP;
3268 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3270 msg.wParam=GetMousewParam(0);
3275 MouseState &= ~MouseButtons.Middle;
3277 msg.message = Msg.WM_MBUTTONUP;
3279 msg.message = Msg.WM_NCMBUTTONUP;
3280 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3282 msg.wParam=GetMousewParam(0);
3287 MouseState &= ~MouseButtons.Right;
3289 msg.message = Msg.WM_RBUTTONUP;
3291 msg.message = Msg.WM_NCRBUTTONUP;
3292 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3294 msg.wParam=GetMousewParam(0);
3299 goto ProcessNextMessage;
3303 goto ProcessNextMessage;
3307 if (!hwnd.Enabled) {
3310 msg.hwnd = hwnd.EnabledHwnd;
3311 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);
3312 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3315 if (Grab.Hwnd != IntPtr.Zero) {
3316 msg.hwnd = Grab.Hwnd;
3319 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3320 MousePosition.X = xevent.ButtonEvent.x;
3321 MousePosition.Y = xevent.ButtonEvent.y;
3325 case XEventName.MotionNotify: {
3327 #if DriverDebugExtra
3328 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);
3331 if (Dnd.HandleMotionNotify (ref xevent))
3332 goto ProcessNextMessage;
3333 if (Grab.Hwnd != IntPtr.Zero) {
3334 msg.hwnd = Grab.Hwnd;
3336 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3339 msg.message = Msg.WM_MOUSEMOVE;
3340 msg.wParam = GetMousewParam(0);
3341 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3343 if (!hwnd.Enabled) {
3346 msg.hwnd = hwnd.EnabledHwnd;
3347 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);
3348 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3351 MousePosition.X = xevent.MotionEvent.x;
3352 MousePosition.Y = xevent.MotionEvent.y;
3354 if ((HoverState.Timer.Enabled) &&
3355 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3356 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3357 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3358 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3359 HoverState.Timer.Stop();
3360 HoverState.Timer.Start();
3361 HoverState.X = MousePosition.X;
3362 HoverState.Y = MousePosition.Y;
3372 #if DriverDebugExtra
3373 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);
3375 msg.message = Msg.WM_NCMOUSEMOVE;
3377 if (!hwnd.Enabled) {
3378 msg.hwnd = hwnd.EnabledHwnd;
3379 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);
3380 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3383 // The hit test is sent in screen coordinates
3384 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3385 xevent.MotionEvent.x, xevent.MotionEvent.y,
3386 out screen_x, out screen_y, out dummy);
3388 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3389 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3390 IntPtr.Zero, msg.lParam).ToInt32 ();
3391 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3393 MousePosition.X = xevent.MotionEvent.x;
3394 MousePosition.Y = xevent.MotionEvent.y;
3400 case XEventName.EnterNotify: {
3401 if (!hwnd.Enabled) {
3402 goto ProcessNextMessage;
3404 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3405 goto ProcessNextMessage;
3407 msg.message = Msg.WM_MOUSE_ENTER;
3408 HoverState.X = xevent.CrossingEvent.x;
3409 HoverState.Y = xevent.CrossingEvent.y;
3410 HoverState.Timer.Enabled = true;
3411 HoverState.Window = xevent.CrossingEvent.window;
3415 case XEventName.LeaveNotify: {
3416 if (!hwnd.Enabled) {
3417 goto ProcessNextMessage;
3419 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3420 goto ProcessNextMessage;
3422 msg.message=Msg.WM_MOUSE_LEAVE;
3423 HoverState.Timer.Enabled = false;
3424 HoverState.Window = IntPtr.Zero;
3429 case XEventName.CreateNotify: {
3430 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3431 msg.message = WM_CREATE;
3432 // Set up CreateStruct
3434 goto ProcessNextMessage;
3441 case XEventName.ReparentNotify: {
3442 if (hwnd.parent == null) { // Toplevel
3443 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3444 // We need to adjust x/y
3445 // This sucks ass, part 2
3446 // Every WM does the reparenting of toplevel windows different, so there's
3447 // no standard way of getting our adjustment considering frames/decorations
3448 // The code below is needed for metacity. KDE doesn't works just fine without this
3456 hwnd.Reparented = true;
3458 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);
3459 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3460 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3463 hwnd.whacky_wm = true;
3466 if (hwnd.opacity != 0xffffffff) {
3469 opacity = (IntPtr)(Int32)hwnd.opacity;
3470 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3472 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3473 goto ProcessNextMessage;
3475 hwnd.Reparented = false;
3476 goto ProcessNextMessage;
3479 goto ProcessNextMessage;
3482 case XEventName.ConfigureNotify: {
3483 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3484 #if DriverDebugExtra
3485 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);
3487 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3488 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3489 hwnd.configure_pending = false;
3491 // We need to adjust our client window to track the resize of whole_window
3492 PerformNCCalc(hwnd);
3495 goto ProcessNextMessage;
3498 case XEventName.FocusIn: {
3499 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3500 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3501 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3502 // about it having focus again
3503 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3504 goto ProcessNextMessage;
3507 if (FocusWindow == IntPtr.Zero) {
3508 Control c = Control.FromHandle (hwnd.client_window);
3510 goto ProcessNextMessage;
3511 Form form = c.FindForm ();
3513 goto ProcessNextMessage;
3514 ActiveWindow = form.Handle;
3515 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3516 goto ProcessNextMessage;
3518 Keyboard.FocusIn(FocusWindow);
3519 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3520 goto ProcessNextMessage;
3523 case XEventName.FocusOut: {
3524 // Se the comment for our FocusIn handler
3525 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3526 goto ProcessNextMessage;
3528 Keyboard.FocusOut(FocusWindow);
3530 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3531 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3534 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3535 goto ProcessNextMessage;
3538 case XEventName.Expose: {
3539 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3541 hwnd.expose_pending = false;
3543 hwnd.nc_expose_pending = false;
3545 goto ProcessNextMessage;
3549 if (!hwnd.expose_pending) {
3550 goto ProcessNextMessage;
3553 if (!hwnd.nc_expose_pending) {
3554 goto ProcessNextMessage;
3557 switch (hwnd.border_style) {
3558 case FormBorderStyle.Fixed3D: {
3561 g = Graphics.FromHwnd(hwnd.whole_window);
3562 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3567 case FormBorderStyle.FixedSingle: {
3570 g = Graphics.FromHwnd(hwnd.whole_window);
3571 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3576 #if DriverDebugExtra
3577 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);
3580 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3581 Region region = new Region (rect);
3582 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3583 msg.message = Msg.WM_NCPAINT;
3584 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3587 #if DriverDebugExtra
3588 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);
3590 if (Caret.Visible == true) {
3591 Caret.Paused = true;
3595 if (Caret.Visible == true) {
3597 Caret.Paused = false;
3599 msg.message = Msg.WM_PAINT;
3603 case XEventName.DestroyNotify: {
3605 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3606 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3608 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3609 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3610 CleanupCachedWindows (hwnd);
3612 #if DriverDebugDestroy
3613 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3617 /* this window is being destroyed via DestroyWindow, so we let that code
3618 take care of sending the WM_DESTROY message. Just dispose of it here. */
3620 goto ProcessNextMessage;
3623 msg.hwnd = hwnd.client_window;
3624 msg.message=Msg.WM_DESTROY;
3628 goto ProcessNextMessage;
3634 case XEventName.ClientMessage: {
3635 if (Dnd.HandleClientMessage (ref xevent)) {
3636 goto ProcessNextMessage;
3639 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3640 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3641 goto ProcessNextMessage;
3644 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3645 msg.message = Msg.WM_MOUSEHOVER;
3646 msg.wParam = GetMousewParam(0);
3647 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3651 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3652 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3653 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3654 msg.wParam = xevent.ClientMessageEvent.ptr3;
3655 msg.lParam = xevent.ClientMessageEvent.ptr4;
3660 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3661 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3666 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3667 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3668 msg.message = Msg.WM_CLOSE;
3672 // We should not get this, but I'll leave the code in case we need it in the future
3673 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3674 goto ProcessNextMessage;
3677 goto ProcessNextMessage;
3680 case XEventName.TimerNotify: {
3681 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3682 goto ProcessNextMessage;
3686 goto ProcessNextMessage;
3693 internal override bool GetText(IntPtr handle, out string text) {
3696 textptr = IntPtr.Zero;
3699 // FIXME - use _NET properties
3700 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3702 if (textptr != IntPtr.Zero) {
3703 text = Marshal.PtrToStringAnsi(textptr);
3712 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) {
3715 hwnd = Hwnd.ObjectFromHandle(handle);
3721 height = hwnd.height;
3723 PerformNCCalc(hwnd);
3725 client_width = hwnd.ClientRect.Width;
3726 client_height = hwnd.ClientRect.Height;
3731 // Should we throw an exception or fail silently?
3732 // throw new ArgumentException("Called with an invalid window handle", "handle");
3742 internal override FormWindowState GetWindowState(IntPtr handle) {
3747 IntPtr prop = IntPtr.Zero;
3751 XWindowAttributes attributes;
3754 hwnd = Hwnd.ObjectFromHandle(handle);
3758 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);
3759 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3760 for (int i = 0; i < (long)nitems; i++) {
3761 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3762 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3764 } else if (atom == _NET_WM_STATE_HIDDEN) {
3772 return FormWindowState.Minimized;
3773 } else if (maximized == 2) {
3774 return FormWindowState.Maximized;
3777 attributes = new XWindowAttributes();
3778 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3779 if (attributes.map_state == MapState.IsUnmapped) {
3780 throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
3784 return FormWindowState.Normal;
3787 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3789 GrabConfined = Grab.Confined;
3790 GrabArea = Grab.Area;
3793 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3795 IntPtr confine_to_window;
3797 confine_to_window = IntPtr.Zero;
3799 if (confine_to_handle != IntPtr.Zero) {
3800 XWindowAttributes attributes = new XWindowAttributes();
3802 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3805 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3807 Grab.Area.X = attributes.x;
3808 Grab.Area.Y = attributes.y;
3809 Grab.Area.Width = attributes.width;
3810 Grab.Area.Height = attributes.height;
3811 Grab.Confined = true;
3812 confine_to_window = hwnd.client_window;
3817 hwnd = Hwnd.ObjectFromHandle(handle);
3820 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3821 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3822 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3823 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3827 internal override void UngrabWindow(IntPtr hwnd) {
3829 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3830 XFlush(DisplayHandle);
3832 Grab.Hwnd = IntPtr.Zero;
3833 Grab.Confined = false;
3836 internal override void HandleException(Exception e) {
3837 StackTrace st = new StackTrace(e, true);
3838 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3839 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3842 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3845 hwnd = Hwnd.ObjectFromHandle(handle);
3848 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3850 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3854 internal override bool IsEnabled(IntPtr handle) {
3855 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3856 return (hwnd != null && hwnd.Enabled);
3859 internal override bool IsVisible(IntPtr handle) {
3860 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3861 return (hwnd != null && hwnd.visible);
3864 internal override void KillTimer(Timer timer) {
3865 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3867 if (queue == null) {
3868 // This isn't really an error, MS doesn't start the timer if
3869 // it has no assosciated queue
3872 queue.timer_list.Remove (timer);
3875 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3881 hwnd = Hwnd.ObjectFromHandle(handle);
3884 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3891 internal override void OverrideCursor(IntPtr cursor) {
3892 OverrideCursorHandle = cursor;
3895 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3896 PaintEventArgs paint_event;
3899 hwnd = Hwnd.ObjectFromHandle(handle);
3901 if (Caret.Visible == true) {
3902 Caret.Paused = true;
3908 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3910 // Protected against illegal cross-thread painting
3912 if (hwnd.client_dc != null) {
3916 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3920 Region clip_region = new Region ();
3921 clip_region.MakeEmpty();
3923 foreach (Rectangle r in hwnd.ClipRectangles) {
3924 clip_region.Union (r);
3927 if (hwnd.UserClip != null) {
3928 clip_region.Intersect(hwnd.UserClip);
3931 hwnd.client_dc.Clip = clip_region;
3932 paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.Invalid);
3933 hwnd.expose_pending = false;
3935 hwnd.ClearInvalidArea();
3939 hwnd.non_client_dc = Graphics.FromHwnd (hwnd.whole_window);
3941 if (!hwnd.nc_invalid.IsEmpty) {
3942 hwnd.non_client_dc.SetClip (hwnd.nc_invalid);
3943 paint_event = new PaintEventArgs(hwnd.non_client_dc, hwnd.nc_invalid);
3945 paint_event = new PaintEventArgs(hwnd.non_client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3947 hwnd.nc_expose_pending = false;
3949 hwnd.ClearNcInvalidArea ();
3955 internal override void PaintEventEnd(IntPtr handle, bool client) {
3958 hwnd = Hwnd.ObjectFromHandle(handle);
3962 hwnd.client_dc.Flush();
3963 hwnd.client_dc.Dispose();
3964 hwnd.client_dc = null;
3967 hwnd.client_dc.Flush();
3968 hwnd.client_dc.Dispose();
3969 hwnd.client_dc = null;
3973 hwnd.non_client_dc.Flush ();
3974 hwnd.non_client_dc.Dispose ();
3975 hwnd.non_client_dc = null;
3979 if (Caret.Visible == true) {
3981 Caret.Paused = false;
3985 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3986 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3987 XEventQueue queue = (XEventQueue) queue_id;
3990 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3991 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3995 if (queue.Count > 0) {
3998 // Only call UpdateMessageQueue if real events are pending
3999 // otherwise we go to sleep on the socket
4000 if (XPending(DisplayHandle) != 0) {
4001 UpdateMessageQueue((XEventQueue)queue_id);
4003 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4008 CheckTimers(queue.timer_list, DateTime.UtcNow);
4013 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4016 // FIXME - I think this should just enqueue directly
4017 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4018 XEvent xevent = new XEvent ();
4019 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4021 xevent.type = XEventName.ClientMessage;
4022 xevent.ClientMessageEvent.display = DisplayHandle;
4025 xevent.ClientMessageEvent.window = hwnd.whole_window;
4027 xevent.ClientMessageEvent.window = IntPtr.Zero;
4030 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4031 xevent.ClientMessageEvent.format = 32;
4032 xevent.ClientMessageEvent.ptr1 = handle;
4033 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4034 xevent.ClientMessageEvent.ptr3 = wparam;
4035 xevent.ClientMessageEvent.ptr4 = lparam;
4037 hwnd.Queue.Enqueue (xevent);
4042 internal override void PostQuitMessage(int exitCode) {
4044 XFlush(DisplayHandle);
4045 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4048 internal override void RequestNCRecalc(IntPtr handle) {
4051 hwnd = Hwnd.ObjectFromHandle(handle);
4057 PerformNCCalc(hwnd);
4058 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4059 InvalidateWholeWindow(handle);
4062 internal override void ResetMouseHover(IntPtr handle) {
4065 hwnd = Hwnd.ObjectFromHandle(handle);
4070 HoverState.Timer.Enabled = true;
4071 HoverState.X = MousePosition.X;
4072 HoverState.Y = MousePosition.Y;
4073 HoverState.Window = handle;
4077 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4083 hwnd = Hwnd.ObjectFromHandle(handle);
4086 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4093 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4099 hwnd = Hwnd.ObjectFromHandle(handle);
4102 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4109 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4112 XGCValues gc_values;
4115 hwnd = Hwnd.ObjectFromHandle(handle);
4118 if (r != Rectangle.Empty) {
4119 /* We have an invalid area in the window we're scrolling.
4120 Adjust our stored invalid rectangle to to match the scrolled amount */
4135 hwnd.ClearInvalidArea();
4136 hwnd.AddInvalidArea(r);
4139 gc_values = new XGCValues();
4141 if (with_children) {
4142 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4145 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4153 height = area.Height - YAmount;
4154 dest_y = area.Y + YAmount;
4157 src_y = area.Y - YAmount;
4158 height = area.Height + YAmount;
4164 width = area.Width - XAmount;
4165 dest_x = area.X + XAmount;
4168 src_x = area.X - XAmount;
4169 width = area.Width + XAmount;
4173 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4175 // Generate an expose for the area exposed by the horizontal scroll
4176 // We don't use AddExpose since we're
4178 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4179 } else if (XAmount < 0) {
4180 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4183 // Generate an expose for the area exposed by the vertical scroll
4185 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4186 } else if (YAmount < 0) {
4187 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4189 XFreeGC(DisplayHandle, gc);
4192 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4196 hwnd = Hwnd.GetObjectFromWindow(handle);
4198 rect = hwnd.ClientRect;
4201 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4204 internal override void SendAsyncMethod (AsyncMethodData method) {
4206 XEvent xevent = new XEvent ();
4208 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4210 xevent.type = XEventName.ClientMessage;
4211 xevent.ClientMessageEvent.display = DisplayHandle;
4212 xevent.ClientMessageEvent.window = method.Handle;
4213 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4214 xevent.ClientMessageEvent.format = 32;
4215 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4217 hwnd.Queue.EnqueueLocked (xevent);
4222 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4224 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4227 h = Hwnd.ObjectFromHandle(hwnd);
4229 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4230 AsyncMethodResult result;
4231 AsyncMethodData data;
4233 result = new AsyncMethodResult ();
4234 data = new AsyncMethodData ();
4237 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4238 data.Args = new object[] { hwnd, message, wParam, lParam };
4239 data.Result = result;
4241 SendAsyncMethod (data);
4242 #if DriverDebug || DriverDebugParent
4243 Console.WriteLine ("Sending {0} message across.", message);
4248 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4251 internal override void SetAllowDrop (IntPtr handle, bool value)
4253 // We allow drop on all windows
4256 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4257 DragDropEffects allowed_effects)
4259 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4262 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4264 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4267 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4270 hwnd = Hwnd.ObjectFromHandle(handle);
4272 Form form = Control.FromHandle (handle) as Form;
4273 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4274 border_style == FormBorderStyle.SizableToolWindow)) {
4275 form.window_manager = new InternalWindowManager (form);
4278 hwnd.border_style = border_style;
4279 RequestNCRecalc(handle);
4282 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4283 if (Caret.Hwnd == handle) {
4290 if (Caret.Visible == true) {
4292 Caret.Timer.Start();
4297 internal override void SetClipRegion(IntPtr handle, Region region) {
4300 hwnd = Hwnd.ObjectFromHandle(handle);
4305 hwnd.UserClip = region;
4306 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4309 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4312 if (OverrideCursorHandle == IntPtr.Zero) {
4313 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4317 LastCursorHandle = cursor;
4318 LastCursorWindow = handle;
4320 hwnd = Hwnd.ObjectFromHandle(handle);
4322 if (cursor != IntPtr.Zero) {
4323 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4325 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4327 XFlush(DisplayHandle);
4332 hwnd = Hwnd.ObjectFromHandle(handle);
4334 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4338 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4339 out int root_x, out int root_y, out int child_x, out int child_y,
4342 /* this code was written with the help of
4343 glance at gdk. I never would have realized we
4344 needed a loop in order to traverse down in the
4345 hierarchy. I would have assumed you'd get the
4346 most deeply nested child and have to do
4347 XQueryTree to move back up the hierarchy..
4348 stupid me, of course. */
4351 XGrabServer (display);
4353 XQueryPointer(display, w, out root, out c,
4354 out root_x, out root_y, out child_x, out child_y,
4360 IntPtr child_last = IntPtr.Zero;
4361 while (c != IntPtr.Zero) {
4363 XQueryPointer(display, c, out root, out c,
4364 out root_x, out root_y, out child_x, out child_y,
4367 XUngrabServer (display);
4372 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4373 if (handle == IntPtr.Zero) {
4376 int root_x, root_y, child_x, child_y, mask;
4379 * QueryPointer before warping
4380 * because if the warp is on
4381 * the RootWindow, the x/y are
4382 * relative to the current
4385 QueryPointer (DisplayHandle, RootWindow,
4388 out root_x, out root_y,
4389 out child_x, out child_y,
4392 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4394 XFlush (DisplayHandle);
4396 /* then we need to a
4397 * QueryPointer after warping
4398 * to manually generate a
4399 * motion event for the window
4402 QueryPointer (DisplayHandle, RootWindow,
4405 out root_x, out root_y,
4406 out child_x, out child_y,
4409 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4410 if (child_hwnd == null) {
4414 XEvent xevent = new XEvent ();
4416 xevent.type = XEventName.MotionNotify;
4417 xevent.MotionEvent.display = DisplayHandle;
4418 xevent.MotionEvent.window = child_hwnd.client_window;
4419 xevent.MotionEvent.root = RootWindow;
4420 xevent.MotionEvent.x = child_x;
4421 xevent.MotionEvent.y = child_y;
4422 xevent.MotionEvent.x_root = root_x;
4423 xevent.MotionEvent.y_root = root_y;
4424 xevent.MotionEvent.state = mask;
4426 child_hwnd.Queue.Enqueue (xevent);
4431 hwnd = Hwnd.ObjectFromHandle(handle);
4433 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4438 internal override void SetFocus(IntPtr handle) {
4440 IntPtr prev_focus_window;
4442 hwnd = Hwnd.ObjectFromHandle(handle);
4444 if (hwnd.client_window == FocusWindow) {
4448 prev_focus_window = FocusWindow;
4449 FocusWindow = hwnd.client_window;
4451 if (prev_focus_window != IntPtr.Zero) {
4452 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4454 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4456 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4459 internal override void SetIcon(IntPtr handle, Icon icon) {
4462 hwnd = Hwnd.ObjectFromHandle(handle);
4464 SetIcon(hwnd, icon);
4468 internal override void SetMenu(IntPtr handle, Menu menu) {
4471 hwnd = Hwnd.ObjectFromHandle(handle);
4474 RequestNCRecalc(handle);
4477 internal override void SetModal(IntPtr handle, bool Modal) {
4479 ModalWindows.Push(handle);
4481 if (ModalWindows.Contains(handle)) {
4484 if (ModalWindows.Count > 0) {
4485 Activate((IntPtr)ModalWindows.Peek());
4490 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4493 hwnd = Hwnd.ObjectFromHandle(handle);
4494 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4497 #if DriverDebug || DriverDebugParent
4498 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4500 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4506 internal override void SetTimer (Timer timer) {
4507 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4509 if (queue == null) {
4510 // This isn't really an error, MS doesn't start the timer if
4511 // it has no assosciated queue
4514 queue.timer_list.Add (timer);
4518 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4522 hwnd = Hwnd.ObjectFromHandle(handle);
4524 if (handle_owner != IntPtr.Zero) {
4525 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4536 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4537 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4539 if (hwnd_owner != null) {
4540 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4542 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4547 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4553 internal override bool SetVisible(IntPtr handle, bool visible) {
4556 hwnd = Hwnd.ObjectFromHandle(handle);
4557 hwnd.visible = visible;
4561 if (Control.FromHandle(handle) is Form) {
4564 s = ((Form)Control.FromHandle(handle)).WindowState;
4566 MapWindow(hwnd, WindowType.Both);
4569 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4570 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4574 MapWindow(hwnd, WindowType.Both);
4576 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4578 UnmapWindow(hwnd, WindowType.Whole);
4584 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4589 hwnd = Hwnd.ObjectFromHandle(handle);
4594 hints = new XSizeHints();
4596 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4597 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4598 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4599 hints.min_width = min.Width;
4600 hints.min_height = min.Height;
4603 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4604 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4605 hints.max_width = max.Width;
4606 hints.max_height = max.Height;
4609 if (hints.flags != IntPtr.Zero) {
4610 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4613 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4614 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4615 hints.x = maximized.X;
4616 hints.y = maximized.Y;
4617 hints.width = maximized.Width;
4618 hints.height = maximized.Height;
4620 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4621 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4626 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4629 hwnd = Hwnd.ObjectFromHandle(handle);
4635 // X requires a sanity check for width & height; otherwise it dies
4636 if (hwnd.zero_sized && width > 0 && height > 0) {
4638 MapWindow(hwnd, WindowType.Whole);
4640 hwnd.zero_sized = false;
4643 if ((width < 1) || (height < 1)) {
4644 hwnd.zero_sized = true;
4645 UnmapWindow(hwnd, WindowType.Whole);
4648 // Save a server roundtrip (and prevent a feedback loop)
4649 if ((hwnd.x == x) && (hwnd.y == y) &&
4650 (hwnd.width == width) && (hwnd.height == height)) {
4654 if (!hwnd.zero_sized) {
4659 hwnd.height = height;
4660 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4662 if (hwnd.fixed_size) {
4663 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4667 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4668 PerformNCCalc(hwnd);
4672 // Update our position/size immediately, so
4673 // that future calls to SetWindowPos aren't
4674 // kept from calling XMoveResizeWindow (by the
4675 // "Save a server roundtrip" block above).
4679 hwnd.height = height;
4682 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4683 FormWindowState current_state;
4686 hwnd = Hwnd.ObjectFromHandle(handle);
4689 current_state = GetWindowState(handle);
4691 catch (NotSupportedException) {
4692 current_state = (FormWindowState)(-1);
4695 if (current_state == state) {
4700 case FormWindowState.Normal: {
4702 if (current_state == FormWindowState.Minimized) {
4703 MapWindow(hwnd, WindowType.Both);
4704 } else if (current_state == FormWindowState.Maximized) {
4705 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4712 case FormWindowState.Minimized: {
4714 if (current_state == FormWindowState.Maximized) {
4715 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4717 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4722 case FormWindowState.Maximized: {
4724 if (current_state == FormWindowState.Minimized) {
4725 MapWindow(hwnd, WindowType.Both);
4728 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4736 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4739 hwnd = Hwnd.ObjectFromHandle(handle);
4740 SetHwndStyles(hwnd, cp);
4741 SetWMStyles(hwnd, cp);
4744 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4748 hwnd = Hwnd.ObjectFromHandle(handle);
4754 hwnd.opacity = (uint)(0xffffffff * transparency);
4755 opacity = (IntPtr)((int)hwnd.opacity);
4757 if (hwnd.reparented) {
4758 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4762 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4763 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4771 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4774 } else if (!bottom) {
4775 Hwnd after_hwnd = null;
4777 if (after_handle != IntPtr.Zero) {
4778 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4781 XWindowChanges values = new XWindowChanges();
4783 if (after_hwnd == null) {
4784 // Work around metacity 'issues'
4788 atoms[0] = unixtime();
4789 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4791 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4792 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
4794 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4797 values.sibling = after_hwnd.whole_window;
4798 values.stack_mode = StackMode.Below;
4801 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4806 XLowerWindow(DisplayHandle, hwnd.whole_window);
4813 internal override void ShowCursor(bool show) {
4814 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4817 internal override object StartLoop(Thread thread) {
4818 return (Object) ThreadQueue(thread);
4821 internal override bool SupportsTransparency() {
4822 // We need to check if the x compositing manager is running
4826 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4827 GetSystrayManagerWindow();
4829 if (SystrayMgrWindow != IntPtr.Zero) {
4830 XSizeHints size_hints;
4834 hwnd = Hwnd.ObjectFromHandle(handle);
4836 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4840 if (hwnd.client_window != hwnd.whole_window) {
4841 XDestroyWindow(DisplayHandle, hwnd.client_window);
4842 hwnd.client_window = hwnd.whole_window;
4845 size_hints = new XSizeHints();
4847 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints, out dummy);
4848 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4849 size_hints.min_width = icon.Width;
4850 size_hints.min_height = icon.Height;
4852 size_hints.max_width = icon.Width;
4853 size_hints.max_height = icon.Height;
4855 size_hints.base_width = icon.Width;
4856 size_hints.base_height = icon.Height;
4857 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4859 int[] atoms = new int[2];
4860 atoms [0] = 1; // Version 1
4861 atoms [1] = 1; // we want to be mapped
4863 // This line cost me 3 days...
4864 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4866 // Need to pick some reasonable defaults
4868 tt.AutomaticDelay = 100;
4869 tt.InitialDelay = 250;
4870 tt.ReshowDelay = 250;
4871 tt.ShowAlways = true;
4873 if ((tip != null) && (tip != string.Empty)) {
4874 tt.SetToolTip(Control.FromHandle(handle), tip);
4880 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4888 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4891 control = Control.FromHandle(handle);
4892 if (control != null && tt != null) {
4893 tt.SetToolTip(control, tip);
4901 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4903 #if GTKSOCKET_SUPPORTS_REPARENTING
4906 hwnd = Hwnd.ObjectFromHandle(handle);
4908 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4909 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4910 * 2. The client can reparent its window out of the embedder window.
4911 * 3. The client can destroy its window.
4913 * this call to SetParent is case 2, but in
4914 * the spec it also mentions that gtk doesn't
4915 * support this at present. Looking at HEAD
4916 * gtksocket-x11.c jives with this statement.
4918 * so we can't reparent. we have to destroy.
4920 SetParent(hwnd.whole_window, FosterParent);
4922 Control control = Control.FromHandle(handle);
4923 if (control is NotifyIcon.NotifyIconWindow)
4924 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
4927 // The caller can now re-dock it later...
4934 internal override bool Text(IntPtr handle, string text) {
4936 // FIXME - use _NET properties
4937 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4942 internal override bool TranslateMessage(ref MSG msg) {
4943 return Keyboard.TranslateMessage (ref msg);
4946 internal override void UpdateWindow(IntPtr handle) {
4949 hwnd = Hwnd.ObjectFromHandle(handle);
4951 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
4955 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4956 hwnd.Queue.Paint.Remove(hwnd);
4959 #endregion // Public Static Methods
4962 internal override event EventHandler Idle;
4963 #endregion // Events
4966 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4967 internal extern static IntPtr XOpenDisplay(IntPtr display);
4968 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4969 internal extern static int XCloseDisplay(IntPtr display);
4970 [DllImport ("libX11", EntryPoint="XSynchronize")]
4971 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4973 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4974 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);
4975 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4976 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4977 [DllImport ("libX11", EntryPoint="XMapWindow")]
4978 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4979 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4980 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4981 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4982 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4983 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4984 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4985 [DllImport ("libX11", EntryPoint="XRootWindow")]
4986 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4987 [DllImport ("libX11", EntryPoint="XNextEvent")]
4988 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4989 [DllImport ("libX11")]
4990 internal extern static int XConnectionNumber (IntPtr diplay);
4991 [DllImport ("libX11")]
4992 internal extern static int XPending (IntPtr diplay);
4993 [DllImport ("libX11", EntryPoint="XSelectInput")]
4994 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4996 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4997 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4999 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5000 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5001 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5002 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5004 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5005 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5007 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5008 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5010 [DllImport ("libX11", EntryPoint="XFlush")]
5011 internal extern static int XFlush(IntPtr display);
5013 [DllImport ("libX11", EntryPoint="XSetWMName")]
5014 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5016 [DllImport ("libX11", EntryPoint="XStoreName")]
5017 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5019 [DllImport ("libX11", EntryPoint="XFetchName")]
5020 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5022 [DllImport ("libX11", EntryPoint="XSendEvent")]
5023 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5025 [DllImport ("libX11", EntryPoint="XQueryTree")]
5026 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);
5028 [DllImport ("libX11", EntryPoint="XFree")]
5029 internal extern static int XFree(IntPtr data);
5031 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5032 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5034 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5035 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5037 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5038 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5040 [DllImport ("libX11", EntryPoint="XInternAtom")]
5041 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5043 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5044 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5046 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5047 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);
5049 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5050 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5052 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5053 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);
5055 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5056 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);
5058 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5059 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);
5061 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5062 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);
5064 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5065 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);
5067 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5068 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);
5070 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5071 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);
5073 [DllImport ("libX11", EntryPoint="XClearWindow")]
5074 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5076 [DllImport ("libX11", EntryPoint="XClearArea")]
5077 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5080 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5081 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5083 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5084 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5086 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5087 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5089 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5090 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5092 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5093 internal extern static int XDefaultScreen(IntPtr display);
5095 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5096 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5098 [DllImport ("libX11", EntryPoint="XLookupColor")]
5099 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5101 [DllImport ("libX11", EntryPoint="XAllocColor")]
5102 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5104 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5105 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5107 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5108 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5110 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5111 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5113 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5114 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5116 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5117 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5119 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5120 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5122 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5123 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5125 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5126 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5128 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5129 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5131 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5132 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5134 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5135 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5138 [DllImport ("libX11", EntryPoint="XCreateGC")]
5139 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5141 [DllImport ("libX11", EntryPoint="XFreeGC")]
5142 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5144 [DllImport ("libX11", EntryPoint="XSetFunction")]
5145 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5147 [DllImport ("libX11", EntryPoint="XDrawLine")]
5148 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5150 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5151 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5153 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5154 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5156 [DllImport ("libX11", EntryPoint="XCopyArea")]
5157 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);
5159 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5160 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);
5162 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5163 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5165 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5166 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5168 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5169 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5171 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5172 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5174 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5175 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5177 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5178 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5180 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5181 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);
5183 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5184 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5186 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5187 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5189 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5190 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5192 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5193 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5195 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5196 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5198 [DllImport ("libX11", EntryPoint="XGrabServer")]
5199 internal extern static void XGrabServer(IntPtr display);
5201 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5202 internal extern static void XUngrabServer(IntPtr display);
5204 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5205 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5207 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5208 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5210 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5211 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5213 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5214 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5216 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5217 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5219 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5220 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5222 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5223 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5225 [DllImport ("libX11", EntryPoint="XInitThreads")]
5226 internal extern static int XInitThreads();
5228 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5229 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5231 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5232 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5234 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5235 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5237 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5238 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5240 [DllImport ("libX11", EntryPoint="XSetForeground")]
5241 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5243 [DllImport ("libX11", EntryPoint="XSetBackground")]
5244 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5246 [DllImport ("libX11", EntryPoint="XBell")]
5247 internal extern static int XBell(IntPtr display, int percent);
5249 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5250 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5252 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5253 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5255 [DllImport ("libX11")]
5256 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5258 [DllImport ("libX11")]
5259 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);