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_SKIP_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_SKIP_TASKBAR = XInternAtom(DisplayHandle, "_NET_WM_STATE_SKIP_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 = GetWindowState (hwnd.Handle);
862 if (current_state == (FormWindowState)(-1))
863 current_state = FormWindowState.Normal;
865 client_rect = hwnd.ClientRect;
867 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
868 // and get those windows in front of their parents
869 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
870 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
871 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
872 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
875 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
876 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
877 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
878 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
880 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
881 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
882 /* this line keeps the window from showing up in gnome's taskbar */
883 //XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
885 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
886 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
888 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
893 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
894 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
896 /* we need to add these atoms in the
897 * event we're maximized, since we're
898 * replacing the existing
899 * _NET_WM_STATE here. If we don't
900 * add them, future calls to
901 * GetWindowState will return Normal
902 * for a window which is maximized. */
903 if (current_state == FormWindowState.Maximized) {
904 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
905 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
907 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
910 IntPtr[] atom_ptrs = new IntPtr[2];
911 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
912 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
913 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
916 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
920 private void SetIcon(Hwnd hwnd, Icon icon) {
926 bitmap = icon.ToBitmap();
928 size = bitmap.Width * bitmap.Height + 2;
929 data = new IntPtr[size];
931 data[index++] = (IntPtr)bitmap.Width;
932 data[index++] = (IntPtr)bitmap.Height;
934 for (int y = 0; y < bitmap.Height; y++) {
935 for (int x = 0; x < bitmap.Width; x++) {
936 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
940 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
943 private IntPtr ImageToPixmap(Image image) {
947 private void WakeupMain () {
948 wake.Send (new byte [] { 0xFF });
951 private XEventQueue ThreadQueue(Thread thread) {
954 queue = (XEventQueue)MessageQueues[thread];
956 queue = new XEventQueue(thread);
957 MessageQueues[thread] = queue;
963 private void TranslatePropertyToClipboard(IntPtr property) {
968 IntPtr prop = IntPtr.Zero;
970 Clipboard.Item = null;
972 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);
974 if ((long)nitems > 0) {
975 if (property == (IntPtr)Atom.XA_STRING) {
976 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
977 } else if (property == (IntPtr)Atom.XA_BITMAP) {
978 // FIXME - convert bitmap to image
979 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
980 // FIXME - convert pixmap to image
981 } else if (property == OEMTEXT) {
982 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
983 } else if (property == UNICODETEXT) {
984 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
991 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
993 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
997 // Keep the invalid area as small as needed
998 if ((x + width) > hwnd.width) {
999 width = hwnd.width - x;
1002 if ((y + height) > hwnd.height) {
1003 height = hwnd.height - y;
1007 hwnd.AddInvalidArea(x, y, width, height);
1008 if (!hwnd.expose_pending) {
1009 if (!hwnd.nc_expose_pending) {
1010 hwnd.Queue.Paint.Enqueue(hwnd);
1012 hwnd.expose_pending = true;
1015 hwnd.AddNcInvalidArea (x, y, width, height);
1017 if (!hwnd.nc_expose_pending) {
1018 if (!hwnd.expose_pending) {
1019 hwnd.Queue.Paint.Enqueue(hwnd);
1021 hwnd.nc_expose_pending = true;
1026 private void InvalidateWholeWindow(IntPtr handle) {
1029 hwnd = Hwnd.ObjectFromHandle(handle);
1031 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
1034 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
1037 hwnd = Hwnd.ObjectFromHandle(handle);
1039 AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
1042 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
1048 hwnd = Hwnd.ObjectFromHandle(handle);
1051 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1058 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
1079 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
1080 if (win == window) {
1086 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
1090 if (children != IntPtr.Zero) {
1094 } while (win != root);
1099 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
1102 private void FrameExtents(IntPtr window, out int left, out int top) {
1107 IntPtr prop = IntPtr.Zero;
1109 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);
1110 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1111 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1112 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1113 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1114 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1120 if (prop != IntPtr.Zero) {
1126 private void AddConfigureNotify (XEvent xevent) {
1129 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1136 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1137 if (!hwnd.reparented) {
1138 hwnd.x = xevent.ConfigureEvent.x;
1139 hwnd.y = xevent.ConfigureEvent.y;
1141 // This sucks ass, part 1
1142 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1143 // no standard way of getting our adjustment.
1144 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1145 // Several other WMs do their decorations different yet again and we fail to deal
1146 // with that, since I couldn't find any frigging commonality between them.
1147 // The only sane WM seems to be KDE
1149 if (!xevent.ConfigureEvent.send_event) {
1152 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1154 // This is a synthetic event, coordinates are in root space
1155 hwnd.x = xevent.ConfigureEvent.x;
1156 hwnd.y = xevent.ConfigureEvent.y;
1157 if (hwnd.whacky_wm) {
1161 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1162 hwnd.x -= frame_left;
1163 hwnd.y -= frame_top;
1167 hwnd.width = xevent.ConfigureEvent.width;
1168 hwnd.height = xevent.ConfigureEvent.height;
1169 hwnd.ClientRect = Rectangle.Empty;
1171 if (!hwnd.configure_pending) {
1172 hwnd.Queue.Enqueue(xevent);
1173 hwnd.configure_pending = true;
1176 // We drop configure events for Client windows
1179 private void ShowCaret() {
1180 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1186 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1190 private void HideCaret() {
1191 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1197 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1201 private int NextTimeout (ArrayList timers, DateTime now) {
1202 int timeout = Int32.MaxValue;
1204 foreach (Timer timer in timers) {
1205 int next = (int) (timer.Expires - now).TotalMilliseconds;
1207 return 0; // Have a timer that has already expired
1210 if (next < timeout) {
1214 if (timeout < Timer.Minimum) {
1215 timeout = Timer.Minimum;
1223 private void CheckTimers (ArrayList timers, DateTime now) {
1226 count = timers.Count;
1231 for (int i = 0; i < timers.Count; i++) {
1234 timer = (Timer) timers [i];
1236 if (timer.Enabled && timer.Expires <= now) {
1243 private void MapWindow(Hwnd hwnd, WindowType windows) {
1245 if ((windows & WindowType.Whole) != 0) {
1246 XMapWindow(DisplayHandle, hwnd.whole_window);
1248 if ((windows & WindowType.Client) != 0) {
1249 XMapWindow(DisplayHandle, hwnd.client_window);
1253 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1254 hwnd.mapped = false;
1255 if ((windows & WindowType.Whole) != 0) {
1256 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1258 if ((windows & WindowType.Client) != 0) {
1259 XUnmapWindow(DisplayHandle, hwnd.client_window);
1263 private void UpdateMessageQueue (XEventQueue queue) {
1268 now = DateTime.UtcNow;
1271 pending = XPending (DisplayHandle);
1275 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1276 Idle (this, EventArgs.Empty);
1280 pending = XPending (DisplayHandle);
1287 if (queue != null) {
1288 if (queue.Paint.Count > 0)
1291 timeout = NextTimeout (queue.timer_list, now);
1296 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1297 // Clean out buffer, so we're not busy-looping on the same data
1298 if (pollfds[1].revents != 0) {
1299 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1303 pending = XPending (DisplayHandle);
1309 CheckTimers (queue.timer_list, now);
1312 XEvent xevent = new XEvent ();
1315 if (XPending (DisplayHandle) == 0)
1318 XNextEvent (DisplayHandle, ref xevent);
1320 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1321 if (XFilterEvent(ref xevent, FosterParent)) {
1327 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1331 switch (xevent.type) {
1332 case XEventName.Expose:
1333 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1336 case XEventName.SelectionClear: {
1337 // Should we do something?
1341 case XEventName.SelectionRequest: {
1342 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1346 sel_event = new XEvent();
1347 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1348 sel_event.SelectionEvent.send_event = true;
1349 sel_event.SelectionEvent.display = DisplayHandle;
1350 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1351 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1352 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1353 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1354 sel_event.SelectionEvent.property = IntPtr.Zero;
1356 // Seems that some apps support asking for supported types
1357 if (xevent.SelectionEvent.target == TARGETS) {
1364 if (Clipboard.Item is String) {
1365 atoms[atom_count++] = (int)Atom.XA_STRING;
1366 atoms[atom_count++] = (int)OEMTEXT;
1367 atoms[atom_count++] = (int)UNICODETEXT;
1368 } else if (Clipboard.Item is Image) {
1369 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1370 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1372 // FIXME - handle other types
1375 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1376 } else if (Clipboard.Item is string) {
1382 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1385 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1386 buffer = Marshal.AllocHGlobal(bytes.Length);
1387 buflen = bytes.Length;
1389 for (int i = 0; i < buflen; i++) {
1390 Marshal.WriteByte(buffer, i, bytes[i]);
1392 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1393 // FIXME - this should encode into ISO2022
1394 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1395 while (Marshal.ReadByte(buffer, buflen) != 0) {
1398 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1399 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1400 while (Marshal.ReadByte(buffer, buflen) != 0) {
1404 buffer = IntPtr.Zero;
1407 if (buffer != IntPtr.Zero) {
1408 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1409 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1410 Marshal.FreeHGlobal(buffer);
1412 } else if (Clipboard.Item is Image) {
1413 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1414 // FIXME - convert image and store as property
1415 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1416 // FIXME - convert image and store as property
1420 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1424 case XEventName.SelectionNotify: {
1425 if (Clipboard.Enumerating) {
1426 Clipboard.Enumerating = false;
1427 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1428 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1429 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1430 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1431 #if DriverDebugExtra
1432 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1436 } else if (Clipboard.Retrieving) {
1437 Clipboard.Retrieving = false;
1438 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1439 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1441 Clipboard.Item = null;
1444 Dnd.HandleSelectionNotifyEvent (ref xevent);
1449 case XEventName.MapNotify: {
1450 if (hwnd.client_window == xevent.MapEvent.window) {
1456 case XEventName.UnmapNotify: {
1457 if (hwnd.client_window == xevent.MapEvent.window) {
1458 hwnd.mapped = false;
1463 case XEventName.KeyRelease:
1464 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1465 XEvent nextevent = new XEvent ();
1467 XPeekEvent (DisplayHandle, ref nextevent);
1469 if (nextevent.type == XEventName.KeyPress &&
1470 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1471 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1475 goto case XEventName.KeyPress;
1477 case XEventName.MotionNotify: {
1480 if (hwnd.Queue.Count > 0) {
1481 peek = hwnd.Queue.Peek();
1482 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1486 goto case XEventName.KeyPress;
1489 case XEventName.KeyPress:
1490 case XEventName.ButtonPress:
1491 case XEventName.ButtonRelease:
1492 case XEventName.EnterNotify:
1493 case XEventName.LeaveNotify:
1494 case XEventName.CreateNotify:
1495 case XEventName.DestroyNotify:
1496 case XEventName.FocusIn:
1497 case XEventName.FocusOut:
1498 case XEventName.ClientMessage:
1499 case XEventName.ReparentNotify:
1500 hwnd.Queue.Enqueue (xevent);
1503 case XEventName.ConfigureNotify:
1504 AddConfigureNotify(xevent);
1507 case XEventName.PropertyNotify:
1508 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1513 IntPtr prop = IntPtr.Zero;
1514 IntPtr prev_active;;
1516 prev_active = ActiveWindow;
1517 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);
1518 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1519 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1522 if (prev_active != ActiveWindow) {
1523 if (prev_active != IntPtr.Zero) {
1524 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1526 if (ActiveWindow != IntPtr.Zero) {
1527 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1530 if (ModalWindows.Count == 0) {
1533 // Modality handling, if we are modal and the new active window is one
1534 // of ours but not the modal one, switch back to the modal window
1536 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1537 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1538 Activate((IntPtr)ModalWindows.Peek());
1551 private IntPtr GetMousewParam(int Delta) {
1554 if ((MouseState & MouseButtons.Left) != 0) {
1555 result |= (int)MsgButtons.MK_LBUTTON;
1558 if ((MouseState & MouseButtons.Middle) != 0) {
1559 result |= (int)MsgButtons.MK_MBUTTON;
1562 if ((MouseState & MouseButtons.Right) != 0) {
1563 result |= (int)MsgButtons.MK_RBUTTON;
1566 Keys mods = ModifierKeys;
1567 if ((mods & Keys.Control) != 0) {
1568 result |= (int)MsgButtons.MK_CONTROL;
1571 if ((mods & Keys.Shift) != 0) {
1572 result |= (int)MsgButtons.MK_SHIFT;
1575 result |= Delta << 16;
1577 return (IntPtr)result;
1579 private IntPtr XGetParent(IntPtr handle) {
1586 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1589 if (Children!=IntPtr.Zero) {
1597 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1598 if (ErrorExceptions) {
1599 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1601 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());
1606 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1609 Control[] controls = c.child_controls.GetAllControls ();
1611 if (c.IsHandleCreated && !c.IsDisposed) {
1612 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1614 #if DriverDebug || DriverDebugDestroy
1615 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1616 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1620 CleanupCachedWindows (hwnd);
1624 for (int i = 0; i < controls.Length; i ++) {
1625 AccumulateDestroyedHandles (controls[i], list);
1631 void CleanupCachedWindows (Hwnd hwnd)
1633 if (ActiveWindow == hwnd.Handle) {
1634 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1635 ActiveWindow = IntPtr.Zero;
1638 if (FocusWindow == hwnd.Handle) {
1639 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1640 FocusWindow = IntPtr.Zero;
1643 if (Grab.Hwnd == hwnd.Handle) {
1644 Grab.Hwnd = IntPtr.Zero;
1645 Grab.Confined = false;
1648 DestroyCaret (hwnd.Handle);
1651 private void PerformNCCalc(Hwnd hwnd) {
1652 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1656 rect = hwnd.DefaultClientRect;
1658 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1659 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1661 ncp.rgrc1.left = rect.Left;
1662 ncp.rgrc1.top = rect.Top;
1663 ncp.rgrc1.right = rect.Right;
1664 ncp.rgrc1.bottom = rect.Bottom;
1666 Marshal.StructureToPtr(ncp, ptr, true);
1667 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1668 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1669 Marshal.FreeHGlobal(ptr);
1671 // FIXME - debug this with Menus
1673 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1674 hwnd.ClientRect = rect;
1677 if ((rect.Width < 1) || (rect.Height < 1)) {
1678 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1680 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1684 #endregion // Private Methods
1687 private void MouseHover(object sender, EventArgs e) {
1691 HoverState.Timer.Enabled = false;
1693 if (HoverState.Window != IntPtr.Zero) {
1694 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1696 xevent = new XEvent ();
1698 xevent.type = XEventName.ClientMessage;
1699 xevent.ClientMessageEvent.display = DisplayHandle;
1700 xevent.ClientMessageEvent.window = HoverState.Window;
1701 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1702 xevent.ClientMessageEvent.format = 32;
1703 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1705 hwnd.Queue.EnqueueLocked (xevent);
1712 private void CaretCallback(object sender, EventArgs e) {
1716 Caret.On = !Caret.On;
1718 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1720 #endregion // Callbacks
1722 #region Public Properties
1724 internal override int Caption {
1730 internal override Size CursorSize {
1735 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1736 return new Size(x, y);
1738 return new Size(16, 16);
1743 internal override bool DragFullWindows {
1749 internal override Size DragSize {
1751 return new Size(4, 4);
1755 internal override Size FrameBorderSize {
1757 throw new NotImplementedException();
1761 internal override Size IconSize {
1767 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1771 current = (long)list;
1774 size = new XIconSize();
1776 for (int i = 0; i < count; i++) {
1777 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1778 current += Marshal.SizeOf(size);
1780 // Look for our preferred size
1781 if (size.min_width == 32) {
1783 return new Size(32, 32);
1786 if (size.max_width == 32) {
1788 return new Size(32, 32);
1791 if (size.min_width < 32 && size.max_width > 32) {
1794 // check if we can fit one
1796 while (x < size.max_width) {
1797 x += size.width_inc;
1800 return new Size(32, 32);
1805 if (largest < size.max_width) {
1806 largest = size.max_width;
1810 // We didn't find a match or we wouldn't be here
1811 return new Size(largest, largest);
1814 return new Size(32, 32);
1819 internal override int KeyboardSpeed {
1822 // A lot harder: need to do:
1823 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1824 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1825 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1827 // And from that we can tell the repetition rate
1829 // Notice, the values must map to:
1830 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1836 internal override int KeyboardDelay {
1839 // Return values must range from 0 to 4, 0 meaning 250ms,
1840 // and 4 meaning 1000 ms.
1842 return 1; // ie, 500 ms
1846 internal override Size MaxWindowTrackSize {
1848 return new Size (WorkingArea.Width, WorkingArea.Height);
1852 internal override Size MinimizedWindowSize {
1854 return new Size(1, 1);
1858 internal override Size MinimizedWindowSpacingSize {
1860 return new Size(1, 1);
1864 internal override Size MinimumWindowSize {
1866 return new Size(1, 1);
1870 internal override Size MinWindowTrackSize {
1872 return new Size(1, 1);
1876 internal override Keys ModifierKeys {
1878 return Keyboard.ModifierKeys;
1882 internal override Size SmallIconSize {
1888 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1892 current = (long)list;
1895 size = new XIconSize();
1897 for (int i = 0; i < count; i++) {
1898 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1899 current += Marshal.SizeOf(size);
1901 // Look for our preferred size
1902 if (size.min_width == 16) {
1904 return new Size(16, 16);
1907 if (size.max_width == 16) {
1909 return new Size(16, 16);
1912 if (size.min_width < 16 && size.max_width > 16) {
1915 // check if we can fit one
1917 while (x < size.max_width) {
1918 x += size.width_inc;
1921 return new Size(16, 16);
1926 if (smallest == 0 || smallest > size.min_width) {
1927 smallest = size.min_width;
1931 // We didn't find a match or we wouldn't be here
1932 return new Size(smallest, smallest);
1935 return new Size(16, 16);
1940 internal override int MouseButtonCount {
1946 internal override bool MouseButtonsSwapped {
1948 return false; // FIXME - how to detect?
1952 internal override Size MouseHoverSize {
1954 return new Size (1, 1);
1958 internal override int MouseHoverTime {
1960 return HoverState.Interval;
1966 internal override bool MouseWheelPresent {
1968 return true; // FIXME - how to detect?
1972 internal override Rectangle VirtualScreen {
1978 internal override Rectangle WorkingArea {
1984 IntPtr prop = IntPtr.Zero;
1987 int current_desktop;
1991 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);
1992 if ((long)nitems < 1) {
1996 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
1999 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);
2000 if ((long)nitems < 4 * current_desktop) {
2004 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2005 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2006 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2007 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2010 return new Rectangle(x, y, width, height);
2013 XWindowAttributes attributes=new XWindowAttributes();
2016 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2019 return new Rectangle(0, 0, attributes.width, attributes.height);
2023 internal override bool ThemesEnabled {
2025 return XplatUIX11.themes_enabled;
2030 #endregion // Public properties
2032 #region Public Static Methods
2033 internal override IntPtr InitializeDriver() {
2035 if (DisplayHandle==IntPtr.Zero) {
2036 SetDisplay(XOpenDisplay(IntPtr.Zero));
2042 internal override void ShutdownDriver(IntPtr token) {
2044 if (DisplayHandle!=IntPtr.Zero) {
2045 XCloseDisplay(DisplayHandle);
2046 DisplayHandle=IntPtr.Zero;
2051 internal override void EnableThemes() {
2052 themes_enabled = true;
2056 internal override void Activate(IntPtr handle) {
2059 hwnd = Hwnd.ObjectFromHandle(handle);
2063 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2064 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2067 // XRaiseWindow(DisplayHandle, handle);
2073 internal override void AudibleAlert() {
2074 XBell(DisplayHandle, 0);
2079 internal override void CaretVisible(IntPtr handle, bool visible) {
2080 if (Caret.Hwnd == handle) {
2082 if (!Caret.Visible) {
2083 Caret.Visible = true;
2085 Caret.Timer.Start();
2088 Caret.Visible = false;
2095 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2096 FormBorderStyle border_style;
2097 TitleStyle title_style;
2099 int tool_caption_height;
2101 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2102 out caption_height, out tool_caption_height);
2104 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2105 caption_height, tool_caption_height,
2110 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2116 hwnd = Hwnd.ObjectFromHandle(handle);
2119 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2126 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2127 DataFormats.Format f;
2130 f = DataFormats.Format.List;
2132 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2136 Clipboard.Formats = new ArrayList();
2139 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2141 Clipboard.Enumerating = true;
2142 while (Clipboard.Enumerating) {
2143 UpdateMessageQueue(null);
2148 result = new int[Clipboard.Formats.Count];
2150 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2151 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2154 Clipboard.Formats = null;
2158 internal override void ClipboardClose(IntPtr handle) {
2159 if (handle != ClipMagic) {
2160 throw new ArgumentException("handle is not a valid clipboard handle");
2165 internal override int ClipboardGetID(IntPtr handle, string format) {
2166 if (handle != ClipMagic) {
2167 throw new ArgumentException("handle is not a valid clipboard handle");
2170 if (format == "Text" ) return (int)Atom.XA_STRING;
2171 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2172 //else if (format == "MetaFilePict" ) return 3;
2173 //else if (format == "SymbolicLink" ) return 4;
2174 //else if (format == "DataInterchangeFormat" ) return 5;
2175 //else if (format == "Tiff" ) return 6;
2176 else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
2177 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2178 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2179 //else if (format == "PenData" ) return 10;
2180 //else if (format == "RiffAudio" ) return 11;
2181 //else if (format == "WaveAudio" ) return 12;
2182 else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
2183 //else if (format == "EnhancedMetafile" ) return 14;
2184 //else if (format == "FileDrop" ) return 15;
2185 //else if (format == "Locale" ) return 16;
2187 return XInternAtom(DisplayHandle, format, false).ToInt32();
2190 internal override IntPtr ClipboardOpen(bool primary_selection) {
2191 if (!primary_selection)
2192 ClipMagic = CLIPBOARD;
2194 ClipMagic = PRIMARY;
2198 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2199 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2201 Clipboard.Retrieving = true;
2202 while (Clipboard.Retrieving) {
2203 UpdateMessageQueue(null);
2206 return Clipboard.Item;
2209 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2210 Clipboard.Item = obj;
2211 Clipboard.Type = type;
2212 Clipboard.Converter = converter;
2215 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2217 // Clearing the selection
2218 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2222 internal override void CreateCaret(IntPtr handle, int width, int height) {
2223 XGCValues gc_values;
2226 hwnd = Hwnd.ObjectFromHandle(handle);
2228 if (Caret.Hwnd != IntPtr.Zero) {
2229 DestroyCaret(Caret.Hwnd);
2232 Caret.Hwnd = handle;
2233 Caret.Window = hwnd.client_window;
2234 Caret.Width = width;
2235 Caret.Height = height;
2236 Caret.Visible = false;
2239 gc_values = new XGCValues();
2240 gc_values.line_width = width;
2242 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2243 if (Caret.gc == IntPtr.Zero) {
2244 Caret.Hwnd = IntPtr.Zero;
2248 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2251 internal override IntPtr CreateWindow(CreateParams cp) {
2252 XSetWindowAttributes Attributes;
2258 IntPtr ParentHandle;
2260 IntPtr ClientWindow;
2261 Rectangle ClientRect;
2262 SetWindowValuemask ValueMask;
2267 Attributes = new XSetWindowAttributes();
2273 if (Width<1) Width=1;
2274 if (Height<1) Height=1;
2276 if (cp.Parent != IntPtr.Zero) {
2277 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2279 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2280 // We need to use our foster parent window until this poor child gets it's parent assigned
2281 ParentHandle=FosterParent;
2282 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2283 ParentHandle=RootWindow;
2285 // Default position on screen, if window manager doesn't place us somewhere else
2288 ParentHandle=RootWindow;
2292 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2294 Attributes.bit_gravity = Gravity.NorthWestGravity;
2295 Attributes.win_gravity = Gravity.NorthWestGravity;
2297 // Save what's under the toolwindow
2298 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2299 Attributes.save_under = true;
2300 ValueMask |= SetWindowValuemask.SaveUnder;
2304 // If we're a popup without caption we override the WM
2305 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2306 Attributes.override_redirect = true;
2307 ValueMask |= SetWindowValuemask.OverrideRedirect;
2313 hwnd.height = Height;
2314 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2316 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2317 hwnd.enabled = false;
2320 ClientRect = hwnd.ClientRect;
2321 ClientWindow = IntPtr.Zero;
2324 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2325 if (WholeWindow != IntPtr.Zero) {
2326 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2328 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2329 ValueMask = SetWindowValuemask.ColorMap;
2330 Attributes.colormap = CustomColormap;
2332 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);
2336 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2337 throw new Exception("Could not create X11 windows");
2340 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2341 hwnd.WholeWindow = WholeWindow;
2342 hwnd.ClientWindow = ClientWindow;
2344 #if DriverDebug || DriverDebugCreate
2345 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);
2348 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2349 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2352 hints = new XSizeHints();
2355 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2356 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2361 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2362 if (hwnd.whole_window != hwnd.client_window)
2363 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2365 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2366 MapWindow(hwnd, WindowType.Both);
2367 hwnd.visible = true;
2371 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2373 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2374 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2376 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2377 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
2378 /* this line keeps the window from showing up in gnome's taskbar */
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}", XplatUI.Window(hwnd.client_window));
2826 CleanupCachedWindows (hwnd);
2828 ArrayList windows = new ArrayList ();
2830 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2833 if (hwnd.whole_window != IntPtr.Zero) {
2834 #if DriverDebug || DriverDebugDestroy
2835 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2837 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2839 else if (hwnd.client_window != IntPtr.Zero) {
2840 #if DriverDebug || DriverDebugDestroy
2841 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2843 XDestroyWindow(DisplayHandle, hwnd.client_window);
2848 foreach (Hwnd h in windows) {
2849 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2853 internal override IntPtr DispatchMessage(ref MSG msg) {
2854 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2857 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2859 XGCValues gc_values;
2862 hwnd = Hwnd.ObjectFromHandle(handle);
2864 gc_values = new XGCValues();
2866 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2867 gc_values.line_width = line_width;
2868 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2870 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2871 //mask = foreground ^ background;
2872 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2873 //XSetBackground(DisplayHandle, gc, background);
2874 //XSetFunction(DisplayHandle, gc, GXxor);
2875 //XSetPlaneMask(DisplayHandle, gc, mask);
2878 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2883 control = Control.FromHandle(handle);
2885 XColor xcolor = new XColor();
2887 xcolor.red = (ushort)(control.ForeColor.R * 257);
2888 xcolor.green = (ushort)(control.ForeColor.G * 257);
2889 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2890 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2891 foreground = (uint)xcolor.pixel.ToInt32();
2893 xcolor.red = (ushort)(control.BackColor.R * 257);
2894 xcolor.green = (ushort)(control.BackColor.G * 257);
2895 xcolor.blue = (ushort)(control.BackColor.B * 257);
2896 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2897 background = (uint)xcolor.pixel.ToInt32();
2899 uint mask = foreground ^ background;
2901 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2902 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2903 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2904 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2906 if ((rect.Width > 0) && (rect.Height > 0)) {
2907 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2909 if (rect.Width > 0) {
2910 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2912 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2915 XFreeGC(DisplayHandle, gc);
2918 internal override void DoEvents() {
2919 MSG msg = new MSG ();
2922 if (OverrideCursorHandle != IntPtr.Zero) {
2923 OverrideCursorHandle = IntPtr.Zero;
2926 queue = ThreadQueue(Thread.CurrentThread);
2928 queue.DispatchIdle = false;
2930 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2931 TranslateMessage (ref msg);
2932 DispatchMessage (ref msg);
2935 queue.DispatchIdle = true;
2938 internal override void EnableWindow(IntPtr handle, bool Enable) {
2941 hwnd = Hwnd.ObjectFromHandle(handle);
2943 hwnd.Enabled = Enable;
2947 internal override void EndLoop(Thread thread) {
2948 // This is where we one day will shut down the loop for the thread
2952 internal override IntPtr GetActive() {
2957 IntPtr prop = IntPtr.Zero;
2958 IntPtr active = IntPtr.Zero;
2960 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);
2961 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2962 active = (IntPtr)Marshal.ReadInt32(prop);
2966 if (active != IntPtr.Zero) {
2969 hwnd = Hwnd.GetObjectFromWindow(active);
2971 active = hwnd.Handle;
2973 active = IntPtr.Zero;
2979 internal override Region GetClipRegion(IntPtr handle) {
2982 hwnd = Hwnd.ObjectFromHandle(handle);
2984 return hwnd.UserClip;
2990 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2997 internal override void GetDisplaySize(out Size size) {
2998 XWindowAttributes attributes=new XWindowAttributes();
3001 // FIXME - use _NET_WM messages instead?
3002 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3005 size = new Size(attributes.width, attributes.height);
3008 internal override SizeF GetAutoScaleSize(Font font) {
3011 string magic_string = "The quick brown fox jumped over the lazy dog.";
3012 double magic_number = 44.549996948242189;
3014 g = Graphics.FromHwnd(FosterParent);
3016 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3017 return new SizeF(width, font.Height);
3020 internal override IntPtr GetParent(IntPtr handle) {
3023 hwnd = Hwnd.ObjectFromHandle(handle);
3024 if (hwnd != null && hwnd.parent != null) {
3025 return hwnd.parent.Handle;
3030 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3040 if (handle != IntPtr.Zero) {
3041 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3043 use_handle = RootWindow;
3047 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3050 if (handle != IntPtr.Zero) {
3059 internal override IntPtr GetFocus() {
3064 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3065 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3068 internal override Point GetMenuOrigin(IntPtr handle) {
3071 hwnd = Hwnd.ObjectFromHandle(handle);
3074 return hwnd.MenuOrigin;
3079 [MonoTODO("Implement filtering")]
3080 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3087 if (((XEventQueue)queue_id).Count > 0) {
3088 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3090 UpdateMessageQueue ((XEventQueue)queue_id);
3092 if (((XEventQueue)queue_id).Count > 0) {
3093 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3094 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3095 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3097 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3098 msg.hwnd= IntPtr.Zero;
3099 msg.message = Msg.WM_ENTERIDLE;
3103 // We reset ourselves so GetMessage can be called again
3104 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3110 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3112 // Handle messages for windows that are already or are about to be destroyed.
3114 // we need a special block for this because unless we remove the hwnd from the paint
3115 // queue it will always stay there (since we don't handle the expose), and we'll
3116 // effectively loop infinitely trying to repaint a non-existant window.
3117 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3118 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3119 hwnd.Queue.Paint.Remove (hwnd);
3120 goto ProcessNextMessage;
3123 // We need to make sure we only allow DestroyNotify events through for zombie
3124 // hwnds, since much of the event handling code makes requests using the hwnd's
3125 // client_window, and that'll result in BadWindow errors if there's some lag
3126 // between the XDestroyWindow call and the DestroyNotify event.
3127 if (hwnd == null || hwnd.zombie) {
3128 #if DriverDebug || DriverDebugDestroy
3129 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3131 goto ProcessNextMessage;
3134 if (hwnd.client_window == xevent.AnyEvent.window) {
3136 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3139 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3142 msg.hwnd = hwnd.Handle;
3145 // If you add a new event to this switch make sure to add it in
3146 // UpdateMessage also unless it is not coming through the X event system.
3148 switch(xevent.type) {
3149 case XEventName.KeyPress: {
3150 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3154 case XEventName.KeyRelease: {
3155 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3159 case XEventName.ButtonPress: {
3160 switch(xevent.ButtonEvent.button) {
3162 MouseState |= MouseButtons.Left;
3164 msg.message = Msg.WM_LBUTTONDOWN;
3166 msg.message = Msg.WM_NCLBUTTONDOWN;
3167 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3169 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3170 msg.wParam=GetMousewParam(0);
3175 MouseState |= MouseButtons.Middle;
3177 msg.message = Msg.WM_MBUTTONDOWN;
3179 msg.message = Msg.WM_NCMBUTTONDOWN;
3180 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3182 msg.wParam=GetMousewParam(0);
3187 MouseState |= MouseButtons.Right;
3189 msg.message = Msg.WM_RBUTTONDOWN;
3191 msg.message = Msg.WM_NCRBUTTONDOWN;
3192 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3194 msg.wParam=GetMousewParam(0);
3199 msg.hwnd = FocusWindow;
3200 msg.message=Msg.WM_MOUSEWHEEL;
3201 msg.wParam=GetMousewParam(120);
3206 msg.hwnd = FocusWindow;
3207 msg.message=Msg.WM_MOUSEWHEEL;
3208 msg.wParam=GetMousewParam(-120);
3214 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3215 MousePosition.X = xevent.ButtonEvent.x;
3216 MousePosition.Y = xevent.ButtonEvent.y;
3218 if (!hwnd.Enabled) {
3221 msg.hwnd = hwnd.EnabledHwnd;
3222 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);
3223 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3226 if (Grab.Hwnd != IntPtr.Zero) {
3227 msg.hwnd = Grab.Hwnd;
3230 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3231 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3232 switch(xevent.ButtonEvent.button) {
3234 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3239 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3244 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3248 ClickPending.Pending = false;
3250 ClickPending.Pending = true;
3251 ClickPending.Hwnd = msg.hwnd;
3252 ClickPending.Message = msg.message;
3253 ClickPending.wParam = msg.wParam;
3254 ClickPending.lParam = msg.lParam;
3255 ClickPending.Time = (long)xevent.ButtonEvent.time;
3261 case XEventName.ButtonRelease: {
3263 Dnd.HandleButtonRelease (ref xevent);
3267 switch(xevent.ButtonEvent.button) {
3269 MouseState &= ~MouseButtons.Left;
3271 msg.message = Msg.WM_LBUTTONUP;
3273 msg.message = Msg.WM_NCLBUTTONUP;
3274 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3276 msg.wParam=GetMousewParam(0);
3281 MouseState &= ~MouseButtons.Middle;
3283 msg.message = Msg.WM_MBUTTONUP;
3285 msg.message = Msg.WM_NCMBUTTONUP;
3286 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3288 msg.wParam=GetMousewParam(0);
3293 MouseState &= ~MouseButtons.Right;
3295 msg.message = Msg.WM_RBUTTONUP;
3297 msg.message = Msg.WM_NCRBUTTONUP;
3298 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3300 msg.wParam=GetMousewParam(0);
3305 goto ProcessNextMessage;
3309 goto ProcessNextMessage;
3313 if (!hwnd.Enabled) {
3316 msg.hwnd = hwnd.EnabledHwnd;
3317 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);
3318 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3321 if (Grab.Hwnd != IntPtr.Zero) {
3322 msg.hwnd = Grab.Hwnd;
3325 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3326 MousePosition.X = xevent.ButtonEvent.x;
3327 MousePosition.Y = xevent.ButtonEvent.y;
3331 case XEventName.MotionNotify: {
3333 #if DriverDebugExtra
3334 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);
3337 if (Dnd.HandleMotionNotify (ref xevent))
3338 goto ProcessNextMessage;
3339 if (Grab.Hwnd != IntPtr.Zero) {
3340 msg.hwnd = Grab.Hwnd;
3342 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3345 msg.message = Msg.WM_MOUSEMOVE;
3346 msg.wParam = GetMousewParam(0);
3347 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3349 if (!hwnd.Enabled) {
3352 msg.hwnd = hwnd.EnabledHwnd;
3353 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);
3354 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3357 MousePosition.X = xevent.MotionEvent.x;
3358 MousePosition.Y = xevent.MotionEvent.y;
3360 if ((HoverState.Timer.Enabled) &&
3361 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3362 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3363 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3364 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3365 HoverState.Timer.Stop();
3366 HoverState.Timer.Start();
3367 HoverState.X = MousePosition.X;
3368 HoverState.Y = MousePosition.Y;
3378 #if DriverDebugExtra
3379 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);
3381 msg.message = Msg.WM_NCMOUSEMOVE;
3383 if (!hwnd.Enabled) {
3384 msg.hwnd = hwnd.EnabledHwnd;
3385 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);
3386 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3389 // The hit test is sent in screen coordinates
3390 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3391 xevent.MotionEvent.x, xevent.MotionEvent.y,
3392 out screen_x, out screen_y, out dummy);
3394 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3395 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3396 IntPtr.Zero, msg.lParam).ToInt32 ();
3397 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3399 MousePosition.X = xevent.MotionEvent.x;
3400 MousePosition.Y = xevent.MotionEvent.y;
3406 case XEventName.EnterNotify: {
3407 if (!hwnd.Enabled) {
3408 goto ProcessNextMessage;
3410 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3411 goto ProcessNextMessage;
3413 msg.message = Msg.WM_MOUSE_ENTER;
3414 HoverState.X = xevent.CrossingEvent.x;
3415 HoverState.Y = xevent.CrossingEvent.y;
3416 HoverState.Timer.Enabled = true;
3417 HoverState.Window = xevent.CrossingEvent.window;
3421 case XEventName.LeaveNotify: {
3422 if (!hwnd.Enabled) {
3423 goto ProcessNextMessage;
3425 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3426 goto ProcessNextMessage;
3428 msg.message=Msg.WM_MOUSE_LEAVE;
3429 HoverState.Timer.Enabled = false;
3430 HoverState.Window = IntPtr.Zero;
3435 case XEventName.CreateNotify: {
3436 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3437 msg.message = WM_CREATE;
3438 // Set up CreateStruct
3440 goto ProcessNextMessage;
3447 case XEventName.ReparentNotify: {
3448 if (hwnd.parent == null) { // Toplevel
3449 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3450 // We need to adjust x/y
3451 // This sucks ass, part 2
3452 // Every WM does the reparenting of toplevel windows different, so there's
3453 // no standard way of getting our adjustment considering frames/decorations
3454 // The code below is needed for metacity. KDE doesn't works just fine without this
3462 hwnd.Reparented = true;
3464 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);
3465 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3466 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3469 hwnd.whacky_wm = true;
3472 if (hwnd.opacity != 0xffffffff) {
3475 opacity = (IntPtr)(Int32)hwnd.opacity;
3476 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3478 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3479 goto ProcessNextMessage;
3481 hwnd.Reparented = false;
3482 goto ProcessNextMessage;
3485 goto ProcessNextMessage;
3488 case XEventName.ConfigureNotify: {
3489 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3490 #if DriverDebugExtra
3491 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);
3493 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3494 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3495 hwnd.configure_pending = false;
3497 // We need to adjust our client window to track the resize of whole_window
3498 if (hwnd.whole_window != hwnd.client_window)
3499 PerformNCCalc(hwnd);
3502 goto ProcessNextMessage;
3505 case XEventName.FocusIn: {
3506 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3507 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3508 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3509 // about it having focus again
3510 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3511 goto ProcessNextMessage;
3514 if (FocusWindow == IntPtr.Zero) {
3515 Control c = Control.FromHandle (hwnd.client_window);
3517 goto ProcessNextMessage;
3518 Form form = c.FindForm ();
3520 goto ProcessNextMessage;
3521 ActiveWindow = form.Handle;
3522 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3523 goto ProcessNextMessage;
3525 Keyboard.FocusIn(FocusWindow);
3526 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3527 goto ProcessNextMessage;
3530 case XEventName.FocusOut: {
3531 // Se the comment for our FocusIn handler
3532 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3533 goto ProcessNextMessage;
3535 Keyboard.FocusOut(FocusWindow);
3537 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3538 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3541 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3542 goto ProcessNextMessage;
3545 case XEventName.Expose: {
3546 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3548 hwnd.expose_pending = false;
3550 hwnd.nc_expose_pending = false;
3552 goto ProcessNextMessage;
3556 if (!hwnd.expose_pending) {
3557 goto ProcessNextMessage;
3560 if (!hwnd.nc_expose_pending) {
3561 goto ProcessNextMessage;
3564 switch (hwnd.border_style) {
3565 case FormBorderStyle.Fixed3D: {
3568 g = Graphics.FromHwnd(hwnd.whole_window);
3569 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3574 case FormBorderStyle.FixedSingle: {
3577 g = Graphics.FromHwnd(hwnd.whole_window);
3578 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3583 #if DriverDebugExtra
3584 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);
3587 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3588 Region region = new Region (rect);
3589 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3590 msg.message = Msg.WM_NCPAINT;
3591 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3594 #if DriverDebugExtra
3595 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);
3597 if (Caret.Visible == true) {
3598 Caret.Paused = true;
3602 if (Caret.Visible == true) {
3604 Caret.Paused = false;
3606 msg.message = Msg.WM_PAINT;
3610 case XEventName.DestroyNotify: {
3612 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3613 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3615 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3616 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3617 CleanupCachedWindows (hwnd);
3619 #if DriverDebugDestroy
3620 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3623 msg.hwnd = hwnd.client_window;
3624 msg.message=Msg.WM_DESTROY;
3627 goto ProcessNextMessage;
3633 case XEventName.ClientMessage: {
3634 if (Dnd.HandleClientMessage (ref xevent)) {
3635 goto ProcessNextMessage;
3638 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3639 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3640 goto ProcessNextMessage;
3643 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3644 msg.message = Msg.WM_MOUSEHOVER;
3645 msg.wParam = GetMousewParam(0);
3646 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3650 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3651 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3652 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3653 msg.wParam = xevent.ClientMessageEvent.ptr3;
3654 msg.lParam = xevent.ClientMessageEvent.ptr4;
3659 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3660 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3665 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3666 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3667 msg.message = Msg.WM_CLOSE;
3671 // We should not get this, but I'll leave the code in case we need it in the future
3672 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3673 goto ProcessNextMessage;
3676 goto ProcessNextMessage;
3679 case XEventName.TimerNotify: {
3680 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3681 goto ProcessNextMessage;
3685 goto ProcessNextMessage;
3692 internal override bool GetText(IntPtr handle, out string text) {
3695 textptr = IntPtr.Zero;
3698 // FIXME - use _NET properties
3699 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3701 if (textptr != IntPtr.Zero) {
3702 text = Marshal.PtrToStringAnsi(textptr);
3711 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) {
3714 hwnd = Hwnd.ObjectFromHandle(handle);
3720 height = hwnd.height;
3722 PerformNCCalc(hwnd);
3724 client_width = hwnd.ClientRect.Width;
3725 client_height = hwnd.ClientRect.Height;
3730 // Should we throw an exception or fail silently?
3731 // throw new ArgumentException("Called with an invalid window handle", "handle");
3741 internal override FormWindowState GetWindowState(IntPtr handle) {
3746 IntPtr prop = IntPtr.Zero;
3750 XWindowAttributes attributes;
3753 hwnd = Hwnd.ObjectFromHandle(handle);
3757 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);
3758 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3759 for (int i = 0; i < (long)nitems; i++) {
3760 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3761 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3763 } else if (atom == _NET_WM_STATE_HIDDEN) {
3771 return FormWindowState.Minimized;
3772 } else if (maximized == 2) {
3773 return FormWindowState.Maximized;
3776 attributes = new XWindowAttributes();
3777 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3778 if (attributes.map_state == MapState.IsUnmapped) {
3779 return (FormWindowState)(-1);
3783 return FormWindowState.Normal;
3786 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3788 GrabConfined = Grab.Confined;
3789 GrabArea = Grab.Area;
3792 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3794 IntPtr confine_to_window;
3796 confine_to_window = IntPtr.Zero;
3798 if (confine_to_handle != IntPtr.Zero) {
3799 XWindowAttributes attributes = new XWindowAttributes();
3801 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3804 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3806 Grab.Area.X = attributes.x;
3807 Grab.Area.Y = attributes.y;
3808 Grab.Area.Width = attributes.width;
3809 Grab.Area.Height = attributes.height;
3810 Grab.Confined = true;
3811 confine_to_window = hwnd.client_window;
3816 hwnd = Hwnd.ObjectFromHandle(handle);
3819 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3820 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3821 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3822 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3826 internal override void UngrabWindow(IntPtr hwnd) {
3828 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3829 XFlush(DisplayHandle);
3831 Grab.Hwnd = IntPtr.Zero;
3832 Grab.Confined = false;
3835 internal override void HandleException(Exception e) {
3836 StackTrace st = new StackTrace(e, true);
3837 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3838 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3841 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3844 hwnd = Hwnd.ObjectFromHandle(handle);
3847 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3849 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3853 internal override bool IsEnabled(IntPtr handle) {
3854 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3855 return (hwnd != null && hwnd.Enabled);
3858 internal override bool IsVisible(IntPtr handle) {
3859 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3860 return (hwnd != null && hwnd.visible);
3863 internal override void KillTimer(Timer timer) {
3864 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3866 if (queue == null) {
3867 // This isn't really an error, MS doesn't start the timer if
3868 // it has no assosciated queue
3871 queue.timer_list.Remove (timer);
3874 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3880 hwnd = Hwnd.ObjectFromHandle(handle);
3883 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3890 internal override void OverrideCursor(IntPtr cursor) {
3891 OverrideCursorHandle = cursor;
3894 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3895 PaintEventArgs paint_event;
3898 hwnd = Hwnd.ObjectFromHandle(handle);
3900 if (Caret.Visible == true) {
3901 Caret.Paused = true;
3908 dc = Graphics.FromHwnd (hwnd.client_window);
3910 Region clip_region = new Region ();
3911 clip_region.MakeEmpty();
3913 foreach (Rectangle r in hwnd.ClipRectangles) {
3914 clip_region.Union (r);
3917 if (hwnd.UserClip != null) {
3918 clip_region.Intersect(hwnd.UserClip);
3921 dc.Clip = clip_region;
3922 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
3923 hwnd.expose_pending = false;
3925 hwnd.ClearInvalidArea();
3927 hwnd.drawing_stack.Push (dc);
3931 dc = Graphics.FromHwnd (hwnd.whole_window);
3933 if (!hwnd.nc_invalid.IsEmpty) {
3934 dc.SetClip (hwnd.nc_invalid);
3935 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
3937 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3939 hwnd.nc_expose_pending = false;
3941 hwnd.ClearNcInvalidArea ();
3943 hwnd.drawing_stack.Push (dc);
3949 internal override void PaintEventEnd(IntPtr handle, bool client) {
3952 hwnd = Hwnd.ObjectFromHandle(handle);
3954 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
3958 if (Caret.Visible == true) {
3960 Caret.Paused = false;
3964 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3965 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3966 XEventQueue queue = (XEventQueue) queue_id;
3969 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3970 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3974 if (queue.Count > 0) {
3977 // Only call UpdateMessageQueue if real events are pending
3978 // otherwise we go to sleep on the socket
3979 if (XPending(DisplayHandle) != 0) {
3980 UpdateMessageQueue((XEventQueue)queue_id);
3982 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3987 CheckTimers(queue.timer_list, DateTime.UtcNow);
3992 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
3995 // FIXME - I think this should just enqueue directly
3996 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3997 XEvent xevent = new XEvent ();
3998 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4000 xevent.type = XEventName.ClientMessage;
4001 xevent.ClientMessageEvent.display = DisplayHandle;
4004 xevent.ClientMessageEvent.window = hwnd.whole_window;
4006 xevent.ClientMessageEvent.window = IntPtr.Zero;
4009 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4010 xevent.ClientMessageEvent.format = 32;
4011 xevent.ClientMessageEvent.ptr1 = handle;
4012 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4013 xevent.ClientMessageEvent.ptr3 = wparam;
4014 xevent.ClientMessageEvent.ptr4 = lparam;
4016 hwnd.Queue.Enqueue (xevent);
4021 internal override void PostQuitMessage(int exitCode) {
4023 XFlush(DisplayHandle);
4024 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4027 internal override void RequestNCRecalc(IntPtr handle) {
4030 hwnd = Hwnd.ObjectFromHandle(handle);
4036 PerformNCCalc(hwnd);
4037 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4038 InvalidateWholeWindow(handle);
4041 internal override void ResetMouseHover(IntPtr handle) {
4044 hwnd = Hwnd.ObjectFromHandle(handle);
4049 HoverState.Timer.Enabled = true;
4050 HoverState.X = MousePosition.X;
4051 HoverState.Y = MousePosition.Y;
4052 HoverState.Window = handle;
4056 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4062 hwnd = Hwnd.ObjectFromHandle(handle);
4065 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4072 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4078 hwnd = Hwnd.ObjectFromHandle(handle);
4081 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4088 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4091 XGCValues gc_values;
4094 hwnd = Hwnd.ObjectFromHandle(handle);
4097 if (r != Rectangle.Empty) {
4098 /* We have an invalid area in the window we're scrolling.
4099 Adjust our stored invalid rectangle to to match the scrolled amount */
4114 hwnd.ClearInvalidArea();
4115 hwnd.AddInvalidArea(r);
4118 gc_values = new XGCValues();
4120 if (with_children) {
4121 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4124 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4132 height = area.Height - YAmount;
4133 dest_y = area.Y + YAmount;
4136 src_y = area.Y - YAmount;
4137 height = area.Height + YAmount;
4143 width = area.Width - XAmount;
4144 dest_x = area.X + XAmount;
4147 src_x = area.X - XAmount;
4148 width = area.Width + XAmount;
4152 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4154 // Generate an expose for the area exposed by the horizontal scroll
4155 // We don't use AddExpose since we're
4157 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4158 } else if (XAmount < 0) {
4159 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4162 // Generate an expose for the area exposed by the vertical scroll
4164 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4165 } else if (YAmount < 0) {
4166 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4168 XFreeGC(DisplayHandle, gc);
4171 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4175 hwnd = Hwnd.GetObjectFromWindow(handle);
4177 rect = hwnd.ClientRect;
4180 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4183 internal override void SendAsyncMethod (AsyncMethodData method) {
4185 XEvent xevent = new XEvent ();
4187 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4189 xevent.type = XEventName.ClientMessage;
4190 xevent.ClientMessageEvent.display = DisplayHandle;
4191 xevent.ClientMessageEvent.window = method.Handle;
4192 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4193 xevent.ClientMessageEvent.format = 32;
4194 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4196 hwnd.Queue.EnqueueLocked (xevent);
4201 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4203 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4206 h = Hwnd.ObjectFromHandle(hwnd);
4208 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4209 AsyncMethodResult result;
4210 AsyncMethodData data;
4212 result = new AsyncMethodResult ();
4213 data = new AsyncMethodData ();
4216 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4217 data.Args = new object[] { hwnd, message, wParam, lParam };
4218 data.Result = result;
4220 SendAsyncMethod (data);
4221 #if DriverDebug || DriverDebugThreads
4222 Console.WriteLine ("Sending {0} message across.", message);
4227 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4230 internal override void SetAllowDrop (IntPtr handle, bool value)
4232 // We allow drop on all windows
4235 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4236 DragDropEffects allowed_effects)
4238 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4241 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4243 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4246 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4249 hwnd = Hwnd.ObjectFromHandle(handle);
4251 Form form = Control.FromHandle (handle) as Form;
4252 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4253 border_style == FormBorderStyle.SizableToolWindow)) {
4254 form.window_manager = new InternalWindowManager (form);
4257 hwnd.border_style = border_style;
4258 RequestNCRecalc(handle);
4261 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4262 if (Caret.Hwnd == handle) {
4269 if (Caret.Visible == true) {
4271 Caret.Timer.Start();
4276 internal override void SetClipRegion(IntPtr handle, Region region) {
4279 hwnd = Hwnd.ObjectFromHandle(handle);
4284 hwnd.UserClip = region;
4285 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4288 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4291 if (OverrideCursorHandle == IntPtr.Zero) {
4292 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4296 LastCursorHandle = cursor;
4297 LastCursorWindow = handle;
4299 hwnd = Hwnd.ObjectFromHandle(handle);
4301 if (cursor != IntPtr.Zero) {
4302 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4304 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4306 XFlush(DisplayHandle);
4311 hwnd = Hwnd.ObjectFromHandle(handle);
4313 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4317 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4318 out int root_x, out int root_y, out int child_x, out int child_y,
4321 /* this code was written with the help of
4322 glance at gdk. I never would have realized we
4323 needed a loop in order to traverse down in the
4324 hierarchy. I would have assumed you'd get the
4325 most deeply nested child and have to do
4326 XQueryTree to move back up the hierarchy..
4327 stupid me, of course. */
4330 XGrabServer (display);
4332 XQueryPointer(display, w, out root, out c,
4333 out root_x, out root_y, out child_x, out child_y,
4339 IntPtr child_last = IntPtr.Zero;
4340 while (c != IntPtr.Zero) {
4342 XQueryPointer(display, c, out root, out c,
4343 out root_x, out root_y, out child_x, out child_y,
4346 XUngrabServer (display);
4351 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4352 if (handle == IntPtr.Zero) {
4355 int root_x, root_y, child_x, child_y, mask;
4358 * QueryPointer before warping
4359 * because if the warp is on
4360 * the RootWindow, the x/y are
4361 * relative to the current
4364 QueryPointer (DisplayHandle, RootWindow,
4367 out root_x, out root_y,
4368 out child_x, out child_y,
4371 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4373 XFlush (DisplayHandle);
4375 /* then we need to a
4376 * QueryPointer after warping
4377 * to manually generate a
4378 * motion event for the window
4381 QueryPointer (DisplayHandle, RootWindow,
4384 out root_x, out root_y,
4385 out child_x, out child_y,
4388 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4389 if (child_hwnd == null) {
4393 XEvent xevent = new XEvent ();
4395 xevent.type = XEventName.MotionNotify;
4396 xevent.MotionEvent.display = DisplayHandle;
4397 xevent.MotionEvent.window = child_hwnd.client_window;
4398 xevent.MotionEvent.root = RootWindow;
4399 xevent.MotionEvent.x = child_x;
4400 xevent.MotionEvent.y = child_y;
4401 xevent.MotionEvent.x_root = root_x;
4402 xevent.MotionEvent.y_root = root_y;
4403 xevent.MotionEvent.state = mask;
4405 child_hwnd.Queue.Enqueue (xevent);
4410 hwnd = Hwnd.ObjectFromHandle(handle);
4412 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4417 internal override void SetFocus(IntPtr handle) {
4419 IntPtr prev_focus_window;
4421 hwnd = Hwnd.ObjectFromHandle(handle);
4423 if (hwnd.client_window == FocusWindow) {
4427 prev_focus_window = FocusWindow;
4428 FocusWindow = hwnd.client_window;
4430 if (prev_focus_window != IntPtr.Zero) {
4431 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4433 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4435 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4438 internal override void SetIcon(IntPtr handle, Icon icon) {
4441 hwnd = Hwnd.ObjectFromHandle(handle);
4443 SetIcon(hwnd, icon);
4447 internal override void SetMenu(IntPtr handle, Menu menu) {
4450 hwnd = Hwnd.ObjectFromHandle(handle);
4453 RequestNCRecalc(handle);
4456 internal override void SetModal(IntPtr handle, bool Modal) {
4458 ModalWindows.Push(handle);
4460 if (ModalWindows.Contains(handle)) {
4463 if (ModalWindows.Count > 0) {
4464 Activate((IntPtr)ModalWindows.Peek());
4469 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4472 hwnd = Hwnd.ObjectFromHandle(handle);
4473 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4476 #if DriverDebug || DriverDebugParent
4477 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4479 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4485 internal override void SetTimer (Timer timer) {
4486 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4488 if (queue == null) {
4489 // This isn't really an error, MS doesn't start the timer if
4490 // it has no assosciated queue
4493 queue.timer_list.Add (timer);
4497 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4501 hwnd = Hwnd.ObjectFromHandle(handle);
4503 if (handle_owner != IntPtr.Zero) {
4504 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4515 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4516 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4518 if (hwnd_owner != null) {
4519 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4521 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4526 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4532 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4535 hwnd = Hwnd.ObjectFromHandle(handle);
4536 hwnd.visible = visible;
4540 if (Control.FromHandle(handle) is Form) {
4543 s = ((Form)Control.FromHandle(handle)).WindowState;
4545 MapWindow(hwnd, WindowType.Both);
4548 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4549 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4553 MapWindow(hwnd, WindowType.Both);
4555 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4557 UnmapWindow(hwnd, WindowType.Whole);
4563 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4568 hwnd = Hwnd.ObjectFromHandle(handle);
4573 hints = new XSizeHints();
4575 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4576 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4577 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4578 hints.min_width = min.Width;
4579 hints.min_height = min.Height;
4582 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4583 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4584 hints.max_width = max.Width;
4585 hints.max_height = max.Height;
4588 if (hints.flags != IntPtr.Zero) {
4589 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4592 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4593 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4594 hints.x = maximized.X;
4595 hints.y = maximized.Y;
4596 hints.width = maximized.Width;
4597 hints.height = maximized.Height;
4599 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4600 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4605 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4608 hwnd = Hwnd.ObjectFromHandle(handle);
4614 // X requires a sanity check for width & height; otherwise it dies
4615 if (hwnd.zero_sized && width > 0 && height > 0) {
4617 MapWindow(hwnd, WindowType.Whole);
4619 hwnd.zero_sized = false;
4622 if ((width < 1) || (height < 1)) {
4623 hwnd.zero_sized = true;
4624 UnmapWindow(hwnd, WindowType.Whole);
4627 // Save a server roundtrip (and prevent a feedback loop)
4628 if ((hwnd.x == x) && (hwnd.y == y) &&
4629 (hwnd.width == width) && (hwnd.height == height)) {
4633 if (!hwnd.zero_sized) {
4638 hwnd.height = height;
4639 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4641 if (hwnd.fixed_size) {
4642 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4646 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4647 PerformNCCalc(hwnd);
4651 // Update our position/size immediately, so
4652 // that future calls to SetWindowPos aren't
4653 // kept from calling XMoveResizeWindow (by the
4654 // "Save a server roundtrip" block above).
4658 hwnd.height = height;
4659 hwnd.ClientRect = Rectangle.Empty;
4662 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4663 FormWindowState current_state;
4666 hwnd = Hwnd.ObjectFromHandle(handle);
4668 current_state = GetWindowState(handle);
4670 if (current_state == state) {
4675 case FormWindowState.Normal: {
4677 if (current_state == FormWindowState.Minimized) {
4678 MapWindow(hwnd, WindowType.Both);
4679 } else if (current_state == FormWindowState.Maximized) {
4680 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4687 case FormWindowState.Minimized: {
4689 if (current_state == FormWindowState.Maximized) {
4690 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4692 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4697 case FormWindowState.Maximized: {
4699 if (current_state == FormWindowState.Minimized) {
4700 MapWindow(hwnd, WindowType.Both);
4703 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4711 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4714 hwnd = Hwnd.ObjectFromHandle(handle);
4715 SetHwndStyles(hwnd, cp);
4716 SetWMStyles(hwnd, cp);
4719 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4723 hwnd = Hwnd.ObjectFromHandle(handle);
4729 hwnd.opacity = (uint)(0xffffffff * transparency);
4730 opacity = (IntPtr)((int)hwnd.opacity);
4732 if (hwnd.reparented) {
4733 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4737 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4738 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4746 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4749 } else if (!bottom) {
4750 Hwnd after_hwnd = null;
4752 if (after_handle != IntPtr.Zero) {
4753 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4756 XWindowChanges values = new XWindowChanges();
4758 if (after_hwnd == null) {
4759 // Work around metacity 'issues'
4763 atoms[0] = unixtime();
4764 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4766 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4767 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4769 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4772 values.sibling = after_hwnd.whole_window;
4773 values.stack_mode = StackMode.Below;
4776 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4781 XLowerWindow(DisplayHandle, hwnd.whole_window);
4788 internal override void ShowCursor(bool show) {
4789 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4792 internal override object StartLoop(Thread thread) {
4793 return (Object) ThreadQueue(thread);
4796 internal override bool SupportsTransparency() {
4797 // We need to check if the x compositing manager is running
4801 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4802 GetSystrayManagerWindow();
4804 if (SystrayMgrWindow != IntPtr.Zero) {
4805 XSizeHints size_hints;
4808 hwnd = Hwnd.ObjectFromHandle(handle);
4810 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4814 if (hwnd.client_window != hwnd.whole_window) {
4815 XDestroyWindow(DisplayHandle, hwnd.client_window);
4816 hwnd.client_window = hwnd.whole_window;
4818 /* by virtue of the way the tests are ordered when determining if it's PAINT
4819 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
4820 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4821 there's a pending expose). */
4822 if (hwnd.nc_expose_pending) {
4823 hwnd.nc_expose_pending = false;
4824 if (!hwnd.expose_pending)
4825 hwnd.Queue.Paint.Remove (hwnd);
4829 size_hints = new XSizeHints();
4831 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4833 size_hints.min_width = 24;
4834 size_hints.min_height = 24;
4835 size_hints.max_width = 24;
4836 size_hints.max_height = 24;
4837 size_hints.base_width = 24;
4838 size_hints.base_height = 24;
4840 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4842 int[] atoms = new int[2];
4843 atoms [0] = 1; // Version 1
4844 atoms [1] = 1; // we want to be mapped
4846 // This line cost me 3 days...
4847 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4849 // Need to pick some reasonable defaults
4851 tt.AutomaticDelay = 100;
4852 tt.InitialDelay = 250;
4853 tt.ReshowDelay = 250;
4854 tt.ShowAlways = true;
4856 if ((tip != null) && (tip != string.Empty)) {
4857 tt.SetToolTip(Control.FromHandle(handle), tip);
4863 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4871 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4874 control = Control.FromHandle(handle);
4875 if (control != null && tt != null) {
4876 tt.SetToolTip(control, tip);
4884 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4886 #if GTKSOCKET_SUPPORTS_REPARENTING
4889 hwnd = Hwnd.ObjectFromHandle(handle);
4891 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4892 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4893 * 2. The client can reparent its window out of the embedder window.
4894 * 3. The client can destroy its window.
4896 * this call to SetParent is case 2, but in
4897 * the spec it also mentions that gtk doesn't
4898 * support this at present. Looking at HEAD
4899 * gtksocket-x11.c jives with this statement.
4901 * so we can't reparent. we have to destroy.
4903 SetParent(hwnd.whole_window, FosterParent);
4905 Control control = Control.FromHandle(handle);
4906 if (control is NotifyIcon.NotifyIconWindow)
4907 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
4910 // The caller can now re-dock it later...
4917 internal override bool Text(IntPtr handle, string text) {
4919 // FIXME - use _NET properties
4920 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4925 internal override bool TranslateMessage(ref MSG msg) {
4926 return Keyboard.TranslateMessage (ref msg);
4929 internal override void UpdateWindow(IntPtr handle) {
4932 hwnd = Hwnd.ObjectFromHandle(handle);
4934 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
4938 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4939 hwnd.Queue.Paint.Remove(hwnd);
4942 #endregion // Public Static Methods
4945 internal override event EventHandler Idle;
4946 #endregion // Events
4949 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4950 internal extern static IntPtr XOpenDisplay(IntPtr display);
4951 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4952 internal extern static int XCloseDisplay(IntPtr display);
4953 [DllImport ("libX11", EntryPoint="XSynchronize")]
4954 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4956 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4957 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);
4958 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4959 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4960 [DllImport ("libX11", EntryPoint="XMapWindow")]
4961 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4962 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4963 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4964 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4965 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4966 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4967 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4968 [DllImport ("libX11", EntryPoint="XRootWindow")]
4969 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4970 [DllImport ("libX11", EntryPoint="XNextEvent")]
4971 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4972 [DllImport ("libX11")]
4973 internal extern static int XConnectionNumber (IntPtr diplay);
4974 [DllImport ("libX11")]
4975 internal extern static int XPending (IntPtr diplay);
4976 [DllImport ("libX11", EntryPoint="XSelectInput")]
4977 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4979 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4980 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4982 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4983 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4984 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4985 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4987 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4988 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4990 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4991 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4993 [DllImport ("libX11", EntryPoint="XFlush")]
4994 internal extern static int XFlush(IntPtr display);
4996 [DllImport ("libX11", EntryPoint="XSetWMName")]
4997 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4999 [DllImport ("libX11", EntryPoint="XStoreName")]
5000 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5002 [DllImport ("libX11", EntryPoint="XFetchName")]
5003 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5005 [DllImport ("libX11", EntryPoint="XSendEvent")]
5006 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5008 [DllImport ("libX11", EntryPoint="XQueryTree")]
5009 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);
5011 [DllImport ("libX11", EntryPoint="XFree")]
5012 internal extern static int XFree(IntPtr data);
5014 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5015 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5017 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5018 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5020 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5021 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5023 [DllImport ("libX11", EntryPoint="XInternAtom")]
5024 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5026 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5027 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5029 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5030 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);
5032 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5033 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5035 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5036 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);
5038 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5039 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);
5041 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5042 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);
5044 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5045 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);
5047 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5048 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);
5050 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5051 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);
5053 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5054 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);
5056 [DllImport ("libX11", EntryPoint="XClearWindow")]
5057 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5059 [DllImport ("libX11", EntryPoint="XClearArea")]
5060 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5063 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5064 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5066 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5067 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5069 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5070 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5072 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5073 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5075 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5076 internal extern static int XDefaultScreen(IntPtr display);
5078 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5079 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5081 [DllImport ("libX11", EntryPoint="XLookupColor")]
5082 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5084 [DllImport ("libX11", EntryPoint="XAllocColor")]
5085 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5087 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5088 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5090 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5091 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5093 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5094 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5096 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5097 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5099 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5100 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5102 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5103 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5105 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5106 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5108 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5109 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5111 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5112 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5114 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5115 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5117 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5118 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5121 [DllImport ("libX11", EntryPoint="XCreateGC")]
5122 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5124 [DllImport ("libX11", EntryPoint="XFreeGC")]
5125 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5127 [DllImport ("libX11", EntryPoint="XSetFunction")]
5128 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5130 [DllImport ("libX11", EntryPoint="XDrawLine")]
5131 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5133 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5134 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5136 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5137 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5139 [DllImport ("libX11", EntryPoint="XCopyArea")]
5140 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);
5142 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5143 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);
5145 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5146 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5148 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5149 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5151 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5152 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5154 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5155 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5157 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5158 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5160 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5161 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5163 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5164 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);
5166 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5167 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5169 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5170 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5172 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5173 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5175 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5176 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5178 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5179 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5181 [DllImport ("libX11", EntryPoint="XGrabServer")]
5182 internal extern static void XGrabServer(IntPtr display);
5184 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5185 internal extern static void XUngrabServer(IntPtr display);
5187 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5188 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5190 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5191 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5193 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5194 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5196 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5197 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5199 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5200 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5202 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5203 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5205 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5206 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5208 [DllImport ("libX11", EntryPoint="XInitThreads")]
5209 internal extern static int XInitThreads();
5211 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5212 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5214 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5215 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5217 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5218 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5220 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5221 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5223 [DllImport ("libX11", EntryPoint="XSetForeground")]
5224 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5226 [DllImport ("libX11", EntryPoint="XSetBackground")]
5227 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5229 [DllImport ("libX11", EntryPoint="XBell")]
5230 internal extern static int XBell(IntPtr display, int percent);
5232 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5233 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5235 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5236 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5238 [DllImport ("libX11")]
5239 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5241 [DllImport ("libX11")]
5242 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);