1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
92 private static IntPtr ClipMagic;
93 private static ClipboardStruct Clipboard; // Our clipboard
96 private static IntPtr PostAtom; // PostMessage atom
97 private static IntPtr AsyncAtom; // Support for async messages
100 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
102 private static Pollfd[] pollfds; // For watching the X11 socket
104 private static X11Keyboard Keyboard; //
105 private static X11Dnd Dnd;
106 private static Socket listen; //
107 private static Socket wake; //
108 private static Socket wake_receive; //
109 private static byte[] network_buffer; //
110 private static bool detectable_key_auto_repeat;
113 private static IntPtr ActiveWindow; // Handle of the active window
114 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
117 private static Stack ModalWindows; // Stack of our modal windows
120 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
123 private static IntPtr LastCursorWindow; // The last window we set the cursor on
124 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
125 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
128 private static CaretStruct Caret; //
131 private static IntPtr WM_PROTOCOLS;
132 private static IntPtr WM_DELETE_WINDOW;
133 private static IntPtr WM_TAKE_FOCUS;
134 private static IntPtr _NET_SUPPORTED;
135 private static IntPtr _NET_CLIENT_LIST;
136 private static IntPtr _NET_NUMBER_OF_DESKTOPS;
137 private static IntPtr _NET_DESKTOP_GEOMETRY;
138 private static IntPtr _NET_DESKTOP_VIEWPORT;
139 private static IntPtr _NET_CURRENT_DESKTOP;
140 private static IntPtr _NET_DESKTOP_NAMES;
141 private static IntPtr _NET_ACTIVE_WINDOW;
142 private static IntPtr _NET_WORKAREA;
143 private static IntPtr _NET_SUPPORTING_WM_CHECK;
144 private static IntPtr _NET_VIRTUAL_ROOTS;
145 private static IntPtr _NET_DESKTOP_LAYOUT;
146 private static IntPtr _NET_SHOWING_DESKTOP;
147 private static IntPtr _NET_CLOSE_WINDOW;
148 private static IntPtr _NET_MOVERESIZE_WINDOW;
149 private static IntPtr _NET_WM_MOVERESIZE;
150 private static IntPtr _NET_RESTACK_WINDOW;
151 private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
152 private static IntPtr _NET_WM_NAME;
153 private static IntPtr _NET_WM_VISIBLE_NAME;
154 private static IntPtr _NET_WM_ICON_NAME;
155 private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
156 private static IntPtr _NET_WM_DESKTOP;
157 private static IntPtr _NET_WM_WINDOW_TYPE;
158 private static IntPtr _NET_WM_STATE;
159 private static IntPtr _NET_WM_ALLOWED_ACTIONS;
160 private static IntPtr _NET_WM_STRUT;
161 private static IntPtr _NET_WM_STRUT_PARTIAL;
162 private static IntPtr _NET_WM_ICON_GEOMETRY;
163 private static IntPtr _NET_WM_ICON;
164 private static IntPtr _NET_WM_PID;
165 private static IntPtr _NET_WM_HANDLED_ICONS;
166 private static IntPtr _NET_WM_USER_TIME;
167 private static IntPtr _NET_FRAME_EXTENTS;
168 private static IntPtr _NET_WM_PING;
169 private static IntPtr _NET_WM_SYNC_REQUEST;
170 private static IntPtr _NET_SYSTEM_TRAY_S;
171 private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
172 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
173 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
174 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
175 private static IntPtr _XEMBED;
176 private static IntPtr _XEMBED_INFO;
177 private static IntPtr _MOTIF_WM_HINTS;
178 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
179 private static IntPtr _NET_WM_STATE_ABOVE;
180 private static IntPtr _NET_WM_STATE_MODAL;
181 private static IntPtr _NET_WM_STATE_HIDDEN;
182 private static IntPtr _NET_WM_CONTEXT_HELP;
183 private static IntPtr _NET_WM_WINDOW_OPACITY;
184 private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
185 private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
186 private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
187 private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
188 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
189 private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
190 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
191 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
192 private static IntPtr CLIPBOARD;
193 private static IntPtr PRIMARY;
194 private static IntPtr DIB;
195 private static IntPtr OEMTEXT;
196 private static IntPtr UNICODETEXT;
197 private static IntPtr TARGETS;
199 // mouse hover message generation
200 private static HoverStruct HoverState; //
202 // double click message generation
203 private static ClickStruct ClickPending; //
205 // Support for mouse grab
206 private static GrabStruct Grab; //
209 private static Point MousePosition; // Last position of mouse, in screen coords
210 internal static MouseButtons MouseState; // Last state of mouse buttons
213 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
215 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
216 EventMask.ButtonReleaseMask |
217 EventMask.KeyPressMask |
218 EventMask.KeyReleaseMask |
219 EventMask.EnterWindowMask |
220 EventMask.LeaveWindowMask |
221 EventMask.ExposureMask |
222 EventMask.FocusChangeMask |
223 EventMask.PointerMotionMask |
224 EventMask.SubstructureNotifyMask);
226 static readonly object lockobj = new object ();
228 #endregion // Local Variables
230 private XplatUIX11() {
231 // Handle singleton stuff first
234 // Now regular initialization
235 XlibLock = new object ();
236 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
239 ErrorExceptions = false;
241 // X11 Initialization
242 SetDisplay(XOpenDisplay(IntPtr.Zero));
243 X11DesktopColors.Initialize();
246 // Disable keyboard autorepeat
248 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
249 detectable_key_auto_repeat = true;
251 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
252 detectable_key_auto_repeat = false;
255 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
256 ErrorHandler = new XErrorHandler(HandleError);
257 XSetErrorHandler(ErrorHandler);
261 // Remove our display handle from S.D
262 Graphics.FromHdcInternal (IntPtr.Zero);
265 #endregion // Constructors
267 #region Singleton Specific Code
268 public static XplatUIX11 GetInstance() {
270 if (Instance == null) {
271 Instance=new XplatUIX11();
278 public int Reference {
285 #region Internal Properties
286 internal static IntPtr Display {
288 return DisplayHandle;
292 XplatUIX11.GetInstance().SetDisplay(value);
296 internal static int Screen {
306 internal static IntPtr RootWindowHandle {
316 internal static IntPtr Visual {
322 CustomVisual = value;
326 internal static IntPtr ColorMap {
328 return CustomColormap;
332 CustomColormap = value;
337 #region XExceptionClass
338 internal class XException : ApplicationException {
342 XRequest RequestCode;
346 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
347 this.Display = Display;
348 this.ResourceID = ResourceID;
349 this.Serial = Serial;
350 this.RequestCode = RequestCode;
351 this.ErrorCode = ErrorCode;
352 this.MinorCode = MinorCode;
355 public override string Message {
357 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
361 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
370 sb = new StringBuilder(160);
371 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
372 x_error_text = sb.ToString();
373 hwnd = Hwnd.ObjectFromHandle(ResourceID);
375 hwnd_text = hwnd.ToString();
376 c = Control.FromHandle(hwnd.Handle);
378 control_text = c.ToString();
380 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
383 hwnd_text = "<null>";
384 control_text = "<null>";
388 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);
392 #endregion // XExceptionClass
394 #region Internal Methods
395 internal void SetDisplay(IntPtr display_handle) {
396 if (display_handle != IntPtr.Zero) {
399 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
400 hwnd = Hwnd.ObjectFromHandle(FosterParent);
401 XDestroyWindow(DisplayHandle, FosterParent);
405 if (DisplayHandle != IntPtr.Zero) {
406 XCloseDisplay(DisplayHandle);
409 DisplayHandle=display_handle;
411 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
412 // been hacked to do this for us.
413 Graphics.FromHdcInternal (DisplayHandle);
416 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
417 XSynchronize(DisplayHandle, true);
420 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
421 ErrorExceptions = true;
425 ScreenNo = XDefaultScreen(DisplayHandle);
426 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
427 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
429 // Create the foster parent
430 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
431 if (FosterParent==IntPtr.Zero) {
432 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
436 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
437 hwnd.WholeWindow = FosterParent;
438 hwnd.ClientWindow = FosterParent;
440 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
442 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
443 hwnd.whole_window = RootWindow;
444 hwnd.ClientWindow = RootWindow;
446 // For sleeping on the X11 socket
447 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
448 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
452 // To wake up when a timer is ready
453 network_buffer = new byte[10];
455 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
456 wake.Connect(listen.LocalEndPoint);
457 wake_receive = listen.Accept();
460 pollfds = new Pollfd [2];
461 pollfds [0] = new Pollfd ();
462 pollfds [0].fd = XConnectionNumber (DisplayHandle);
463 pollfds [0].events = PollEvents.POLLIN;
465 pollfds [1] = new Pollfd ();
466 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
467 pollfds [1].events = PollEvents.POLLIN;
470 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
471 Dnd = new X11Dnd (DisplayHandle);
473 DoubleClickInterval = 500;
475 HoverState.Interval = 500;
476 HoverState.Timer = new Timer();
477 HoverState.Timer.Enabled = false;
478 HoverState.Timer.Interval = HoverState.Interval;
479 HoverState.Timer.Tick += new EventHandler(MouseHover);
480 HoverState.Size = new Size(4, 4);
484 ActiveWindow = IntPtr.Zero;
485 FocusWindow = IntPtr.Zero;
486 ModalWindows = new Stack(3);
488 MouseState = MouseButtons.None;
489 MousePosition = new Point(0, 0);
491 Caret.Timer = new Timer();
492 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
493 Caret.Timer.Tick += new EventHandler(CaretCallback);
497 // Grab atom changes off the root window to catch certain WM events
498 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
500 // Handle any upcoming errors
501 ErrorHandler = new XErrorHandler(HandleError);
502 XSetErrorHandler(ErrorHandler);
504 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
508 internal static void Where() {
509 Console.WriteLine("Here: {0}\n", WhereString());
512 internal static string WhereString() {
520 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
521 unknown = Locale.GetText("<unknown method>");
522 sb = new StringBuilder();
523 stack = new StackTrace(true);
525 for (int i = 0; i < stack.FrameCount; i++) {
526 frame = stack.GetFrame(i);
529 method = frame.GetMethod();
530 if (method != null) {
532 sb.AppendFormat(frame.ToString());
534 if (frame.GetFileLineNumber() != 0) {
535 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
537 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
543 return sb.ToString();
545 #endregion // Internal Methods
547 #region Private Methods
548 private int unixtime() {
549 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
551 return (int) t.TotalSeconds;
554 private static void SetupAtoms() {
555 // make sure this array stays in sync with the statements below
556 string [] atom_names = new string[] {
562 "_NET_NUMBER_OF_DESKTOPS",
563 "_NET_DESKTOP_GEOMETRY",
564 "_NET_DESKTOP_VIEWPORT",
565 "_NET_CURRENT_DESKTOP",
566 "_NET_DESKTOP_NAMES",
567 "_NET_ACTIVE_WINDOW",
569 "_NET_SUPPORTING_WM_CHECK",
570 "_NET_VIRTUAL_ROOTS",
571 "_NET_DESKTOP_LAYOUT",
572 "_NET_SHOWING_DESKTOP",
574 "_NET_MOVERESIZE_WINDOW",
575 "_NET_WM_MOVERESIZE",
576 "_NET_RESTACK_WINDOW",
577 "_NET_REQUEST_FRAME_EXTENTS",
579 "_NET_WM_VISIBLE_NAME",
581 "_NET_WM_VISIBLE_ICON_NAME",
583 "_NET_WM_WINDOW_TYPE",
585 "_NET_WM_ALLOWED_ACTIONS",
587 "_NET_WM_STRUT_PARTIAL",
588 "_NET_WM_ICON_GEOMETRY",
591 "_NET_WM_HANDLED_ICONS",
593 "_NET_FRAME_EXTENTS",
595 "_NET_WM_SYNC_REQUEST",
596 "_NET_SYSTEM_TRAY_OPCODE",
597 "_NET_SYSTEM_TRAY_ORIENTATION",
598 "_NET_WM_STATE_MAXIMIZED_HORZ",
599 "_NET_WM_STATE_MAXIMIZED_VERT",
600 "_NET_WM_STATE_HIDDEN",
604 "_NET_WM_STATE_SKIP_TASKBAR",
605 "_NET_WM_STATE_ABOVE",
606 "_NET_WM_STATE_MODAL",
607 "_NET_WM_CONTEXT_HELP",
608 "_NET_WM_WINDOW_OPACITY",
609 "_NET_WM_WINDOW_TYPE_DESKTOP",
610 "_NET_WM_WINDOW_TYPE_DOCK",
611 "_NET_WM_WINDOW_TYPE_TOOLBAR",
612 "_NET_WM_WINDOW_TYPE_MENU",
613 "_NET_WM_WINDOW_TYPE_UTILITY",
614 "_NET_WM_WINDOW_TYPE_DIALOG",
615 "_NET_WM_WINDOW_TYPE_SPLASH",
616 "_NET_WM_WINDOW_TYPE_NORMAL",
623 "_SWF_PostMessageAtom",
626 IntPtr[] atoms = new IntPtr [atom_names.Length];;
628 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
631 WM_PROTOCOLS = atoms [off++];
632 WM_DELETE_WINDOW = atoms [off++];
633 WM_TAKE_FOCUS = atoms [off++];
634 _NET_SUPPORTED = atoms [off++];
635 _NET_CLIENT_LIST = atoms [off++];
636 _NET_NUMBER_OF_DESKTOPS = atoms [off++];
637 _NET_DESKTOP_GEOMETRY = atoms [off++];
638 _NET_DESKTOP_VIEWPORT = atoms [off++];
639 _NET_CURRENT_DESKTOP = atoms [off++];
640 _NET_DESKTOP_NAMES = atoms [off++];
641 _NET_ACTIVE_WINDOW = atoms [off++];
642 _NET_WORKAREA = atoms [off++];
643 _NET_SUPPORTING_WM_CHECK = atoms [off++];
644 _NET_VIRTUAL_ROOTS = atoms [off++];
645 _NET_DESKTOP_LAYOUT = atoms [off++];
646 _NET_SHOWING_DESKTOP = atoms [off++];
647 _NET_CLOSE_WINDOW = atoms [off++];
648 _NET_MOVERESIZE_WINDOW = atoms [off++];
649 _NET_WM_MOVERESIZE = atoms [off++];
650 _NET_RESTACK_WINDOW = atoms [off++];
651 _NET_REQUEST_FRAME_EXTENTS = atoms [off++];
652 _NET_WM_NAME = atoms [off++];
653 _NET_WM_VISIBLE_NAME = atoms [off++];
654 _NET_WM_ICON_NAME = atoms [off++];
655 _NET_WM_VISIBLE_ICON_NAME = atoms [off++];
656 _NET_WM_DESKTOP = atoms [off++];
657 _NET_WM_WINDOW_TYPE = atoms [off++];
658 _NET_WM_STATE = atoms [off++];
659 _NET_WM_ALLOWED_ACTIONS = atoms [off++];
660 _NET_WM_STRUT = atoms [off++];
661 _NET_WM_STRUT_PARTIAL = atoms [off++];
662 _NET_WM_ICON_GEOMETRY = atoms [off++];
663 _NET_WM_ICON = atoms [off++];
664 _NET_WM_PID = atoms [off++];
665 _NET_WM_HANDLED_ICONS = atoms [off++];
666 _NET_WM_USER_TIME = atoms [off++];
667 _NET_FRAME_EXTENTS = atoms [off++];
668 _NET_WM_PING = atoms [off++];
669 _NET_WM_SYNC_REQUEST = atoms [off++];
670 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
671 _NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
672 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
673 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
674 _NET_WM_STATE_HIDDEN = atoms [off++];
675 _XEMBED = atoms [off++];
676 _XEMBED_INFO = atoms [off++];
677 _MOTIF_WM_HINTS = atoms [off++];
678 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
679 _NET_WM_STATE_ABOVE = atoms [off++];
680 _NET_WM_STATE_MODAL = atoms [off++];
681 _NET_WM_CONTEXT_HELP = atoms [off++];
682 _NET_WM_WINDOW_OPACITY = atoms [off++];
683 _NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
684 _NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
685 _NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
686 _NET_WM_WINDOW_TYPE_MENU = atoms [off++];
687 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
688 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
689 _NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
690 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
691 CLIPBOARD = atoms [off++];
692 PRIMARY = atoms [off++];
693 OEMTEXT = atoms [off++];
694 UNICODETEXT = atoms [off++];
695 TARGETS = atoms [off++];
696 AsyncAtom = atoms [off++];
697 PostAtom = atoms [off++];
698 HoverState.Atom = atoms [off++];
700 DIB = (IntPtr)Atom.XA_PIXMAP;
701 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
704 private void GetSystrayManagerWindow() {
705 XGrabServer(DisplayHandle);
706 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
707 XUngrabServer(DisplayHandle);
708 XFlush(DisplayHandle);
711 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
715 xev.ClientMessageEvent.type = XEventName.ClientMessage;
716 xev.ClientMessageEvent.send_event = true;
717 xev.ClientMessageEvent.window = window;
718 xev.ClientMessageEvent.message_type = message_type;
719 xev.ClientMessageEvent.format = 32;
720 xev.ClientMessageEvent.ptr1 = l0;
721 xev.ClientMessageEvent.ptr2 = l1;
722 xev.ClientMessageEvent.ptr3 = l2;
723 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
726 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
730 xev.ClientMessageEvent.type = XEventName.ClientMessage;
731 xev.ClientMessageEvent.send_event = true;
732 xev.ClientMessageEvent.window = window;
733 xev.ClientMessageEvent.message_type = message_type;
734 xev.ClientMessageEvent.format = 32;
735 xev.ClientMessageEvent.ptr1 = l0;
736 xev.ClientMessageEvent.ptr2 = l1;
737 xev.ClientMessageEvent.ptr3 = l2;
738 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
741 bool StyleSet (int s, WindowStyles ws)
743 return (s & (int)ws) == (int)ws;
746 bool ExStyleSet (int ex, WindowExStyles exws)
748 return (ex & (int)exws) == (int)exws;
751 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
753 // Only MDI windows get caption_heights
755 tool_caption_height = 19;
757 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
758 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
759 border_style = FormBorderStyle.Fixed3D;
760 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
761 border_style = FormBorderStyle.None;
763 border_style = FormBorderStyle.FixedSingle;
765 title_style = TitleStyle.None;
767 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
770 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
771 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
772 title_style = TitleStyle.Tool;
774 title_style = TitleStyle.Normal;
778 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
779 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
780 border_style = (FormBorderStyle) 0xFFFF;
782 border_style = FormBorderStyle.None;
787 title_style = TitleStyle.None;
788 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
789 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
790 title_style = TitleStyle.Tool;
792 title_style = TitleStyle.Normal;
796 border_style = FormBorderStyle.None;
798 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
799 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
800 border_style = FormBorderStyle.SizableToolWindow;
802 border_style = FormBorderStyle.Sizable;
805 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
806 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
807 border_style = FormBorderStyle.Fixed3D;
808 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
809 border_style = FormBorderStyle.FixedDialog;
810 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
811 border_style = FormBorderStyle.FixedToolWindow;
812 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
813 border_style = FormBorderStyle.FixedSingle;
816 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
817 border_style = FormBorderStyle.FixedSingle;
824 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
825 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
828 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
829 MotifWmHints mwmHints;
830 MotifFunctions functions;
831 MotifDecorations decorations;
834 Rectangle client_rect;
836 // Child windows don't need WM window styles
837 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
842 mwmHints = new MotifWmHints();
846 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
847 mwmHints.functions = (IntPtr)0;
848 mwmHints.decorations = (IntPtr)0;
850 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
851 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
852 /* tool windows get no window manager
853 decorations, and neither do windows
854 which lack CAPTION/BORDER/DLGFRAME
858 /* just because the window doesn't get any decorations doesn't
859 mean we should disable the functions. for instance, without
860 MotifFunctions.Maximize, changing the windowstate to Maximized
861 is ignored by metacity. */
862 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
865 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
866 functions |= MotifFunctions.Move;
867 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
870 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
871 functions |= MotifFunctions.Move | MotifFunctions.Resize;
872 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
875 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
876 functions |= MotifFunctions.Minimize;
877 decorations |= MotifDecorations.Minimize;
880 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
881 functions |= MotifFunctions.Maximize;
882 decorations |= MotifDecorations.Maximize;
885 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
886 functions |= MotifFunctions.Resize;
887 decorations |= MotifDecorations.ResizeH;
890 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
891 decorations |= MotifDecorations.Border;
894 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
895 decorations |= MotifDecorations.Border;
898 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
899 decorations |= MotifDecorations.Border;
902 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
903 functions |= MotifFunctions.Close;
906 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
907 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
908 if (cp.Caption == "") {
909 functions &= ~MotifFunctions.Move;
910 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
915 if ((functions & MotifFunctions.Resize) == 0) {
916 hwnd.fixed_size = true;
917 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));
919 hwnd.fixed_size = false;
922 mwmHints.functions = (IntPtr)functions;
923 mwmHints.decorations = (IntPtr)decorations;
925 FormWindowState current_state = GetWindowState (hwnd.Handle);
926 if (current_state == (FormWindowState)(-1))
927 current_state = FormWindowState.Normal;
929 client_rect = hwnd.ClientRect;
933 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
934 // and get those windows in front of their parents
935 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
936 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
937 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
938 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
940 Form f = Control.FromHandle(hwnd.Handle) as Form;
941 if (f != null && !hwnd.reparented) {
942 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
943 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
944 if (owner_hwnd != null)
945 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
946 owner_hwnd.whole_window);
951 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
952 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
953 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
954 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
956 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
957 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
958 /* this line keeps the window from showing up in gnome's taskbar */
959 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
961 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
962 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
964 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
967 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
968 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
970 /* we need to add these atoms in the
971 * event we're maximized, since we're
972 * replacing the existing
973 * _NET_WM_STATE here. If we don't
974 * add them, future calls to
975 * GetWindowState will return Normal
976 * for a window which is maximized. */
977 if (current_state == FormWindowState.Maximized) {
978 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
979 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
981 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
984 IntPtr[] atom_ptrs = new IntPtr[2];
985 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
986 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
987 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
990 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
994 private void SetIcon(Hwnd hwnd, Icon icon) {
1000 bitmap = icon.ToBitmap();
1002 size = bitmap.Width * bitmap.Height + 2;
1003 data = new IntPtr[size];
1005 data[index++] = (IntPtr)bitmap.Width;
1006 data[index++] = (IntPtr)bitmap.Height;
1008 for (int y = 0; y < bitmap.Height; y++) {
1009 for (int x = 0; x < bitmap.Width; x++) {
1010 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
1014 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
1017 private IntPtr ImageToPixmap(Image image) {
1021 private void WakeupMain () {
1022 wake.Send (new byte [] { 0xFF });
1025 private XEventQueue ThreadQueue(Thread thread) {
1028 queue = (XEventQueue)MessageQueues[thread];
1029 if (queue == null) {
1030 queue = new XEventQueue(thread);
1031 MessageQueues[thread] = queue;
1037 private void TranslatePropertyToClipboard(IntPtr property) {
1042 IntPtr prop = IntPtr.Zero;
1044 Clipboard.Item = null;
1046 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);
1048 if ((long)nitems > 0) {
1049 if (property == (IntPtr)Atom.XA_STRING) {
1050 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1051 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1052 // FIXME - convert bitmap to image
1053 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1054 // FIXME - convert pixmap to image
1055 } else if (property == OEMTEXT) {
1056 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1057 } else if (property == UNICODETEXT) {
1058 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1065 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1067 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1071 // Keep the invalid area as small as needed
1072 if ((x + width) > hwnd.width) {
1073 width = hwnd.width - x;
1076 if ((y + height) > hwnd.height) {
1077 height = hwnd.height - y;
1081 hwnd.AddInvalidArea(x, y, width, height);
1082 if (!hwnd.expose_pending) {
1083 if (!hwnd.nc_expose_pending) {
1084 hwnd.Queue.Paint.Enqueue(hwnd);
1086 hwnd.expose_pending = true;
1089 hwnd.AddNcInvalidArea (x, y, width, height);
1091 if (!hwnd.nc_expose_pending) {
1092 if (!hwnd.expose_pending) {
1093 hwnd.Queue.Paint.Enqueue(hwnd);
1095 hwnd.nc_expose_pending = true;
1100 private void InvalidateWholeWindow(IntPtr handle) {
1103 hwnd = Hwnd.ObjectFromHandle(handle);
1105 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
1108 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
1111 hwnd = Hwnd.ObjectFromHandle(handle);
1113 AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
1116 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
1122 hwnd = Hwnd.ObjectFromHandle(handle);
1125 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1132 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
1153 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
1154 if (win == window) {
1160 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
1164 if (children != IntPtr.Zero) {
1168 } while (win != root);
1173 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
1176 private void FrameExtents(IntPtr window, out int left, out int top) {
1181 IntPtr prop = IntPtr.Zero;
1183 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);
1184 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1185 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1186 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1187 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1188 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1194 if (prop != IntPtr.Zero) {
1200 private void AddConfigureNotify (XEvent xevent) {
1203 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1210 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1211 if (!hwnd.reparented) {
1212 hwnd.x = xevent.ConfigureEvent.x;
1213 hwnd.y = xevent.ConfigureEvent.y;
1215 // This sucks ass, part 1
1216 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1217 // no standard way of getting our adjustment.
1218 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1219 // Several other WMs do their decorations different yet again and we fail to deal
1220 // with that, since I couldn't find any frigging commonality between them.
1221 // The only sane WM seems to be KDE
1223 if (!xevent.ConfigureEvent.send_event) {
1226 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1228 // This is a synthetic event, coordinates are in root space
1229 hwnd.x = xevent.ConfigureEvent.x;
1230 hwnd.y = xevent.ConfigureEvent.y;
1231 if (hwnd.whacky_wm) {
1235 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1236 hwnd.x -= frame_left;
1237 hwnd.y -= frame_top;
1241 hwnd.width = xevent.ConfigureEvent.width;
1242 hwnd.height = xevent.ConfigureEvent.height;
1243 hwnd.ClientRect = Rectangle.Empty;
1245 if (!hwnd.configure_pending) {
1246 hwnd.Queue.Enqueue(xevent);
1247 hwnd.configure_pending = true;
1250 // We drop configure events for Client windows
1253 private void ShowCaret() {
1254 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1260 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1264 private void HideCaret() {
1265 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1271 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1275 private int NextTimeout (ArrayList timers, DateTime now) {
1276 int timeout = Int32.MaxValue;
1278 foreach (Timer timer in timers) {
1279 int next = (int) (timer.Expires - now).TotalMilliseconds;
1281 return 0; // Have a timer that has already expired
1284 if (next < timeout) {
1288 if (timeout < Timer.Minimum) {
1289 timeout = Timer.Minimum;
1297 private void CheckTimers (ArrayList timers, DateTime now) {
1300 count = timers.Count;
1305 for (int i = 0; i < timers.Count; i++) {
1308 timer = (Timer) timers [i];
1310 if (timer.Enabled && timer.Expires <= now) {
1317 private void MapWindow(Hwnd hwnd, WindowType windows) {
1319 if ((windows & WindowType.Whole) != 0) {
1320 XMapWindow(DisplayHandle, hwnd.whole_window);
1322 if ((windows & WindowType.Client) != 0) {
1323 XMapWindow(DisplayHandle, hwnd.client_window);
1327 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1328 hwnd.mapped = false;
1329 if ((windows & WindowType.Whole) != 0) {
1330 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1332 if ((windows & WindowType.Client) != 0) {
1333 XUnmapWindow(DisplayHandle, hwnd.client_window);
1337 private void UpdateMessageQueue (XEventQueue queue) {
1342 now = DateTime.UtcNow;
1345 pending = XPending (DisplayHandle);
1349 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1350 Idle (this, EventArgs.Empty);
1354 pending = XPending (DisplayHandle);
1361 if (queue != null) {
1362 if (queue.Paint.Count > 0)
1365 timeout = NextTimeout (queue.timer_list, now);
1370 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1371 // Clean out buffer, so we're not busy-looping on the same data
1372 if (pollfds[1].revents != 0) {
1373 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1377 pending = XPending (DisplayHandle);
1383 CheckTimers (queue.timer_list, now);
1386 XEvent xevent = new XEvent ();
1389 if (XPending (DisplayHandle) == 0)
1392 XNextEvent (DisplayHandle, ref xevent);
1394 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1395 if (XFilterEvent(ref xevent, FosterParent)) {
1401 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1405 switch (xevent.type) {
1406 case XEventName.Expose:
1407 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1410 case XEventName.SelectionClear: {
1411 // Should we do something?
1415 case XEventName.SelectionRequest: {
1416 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1420 sel_event = new XEvent();
1421 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1422 sel_event.SelectionEvent.send_event = true;
1423 sel_event.SelectionEvent.display = DisplayHandle;
1424 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1425 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1426 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1427 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1428 sel_event.SelectionEvent.property = IntPtr.Zero;
1430 // Seems that some apps support asking for supported types
1431 if (xevent.SelectionEvent.target == TARGETS) {
1438 if (Clipboard.Item is String) {
1439 atoms[atom_count++] = (int)Atom.XA_STRING;
1440 atoms[atom_count++] = (int)OEMTEXT;
1441 atoms[atom_count++] = (int)UNICODETEXT;
1442 } else if (Clipboard.Item is Image) {
1443 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1444 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1446 // FIXME - handle other types
1449 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1450 } else if (Clipboard.Item is string) {
1456 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1459 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1460 buffer = Marshal.AllocHGlobal(bytes.Length);
1461 buflen = bytes.Length;
1463 for (int i = 0; i < buflen; i++) {
1464 Marshal.WriteByte(buffer, i, bytes[i]);
1466 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1467 // FIXME - this should encode into ISO2022
1468 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1469 while (Marshal.ReadByte(buffer, buflen) != 0) {
1472 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1473 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1474 while (Marshal.ReadByte(buffer, buflen) != 0) {
1478 buffer = IntPtr.Zero;
1481 if (buffer != IntPtr.Zero) {
1482 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1483 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1484 Marshal.FreeHGlobal(buffer);
1486 } else if (Clipboard.Item is Image) {
1487 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1488 // FIXME - convert image and store as property
1489 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1490 // FIXME - convert image and store as property
1494 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1498 case XEventName.SelectionNotify: {
1499 if (Clipboard.Enumerating) {
1500 Clipboard.Enumerating = false;
1501 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1502 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1503 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1504 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1505 #if DriverDebugExtra
1506 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1510 } else if (Clipboard.Retrieving) {
1511 Clipboard.Retrieving = false;
1512 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1513 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1515 Clipboard.Item = null;
1518 Dnd.HandleSelectionNotifyEvent (ref xevent);
1523 case XEventName.MapNotify: {
1524 if (hwnd.client_window == xevent.MapEvent.window) {
1530 case XEventName.UnmapNotify: {
1531 if (hwnd.client_window == xevent.MapEvent.window) {
1532 hwnd.mapped = false;
1537 case XEventName.KeyRelease:
1538 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1539 XEvent nextevent = new XEvent ();
1541 XPeekEvent (DisplayHandle, ref nextevent);
1543 if (nextevent.type == XEventName.KeyPress &&
1544 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1545 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1549 goto case XEventName.KeyPress;
1551 case XEventName.MotionNotify: {
1554 if (hwnd.Queue.Count > 0) {
1555 peek = hwnd.Queue.Peek();
1556 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1560 goto case XEventName.KeyPress;
1563 case XEventName.KeyPress:
1564 case XEventName.ButtonPress:
1565 case XEventName.ButtonRelease:
1566 case XEventName.EnterNotify:
1567 case XEventName.LeaveNotify:
1568 case XEventName.CreateNotify:
1569 case XEventName.DestroyNotify:
1570 case XEventName.FocusIn:
1571 case XEventName.FocusOut:
1572 case XEventName.ClientMessage:
1573 case XEventName.ReparentNotify:
1574 hwnd.Queue.Enqueue (xevent);
1577 case XEventName.ConfigureNotify:
1578 AddConfigureNotify(xevent);
1581 case XEventName.PropertyNotify:
1582 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1587 IntPtr prop = IntPtr.Zero;
1588 IntPtr prev_active;;
1590 prev_active = ActiveWindow;
1591 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);
1592 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1593 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1596 if (prev_active != ActiveWindow) {
1597 if (prev_active != IntPtr.Zero) {
1598 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1600 if (ActiveWindow != IntPtr.Zero) {
1601 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1604 if (ModalWindows.Count == 0) {
1607 // Modality handling, if we are modal and the new active window is one
1608 // of ours but not the modal one, switch back to the modal window
1610 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1611 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1612 Activate((IntPtr)ModalWindows.Peek());
1625 private IntPtr GetMousewParam(int Delta) {
1628 if ((MouseState & MouseButtons.Left) != 0) {
1629 result |= (int)MsgButtons.MK_LBUTTON;
1632 if ((MouseState & MouseButtons.Middle) != 0) {
1633 result |= (int)MsgButtons.MK_MBUTTON;
1636 if ((MouseState & MouseButtons.Right) != 0) {
1637 result |= (int)MsgButtons.MK_RBUTTON;
1640 Keys mods = ModifierKeys;
1641 if ((mods & Keys.Control) != 0) {
1642 result |= (int)MsgButtons.MK_CONTROL;
1645 if ((mods & Keys.Shift) != 0) {
1646 result |= (int)MsgButtons.MK_SHIFT;
1649 result |= Delta << 16;
1651 return (IntPtr)result;
1653 private IntPtr XGetParent(IntPtr handle) {
1660 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1663 if (Children!=IntPtr.Zero) {
1671 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1672 if (ErrorExceptions) {
1673 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1675 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());
1680 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1683 Control[] controls = c.child_controls.GetAllControls ();
1685 if (c.IsHandleCreated && !c.IsDisposed) {
1686 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1688 #if DriverDebug || DriverDebugDestroy
1689 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1690 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1694 CleanupCachedWindows (hwnd);
1698 for (int i = 0; i < controls.Length; i ++) {
1699 AccumulateDestroyedHandles (controls[i], list);
1705 void CleanupCachedWindows (Hwnd hwnd)
1707 if (ActiveWindow == hwnd.Handle) {
1708 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1709 ActiveWindow = IntPtr.Zero;
1712 if (FocusWindow == hwnd.Handle) {
1713 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1714 FocusWindow = IntPtr.Zero;
1717 if (Grab.Hwnd == hwnd.Handle) {
1718 Grab.Hwnd = IntPtr.Zero;
1719 Grab.Confined = false;
1722 DestroyCaret (hwnd.Handle);
1725 private void PerformNCCalc(Hwnd hwnd) {
1726 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1730 rect = hwnd.DefaultClientRect;
1732 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1733 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1735 ncp.rgrc1.left = rect.Left;
1736 ncp.rgrc1.top = rect.Top;
1737 ncp.rgrc1.right = rect.Right;
1738 ncp.rgrc1.bottom = rect.Bottom;
1740 Marshal.StructureToPtr(ncp, ptr, true);
1741 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1742 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1743 Marshal.FreeHGlobal(ptr);
1745 // FIXME - debug this with Menus
1747 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1748 hwnd.ClientRect = rect;
1751 if ((rect.Width < 1) || (rect.Height < 1)) {
1752 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1754 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1758 #endregion // Private Methods
1761 private void MouseHover(object sender, EventArgs e) {
1765 HoverState.Timer.Enabled = false;
1767 if (HoverState.Window != IntPtr.Zero) {
1768 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1770 xevent = new XEvent ();
1772 xevent.type = XEventName.ClientMessage;
1773 xevent.ClientMessageEvent.display = DisplayHandle;
1774 xevent.ClientMessageEvent.window = HoverState.Window;
1775 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1776 xevent.ClientMessageEvent.format = 32;
1777 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1779 hwnd.Queue.EnqueueLocked (xevent);
1786 private void CaretCallback(object sender, EventArgs e) {
1790 Caret.On = !Caret.On;
1792 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1794 #endregion // Callbacks
1796 #region Public Properties
1798 internal override int Caption {
1804 internal override Size CursorSize {
1809 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1810 return new Size(x, y);
1812 return new Size(16, 16);
1817 internal override bool DragFullWindows {
1823 internal override Size DragSize {
1825 return new Size(4, 4);
1829 internal override Size FrameBorderSize {
1831 throw new NotImplementedException();
1835 internal override Size IconSize {
1841 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1845 current = (long)list;
1848 size = new XIconSize();
1850 for (int i = 0; i < count; i++) {
1851 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1852 current += Marshal.SizeOf(size);
1854 // Look for our preferred size
1855 if (size.min_width == 32) {
1857 return new Size(32, 32);
1860 if (size.max_width == 32) {
1862 return new Size(32, 32);
1865 if (size.min_width < 32 && size.max_width > 32) {
1868 // check if we can fit one
1870 while (x < size.max_width) {
1871 x += size.width_inc;
1874 return new Size(32, 32);
1879 if (largest < size.max_width) {
1880 largest = size.max_width;
1884 // We didn't find a match or we wouldn't be here
1885 return new Size(largest, largest);
1888 return new Size(32, 32);
1893 internal override int KeyboardSpeed {
1896 // A lot harder: need to do:
1897 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1898 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1899 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1901 // And from that we can tell the repetition rate
1903 // Notice, the values must map to:
1904 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1910 internal override int KeyboardDelay {
1913 // Return values must range from 0 to 4, 0 meaning 250ms,
1914 // and 4 meaning 1000 ms.
1916 return 1; // ie, 500 ms
1920 internal override Size MaxWindowTrackSize {
1922 return new Size (WorkingArea.Width, WorkingArea.Height);
1926 internal override Size MinimizedWindowSize {
1928 return new Size(1, 1);
1932 internal override Size MinimizedWindowSpacingSize {
1934 return new Size(1, 1);
1938 internal override Size MinimumWindowSize {
1940 return new Size(1, 1);
1944 internal override Size MinWindowTrackSize {
1946 return new Size(1, 1);
1950 internal override Keys ModifierKeys {
1952 return Keyboard.ModifierKeys;
1956 internal override Size SmallIconSize {
1962 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1966 current = (long)list;
1969 size = new XIconSize();
1971 for (int i = 0; i < count; i++) {
1972 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1973 current += Marshal.SizeOf(size);
1975 // Look for our preferred size
1976 if (size.min_width == 16) {
1978 return new Size(16, 16);
1981 if (size.max_width == 16) {
1983 return new Size(16, 16);
1986 if (size.min_width < 16 && size.max_width > 16) {
1989 // check if we can fit one
1991 while (x < size.max_width) {
1992 x += size.width_inc;
1995 return new Size(16, 16);
2000 if (smallest == 0 || smallest > size.min_width) {
2001 smallest = size.min_width;
2005 // We didn't find a match or we wouldn't be here
2006 return new Size(smallest, smallest);
2009 return new Size(16, 16);
2014 internal override int MouseButtonCount {
2020 internal override bool MouseButtonsSwapped {
2022 return false; // FIXME - how to detect?
2026 internal override Size MouseHoverSize {
2028 return new Size (1, 1);
2032 internal override int MouseHoverTime {
2034 return HoverState.Interval;
2040 internal override bool MouseWheelPresent {
2042 return true; // FIXME - how to detect?
2046 internal override Rectangle VirtualScreen {
2052 internal override Rectangle WorkingArea {
2058 IntPtr prop = IntPtr.Zero;
2061 int current_desktop;
2065 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);
2066 if ((long)nitems < 1) {
2070 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2073 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);
2074 if ((long)nitems < 4 * current_desktop) {
2078 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2079 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2080 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2081 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2084 return new Rectangle(x, y, width, height);
2087 XWindowAttributes attributes=new XWindowAttributes();
2090 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2093 return new Rectangle(0, 0, attributes.width, attributes.height);
2097 internal override bool ThemesEnabled {
2099 return XplatUIX11.themes_enabled;
2104 #endregion // Public properties
2106 #region Public Static Methods
2107 internal override IntPtr InitializeDriver() {
2109 if (DisplayHandle==IntPtr.Zero) {
2110 SetDisplay(XOpenDisplay(IntPtr.Zero));
2116 internal override void ShutdownDriver(IntPtr token) {
2118 if (DisplayHandle!=IntPtr.Zero) {
2119 XCloseDisplay(DisplayHandle);
2120 DisplayHandle=IntPtr.Zero;
2125 internal override void EnableThemes() {
2126 themes_enabled = true;
2130 internal override void Activate(IntPtr handle) {
2133 hwnd = Hwnd.ObjectFromHandle(handle);
2137 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2138 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2141 // XRaiseWindow(DisplayHandle, handle);
2147 internal override void AudibleAlert() {
2148 XBell(DisplayHandle, 0);
2153 internal override void CaretVisible(IntPtr handle, bool visible) {
2154 if (Caret.Hwnd == handle) {
2156 if (!Caret.Visible) {
2157 Caret.Visible = true;
2159 Caret.Timer.Start();
2162 Caret.Visible = false;
2169 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2170 FormBorderStyle border_style;
2171 TitleStyle title_style;
2173 int tool_caption_height;
2175 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2176 out caption_height, out tool_caption_height);
2178 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2179 caption_height, tool_caption_height,
2184 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2190 hwnd = Hwnd.ObjectFromHandle(handle);
2193 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2200 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2201 DataFormats.Format f;
2204 f = DataFormats.Format.List;
2206 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2210 Clipboard.Formats = new ArrayList();
2213 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2215 Clipboard.Enumerating = true;
2216 while (Clipboard.Enumerating) {
2217 UpdateMessageQueue(null);
2222 result = new int[Clipboard.Formats.Count];
2224 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2225 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2228 Clipboard.Formats = null;
2232 internal override void ClipboardClose(IntPtr handle) {
2233 if (handle != ClipMagic) {
2234 throw new ArgumentException("handle is not a valid clipboard handle");
2239 internal override int ClipboardGetID(IntPtr handle, string format) {
2240 if (handle != ClipMagic) {
2241 throw new ArgumentException("handle is not a valid clipboard handle");
2244 if (format == "Text" ) return (int)Atom.XA_STRING;
2245 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2246 //else if (format == "MetaFilePict" ) return 3;
2247 //else if (format == "SymbolicLink" ) return 4;
2248 //else if (format == "DataInterchangeFormat" ) return 5;
2249 //else if (format == "Tiff" ) return 6;
2250 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2251 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2252 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2253 //else if (format == "PenData" ) return 10;
2254 //else if (format == "RiffAudio" ) return 11;
2255 //else if (format == "WaveAudio" ) return 12;
2256 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2257 //else if (format == "EnhancedMetafile" ) return 14;
2258 //else if (format == "FileDrop" ) return 15;
2259 //else if (format == "Locale" ) return 16;
2261 return XInternAtom(DisplayHandle, format, false).ToInt32();
2264 internal override IntPtr ClipboardOpen(bool primary_selection) {
2265 if (!primary_selection)
2266 ClipMagic = CLIPBOARD;
2268 ClipMagic = PRIMARY;
2272 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2273 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2275 Clipboard.Retrieving = true;
2276 while (Clipboard.Retrieving) {
2277 UpdateMessageQueue(null);
2280 return Clipboard.Item;
2283 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2284 Clipboard.Item = obj;
2285 Clipboard.Type = type;
2286 Clipboard.Converter = converter;
2289 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2291 // Clearing the selection
2292 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2296 internal override void CreateCaret(IntPtr handle, int width, int height) {
2297 XGCValues gc_values;
2300 hwnd = Hwnd.ObjectFromHandle(handle);
2302 if (Caret.Hwnd != IntPtr.Zero) {
2303 DestroyCaret(Caret.Hwnd);
2306 Caret.Hwnd = handle;
2307 Caret.Window = hwnd.client_window;
2308 Caret.Width = width;
2309 Caret.Height = height;
2310 Caret.Visible = false;
2313 gc_values = new XGCValues();
2314 gc_values.line_width = width;
2316 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2317 if (Caret.gc == IntPtr.Zero) {
2318 Caret.Hwnd = IntPtr.Zero;
2322 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2325 internal override IntPtr CreateWindow(CreateParams cp) {
2326 XSetWindowAttributes Attributes;
2332 IntPtr ParentHandle;
2334 IntPtr ClientWindow;
2335 Rectangle ClientRect;
2336 SetWindowValuemask ValueMask;
2341 Attributes = new XSetWindowAttributes();
2347 if (Width<1) Width=1;
2348 if (Height<1) Height=1;
2350 if (cp.Parent != IntPtr.Zero) {
2351 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2353 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2354 // We need to use our foster parent window until this poor child gets it's parent assigned
2355 ParentHandle=FosterParent;
2356 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2357 ParentHandle=RootWindow;
2359 // Default position on screen, if window manager doesn't place us somewhere else
2362 ParentHandle=RootWindow;
2366 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2368 Attributes.bit_gravity = Gravity.NorthWestGravity;
2369 Attributes.win_gravity = Gravity.NorthWestGravity;
2371 // Save what's under the toolwindow
2372 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2373 Attributes.save_under = true;
2374 ValueMask |= SetWindowValuemask.SaveUnder;
2378 // If we're a popup without caption we override the WM
2379 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2380 Attributes.override_redirect = true;
2381 ValueMask |= SetWindowValuemask.OverrideRedirect;
2387 hwnd.height = Height;
2388 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2390 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2391 hwnd.enabled = false;
2394 ClientRect = hwnd.ClientRect;
2395 ClientWindow = IntPtr.Zero;
2398 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2399 if (WholeWindow != IntPtr.Zero) {
2400 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2402 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2403 ValueMask = SetWindowValuemask.ColorMap;
2404 Attributes.colormap = CustomColormap;
2406 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);
2410 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2411 throw new Exception("Could not create X11 windows");
2414 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2415 hwnd.WholeWindow = WholeWindow;
2416 hwnd.ClientWindow = ClientWindow;
2418 #if DriverDebug || DriverDebugCreate
2419 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);
2422 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2423 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2426 hints = new XSizeHints();
2429 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2430 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2435 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2436 if (hwnd.whole_window != hwnd.client_window)
2437 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2439 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2440 MapWindow(hwnd, WindowType.Both);
2441 hwnd.visible = true;
2445 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2447 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2448 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2450 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2453 SetWMStyles(hwnd, cp);
2455 // set the group leader
2456 XWMHints wm_hints = new XWMHints ();
2458 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2459 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2460 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2462 if (ParentHandle != RootWindow) {
2463 wm_hints.window_group = hwnd.whole_window;
2465 wm_hints.window_group = ParentHandle;
2469 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2472 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2473 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2474 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2475 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2478 // for now make all windows dnd enabled
2479 Dnd.SetAllowDrop (hwnd, true);
2481 // Set caption/window title
2482 Text(hwnd.Handle, cp.Caption);
2487 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2488 CreateParams create_params = new CreateParams();
2490 create_params.Caption = "";
2491 create_params.X = X;
2492 create_params.Y = Y;
2493 create_params.Width = Width;
2494 create_params.Height = Height;
2496 create_params.ClassName=XplatUI.DefaultClassName;
2497 create_params.ClassStyle = 0;
2498 create_params.ExStyle=0;
2499 create_params.Parent=IntPtr.Zero;
2500 create_params.Param=0;
2502 return CreateWindow(create_params);
2505 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2507 Bitmap cursor_bitmap;
2515 IntPtr cursor_pixmap;
2522 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2526 // Win32 only allows creation cursors of a certain size
2527 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2528 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2529 cursor_mask = new Bitmap(mask, new Size(width, height));
2531 cursor_bitmap = bitmap;
2535 width = cursor_bitmap.Width;
2536 height = cursor_bitmap.Height;
2538 cursor_bits = new Byte[(width / 8) * height];
2539 mask_bits = new Byte[(width / 8) * height];
2541 for (int y = 0; y < height; y++) {
2542 for (int x = 0; x < width; x++) {
2543 c_pixel = cursor_bitmap.GetPixel(x, y);
2544 m_pixel = cursor_mask.GetPixel(x, y);
2546 and = c_pixel == cursor_pixel;
2547 xor = m_pixel == mask_pixel;
2551 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2552 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2553 } else if (and && !xor) {
2555 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2556 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2558 } else if (and && !xor) {
2560 } else if (and && xor) {
2563 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2564 // we want both to be 0 so nothing to be done
2565 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2566 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2572 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2573 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2577 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2578 fg.red = (ushort)65535;
2579 fg.green = (ushort)65535;
2580 fg.blue = (ushort)65535;
2582 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2584 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2586 XFreePixmap(DisplayHandle, cursor_pixmap);
2587 XFreePixmap(DisplayHandle, mask_pixmap);
2592 internal override IntPtr DefineStdCursor(StdCursor id) {
2593 CursorFontShape shape;
2596 // FIXME - define missing shapes
2599 case StdCursor.AppStarting: {
2600 shape = CursorFontShape.XC_watch;
2604 case StdCursor.Arrow: {
2605 shape = CursorFontShape.XC_top_left_arrow;
2609 case StdCursor.Cross: {
2610 shape = CursorFontShape.XC_crosshair;
2614 case StdCursor.Default: {
2615 shape = CursorFontShape.XC_top_left_arrow;
2619 case StdCursor.Hand: {
2620 shape = CursorFontShape.XC_hand1;
2624 case StdCursor.Help: {
2625 shape = CursorFontShape.XC_question_arrow;
2629 case StdCursor.HSplit: {
2630 shape = CursorFontShape.XC_sb_v_double_arrow;
2634 case StdCursor.IBeam: {
2635 shape = CursorFontShape.XC_xterm;
2639 case StdCursor.No: {
2640 shape = CursorFontShape.XC_circle;
2644 case StdCursor.NoMove2D: {
2645 shape = CursorFontShape.XC_fleur;
2649 case StdCursor.NoMoveHoriz: {
2650 shape = CursorFontShape.XC_fleur;
2654 case StdCursor.NoMoveVert: {
2655 shape = CursorFontShape.XC_fleur;
2659 case StdCursor.PanEast: {
2660 shape = CursorFontShape.XC_fleur;
2664 case StdCursor.PanNE: {
2665 shape = CursorFontShape.XC_fleur;
2669 case StdCursor.PanNorth: {
2670 shape = CursorFontShape.XC_fleur;
2674 case StdCursor.PanNW: {
2675 shape = CursorFontShape.XC_fleur;
2679 case StdCursor.PanSE: {
2680 shape = CursorFontShape.XC_fleur;
2684 case StdCursor.PanSouth: {
2685 shape = CursorFontShape.XC_fleur;
2689 case StdCursor.PanSW: {
2690 shape = CursorFontShape.XC_fleur;
2694 case StdCursor.PanWest: {
2695 shape = CursorFontShape.XC_sizing;
2699 case StdCursor.SizeAll: {
2700 shape = CursorFontShape.XC_fleur;
2704 case StdCursor.SizeNESW: {
2705 shape = CursorFontShape.XC_top_right_corner;
2709 case StdCursor.SizeNS: {
2710 shape = CursorFontShape.XC_sb_v_double_arrow;
2714 case StdCursor.SizeNWSE: {
2715 shape = CursorFontShape.XC_top_left_corner;
2719 case StdCursor.SizeWE: {
2720 shape = CursorFontShape.XC_sb_h_double_arrow;
2724 case StdCursor.UpArrow: {
2725 shape = CursorFontShape.XC_center_ptr;
2729 case StdCursor.VSplit: {
2730 shape = CursorFontShape.XC_sb_h_double_arrow;
2734 case StdCursor.WaitCursor: {
2735 shape = CursorFontShape.XC_watch;
2745 cursor = XCreateFontCursor(DisplayHandle, shape);
2750 internal override IntPtr DefWndProc(ref Message msg) {
2751 switch ((Msg)msg.Msg) {
2752 case Msg.WM_PAINT: {
2755 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2757 hwnd.expose_pending = false;
2763 case Msg.WM_NCPAINT: {
2766 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2768 hwnd.nc_expose_pending = false;
2774 case Msg.WM_CONTEXTMENU: {
2777 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2779 if ((hwnd != null) && (hwnd.parent != null)) {
2780 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2785 case Msg.WM_MOUSEWHEEL: {
2788 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2790 if ((hwnd != null) && (hwnd.parent != null)) {
2791 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2792 if (msg.Result == IntPtr.Zero) {
2799 case Msg.WM_SETCURSOR: {
2802 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2804 break; // not sure how this happens, but it does
2806 // Pass to parent window first
2807 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2809 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2812 if (msg.Result == IntPtr.Zero) {
2815 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2816 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2817 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2818 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2819 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2820 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2823 handle = Cursors.Default.handle;
2826 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2827 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2828 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2829 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2830 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2831 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2834 case HitTest.HTGROWBOX:
2835 case HitTest.HTSIZE:
2836 case HitTest.HTZOOM:
2837 case HitTest.HTVSCROLL:
2838 case HitTest.HTSYSMENU:
2839 case HitTest.HTREDUCE:
2840 case HitTest.HTNOWHERE:
2841 case HitTest.HTMAXBUTTON:
2842 case HitTest.HTMINBUTTON:
2843 case HitTest.HTMENU:
2844 case HitTest.HSCROLL:
2845 case HitTest.HTBOTTOM:
2846 case HitTest.HTCAPTION:
2847 case HitTest.HTCLIENT:
2848 case HitTest.HTCLOSE:
2850 default: handle = Cursors.Default.handle; break;
2852 SetCursor(msg.HWnd, handle);
2860 internal override void DestroyCaret(IntPtr handle) {
2861 if (Caret.Hwnd == handle) {
2862 if (Caret.Visible == true) {
2865 if (Caret.gc != IntPtr.Zero) {
2866 XFreeGC(DisplayHandle, Caret.gc);
2867 Caret.gc = IntPtr.Zero;
2869 Caret.Hwnd = IntPtr.Zero;
2870 Caret.Visible = false;
2875 internal override void DestroyCursor(IntPtr cursor) {
2877 XFreeCursor(DisplayHandle, cursor);
2881 internal override void DestroyWindow(IntPtr handle) {
2884 hwnd = Hwnd.ObjectFromHandle(handle);
2887 #if DriverDebug || DriverDebugDestroy
2888 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2893 #if DriverDebug || DriverDebugDestroy
2894 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2897 CleanupCachedWindows (hwnd);
2899 ArrayList windows = new ArrayList ();
2901 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2904 if (hwnd.whole_window != IntPtr.Zero) {
2905 #if DriverDebug || DriverDebugDestroy
2906 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2908 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2910 else if (hwnd.client_window != IntPtr.Zero) {
2911 #if DriverDebug || DriverDebugDestroy
2912 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2914 XDestroyWindow(DisplayHandle, hwnd.client_window);
2919 foreach (Hwnd h in windows) {
2920 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2924 internal override IntPtr DispatchMessage(ref MSG msg) {
2925 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2928 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2930 XGCValues gc_values;
2933 hwnd = Hwnd.ObjectFromHandle(handle);
2935 gc_values = new XGCValues();
2937 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2938 gc_values.line_width = line_width;
2939 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2941 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2942 //mask = foreground ^ background;
2943 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2944 //XSetBackground(DisplayHandle, gc, background);
2945 //XSetFunction(DisplayHandle, gc, GXxor);
2946 //XSetPlaneMask(DisplayHandle, gc, mask);
2949 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2954 control = Control.FromHandle(handle);
2956 XColor xcolor = new XColor();
2958 xcolor.red = (ushort)(control.ForeColor.R * 257);
2959 xcolor.green = (ushort)(control.ForeColor.G * 257);
2960 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2961 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2962 foreground = (uint)xcolor.pixel.ToInt32();
2964 xcolor.red = (ushort)(control.BackColor.R * 257);
2965 xcolor.green = (ushort)(control.BackColor.G * 257);
2966 xcolor.blue = (ushort)(control.BackColor.B * 257);
2967 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2968 background = (uint)xcolor.pixel.ToInt32();
2970 uint mask = foreground ^ background;
2972 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2973 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2974 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2975 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2977 if ((rect.Width > 0) && (rect.Height > 0)) {
2978 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2980 if (rect.Width > 0) {
2981 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2983 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2986 XFreeGC(DisplayHandle, gc);
2989 internal override void DoEvents() {
2990 MSG msg = new MSG ();
2993 if (OverrideCursorHandle != IntPtr.Zero) {
2994 OverrideCursorHandle = IntPtr.Zero;
2997 queue = ThreadQueue(Thread.CurrentThread);
2999 queue.DispatchIdle = false;
3001 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3002 TranslateMessage (ref msg);
3003 DispatchMessage (ref msg);
3006 queue.DispatchIdle = true;
3009 internal override void EnableWindow(IntPtr handle, bool Enable) {
3012 hwnd = Hwnd.ObjectFromHandle(handle);
3014 hwnd.Enabled = Enable;
3018 internal override void EndLoop(Thread thread) {
3019 // This is where we one day will shut down the loop for the thread
3023 internal override IntPtr GetActive() {
3028 IntPtr prop = IntPtr.Zero;
3029 IntPtr active = IntPtr.Zero;
3031 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);
3032 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3033 active = (IntPtr)Marshal.ReadInt32(prop);
3037 if (active != IntPtr.Zero) {
3040 hwnd = Hwnd.GetObjectFromWindow(active);
3042 active = hwnd.Handle;
3044 active = IntPtr.Zero;
3050 internal override Region GetClipRegion(IntPtr handle) {
3053 hwnd = Hwnd.ObjectFromHandle(handle);
3055 return hwnd.UserClip;
3061 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3068 internal override void GetDisplaySize(out Size size) {
3069 XWindowAttributes attributes=new XWindowAttributes();
3072 // FIXME - use _NET_WM messages instead?
3073 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3076 size = new Size(attributes.width, attributes.height);
3079 internal override SizeF GetAutoScaleSize(Font font) {
3082 string magic_string = "The quick brown fox jumped over the lazy dog.";
3083 double magic_number = 44.549996948242189;
3085 g = Graphics.FromHwnd(FosterParent);
3087 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3088 return new SizeF(width, font.Height);
3091 internal override IntPtr GetParent(IntPtr handle) {
3094 hwnd = Hwnd.ObjectFromHandle(handle);
3095 if (hwnd != null && hwnd.parent != null) {
3096 return hwnd.parent.Handle;
3101 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3111 if (handle != IntPtr.Zero) {
3112 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3114 use_handle = RootWindow;
3118 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3121 if (handle != IntPtr.Zero) {
3130 internal override IntPtr GetFocus() {
3135 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3136 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3139 internal override Point GetMenuOrigin(IntPtr handle) {
3142 hwnd = Hwnd.ObjectFromHandle(handle);
3145 return hwnd.MenuOrigin;
3150 [MonoTODO("Implement filtering")]
3151 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3158 if (((XEventQueue)queue_id).Count > 0) {
3159 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3161 UpdateMessageQueue ((XEventQueue)queue_id);
3163 if (((XEventQueue)queue_id).Count > 0) {
3164 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3165 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3166 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3168 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3169 msg.hwnd= IntPtr.Zero;
3170 msg.message = Msg.WM_ENTERIDLE;
3174 // We reset ourselves so GetMessage can be called again
3175 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3181 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3183 // Handle messages for windows that are already or are about to be destroyed.
3185 // we need a special block for this because unless we remove the hwnd from the paint
3186 // queue it will always stay there (since we don't handle the expose), and we'll
3187 // effectively loop infinitely trying to repaint a non-existant window.
3188 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3189 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3190 hwnd.Queue.Paint.Remove (hwnd);
3191 goto ProcessNextMessage;
3194 // We need to make sure we only allow DestroyNotify events through for zombie
3195 // hwnds, since much of the event handling code makes requests using the hwnd's
3196 // client_window, and that'll result in BadWindow errors if there's some lag
3197 // between the XDestroyWindow call and the DestroyNotify event.
3198 if (hwnd == null || hwnd.zombie) {
3199 #if DriverDebug || DriverDebugDestroy
3200 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3202 goto ProcessNextMessage;
3205 if (hwnd.client_window == xevent.AnyEvent.window) {
3207 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3210 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3213 msg.hwnd = hwnd.Handle;
3216 // If you add a new event to this switch make sure to add it in
3217 // UpdateMessage also unless it is not coming through the X event system.
3219 switch(xevent.type) {
3220 case XEventName.KeyPress: {
3221 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3225 case XEventName.KeyRelease: {
3226 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3230 case XEventName.ButtonPress: {
3231 switch(xevent.ButtonEvent.button) {
3233 MouseState |= MouseButtons.Left;
3235 msg.message = Msg.WM_LBUTTONDOWN;
3237 msg.message = Msg.WM_NCLBUTTONDOWN;
3238 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3240 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3241 msg.wParam=GetMousewParam(0);
3246 MouseState |= MouseButtons.Middle;
3248 msg.message = Msg.WM_MBUTTONDOWN;
3250 msg.message = Msg.WM_NCMBUTTONDOWN;
3251 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3253 msg.wParam=GetMousewParam(0);
3258 MouseState |= MouseButtons.Right;
3260 msg.message = Msg.WM_RBUTTONDOWN;
3262 msg.message = Msg.WM_NCRBUTTONDOWN;
3263 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3265 msg.wParam=GetMousewParam(0);
3270 msg.hwnd = FocusWindow;
3271 msg.message=Msg.WM_MOUSEWHEEL;
3272 msg.wParam=GetMousewParam(120);
3277 msg.hwnd = FocusWindow;
3278 msg.message=Msg.WM_MOUSEWHEEL;
3279 msg.wParam=GetMousewParam(-120);
3285 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3286 MousePosition.X = xevent.ButtonEvent.x;
3287 MousePosition.Y = xevent.ButtonEvent.y;
3289 if (!hwnd.Enabled) {
3292 msg.hwnd = hwnd.EnabledHwnd;
3293 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);
3294 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3297 if (Grab.Hwnd != IntPtr.Zero) {
3298 msg.hwnd = Grab.Hwnd;
3301 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3302 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3303 switch(xevent.ButtonEvent.button) {
3305 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3310 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3315 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3319 ClickPending.Pending = false;
3321 ClickPending.Pending = true;
3322 ClickPending.Hwnd = msg.hwnd;
3323 ClickPending.Message = msg.message;
3324 ClickPending.wParam = msg.wParam;
3325 ClickPending.lParam = msg.lParam;
3326 ClickPending.Time = (long)xevent.ButtonEvent.time;
3332 case XEventName.ButtonRelease: {
3334 Dnd.HandleButtonRelease (ref xevent);
3338 switch(xevent.ButtonEvent.button) {
3341 msg.message = Msg.WM_LBUTTONUP;
3343 msg.message = Msg.WM_NCLBUTTONUP;
3344 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3346 msg.wParam=GetMousewParam(0);
3347 MouseState &= ~MouseButtons.Left;
3353 msg.message = Msg.WM_MBUTTONUP;
3355 msg.message = Msg.WM_NCMBUTTONUP;
3356 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3358 msg.wParam=GetMousewParam(0);
3359 MouseState &= ~MouseButtons.Middle;
3365 msg.message = Msg.WM_RBUTTONUP;
3367 msg.message = Msg.WM_NCRBUTTONUP;
3368 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3370 msg.wParam=GetMousewParam(0);
3371 MouseState &= ~MouseButtons.Right;
3376 goto ProcessNextMessage;
3380 goto ProcessNextMessage;
3384 if (!hwnd.Enabled) {
3387 msg.hwnd = hwnd.EnabledHwnd;
3388 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);
3389 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3392 if (Grab.Hwnd != IntPtr.Zero) {
3393 msg.hwnd = Grab.Hwnd;
3396 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3397 MousePosition.X = xevent.ButtonEvent.x;
3398 MousePosition.Y = xevent.ButtonEvent.y;
3402 case XEventName.MotionNotify: {
3404 #if DriverDebugExtra
3405 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);
3408 if (Dnd.HandleMotionNotify (ref xevent))
3409 goto ProcessNextMessage;
3410 if (Grab.Hwnd != IntPtr.Zero) {
3411 msg.hwnd = Grab.Hwnd;
3413 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3416 msg.message = Msg.WM_MOUSEMOVE;
3417 msg.wParam = GetMousewParam(0);
3418 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3420 if (!hwnd.Enabled) {
3423 msg.hwnd = hwnd.EnabledHwnd;
3424 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);
3425 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3428 MousePosition.X = xevent.MotionEvent.x;
3429 MousePosition.Y = xevent.MotionEvent.y;
3431 if ((HoverState.Timer.Enabled) &&
3432 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3433 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3434 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3435 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3436 HoverState.Timer.Stop();
3437 HoverState.Timer.Start();
3438 HoverState.X = MousePosition.X;
3439 HoverState.Y = MousePosition.Y;
3449 #if DriverDebugExtra
3450 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);
3452 msg.message = Msg.WM_NCMOUSEMOVE;
3454 if (!hwnd.Enabled) {
3455 msg.hwnd = hwnd.EnabledHwnd;
3456 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);
3457 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3460 // The hit test is sent in screen coordinates
3461 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3462 xevent.MotionEvent.x, xevent.MotionEvent.y,
3463 out screen_x, out screen_y, out dummy);
3465 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3466 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3467 IntPtr.Zero, msg.lParam).ToInt32 ();
3468 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3470 MousePosition.X = xevent.MotionEvent.x;
3471 MousePosition.Y = xevent.MotionEvent.y;
3477 case XEventName.EnterNotify: {
3478 if (!hwnd.Enabled) {
3479 goto ProcessNextMessage;
3481 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3482 goto ProcessNextMessage;
3484 msg.message = Msg.WM_MOUSE_ENTER;
3485 HoverState.X = xevent.CrossingEvent.x;
3486 HoverState.Y = xevent.CrossingEvent.y;
3487 HoverState.Timer.Enabled = true;
3488 HoverState.Window = xevent.CrossingEvent.window;
3492 case XEventName.LeaveNotify: {
3493 if (!hwnd.Enabled) {
3494 goto ProcessNextMessage;
3496 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3497 goto ProcessNextMessage;
3499 msg.message=Msg.WM_MOUSE_LEAVE;
3500 HoverState.Timer.Enabled = false;
3501 HoverState.Window = IntPtr.Zero;
3506 case XEventName.CreateNotify: {
3507 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3508 msg.message = WM_CREATE;
3509 // Set up CreateStruct
3511 goto ProcessNextMessage;
3518 case XEventName.ReparentNotify: {
3519 if (hwnd.parent == null) { // Toplevel
3520 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3521 // We need to adjust x/y
3522 // This sucks ass, part 2
3523 // Every WM does the reparenting of toplevel windows different, so there's
3524 // no standard way of getting our adjustment considering frames/decorations
3525 // The code below is needed for metacity. KDE doesn't works just fine without this
3533 hwnd.Reparented = true;
3535 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);
3536 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3537 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3540 hwnd.whacky_wm = true;
3543 if (hwnd.opacity != 0xffffffff) {
3546 opacity = (IntPtr)(Int32)hwnd.opacity;
3547 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3549 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3550 goto ProcessNextMessage;
3552 hwnd.Reparented = false;
3553 goto ProcessNextMessage;
3556 goto ProcessNextMessage;
3559 case XEventName.ConfigureNotify: {
3560 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3561 #if DriverDebugExtra
3562 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);
3564 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3565 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3566 hwnd.configure_pending = false;
3568 // We need to adjust our client window to track the resize of whole_window
3569 if (hwnd.whole_window != hwnd.client_window)
3570 PerformNCCalc(hwnd);
3573 goto ProcessNextMessage;
3576 case XEventName.FocusIn: {
3577 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3578 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3579 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3580 // about it having focus again
3581 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3582 goto ProcessNextMessage;
3585 if (FocusWindow == IntPtr.Zero) {
3586 Control c = Control.FromHandle (hwnd.client_window);
3588 goto ProcessNextMessage;
3589 Form form = c.FindForm ();
3591 goto ProcessNextMessage;
3592 ActiveWindow = form.Handle;
3593 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3594 goto ProcessNextMessage;
3596 Keyboard.FocusIn(FocusWindow);
3597 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3598 goto ProcessNextMessage;
3601 case XEventName.FocusOut: {
3602 // Se the comment for our FocusIn handler
3603 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3604 goto ProcessNextMessage;
3606 Keyboard.FocusOut(FocusWindow);
3608 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3609 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3612 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3613 goto ProcessNextMessage;
3616 case XEventName.Expose: {
3617 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3619 hwnd.expose_pending = false;
3621 hwnd.nc_expose_pending = false;
3623 goto ProcessNextMessage;
3627 if (!hwnd.expose_pending) {
3628 goto ProcessNextMessage;
3631 if (!hwnd.nc_expose_pending) {
3632 goto ProcessNextMessage;
3635 switch (hwnd.border_style) {
3636 case FormBorderStyle.Fixed3D: {
3639 g = Graphics.FromHwnd(hwnd.whole_window);
3640 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3645 case FormBorderStyle.FixedSingle: {
3648 g = Graphics.FromHwnd(hwnd.whole_window);
3649 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3654 #if DriverDebugExtra
3655 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);
3658 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3659 Region region = new Region (rect);
3660 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3661 msg.message = Msg.WM_NCPAINT;
3662 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3663 msg.refobject = region;
3666 #if DriverDebugExtra
3667 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);
3669 if (Caret.Visible == true) {
3670 Caret.Paused = true;
3674 if (Caret.Visible == true) {
3676 Caret.Paused = false;
3678 msg.message = Msg.WM_PAINT;
3682 case XEventName.DestroyNotify: {
3684 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3685 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3687 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3688 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3689 CleanupCachedWindows (hwnd);
3691 #if DriverDebugDestroy
3692 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3695 msg.hwnd = hwnd.client_window;
3696 msg.message=Msg.WM_DESTROY;
3699 goto ProcessNextMessage;
3705 case XEventName.ClientMessage: {
3706 if (Dnd.HandleClientMessage (ref xevent)) {
3707 goto ProcessNextMessage;
3710 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3711 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3712 goto ProcessNextMessage;
3715 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3716 msg.message = Msg.WM_MOUSEHOVER;
3717 msg.wParam = GetMousewParam(0);
3718 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3722 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3723 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3724 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3725 msg.wParam = xevent.ClientMessageEvent.ptr3;
3726 msg.lParam = xevent.ClientMessageEvent.ptr4;
3730 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3731 #if DriverDebugXEmbed
3732 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3735 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3736 XSizeHints hints = new XSizeHints();
3739 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3741 hwnd.width = hints.max_width;
3742 hwnd.height = hints.max_height;
3743 hwnd.ClientRect = Rectangle.Empty;
3744 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3748 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3749 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3750 msg.message = Msg.WM_CLOSE;
3754 // We should not get this, but I'll leave the code in case we need it in the future
3755 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3756 goto ProcessNextMessage;
3759 goto ProcessNextMessage;
3762 case XEventName.TimerNotify: {
3763 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3764 goto ProcessNextMessage;
3768 goto ProcessNextMessage;
3775 internal override bool GetText(IntPtr handle, out string text) {
3778 textptr = IntPtr.Zero;
3781 // FIXME - use _NET properties
3782 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3784 if (textptr != IntPtr.Zero) {
3785 text = Marshal.PtrToStringAnsi(textptr);
3794 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) {
3797 hwnd = Hwnd.ObjectFromHandle(handle);
3803 height = hwnd.height;
3805 PerformNCCalc(hwnd);
3807 client_width = hwnd.ClientRect.Width;
3808 client_height = hwnd.ClientRect.Height;
3813 // Should we throw an exception or fail silently?
3814 // throw new ArgumentException("Called with an invalid window handle", "handle");
3824 internal override FormWindowState GetWindowState(IntPtr handle) {
3829 IntPtr prop = IntPtr.Zero;
3833 XWindowAttributes attributes;
3836 hwnd = Hwnd.ObjectFromHandle(handle);
3840 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);
3841 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3842 for (int i = 0; i < (long)nitems; i++) {
3843 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3844 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3846 } else if (atom == _NET_WM_STATE_HIDDEN) {
3854 return FormWindowState.Minimized;
3855 } else if (maximized == 2) {
3856 return FormWindowState.Maximized;
3859 attributes = new XWindowAttributes();
3860 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3861 if (attributes.map_state == MapState.IsUnmapped) {
3862 return (FormWindowState)(-1);
3866 return FormWindowState.Normal;
3869 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3871 GrabConfined = Grab.Confined;
3872 GrabArea = Grab.Area;
3875 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3877 IntPtr confine_to_window;
3879 confine_to_window = IntPtr.Zero;
3881 if (confine_to_handle != IntPtr.Zero) {
3882 XWindowAttributes attributes = new XWindowAttributes();
3884 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3887 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3889 Grab.Area.X = attributes.x;
3890 Grab.Area.Y = attributes.y;
3891 Grab.Area.Width = attributes.width;
3892 Grab.Area.Height = attributes.height;
3893 Grab.Confined = true;
3894 confine_to_window = hwnd.client_window;
3899 hwnd = Hwnd.ObjectFromHandle(handle);
3902 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3903 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3904 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3905 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3909 internal override void UngrabWindow(IntPtr hwnd) {
3911 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3912 XFlush(DisplayHandle);
3914 Grab.Hwnd = IntPtr.Zero;
3915 Grab.Confined = false;
3918 internal override void HandleException(Exception e) {
3919 StackTrace st = new StackTrace(e, true);
3920 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3921 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3924 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3927 hwnd = Hwnd.ObjectFromHandle(handle);
3930 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3932 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3936 internal override bool IsEnabled(IntPtr handle) {
3937 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3938 return (hwnd != null && hwnd.Enabled);
3941 internal override bool IsVisible(IntPtr handle) {
3942 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3943 return (hwnd != null && hwnd.visible);
3946 internal override void KillTimer(Timer timer) {
3947 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3949 if (queue == null) {
3950 // This isn't really an error, MS doesn't start the timer if
3951 // it has no assosciated queue
3954 queue.timer_list.Remove (timer);
3957 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3963 hwnd = Hwnd.ObjectFromHandle(handle);
3966 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3973 internal override void OverrideCursor(IntPtr cursor) {
3974 OverrideCursorHandle = cursor;
3977 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3978 PaintEventArgs paint_event;
3981 hwnd = Hwnd.ObjectFromHandle(handle);
3983 if (Caret.Visible == true) {
3984 Caret.Paused = true;
3991 dc = Graphics.FromHwnd (hwnd.client_window);
3993 Region clip_region = new Region ();
3994 clip_region.MakeEmpty();
3996 foreach (Rectangle r in hwnd.ClipRectangles) {
3997 clip_region.Union (r);
4000 if (hwnd.UserClip != null) {
4001 clip_region.Intersect(hwnd.UserClip);
4004 dc.Clip = clip_region;
4005 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4006 hwnd.expose_pending = false;
4008 hwnd.ClearInvalidArea();
4010 hwnd.drawing_stack.Push (paint_event);
4011 hwnd.drawing_stack.Push (dc);
4015 dc = Graphics.FromHwnd (hwnd.whole_window);
4017 if (!hwnd.nc_invalid.IsEmpty) {
4018 dc.SetClip (hwnd.nc_invalid);
4019 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4021 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4023 hwnd.nc_expose_pending = false;
4025 hwnd.ClearNcInvalidArea ();
4027 hwnd.drawing_stack.Push (paint_event);
4028 hwnd.drawing_stack.Push (dc);
4034 internal override void PaintEventEnd(IntPtr handle, bool client) {
4037 hwnd = Hwnd.ObjectFromHandle(handle);
4039 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4043 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4044 pe.SetGraphics (null);
4047 if (Caret.Visible == true) {
4049 Caret.Paused = false;
4053 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4054 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4055 XEventQueue queue = (XEventQueue) queue_id;
4058 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4059 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4063 if (queue.Count > 0) {
4066 // Only call UpdateMessageQueue if real events are pending
4067 // otherwise we go to sleep on the socket
4068 if (XPending(DisplayHandle) != 0) {
4069 UpdateMessageQueue((XEventQueue)queue_id);
4071 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4076 CheckTimers(queue.timer_list, DateTime.UtcNow);
4081 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4084 // FIXME - I think this should just enqueue directly
4085 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4086 XEvent xevent = new XEvent ();
4087 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4089 xevent.type = XEventName.ClientMessage;
4090 xevent.ClientMessageEvent.display = DisplayHandle;
4093 xevent.ClientMessageEvent.window = hwnd.whole_window;
4095 xevent.ClientMessageEvent.window = IntPtr.Zero;
4098 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4099 xevent.ClientMessageEvent.format = 32;
4100 xevent.ClientMessageEvent.ptr1 = handle;
4101 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4102 xevent.ClientMessageEvent.ptr3 = wparam;
4103 xevent.ClientMessageEvent.ptr4 = lparam;
4105 hwnd.Queue.Enqueue (xevent);
4110 internal override void PostQuitMessage(int exitCode) {
4112 XFlush(DisplayHandle);
4113 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4116 internal override void RequestNCRecalc(IntPtr handle) {
4119 hwnd = Hwnd.ObjectFromHandle(handle);
4125 PerformNCCalc(hwnd);
4126 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4127 InvalidateWholeWindow(handle);
4130 internal override void ResetMouseHover(IntPtr handle) {
4133 hwnd = Hwnd.ObjectFromHandle(handle);
4138 HoverState.Timer.Enabled = true;
4139 HoverState.X = MousePosition.X;
4140 HoverState.Y = MousePosition.Y;
4141 HoverState.Window = handle;
4145 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4151 hwnd = Hwnd.ObjectFromHandle(handle);
4154 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4161 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4167 hwnd = Hwnd.ObjectFromHandle(handle);
4170 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4177 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4180 XGCValues gc_values;
4183 hwnd = Hwnd.ObjectFromHandle(handle);
4186 if (r != Rectangle.Empty) {
4187 /* We have an invalid area in the window we're scrolling.
4188 Adjust our stored invalid rectangle to to match the scrolled amount */
4203 hwnd.ClearInvalidArea();
4204 hwnd.AddInvalidArea(r);
4207 gc_values = new XGCValues();
4209 if (with_children) {
4210 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4213 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4221 height = area.Height - YAmount;
4222 dest_y = area.Y + YAmount;
4225 src_y = area.Y - YAmount;
4226 height = area.Height + YAmount;
4232 width = area.Width - XAmount;
4233 dest_x = area.X + XAmount;
4236 src_x = area.X - XAmount;
4237 width = area.Width + XAmount;
4241 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4243 // Generate an expose for the area exposed by the horizontal scroll
4244 // We don't use AddExpose since we're
4246 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4247 } else if (XAmount < 0) {
4248 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4251 // Generate an expose for the area exposed by the vertical scroll
4253 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4254 } else if (YAmount < 0) {
4255 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4257 XFreeGC(DisplayHandle, gc);
4260 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4264 hwnd = Hwnd.GetObjectFromWindow(handle);
4266 rect = hwnd.ClientRect;
4269 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4272 internal override void SendAsyncMethod (AsyncMethodData method) {
4274 XEvent xevent = new XEvent ();
4276 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4278 xevent.type = XEventName.ClientMessage;
4279 xevent.ClientMessageEvent.display = DisplayHandle;
4280 xevent.ClientMessageEvent.window = method.Handle;
4281 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4282 xevent.ClientMessageEvent.format = 32;
4283 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4285 hwnd.Queue.EnqueueLocked (xevent);
4290 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4292 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4295 h = Hwnd.ObjectFromHandle(hwnd);
4297 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4298 AsyncMethodResult result;
4299 AsyncMethodData data;
4301 result = new AsyncMethodResult ();
4302 data = new AsyncMethodData ();
4305 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4306 data.Args = new object[] { hwnd, message, wParam, lParam };
4307 data.Result = result;
4309 SendAsyncMethod (data);
4310 #if DriverDebug || DriverDebugThreads
4311 Console.WriteLine ("Sending {0} message across.", message);
4316 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4319 internal override void SetAllowDrop (IntPtr handle, bool value)
4321 // We allow drop on all windows
4324 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4325 DragDropEffects allowed_effects)
4327 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4330 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4332 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4335 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4338 hwnd = Hwnd.ObjectFromHandle(handle);
4340 Form form = Control.FromHandle (handle) as Form;
4341 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4342 border_style == FormBorderStyle.SizableToolWindow)) {
4343 form.window_manager = new InternalWindowManager (form);
4346 hwnd.border_style = border_style;
4347 RequestNCRecalc(handle);
4350 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4351 if (Caret.Hwnd == handle) {
4358 if (Caret.Visible == true) {
4360 Caret.Timer.Start();
4365 internal override void SetClipRegion(IntPtr handle, Region region) {
4368 hwnd = Hwnd.ObjectFromHandle(handle);
4373 hwnd.UserClip = region;
4374 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4377 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4380 if (OverrideCursorHandle == IntPtr.Zero) {
4381 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4385 LastCursorHandle = cursor;
4386 LastCursorWindow = handle;
4388 hwnd = Hwnd.ObjectFromHandle(handle);
4390 if (cursor != IntPtr.Zero) {
4391 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4393 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4395 XFlush(DisplayHandle);
4400 hwnd = Hwnd.ObjectFromHandle(handle);
4402 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4406 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4407 out int root_x, out int root_y, out int child_x, out int child_y,
4410 /* this code was written with the help of
4411 glance at gdk. I never would have realized we
4412 needed a loop in order to traverse down in the
4413 hierarchy. I would have assumed you'd get the
4414 most deeply nested child and have to do
4415 XQueryTree to move back up the hierarchy..
4416 stupid me, of course. */
4419 XGrabServer (display);
4421 XQueryPointer(display, w, out root, out c,
4422 out root_x, out root_y, out child_x, out child_y,
4428 IntPtr child_last = IntPtr.Zero;
4429 while (c != IntPtr.Zero) {
4431 XQueryPointer(display, c, out root, out c,
4432 out root_x, out root_y, out child_x, out child_y,
4435 XUngrabServer (display);
4440 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4441 if (handle == IntPtr.Zero) {
4444 int root_x, root_y, child_x, child_y, mask;
4447 * QueryPointer before warping
4448 * because if the warp is on
4449 * the RootWindow, the x/y are
4450 * relative to the current
4453 QueryPointer (DisplayHandle, RootWindow,
4456 out root_x, out root_y,
4457 out child_x, out child_y,
4460 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4462 XFlush (DisplayHandle);
4464 /* then we need to a
4465 * QueryPointer after warping
4466 * to manually generate a
4467 * motion event for the window
4470 QueryPointer (DisplayHandle, RootWindow,
4473 out root_x, out root_y,
4474 out child_x, out child_y,
4477 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4478 if (child_hwnd == null) {
4482 XEvent xevent = new XEvent ();
4484 xevent.type = XEventName.MotionNotify;
4485 xevent.MotionEvent.display = DisplayHandle;
4486 xevent.MotionEvent.window = child_hwnd.client_window;
4487 xevent.MotionEvent.root = RootWindow;
4488 xevent.MotionEvent.x = child_x;
4489 xevent.MotionEvent.y = child_y;
4490 xevent.MotionEvent.x_root = root_x;
4491 xevent.MotionEvent.y_root = root_y;
4492 xevent.MotionEvent.state = mask;
4494 child_hwnd.Queue.Enqueue (xevent);
4499 hwnd = Hwnd.ObjectFromHandle(handle);
4501 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4506 internal override void SetFocus(IntPtr handle) {
4508 IntPtr prev_focus_window;
4510 hwnd = Hwnd.ObjectFromHandle(handle);
4512 if (hwnd.client_window == FocusWindow) {
4516 prev_focus_window = FocusWindow;
4517 FocusWindow = hwnd.client_window;
4519 if (prev_focus_window != IntPtr.Zero) {
4520 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4522 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4524 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4527 internal override void SetIcon(IntPtr handle, Icon icon) {
4530 hwnd = Hwnd.ObjectFromHandle(handle);
4532 SetIcon(hwnd, icon);
4536 internal override void SetMenu(IntPtr handle, Menu menu) {
4539 hwnd = Hwnd.ObjectFromHandle(handle);
4542 RequestNCRecalc(handle);
4545 internal override void SetModal(IntPtr handle, bool Modal) {
4547 ModalWindows.Push(handle);
4549 if (ModalWindows.Contains(handle)) {
4552 if (ModalWindows.Count > 0) {
4553 Activate((IntPtr)ModalWindows.Peek());
4558 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4561 hwnd = Hwnd.ObjectFromHandle(handle);
4562 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4565 #if DriverDebug || DriverDebugParent
4566 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4568 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4574 internal override void SetTimer (Timer timer) {
4575 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4577 if (queue == null) {
4578 // This isn't really an error, MS doesn't start the timer if
4579 // it has no assosciated queue
4582 queue.timer_list.Add (timer);
4586 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4590 hwnd = Hwnd.ObjectFromHandle(handle);
4592 if (handle_owner != IntPtr.Zero) {
4593 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4604 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4605 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4607 if (hwnd_owner != null) {
4608 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4610 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4615 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4621 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4624 hwnd = Hwnd.ObjectFromHandle(handle);
4625 hwnd.visible = visible;
4629 if (Control.FromHandle(handle) is Form) {
4632 s = ((Form)Control.FromHandle(handle)).WindowState;
4634 MapWindow(hwnd, WindowType.Both);
4637 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4638 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4642 MapWindow(hwnd, WindowType.Both);
4644 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4646 UnmapWindow(hwnd, WindowType.Whole);
4652 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4657 hwnd = Hwnd.ObjectFromHandle(handle);
4662 hints = new XSizeHints();
4664 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4665 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4666 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4667 hints.min_width = min.Width;
4668 hints.min_height = min.Height;
4671 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4672 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4673 hints.max_width = max.Width;
4674 hints.max_height = max.Height;
4677 if (hints.flags != IntPtr.Zero) {
4678 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4681 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4682 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4683 hints.x = maximized.X;
4684 hints.y = maximized.Y;
4685 hints.width = maximized.Width;
4686 hints.height = maximized.Height;
4688 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4689 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4694 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4697 hwnd = Hwnd.ObjectFromHandle(handle);
4703 // X requires a sanity check for width & height; otherwise it dies
4704 if (hwnd.zero_sized && width > 0 && height > 0) {
4706 MapWindow(hwnd, WindowType.Whole);
4708 hwnd.zero_sized = false;
4711 if ((width < 1) || (height < 1)) {
4712 hwnd.zero_sized = true;
4713 UnmapWindow(hwnd, WindowType.Whole);
4716 // Save a server roundtrip (and prevent a feedback loop)
4717 if ((hwnd.x == x) && (hwnd.y == y) &&
4718 (hwnd.width == width) && (hwnd.height == height)) {
4722 if (!hwnd.zero_sized) {
4727 hwnd.height = height;
4728 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4730 if (hwnd.fixed_size) {
4731 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4735 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4736 PerformNCCalc(hwnd);
4740 // Update our position/size immediately, so
4741 // that future calls to SetWindowPos aren't
4742 // kept from calling XMoveResizeWindow (by the
4743 // "Save a server roundtrip" block above).
4747 hwnd.height = height;
4748 hwnd.ClientRect = Rectangle.Empty;
4751 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4752 FormWindowState current_state;
4755 hwnd = Hwnd.ObjectFromHandle(handle);
4757 current_state = GetWindowState(handle);
4759 if (current_state == state) {
4764 case FormWindowState.Normal: {
4766 if (current_state == FormWindowState.Minimized) {
4767 MapWindow(hwnd, WindowType.Both);
4768 } else if (current_state == FormWindowState.Maximized) {
4769 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4776 case FormWindowState.Minimized: {
4778 if (current_state == FormWindowState.Maximized) {
4779 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4781 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4786 case FormWindowState.Maximized: {
4788 if (current_state == FormWindowState.Minimized) {
4789 MapWindow(hwnd, WindowType.Both);
4792 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4800 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4803 hwnd = Hwnd.ObjectFromHandle(handle);
4804 SetHwndStyles(hwnd, cp);
4805 SetWMStyles(hwnd, cp);
4808 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4812 hwnd = Hwnd.ObjectFromHandle(handle);
4818 hwnd.opacity = (uint)(0xffffffff * transparency);
4819 opacity = (IntPtr)((int)hwnd.opacity);
4821 IntPtr w = hwnd.whole_window;
4822 if (hwnd.reparented)
4823 w = XGetParent (hwnd.whole_window);
4824 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4827 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4828 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4836 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4839 } else if (!bottom) {
4840 Hwnd after_hwnd = null;
4842 if (after_handle != IntPtr.Zero) {
4843 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4846 XWindowChanges values = new XWindowChanges();
4848 if (after_hwnd == null) {
4849 // Work around metacity 'issues'
4853 atoms[0] = unixtime();
4854 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4856 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4857 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4859 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4862 values.sibling = after_hwnd.whole_window;
4863 values.stack_mode = StackMode.Below;
4866 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4871 XLowerWindow(DisplayHandle, hwnd.whole_window);
4878 internal override void ShowCursor(bool show) {
4879 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4882 internal override object StartLoop(Thread thread) {
4883 return (Object) ThreadQueue(thread);
4886 internal override bool SupportsTransparency() {
4887 // We need to check if the x compositing manager is running
4891 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4892 GetSystrayManagerWindow();
4894 if (SystrayMgrWindow != IntPtr.Zero) {
4895 XSizeHints size_hints;
4898 hwnd = Hwnd.ObjectFromHandle(handle);
4900 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4904 if (hwnd.client_window != hwnd.whole_window) {
4905 XDestroyWindow(DisplayHandle, hwnd.client_window);
4906 hwnd.client_window = hwnd.whole_window;
4908 /* by virtue of the way the tests are ordered when determining if it's PAINT
4909 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
4910 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4911 there's a pending expose). */
4912 if (hwnd.nc_expose_pending) {
4913 hwnd.nc_expose_pending = false;
4914 if (!hwnd.expose_pending)
4915 hwnd.Queue.Paint.Remove (hwnd);
4919 size_hints = new XSizeHints();
4921 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4923 size_hints.min_width = 24;
4924 size_hints.min_height = 24;
4925 size_hints.max_width = 24;
4926 size_hints.max_height = 24;
4927 size_hints.base_width = 24;
4928 size_hints.base_height = 24;
4930 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4932 int[] atoms = new int[2];
4933 atoms [0] = 1; // Version 1
4934 atoms [1] = 1; // we want to be mapped
4936 // This line cost me 3 days...
4937 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4939 // Need to pick some reasonable defaults
4941 tt.AutomaticDelay = 100;
4942 tt.InitialDelay = 250;
4943 tt.ReshowDelay = 250;
4944 tt.ShowAlways = true;
4946 if ((tip != null) && (tip != string.Empty)) {
4947 tt.SetToolTip(Control.FromHandle(handle), tip);
4953 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4961 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4964 control = Control.FromHandle(handle);
4965 if (control != null && tt != null) {
4966 tt.SetToolTip(control, tip);
4974 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4976 #if GTKSOCKET_SUPPORTS_REPARENTING
4979 hwnd = Hwnd.ObjectFromHandle(handle);
4981 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4982 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4983 * 2. The client can reparent its window out of the embedder window.
4984 * 3. The client can destroy its window.
4986 * this call to SetParent is case 2, but in
4987 * the spec it also mentions that gtk doesn't
4988 * support this at present. Looking at HEAD
4989 * gtksocket-x11.c jives with this statement.
4991 * so we can't reparent. we have to destroy.
4993 SetParent(hwnd.whole_window, FosterParent);
4995 Control control = Control.FromHandle(handle);
4996 if (control is NotifyIcon.NotifyIconWindow)
4997 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5000 // The caller can now re-dock it later...
5007 internal override bool Text(IntPtr handle, string text) {
5010 hwnd = Hwnd.ObjectFromHandle(handle);
5013 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5014 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5016 // XXX this has problems with UTF8.
5017 // we need to either use the actual
5018 // text if it's latin-1, or convert it
5019 // to compound text if it's in a
5020 // different charset.
5021 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5026 internal override bool TranslateMessage(ref MSG msg) {
5027 return Keyboard.TranslateMessage (ref msg);
5030 internal override void UpdateWindow(IntPtr handle) {
5033 hwnd = Hwnd.ObjectFromHandle(handle);
5035 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5039 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5040 hwnd.Queue.Paint.Remove(hwnd);
5043 #endregion // Public Static Methods
5046 internal override event EventHandler Idle;
5047 #endregion // Events
5050 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5051 internal extern static IntPtr XOpenDisplay(IntPtr display);
5052 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5053 internal extern static int XCloseDisplay(IntPtr display);
5054 [DllImport ("libX11", EntryPoint="XSynchronize")]
5055 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5057 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5058 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);
5059 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5060 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5061 [DllImport ("libX11", EntryPoint="XMapWindow")]
5062 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5063 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5064 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5065 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5066 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5067 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5068 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5069 [DllImport ("libX11", EntryPoint="XRootWindow")]
5070 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5071 [DllImport ("libX11", EntryPoint="XNextEvent")]
5072 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5073 [DllImport ("libX11")]
5074 internal extern static int XConnectionNumber (IntPtr diplay);
5075 [DllImport ("libX11")]
5076 internal extern static int XPending (IntPtr diplay);
5077 [DllImport ("libX11", EntryPoint="XSelectInput")]
5078 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5080 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5081 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5083 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5084 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5085 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5086 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5088 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5089 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5091 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5092 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5094 [DllImport ("libX11", EntryPoint="XFlush")]
5095 internal extern static int XFlush(IntPtr display);
5097 [DllImport ("libX11", EntryPoint="XSetWMName")]
5098 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5100 [DllImport ("libX11", EntryPoint="XStoreName")]
5101 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5103 [DllImport ("libX11", EntryPoint="XFetchName")]
5104 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5106 [DllImport ("libX11", EntryPoint="XSendEvent")]
5107 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5109 [DllImport ("libX11", EntryPoint="XQueryTree")]
5110 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);
5112 [DllImport ("libX11", EntryPoint="XFree")]
5113 internal extern static int XFree(IntPtr data);
5115 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5116 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5118 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5119 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5121 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5122 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5124 [DllImport ("libX11", EntryPoint="XInternAtom")]
5125 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5127 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5128 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5130 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5131 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5133 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5134 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);
5136 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5137 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5139 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5140 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);
5142 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5143 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);
5145 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5146 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);
5148 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5149 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);
5151 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5152 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);
5154 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5155 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);
5157 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5158 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);
5160 [DllImport ("libX11", EntryPoint="XClearWindow")]
5161 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5163 [DllImport ("libX11", EntryPoint="XClearArea")]
5164 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5167 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5168 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5170 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5171 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5173 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5174 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5176 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5177 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5179 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5180 internal extern static int XDefaultScreen(IntPtr display);
5182 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5183 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5185 [DllImport ("libX11", EntryPoint="XLookupColor")]
5186 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5188 [DllImport ("libX11", EntryPoint="XAllocColor")]
5189 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5191 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5192 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5194 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5195 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5197 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5198 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5200 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5201 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5203 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5204 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5206 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5207 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5209 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5210 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5212 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5213 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5215 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5216 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5218 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5219 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5221 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5222 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5225 [DllImport ("libX11", EntryPoint="XCreateGC")]
5226 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5228 [DllImport ("libX11", EntryPoint="XFreeGC")]
5229 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5231 [DllImport ("libX11", EntryPoint="XSetFunction")]
5232 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5234 [DllImport ("libX11", EntryPoint="XDrawLine")]
5235 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5237 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5238 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5240 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5241 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5243 [DllImport ("libX11", EntryPoint="XCopyArea")]
5244 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);
5246 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5247 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);
5249 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5250 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5252 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5253 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5255 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5256 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5258 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5259 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5261 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5262 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5264 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5265 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5267 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5268 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);
5270 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5271 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5273 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5274 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5276 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5277 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5279 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5280 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5282 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5283 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5285 [DllImport ("libX11", EntryPoint="XGrabServer")]
5286 internal extern static void XGrabServer(IntPtr display);
5288 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5289 internal extern static void XUngrabServer(IntPtr display);
5291 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5292 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5294 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5295 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5297 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5298 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5300 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5301 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5303 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5304 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5306 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5307 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5309 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5310 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5312 [DllImport ("libX11", EntryPoint="XInitThreads")]
5313 internal extern static int XInitThreads();
5315 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5316 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5318 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5319 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5321 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5322 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5324 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5325 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5327 [DllImport ("libX11", EntryPoint="XSetForeground")]
5328 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5330 [DllImport ("libX11", EntryPoint="XSetBackground")]
5331 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5333 [DllImport ("libX11", EntryPoint="XBell")]
5334 internal extern static int XBell(IntPtr display, int percent);
5336 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5337 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5339 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5340 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5342 [DllImport ("libX11")]
5343 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5345 [DllImport ("libX11")]
5346 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);