1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
28 // This driver understands the following environment variables: (Set the var to enable feature)
30 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
31 // by default a message is displayed but execution continues
33 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
34 // helps in debugging errors
39 // define to log Window handles and relationships to stdout
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
63 using System.Threading;
65 // Only do the poll when building with mono for now
67 using Mono.Unix.Native;
71 namespace System.Windows.Forms {
72 internal class XplatUIX11 : XplatUIDriver {
73 #region Local Variables
75 static volatile XplatUIX11 Instance;
76 private static int RefCount;
77 private static object XlibLock; // Our locking object
78 private static bool themes_enabled;
81 private static IntPtr DisplayHandle; // X11 handle to display
82 private static int ScreenNo; // Screen number used
83 private static IntPtr DefaultColormap; // Colormap for screen
84 private static IntPtr CustomVisual; // Visual for window creation
85 private static IntPtr CustomColormap; // Colormap for window creation
86 private static IntPtr RootWindow; // Handle of the root window for the screen/display
87 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
88 private static XErrorHandler ErrorHandler; // Error handler delegate
89 private static bool ErrorExceptions; // Throw exceptions on X errors
92 private static IntPtr ClipMagic;
93 private static ClipboardStruct Clipboard; // Our clipboard
96 private static IntPtr PostAtom; // PostMessage atom
97 private static IntPtr AsyncAtom; // Support for async messages
100 private static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
102 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static bool wake_waiting;
104 private static object wake_waiting_lock = new object ();
106 private static X11Keyboard Keyboard; //
107 private static X11Dnd Dnd;
108 private static Socket listen; //
109 private static Socket wake; //
110 private static Socket wake_receive; //
111 private static byte[] network_buffer; //
112 private static bool detectable_key_auto_repeat;
115 private static IntPtr ActiveWindow; // Handle of the active window
116 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
119 private static Stack ModalWindows; // Stack of our modal windows
122 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
125 private static IntPtr LastCursorWindow; // The last window we set the cursor on
126 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
127 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
130 private static CaretStruct Caret; //
133 private static IntPtr WM_PROTOCOLS;
134 private static IntPtr WM_DELETE_WINDOW;
135 private static IntPtr WM_TAKE_FOCUS;
136 private static IntPtr _NET_SUPPORTED;
137 private static IntPtr _NET_CLIENT_LIST;
138 private static IntPtr _NET_NUMBER_OF_DESKTOPS;
139 private static IntPtr _NET_DESKTOP_GEOMETRY;
140 private static IntPtr _NET_DESKTOP_VIEWPORT;
141 private static IntPtr _NET_CURRENT_DESKTOP;
142 private static IntPtr _NET_DESKTOP_NAMES;
143 private static IntPtr _NET_ACTIVE_WINDOW;
144 private static IntPtr _NET_WORKAREA;
145 private static IntPtr _NET_SUPPORTING_WM_CHECK;
146 private static IntPtr _NET_VIRTUAL_ROOTS;
147 private static IntPtr _NET_DESKTOP_LAYOUT;
148 private static IntPtr _NET_SHOWING_DESKTOP;
149 private static IntPtr _NET_CLOSE_WINDOW;
150 private static IntPtr _NET_MOVERESIZE_WINDOW;
151 private static IntPtr _NET_WM_MOVERESIZE;
152 private static IntPtr _NET_RESTACK_WINDOW;
153 private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
154 private static IntPtr _NET_WM_NAME;
155 private static IntPtr _NET_WM_VISIBLE_NAME;
156 private static IntPtr _NET_WM_ICON_NAME;
157 private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
158 private static IntPtr _NET_WM_DESKTOP;
159 private static IntPtr _NET_WM_WINDOW_TYPE;
160 private static IntPtr _NET_WM_STATE;
161 private static IntPtr _NET_WM_ALLOWED_ACTIONS;
162 private static IntPtr _NET_WM_STRUT;
163 private static IntPtr _NET_WM_STRUT_PARTIAL;
164 private static IntPtr _NET_WM_ICON_GEOMETRY;
165 private static IntPtr _NET_WM_ICON;
166 private static IntPtr _NET_WM_PID;
167 private static IntPtr _NET_WM_HANDLED_ICONS;
168 private static IntPtr _NET_WM_USER_TIME;
169 private static IntPtr _NET_FRAME_EXTENTS;
170 private static IntPtr _NET_WM_PING;
171 private static IntPtr _NET_WM_SYNC_REQUEST;
172 private static IntPtr _NET_SYSTEM_TRAY_S;
173 private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
174 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
175 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
176 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
177 private static IntPtr _XEMBED;
178 private static IntPtr _XEMBED_INFO;
179 private static IntPtr _MOTIF_WM_HINTS;
180 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
181 private static IntPtr _NET_WM_STATE_ABOVE;
182 private static IntPtr _NET_WM_STATE_MODAL;
183 private static IntPtr _NET_WM_STATE_HIDDEN;
184 private static IntPtr _NET_WM_CONTEXT_HELP;
185 private static IntPtr _NET_WM_WINDOW_OPACITY;
186 private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
187 private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
188 private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
189 private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
190 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
191 private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
192 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
193 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
194 private static IntPtr CLIPBOARD;
195 private static IntPtr PRIMARY;
196 private static IntPtr DIB;
197 private static IntPtr OEMTEXT;
198 private static IntPtr UNICODETEXT;
199 private static IntPtr TARGETS;
201 // mouse hover message generation
202 private static HoverStruct HoverState; //
204 // double click message generation
205 private static ClickStruct ClickPending; //
207 // Support for mouse grab
208 private static GrabStruct Grab; //
211 private static Point MousePosition; // Last position of mouse, in screen coords
212 internal static MouseButtons MouseState; // Last state of mouse buttons
215 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
217 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
218 EventMask.ButtonReleaseMask |
219 EventMask.KeyPressMask |
220 EventMask.KeyReleaseMask |
221 EventMask.EnterWindowMask |
222 EventMask.LeaveWindowMask |
223 EventMask.ExposureMask |
224 EventMask.FocusChangeMask |
225 EventMask.PointerMotionMask |
226 EventMask.SubstructureNotifyMask);
228 static readonly object lockobj = new object ();
230 #endregion // Local Variables
232 private XplatUIX11() {
233 // Handle singleton stuff first
236 // Now regular initialization
237 XlibLock = new object ();
238 MessageQueues = Hashtable.Synchronized (new Hashtable(7));
241 ErrorExceptions = false;
243 // X11 Initialization
244 SetDisplay(XOpenDisplay(IntPtr.Zero));
245 X11DesktopColors.Initialize();
248 // Disable keyboard autorepeat
250 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
251 detectable_key_auto_repeat = true;
253 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
254 detectable_key_auto_repeat = false;
257 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
258 ErrorHandler = new XErrorHandler(HandleError);
259 XSetErrorHandler(ErrorHandler);
263 // Remove our display handle from S.D
264 Graphics.FromHdcInternal (IntPtr.Zero);
267 #endregion // Constructors
269 #region Singleton Specific Code
270 public static XplatUIX11 GetInstance() {
272 if (Instance == null) {
273 Instance=new XplatUIX11();
280 public int Reference {
287 #region Internal Properties
288 internal static IntPtr Display {
290 return DisplayHandle;
294 XplatUIX11.GetInstance().SetDisplay(value);
298 internal static int Screen {
308 internal static IntPtr RootWindowHandle {
318 internal static IntPtr Visual {
324 CustomVisual = value;
328 internal static IntPtr ColorMap {
330 return CustomColormap;
334 CustomColormap = value;
339 #region XExceptionClass
340 internal class XException : ApplicationException {
344 XRequest RequestCode;
348 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
349 this.Display = Display;
350 this.ResourceID = ResourceID;
351 this.Serial = Serial;
352 this.RequestCode = RequestCode;
353 this.ErrorCode = ErrorCode;
354 this.MinorCode = MinorCode;
357 public override string Message {
359 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
363 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
372 sb = new StringBuilder(160);
373 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
374 x_error_text = sb.ToString();
375 hwnd = Hwnd.ObjectFromHandle(ResourceID);
377 hwnd_text = hwnd.ToString();
378 c = Control.FromHandle(hwnd.Handle);
380 control_text = c.ToString();
382 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
385 hwnd_text = "<null>";
386 control_text = "<null>";
390 error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
394 #endregion // XExceptionClass
396 #region Internal Methods
397 internal void SetDisplay(IntPtr display_handle) {
398 if (display_handle != IntPtr.Zero) {
401 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
402 hwnd = Hwnd.ObjectFromHandle(FosterParent);
403 XDestroyWindow(DisplayHandle, FosterParent);
407 if (DisplayHandle != IntPtr.Zero) {
408 XCloseDisplay(DisplayHandle);
411 DisplayHandle=display_handle;
413 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
414 // been hacked to do this for us.
415 Graphics.FromHdcInternal (DisplayHandle);
418 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
419 XSynchronize(DisplayHandle, true);
422 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
423 ErrorExceptions = true;
427 ScreenNo = XDefaultScreen(DisplayHandle);
428 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
429 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
431 // Create the foster parent
432 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
433 if (FosterParent==IntPtr.Zero) {
434 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
438 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
439 hwnd.WholeWindow = FosterParent;
440 hwnd.ClientWindow = FosterParent;
442 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
444 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
445 hwnd.whole_window = RootWindow;
446 hwnd.ClientWindow = RootWindow;
448 // For sleeping on the X11 socket
449 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
450 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
454 // To wake up when a timer is ready
455 network_buffer = new byte[10];
457 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
458 wake.Connect(listen.LocalEndPoint);
459 wake_receive = listen.Accept();
462 pollfds = new Pollfd [2];
463 pollfds [0] = new Pollfd ();
464 pollfds [0].fd = XConnectionNumber (DisplayHandle);
465 pollfds [0].events = PollEvents.POLLIN;
467 pollfds [1] = new Pollfd ();
468 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
469 pollfds [1].events = PollEvents.POLLIN;
472 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
473 Dnd = new X11Dnd (DisplayHandle);
475 DoubleClickInterval = 500;
477 HoverState.Interval = 500;
478 HoverState.Timer = new Timer();
479 HoverState.Timer.Enabled = false;
480 HoverState.Timer.Interval = HoverState.Interval;
481 HoverState.Timer.Tick += new EventHandler(MouseHover);
482 HoverState.Size = new Size(4, 4);
486 ActiveWindow = IntPtr.Zero;
487 FocusWindow = IntPtr.Zero;
488 ModalWindows = new Stack(3);
490 MouseState = MouseButtons.None;
491 MousePosition = new Point(0, 0);
493 Caret.Timer = new Timer();
494 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
495 Caret.Timer.Tick += new EventHandler(CaretCallback);
499 // Grab atom changes off the root window to catch certain WM events
500 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
502 // Handle any upcoming errors
503 ErrorHandler = new XErrorHandler(HandleError);
504 XSetErrorHandler(ErrorHandler);
506 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
510 internal static void Where() {
511 Console.WriteLine("Here: {0}\n", WhereString());
514 internal static string WhereString() {
522 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
523 unknown = Locale.GetText("<unknown method>");
524 sb = new StringBuilder();
525 stack = new StackTrace(true);
527 for (int i = 0; i < stack.FrameCount; i++) {
528 frame = stack.GetFrame(i);
531 method = frame.GetMethod();
532 if (method != null) {
534 sb.AppendFormat(frame.ToString());
536 if (frame.GetFileLineNumber() != 0) {
537 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
539 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
545 return sb.ToString();
547 #endregion // Internal Methods
549 #region Private Methods
550 private int unixtime() {
551 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
553 return (int) t.TotalSeconds;
556 private static void SetupAtoms() {
557 // make sure this array stays in sync with the statements below
558 string [] atom_names = new string[] {
564 "_NET_NUMBER_OF_DESKTOPS",
565 "_NET_DESKTOP_GEOMETRY",
566 "_NET_DESKTOP_VIEWPORT",
567 "_NET_CURRENT_DESKTOP",
568 "_NET_DESKTOP_NAMES",
569 "_NET_ACTIVE_WINDOW",
571 "_NET_SUPPORTING_WM_CHECK",
572 "_NET_VIRTUAL_ROOTS",
573 "_NET_DESKTOP_LAYOUT",
574 "_NET_SHOWING_DESKTOP",
576 "_NET_MOVERESIZE_WINDOW",
577 "_NET_WM_MOVERESIZE",
578 "_NET_RESTACK_WINDOW",
579 "_NET_REQUEST_FRAME_EXTENTS",
581 "_NET_WM_VISIBLE_NAME",
583 "_NET_WM_VISIBLE_ICON_NAME",
585 "_NET_WM_WINDOW_TYPE",
587 "_NET_WM_ALLOWED_ACTIONS",
589 "_NET_WM_STRUT_PARTIAL",
590 "_NET_WM_ICON_GEOMETRY",
593 "_NET_WM_HANDLED_ICONS",
595 "_NET_FRAME_EXTENTS",
597 "_NET_WM_SYNC_REQUEST",
598 "_NET_SYSTEM_TRAY_OPCODE",
599 "_NET_SYSTEM_TRAY_ORIENTATION",
600 "_NET_WM_STATE_MAXIMIZED_HORZ",
601 "_NET_WM_STATE_MAXIMIZED_VERT",
602 "_NET_WM_STATE_HIDDEN",
606 "_NET_WM_STATE_SKIP_TASKBAR",
607 "_NET_WM_STATE_ABOVE",
608 "_NET_WM_STATE_MODAL",
609 "_NET_WM_CONTEXT_HELP",
610 "_NET_WM_WINDOW_OPACITY",
611 "_NET_WM_WINDOW_TYPE_DESKTOP",
612 "_NET_WM_WINDOW_TYPE_DOCK",
613 "_NET_WM_WINDOW_TYPE_TOOLBAR",
614 "_NET_WM_WINDOW_TYPE_MENU",
615 "_NET_WM_WINDOW_TYPE_UTILITY",
616 "_NET_WM_WINDOW_TYPE_DIALOG",
617 "_NET_WM_WINDOW_TYPE_SPLASH",
618 "_NET_WM_WINDOW_TYPE_NORMAL",
625 "_SWF_PostMessageAtom",
628 IntPtr[] atoms = new IntPtr [atom_names.Length];;
630 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
633 WM_PROTOCOLS = atoms [off++];
634 WM_DELETE_WINDOW = atoms [off++];
635 WM_TAKE_FOCUS = atoms [off++];
636 _NET_SUPPORTED = atoms [off++];
637 _NET_CLIENT_LIST = atoms [off++];
638 _NET_NUMBER_OF_DESKTOPS = atoms [off++];
639 _NET_DESKTOP_GEOMETRY = atoms [off++];
640 _NET_DESKTOP_VIEWPORT = atoms [off++];
641 _NET_CURRENT_DESKTOP = atoms [off++];
642 _NET_DESKTOP_NAMES = atoms [off++];
643 _NET_ACTIVE_WINDOW = atoms [off++];
644 _NET_WORKAREA = atoms [off++];
645 _NET_SUPPORTING_WM_CHECK = atoms [off++];
646 _NET_VIRTUAL_ROOTS = atoms [off++];
647 _NET_DESKTOP_LAYOUT = atoms [off++];
648 _NET_SHOWING_DESKTOP = atoms [off++];
649 _NET_CLOSE_WINDOW = atoms [off++];
650 _NET_MOVERESIZE_WINDOW = atoms [off++];
651 _NET_WM_MOVERESIZE = atoms [off++];
652 _NET_RESTACK_WINDOW = atoms [off++];
653 _NET_REQUEST_FRAME_EXTENTS = atoms [off++];
654 _NET_WM_NAME = atoms [off++];
655 _NET_WM_VISIBLE_NAME = atoms [off++];
656 _NET_WM_ICON_NAME = atoms [off++];
657 _NET_WM_VISIBLE_ICON_NAME = atoms [off++];
658 _NET_WM_DESKTOP = atoms [off++];
659 _NET_WM_WINDOW_TYPE = atoms [off++];
660 _NET_WM_STATE = atoms [off++];
661 _NET_WM_ALLOWED_ACTIONS = atoms [off++];
662 _NET_WM_STRUT = atoms [off++];
663 _NET_WM_STRUT_PARTIAL = atoms [off++];
664 _NET_WM_ICON_GEOMETRY = atoms [off++];
665 _NET_WM_ICON = atoms [off++];
666 _NET_WM_PID = atoms [off++];
667 _NET_WM_HANDLED_ICONS = atoms [off++];
668 _NET_WM_USER_TIME = atoms [off++];
669 _NET_FRAME_EXTENTS = atoms [off++];
670 _NET_WM_PING = atoms [off++];
671 _NET_WM_SYNC_REQUEST = atoms [off++];
672 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
673 _NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
674 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
675 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
676 _NET_WM_STATE_HIDDEN = atoms [off++];
677 _XEMBED = atoms [off++];
678 _XEMBED_INFO = atoms [off++];
679 _MOTIF_WM_HINTS = atoms [off++];
680 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
681 _NET_WM_STATE_ABOVE = atoms [off++];
682 _NET_WM_STATE_MODAL = atoms [off++];
683 _NET_WM_CONTEXT_HELP = atoms [off++];
684 _NET_WM_WINDOW_OPACITY = atoms [off++];
685 _NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
686 _NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
687 _NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
688 _NET_WM_WINDOW_TYPE_MENU = atoms [off++];
689 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
690 _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
691 _NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
692 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
693 CLIPBOARD = atoms [off++];
694 PRIMARY = atoms [off++];
695 OEMTEXT = atoms [off++];
696 UNICODETEXT = atoms [off++];
697 TARGETS = atoms [off++];
698 AsyncAtom = atoms [off++];
699 PostAtom = atoms [off++];
700 HoverState.Atom = atoms [off++];
702 DIB = (IntPtr)Atom.XA_PIXMAP;
703 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
706 private void GetSystrayManagerWindow() {
707 XGrabServer(DisplayHandle);
708 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
709 XUngrabServer(DisplayHandle);
710 XFlush(DisplayHandle);
713 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
717 xev.ClientMessageEvent.type = XEventName.ClientMessage;
718 xev.ClientMessageEvent.send_event = true;
719 xev.ClientMessageEvent.window = window;
720 xev.ClientMessageEvent.message_type = message_type;
721 xev.ClientMessageEvent.format = 32;
722 xev.ClientMessageEvent.ptr1 = l0;
723 xev.ClientMessageEvent.ptr2 = l1;
724 xev.ClientMessageEvent.ptr3 = l2;
725 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
728 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
732 xev.ClientMessageEvent.type = XEventName.ClientMessage;
733 xev.ClientMessageEvent.send_event = true;
734 xev.ClientMessageEvent.window = window;
735 xev.ClientMessageEvent.message_type = message_type;
736 xev.ClientMessageEvent.format = 32;
737 xev.ClientMessageEvent.ptr1 = l0;
738 xev.ClientMessageEvent.ptr2 = l1;
739 xev.ClientMessageEvent.ptr3 = l2;
740 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
743 bool StyleSet (int s, WindowStyles ws)
745 return (s & (int)ws) == (int)ws;
748 bool ExStyleSet (int ex, WindowExStyles exws)
750 return (ex & (int)exws) == (int)exws;
753 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
755 // Only MDI windows get caption_heights
757 tool_caption_height = 19;
759 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
760 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
761 border_style = FormBorderStyle.Fixed3D;
762 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
763 border_style = FormBorderStyle.None;
765 border_style = FormBorderStyle.FixedSingle;
767 title_style = TitleStyle.None;
769 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
772 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
773 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
774 title_style = TitleStyle.Tool;
776 title_style = TitleStyle.Normal;
780 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
781 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
782 border_style = (FormBorderStyle) 0xFFFF;
784 border_style = FormBorderStyle.None;
789 title_style = TitleStyle.None;
790 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
791 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
792 title_style = TitleStyle.Tool;
794 title_style = TitleStyle.Normal;
798 border_style = FormBorderStyle.None;
800 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
801 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
802 border_style = FormBorderStyle.SizableToolWindow;
804 border_style = FormBorderStyle.Sizable;
807 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
808 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
809 border_style = FormBorderStyle.Fixed3D;
810 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
811 border_style = FormBorderStyle.FixedDialog;
812 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
813 border_style = FormBorderStyle.FixedToolWindow;
814 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
815 border_style = FormBorderStyle.FixedSingle;
818 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
819 border_style = FormBorderStyle.FixedSingle;
826 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
827 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
830 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
831 MotifWmHints mwmHints;
832 MotifFunctions functions;
833 MotifDecorations decorations;
836 Rectangle client_rect;
838 // Child windows don't need WM window styles
839 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
844 mwmHints = new MotifWmHints();
848 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
849 mwmHints.functions = (IntPtr)0;
850 mwmHints.decorations = (IntPtr)0;
852 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
853 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
854 /* tool windows get no window manager
855 decorations, and neither do windows
856 which lack CAPTION/BORDER/DLGFRAME
860 /* just because the window doesn't get any decorations doesn't
861 mean we should disable the functions. for instance, without
862 MotifFunctions.Maximize, changing the windowstate to Maximized
863 is ignored by metacity. */
864 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
867 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
868 functions |= MotifFunctions.Move;
869 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
872 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
873 functions |= MotifFunctions.Move | MotifFunctions.Resize;
874 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
877 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
878 functions |= MotifFunctions.Minimize;
879 decorations |= MotifDecorations.Minimize;
882 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
883 functions |= MotifFunctions.Maximize;
884 decorations |= MotifDecorations.Maximize;
887 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
888 functions |= MotifFunctions.Resize;
889 decorations |= MotifDecorations.ResizeH;
892 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
893 decorations |= MotifDecorations.Border;
896 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
897 decorations |= MotifDecorations.Border;
900 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
901 decorations |= MotifDecorations.Border;
904 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
905 functions |= MotifFunctions.Close;
908 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
909 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
910 if (cp.Caption == "") {
911 functions &= ~MotifFunctions.Move;
912 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
917 if ((functions & MotifFunctions.Resize) == 0) {
918 hwnd.fixed_size = true;
919 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));
921 hwnd.fixed_size = false;
924 mwmHints.functions = (IntPtr)functions;
925 mwmHints.decorations = (IntPtr)decorations;
927 FormWindowState current_state = GetWindowState (hwnd.Handle);
928 if (current_state == (FormWindowState)(-1))
929 current_state = FormWindowState.Normal;
931 client_rect = hwnd.ClientRect;
935 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
936 // and get those windows in front of their parents
937 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
938 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
939 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
940 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
942 Form f = Control.FromHandle(hwnd.Handle) as Form;
943 if (f != null && !hwnd.reparented) {
944 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
945 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
946 if (owner_hwnd != null)
947 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
948 owner_hwnd.whole_window);
953 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
954 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
955 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
956 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
958 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
959 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
960 /* this line keeps the window from showing up in gnome's taskbar */
961 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
963 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
964 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
966 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
969 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
970 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
972 /* we need to add these atoms in the
973 * event we're maximized, since we're
974 * replacing the existing
975 * _NET_WM_STATE here. If we don't
976 * add them, future calls to
977 * GetWindowState will return Normal
978 * for a window which is maximized. */
979 if (current_state == FormWindowState.Maximized) {
980 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
981 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
983 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
986 IntPtr[] atom_ptrs = new IntPtr[2];
987 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
988 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
989 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
992 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
996 private void SetIcon(Hwnd hwnd, Icon icon) {
1002 bitmap = icon.ToBitmap();
1004 size = bitmap.Width * bitmap.Height + 2;
1005 data = new IntPtr[size];
1007 data[index++] = (IntPtr)bitmap.Width;
1008 data[index++] = (IntPtr)bitmap.Height;
1010 for (int y = 0; y < bitmap.Height; y++) {
1011 for (int x = 0; x < bitmap.Width; x++) {
1012 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
1016 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
1019 private IntPtr ImageToPixmap(Image image) {
1023 private void WakeupMain () {
1024 wake.Send (new byte [] { 0xFF });
1027 private XEventQueue ThreadQueue(Thread thread) {
1030 queue = (XEventQueue)MessageQueues[thread];
1031 if (queue == null) {
1032 queue = new XEventQueue(thread);
1033 MessageQueues[thread] = queue;
1039 private void TranslatePropertyToClipboard(IntPtr property) {
1044 IntPtr prop = IntPtr.Zero;
1046 Clipboard.Item = null;
1048 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);
1050 if ((long)nitems > 0) {
1051 if (property == (IntPtr)Atom.XA_STRING) {
1052 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1053 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1054 // FIXME - convert bitmap to image
1055 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1056 // FIXME - convert pixmap to image
1057 } else if (property == OEMTEXT) {
1058 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1059 } else if (property == UNICODETEXT) {
1060 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1067 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1069 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1073 // Keep the invalid area as small as needed
1074 if ((x + width) > hwnd.width) {
1075 width = hwnd.width - x;
1078 if ((y + height) > hwnd.height) {
1079 height = hwnd.height - y;
1083 hwnd.AddInvalidArea(x, y, width, height);
1084 if (!hwnd.expose_pending) {
1085 if (!hwnd.nc_expose_pending) {
1086 hwnd.Queue.Paint.Enqueue(hwnd);
1088 hwnd.expose_pending = true;
1091 hwnd.AddNcInvalidArea (x, y, width, height);
1093 if (!hwnd.nc_expose_pending) {
1094 if (!hwnd.expose_pending) {
1095 hwnd.Queue.Paint.Enqueue(hwnd);
1097 hwnd.nc_expose_pending = true;
1102 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
1108 hwnd = Hwnd.ObjectFromHandle(handle);
1111 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1118 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
1139 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
1140 if (win == window) {
1146 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
1150 if (children != IntPtr.Zero) {
1154 } while (win != root);
1159 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
1162 private void FrameExtents(IntPtr window, out int left, out int top) {
1167 IntPtr prop = IntPtr.Zero;
1169 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);
1170 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1171 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1172 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1173 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1174 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1180 if (prop != IntPtr.Zero) {
1186 private void AddConfigureNotify (XEvent xevent) {
1189 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1196 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1197 if (!hwnd.reparented) {
1198 hwnd.x = xevent.ConfigureEvent.x;
1199 hwnd.y = xevent.ConfigureEvent.y;
1201 // This sucks ass, part 1
1202 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1203 // no standard way of getting our adjustment.
1204 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1205 // Several other WMs do their decorations different yet again and we fail to deal
1206 // with that, since I couldn't find any frigging commonality between them.
1207 // The only sane WM seems to be KDE
1209 if (!xevent.ConfigureEvent.send_event) {
1212 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1214 // This is a synthetic event, coordinates are in root space
1215 hwnd.x = xevent.ConfigureEvent.x;
1216 hwnd.y = xevent.ConfigureEvent.y;
1217 if (hwnd.whacky_wm) {
1221 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1222 hwnd.x -= frame_left;
1223 hwnd.y -= frame_top;
1228 // XXX this sucks. this isn't thread safe
1229 hwnd.width = xevent.ConfigureEvent.width;
1230 hwnd.height = xevent.ConfigureEvent.height;
1231 hwnd.ClientRect = Rectangle.Empty;
1233 lock (hwnd.configure_lock) {
1234 if (!hwnd.configure_pending) {
1235 hwnd.Queue.EnqueueLocked (xevent);
1236 hwnd.configure_pending = true;
1240 // We drop configure events for Client windows
1243 private void ShowCaret() {
1244 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1250 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1254 private void HideCaret() {
1255 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1261 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1265 private int NextTimeout (ArrayList timers, DateTime now) {
1266 int timeout = Int32.MaxValue;
1268 foreach (Timer timer in timers) {
1269 int next = (int) (timer.Expires - now).TotalMilliseconds;
1271 return 0; // Have a timer that has already expired
1274 if (next < timeout) {
1278 if (timeout < Timer.Minimum) {
1279 timeout = Timer.Minimum;
1287 private void CheckTimers (ArrayList timers, DateTime now) {
1290 count = timers.Count;
1295 for (int i = 0; i < timers.Count; i++) {
1298 timer = (Timer) timers [i];
1300 if (timer.Enabled && timer.Expires <= now) {
1307 private void MapWindow(Hwnd hwnd, WindowType windows) {
1309 if ((windows & WindowType.Whole) != 0) {
1310 XMapWindow(DisplayHandle, hwnd.whole_window);
1312 if ((windows & WindowType.Client) != 0) {
1313 XMapWindow(DisplayHandle, hwnd.client_window);
1317 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1318 hwnd.mapped = false;
1319 if ((windows & WindowType.Whole) != 0) {
1320 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1322 if ((windows & WindowType.Client) != 0) {
1323 XUnmapWindow(DisplayHandle, hwnd.client_window);
1327 private void UpdateMessageQueue (XEventQueue queue) {
1332 now = DateTime.UtcNow;
1335 pending = XPending (DisplayHandle);
1339 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1340 Idle (this, EventArgs.Empty);
1344 pending = XPending (DisplayHandle);
1351 if (queue != null) {
1352 if (queue.Paint.Count > 0)
1355 timeout = NextTimeout (queue.timer_list, now);
1360 int length = pollfds.Length - 1;
1361 lock (wake_waiting_lock) {
1362 if (wake_waiting == false) {
1364 wake_waiting = true;
1368 Syscall.poll (pollfds, (uint)length, timeout);
1369 // Clean out buffer, so we're not busy-looping on the same data
1370 if (pollfds[1].revents != 0) {
1371 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1372 wake_waiting = false;
1376 pending = XPending (DisplayHandle);
1382 CheckTimers (queue.timer_list, now);
1385 XEvent xevent = new XEvent ();
1388 if (XPending (DisplayHandle) == 0)
1391 XNextEvent (DisplayHandle, ref xevent);
1393 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1394 if (XFilterEvent(ref xevent, FosterParent)) {
1400 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1404 switch (xevent.type) {
1405 case XEventName.Expose:
1406 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1409 case XEventName.SelectionClear: {
1410 // Should we do something?
1414 case XEventName.SelectionRequest: {
1415 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1419 sel_event = new XEvent();
1420 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1421 sel_event.SelectionEvent.send_event = true;
1422 sel_event.SelectionEvent.display = DisplayHandle;
1423 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1424 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1425 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1426 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1427 sel_event.SelectionEvent.property = IntPtr.Zero;
1429 // Seems that some apps support asking for supported types
1430 if (xevent.SelectionEvent.target == TARGETS) {
1437 if (Clipboard.Item is String) {
1438 atoms[atom_count++] = (int)Atom.XA_STRING;
1439 atoms[atom_count++] = (int)OEMTEXT;
1440 atoms[atom_count++] = (int)UNICODETEXT;
1441 } else if (Clipboard.Item is Image) {
1442 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1443 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1445 // FIXME - handle other types
1448 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1449 } else if (Clipboard.Item is string) {
1455 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1458 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1459 buffer = Marshal.AllocHGlobal(bytes.Length);
1460 buflen = bytes.Length;
1462 for (int i = 0; i < buflen; i++) {
1463 Marshal.WriteByte(buffer, i, bytes[i]);
1465 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1466 // FIXME - this should encode into ISO2022
1467 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1468 while (Marshal.ReadByte(buffer, buflen) != 0) {
1471 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1472 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1473 while (Marshal.ReadByte(buffer, buflen) != 0) {
1477 buffer = IntPtr.Zero;
1480 if (buffer != IntPtr.Zero) {
1481 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1482 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1483 Marshal.FreeHGlobal(buffer);
1485 } else if (Clipboard.Item is Image) {
1486 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1487 // FIXME - convert image and store as property
1488 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1489 // FIXME - convert image and store as property
1493 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1497 case XEventName.SelectionNotify: {
1498 if (Clipboard.Enumerating) {
1499 Clipboard.Enumerating = false;
1500 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1501 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1502 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1503 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1504 #if DriverDebugExtra
1505 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1509 } else if (Clipboard.Retrieving) {
1510 Clipboard.Retrieving = false;
1511 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1512 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1514 Clipboard.Item = null;
1517 Dnd.HandleSelectionNotifyEvent (ref xevent);
1522 case XEventName.MapNotify: {
1523 if (hwnd.client_window == xevent.MapEvent.window) {
1529 case XEventName.UnmapNotify: {
1530 if (hwnd.client_window == xevent.MapEvent.window) {
1531 hwnd.mapped = false;
1536 case XEventName.KeyRelease:
1537 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1538 XEvent nextevent = new XEvent ();
1540 XPeekEvent (DisplayHandle, ref nextevent);
1542 if (nextevent.type == XEventName.KeyPress &&
1543 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1544 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1548 goto case XEventName.KeyPress;
1550 case XEventName.MotionNotify: {
1553 /* we can't do motion compression across threads, so just punt if we don't match up */
1554 if (Thread.CurrentThread == hwnd.Queue.Thread && 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.EnqueueLocked (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;
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 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1760 #endregion // Private Methods
1763 private void MouseHover(object sender, EventArgs e) {
1767 HoverState.Timer.Enabled = false;
1769 if (HoverState.Window != IntPtr.Zero) {
1770 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1772 xevent = new XEvent ();
1774 xevent.type = XEventName.ClientMessage;
1775 xevent.ClientMessageEvent.display = DisplayHandle;
1776 xevent.ClientMessageEvent.window = HoverState.Window;
1777 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1778 xevent.ClientMessageEvent.format = 32;
1779 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1781 hwnd.Queue.EnqueueLocked (xevent);
1788 private void CaretCallback(object sender, EventArgs e) {
1792 Caret.On = !Caret.On;
1794 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1796 #endregion // Callbacks
1798 #region Public Properties
1800 internal override int Caption {
1806 internal override Size CursorSize {
1811 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1812 return new Size(x, y);
1814 return new Size(16, 16);
1819 internal override bool DragFullWindows {
1825 internal override Size DragSize {
1827 return new Size(4, 4);
1831 internal override Size FrameBorderSize {
1833 throw new NotImplementedException();
1837 internal override Size IconSize {
1843 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1847 current = (long)list;
1850 size = new XIconSize();
1852 for (int i = 0; i < count; i++) {
1853 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1854 current += Marshal.SizeOf(size);
1856 // Look for our preferred size
1857 if (size.min_width == 32) {
1859 return new Size(32, 32);
1862 if (size.max_width == 32) {
1864 return new Size(32, 32);
1867 if (size.min_width < 32 && size.max_width > 32) {
1870 // check if we can fit one
1872 while (x < size.max_width) {
1873 x += size.width_inc;
1876 return new Size(32, 32);
1881 if (largest < size.max_width) {
1882 largest = size.max_width;
1886 // We didn't find a match or we wouldn't be here
1887 return new Size(largest, largest);
1890 return new Size(32, 32);
1895 internal override int KeyboardSpeed {
1898 // A lot harder: need to do:
1899 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1900 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1901 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1903 // And from that we can tell the repetition rate
1905 // Notice, the values must map to:
1906 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1912 internal override int KeyboardDelay {
1915 // Return values must range from 0 to 4, 0 meaning 250ms,
1916 // and 4 meaning 1000 ms.
1918 return 1; // ie, 500 ms
1922 internal override Size MaxWindowTrackSize {
1924 return new Size (WorkingArea.Width, WorkingArea.Height);
1928 internal override Size MinimizedWindowSize {
1930 return new Size(1, 1);
1934 internal override Size MinimizedWindowSpacingSize {
1936 return new Size(1, 1);
1940 internal override Size MinimumWindowSize {
1942 return new Size(1, 1);
1946 internal override Size MinWindowTrackSize {
1948 return new Size(1, 1);
1952 internal override Keys ModifierKeys {
1954 return Keyboard.ModifierKeys;
1958 internal override Size SmallIconSize {
1964 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1968 current = (long)list;
1971 size = new XIconSize();
1973 for (int i = 0; i < count; i++) {
1974 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1975 current += Marshal.SizeOf(size);
1977 // Look for our preferred size
1978 if (size.min_width == 16) {
1980 return new Size(16, 16);
1983 if (size.max_width == 16) {
1985 return new Size(16, 16);
1988 if (size.min_width < 16 && size.max_width > 16) {
1991 // check if we can fit one
1993 while (x < size.max_width) {
1994 x += size.width_inc;
1997 return new Size(16, 16);
2002 if (smallest == 0 || smallest > size.min_width) {
2003 smallest = size.min_width;
2007 // We didn't find a match or we wouldn't be here
2008 return new Size(smallest, smallest);
2011 return new Size(16, 16);
2016 internal override int MouseButtonCount {
2022 internal override bool MouseButtonsSwapped {
2024 return false; // FIXME - how to detect?
2028 internal override Size MouseHoverSize {
2030 return new Size (1, 1);
2034 internal override int MouseHoverTime {
2036 return HoverState.Interval;
2042 internal override bool MouseWheelPresent {
2044 return true; // FIXME - how to detect?
2048 internal override Rectangle VirtualScreen {
2054 internal override Rectangle WorkingArea {
2060 IntPtr prop = IntPtr.Zero;
2063 int current_desktop;
2067 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);
2068 if ((long)nitems < 1) {
2072 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2075 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);
2076 if ((long)nitems < 4 * current_desktop) {
2080 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2081 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2082 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2083 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2086 return new Rectangle(x, y, width, height);
2089 XWindowAttributes attributes=new XWindowAttributes();
2092 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2095 return new Rectangle(0, 0, attributes.width, attributes.height);
2099 internal override bool ThemesEnabled {
2101 return XplatUIX11.themes_enabled;
2106 #endregion // Public properties
2108 #region Public Static Methods
2109 internal override IntPtr InitializeDriver() {
2111 if (DisplayHandle==IntPtr.Zero) {
2112 SetDisplay(XOpenDisplay(IntPtr.Zero));
2118 internal override void ShutdownDriver(IntPtr token) {
2120 if (DisplayHandle!=IntPtr.Zero) {
2121 XCloseDisplay(DisplayHandle);
2122 DisplayHandle=IntPtr.Zero;
2127 internal override void EnableThemes() {
2128 themes_enabled = true;
2132 internal override void Activate(IntPtr handle) {
2135 hwnd = Hwnd.ObjectFromHandle(handle);
2139 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2140 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2143 // XRaiseWindow(DisplayHandle, handle);
2149 internal override void AudibleAlert() {
2150 XBell(DisplayHandle, 0);
2155 internal override void CaretVisible(IntPtr handle, bool visible) {
2156 if (Caret.Hwnd == handle) {
2158 if (!Caret.Visible) {
2159 Caret.Visible = true;
2161 Caret.Timer.Start();
2164 Caret.Visible = false;
2171 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2172 FormBorderStyle border_style;
2173 TitleStyle title_style;
2175 int tool_caption_height;
2177 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2178 out caption_height, out tool_caption_height);
2180 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2181 caption_height, tool_caption_height,
2186 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2192 hwnd = Hwnd.ObjectFromHandle(handle);
2195 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2202 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2203 DataFormats.Format f;
2206 f = DataFormats.Format.List;
2208 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2212 Clipboard.Formats = new ArrayList();
2215 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2217 Clipboard.Enumerating = true;
2218 while (Clipboard.Enumerating) {
2219 UpdateMessageQueue(null);
2224 result = new int[Clipboard.Formats.Count];
2226 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2227 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2230 Clipboard.Formats = null;
2234 internal override void ClipboardClose(IntPtr handle) {
2235 if (handle != ClipMagic) {
2236 throw new ArgumentException("handle is not a valid clipboard handle");
2241 internal override int ClipboardGetID(IntPtr handle, string format) {
2242 if (handle != ClipMagic) {
2243 throw new ArgumentException("handle is not a valid clipboard handle");
2246 if (format == "Text" ) return (int)Atom.XA_STRING;
2247 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2248 //else if (format == "MetaFilePict" ) return 3;
2249 //else if (format == "SymbolicLink" ) return 4;
2250 //else if (format == "DataInterchangeFormat" ) return 5;
2251 //else if (format == "Tiff" ) return 6;
2252 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2253 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2254 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2255 //else if (format == "PenData" ) return 10;
2256 //else if (format == "RiffAudio" ) return 11;
2257 //else if (format == "WaveAudio" ) return 12;
2258 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2259 //else if (format == "EnhancedMetafile" ) return 14;
2260 //else if (format == "FileDrop" ) return 15;
2261 //else if (format == "Locale" ) return 16;
2263 return XInternAtom(DisplayHandle, format, false).ToInt32();
2266 internal override IntPtr ClipboardOpen(bool primary_selection) {
2267 if (!primary_selection)
2268 ClipMagic = CLIPBOARD;
2270 ClipMagic = PRIMARY;
2274 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2275 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2277 Clipboard.Retrieving = true;
2278 while (Clipboard.Retrieving) {
2279 UpdateMessageQueue(null);
2282 return Clipboard.Item;
2285 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2286 Clipboard.Item = obj;
2287 Clipboard.Type = type;
2288 Clipboard.Converter = converter;
2291 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2293 // Clearing the selection
2294 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2298 internal override void CreateCaret(IntPtr handle, int width, int height) {
2299 XGCValues gc_values;
2302 hwnd = Hwnd.ObjectFromHandle(handle);
2304 if (Caret.Hwnd != IntPtr.Zero) {
2305 DestroyCaret(Caret.Hwnd);
2308 Caret.Hwnd = handle;
2309 Caret.Window = hwnd.client_window;
2310 Caret.Width = width;
2311 Caret.Height = height;
2312 Caret.Visible = false;
2315 gc_values = new XGCValues();
2316 gc_values.line_width = width;
2318 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2319 if (Caret.gc == IntPtr.Zero) {
2320 Caret.Hwnd = IntPtr.Zero;
2324 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2327 internal override IntPtr CreateWindow(CreateParams cp) {
2328 XSetWindowAttributes Attributes;
2334 IntPtr ParentHandle;
2336 IntPtr ClientWindow;
2337 Rectangle ClientRect;
2338 SetWindowValuemask ValueMask;
2343 Attributes = new XSetWindowAttributes();
2349 if (Width<1) Width=1;
2350 if (Height<1) Height=1;
2352 if (cp.Parent != IntPtr.Zero) {
2353 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2355 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2356 // We need to use our foster parent window until this poor child gets it's parent assigned
2357 ParentHandle=FosterParent;
2358 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2359 ParentHandle=RootWindow;
2361 // Default position on screen, if window manager doesn't place us somewhere else
2364 ParentHandle=RootWindow;
2368 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2370 Attributes.bit_gravity = Gravity.NorthWestGravity;
2371 Attributes.win_gravity = Gravity.NorthWestGravity;
2373 // Save what's under the toolwindow
2374 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2375 Attributes.save_under = true;
2376 ValueMask |= SetWindowValuemask.SaveUnder;
2380 // If we're a popup without caption we override the WM
2381 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2382 Attributes.override_redirect = true;
2383 ValueMask |= SetWindowValuemask.OverrideRedirect;
2389 hwnd.height = Height;
2390 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2392 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2393 hwnd.enabled = false;
2396 ClientRect = hwnd.ClientRect;
2397 ClientWindow = IntPtr.Zero;
2400 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2401 if (WholeWindow != IntPtr.Zero) {
2402 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2404 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2405 ValueMask = SetWindowValuemask.ColorMap;
2406 Attributes.colormap = CustomColormap;
2408 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);
2412 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2413 throw new Exception("Could not create X11 windows");
2416 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2417 hwnd.WholeWindow = WholeWindow;
2418 hwnd.ClientWindow = ClientWindow;
2420 #if DriverDebug || DriverDebugCreate
2421 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);
2424 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2425 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2428 hints = new XSizeHints();
2431 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2432 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2437 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2438 if (hwnd.whole_window != hwnd.client_window)
2439 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2441 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2442 MapWindow(hwnd, WindowType.Both);
2443 hwnd.visible = true;
2447 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2449 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2450 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2452 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2455 SetWMStyles(hwnd, cp);
2457 // set the group leader
2458 XWMHints wm_hints = new XWMHints ();
2460 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2461 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2462 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2464 if (ParentHandle != RootWindow) {
2465 wm_hints.window_group = hwnd.whole_window;
2467 wm_hints.window_group = ParentHandle;
2471 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2474 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2475 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2476 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2477 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2480 // for now make all windows dnd enabled
2481 Dnd.SetAllowDrop (hwnd, true);
2483 // Set caption/window title
2484 Text(hwnd.Handle, cp.Caption);
2489 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2490 CreateParams create_params = new CreateParams();
2492 create_params.Caption = "";
2493 create_params.X = X;
2494 create_params.Y = Y;
2495 create_params.Width = Width;
2496 create_params.Height = Height;
2498 create_params.ClassName=XplatUI.DefaultClassName;
2499 create_params.ClassStyle = 0;
2500 create_params.ExStyle=0;
2501 create_params.Parent=IntPtr.Zero;
2502 create_params.Param=0;
2504 return CreateWindow(create_params);
2507 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2509 Bitmap cursor_bitmap;
2517 IntPtr cursor_pixmap;
2524 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2528 // Win32 only allows creation cursors of a certain size
2529 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2530 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2531 cursor_mask = new Bitmap(mask, new Size(width, height));
2533 cursor_bitmap = bitmap;
2537 width = cursor_bitmap.Width;
2538 height = cursor_bitmap.Height;
2540 cursor_bits = new Byte[(width / 8) * height];
2541 mask_bits = new Byte[(width / 8) * height];
2543 for (int y = 0; y < height; y++) {
2544 for (int x = 0; x < width; x++) {
2545 c_pixel = cursor_bitmap.GetPixel(x, y);
2546 m_pixel = cursor_mask.GetPixel(x, y);
2548 and = c_pixel == cursor_pixel;
2549 xor = m_pixel == mask_pixel;
2553 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2554 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2555 } else if (and && !xor) {
2557 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2558 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2560 } else if (and && !xor) {
2562 } else if (and && xor) {
2565 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2566 // we want both to be 0 so nothing to be done
2567 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2568 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2574 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2575 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2579 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2580 fg.red = (ushort)65535;
2581 fg.green = (ushort)65535;
2582 fg.blue = (ushort)65535;
2584 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2586 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2588 XFreePixmap(DisplayHandle, cursor_pixmap);
2589 XFreePixmap(DisplayHandle, mask_pixmap);
2594 internal override IntPtr DefineStdCursor(StdCursor id) {
2595 CursorFontShape shape;
2598 // FIXME - define missing shapes
2601 case StdCursor.AppStarting: {
2602 shape = CursorFontShape.XC_watch;
2606 case StdCursor.Arrow: {
2607 shape = CursorFontShape.XC_top_left_arrow;
2611 case StdCursor.Cross: {
2612 shape = CursorFontShape.XC_crosshair;
2616 case StdCursor.Default: {
2617 shape = CursorFontShape.XC_top_left_arrow;
2621 case StdCursor.Hand: {
2622 shape = CursorFontShape.XC_hand1;
2626 case StdCursor.Help: {
2627 shape = CursorFontShape.XC_question_arrow;
2631 case StdCursor.HSplit: {
2632 shape = CursorFontShape.XC_sb_v_double_arrow;
2636 case StdCursor.IBeam: {
2637 shape = CursorFontShape.XC_xterm;
2641 case StdCursor.No: {
2642 shape = CursorFontShape.XC_circle;
2646 case StdCursor.NoMove2D: {
2647 shape = CursorFontShape.XC_fleur;
2651 case StdCursor.NoMoveHoriz: {
2652 shape = CursorFontShape.XC_fleur;
2656 case StdCursor.NoMoveVert: {
2657 shape = CursorFontShape.XC_fleur;
2661 case StdCursor.PanEast: {
2662 shape = CursorFontShape.XC_fleur;
2666 case StdCursor.PanNE: {
2667 shape = CursorFontShape.XC_fleur;
2671 case StdCursor.PanNorth: {
2672 shape = CursorFontShape.XC_fleur;
2676 case StdCursor.PanNW: {
2677 shape = CursorFontShape.XC_fleur;
2681 case StdCursor.PanSE: {
2682 shape = CursorFontShape.XC_fleur;
2686 case StdCursor.PanSouth: {
2687 shape = CursorFontShape.XC_fleur;
2691 case StdCursor.PanSW: {
2692 shape = CursorFontShape.XC_fleur;
2696 case StdCursor.PanWest: {
2697 shape = CursorFontShape.XC_sizing;
2701 case StdCursor.SizeAll: {
2702 shape = CursorFontShape.XC_fleur;
2706 case StdCursor.SizeNESW: {
2707 shape = CursorFontShape.XC_top_right_corner;
2711 case StdCursor.SizeNS: {
2712 shape = CursorFontShape.XC_sb_v_double_arrow;
2716 case StdCursor.SizeNWSE: {
2717 shape = CursorFontShape.XC_top_left_corner;
2721 case StdCursor.SizeWE: {
2722 shape = CursorFontShape.XC_sb_h_double_arrow;
2726 case StdCursor.UpArrow: {
2727 shape = CursorFontShape.XC_center_ptr;
2731 case StdCursor.VSplit: {
2732 shape = CursorFontShape.XC_sb_h_double_arrow;
2736 case StdCursor.WaitCursor: {
2737 shape = CursorFontShape.XC_watch;
2747 cursor = XCreateFontCursor(DisplayHandle, shape);
2752 internal override IntPtr DefWndProc(ref Message msg) {
2753 switch ((Msg)msg.Msg) {
2754 case Msg.WM_PAINT: {
2757 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2759 hwnd.expose_pending = false;
2765 case Msg.WM_NCPAINT: {
2768 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2770 hwnd.nc_expose_pending = false;
2776 case Msg.WM_CONTEXTMENU: {
2779 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2781 if ((hwnd != null) && (hwnd.parent != null)) {
2782 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2787 case Msg.WM_MOUSEWHEEL: {
2790 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2792 if ((hwnd != null) && (hwnd.parent != null)) {
2793 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2794 if (msg.Result == IntPtr.Zero) {
2801 case Msg.WM_SETCURSOR: {
2804 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2806 break; // not sure how this happens, but it does
2808 // Pass to parent window first
2809 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2811 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2814 if (msg.Result == IntPtr.Zero) {
2817 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2818 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2819 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2820 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2821 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2822 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2825 handle = Cursors.Default.handle;
2828 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2829 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2830 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2831 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2832 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2833 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2836 case HitTest.HTGROWBOX:
2837 case HitTest.HTSIZE:
2838 case HitTest.HTZOOM:
2839 case HitTest.HTVSCROLL:
2840 case HitTest.HTSYSMENU:
2841 case HitTest.HTREDUCE:
2842 case HitTest.HTNOWHERE:
2843 case HitTest.HTMAXBUTTON:
2844 case HitTest.HTMINBUTTON:
2845 case HitTest.HTMENU:
2846 case HitTest.HSCROLL:
2847 case HitTest.HTBOTTOM:
2848 case HitTest.HTCAPTION:
2849 case HitTest.HTCLIENT:
2850 case HitTest.HTCLOSE:
2852 default: handle = Cursors.Default.handle; break;
2854 SetCursor(msg.HWnd, handle);
2862 internal override void DestroyCaret(IntPtr handle) {
2863 if (Caret.Hwnd == handle) {
2864 if (Caret.Visible == true) {
2867 if (Caret.gc != IntPtr.Zero) {
2868 XFreeGC(DisplayHandle, Caret.gc);
2869 Caret.gc = IntPtr.Zero;
2871 Caret.Hwnd = IntPtr.Zero;
2872 Caret.Visible = false;
2877 internal override void DestroyCursor(IntPtr cursor) {
2879 XFreeCursor(DisplayHandle, cursor);
2883 internal override void DestroyWindow(IntPtr handle) {
2886 hwnd = Hwnd.ObjectFromHandle(handle);
2889 #if DriverDebug || DriverDebugDestroy
2890 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2895 #if DriverDebug || DriverDebugDestroy
2896 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2899 CleanupCachedWindows (hwnd);
2901 ArrayList windows = new ArrayList ();
2903 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2906 if (hwnd.whole_window != IntPtr.Zero) {
2907 #if DriverDebug || DriverDebugDestroy
2908 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2910 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2912 else if (hwnd.client_window != IntPtr.Zero) {
2913 #if DriverDebug || DriverDebugDestroy
2914 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2916 XDestroyWindow(DisplayHandle, hwnd.client_window);
2921 foreach (Hwnd h in windows) {
2922 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2926 internal override IntPtr DispatchMessage(ref MSG msg) {
2927 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2930 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2932 XGCValues gc_values;
2935 hwnd = Hwnd.ObjectFromHandle(handle);
2937 gc_values = new XGCValues();
2939 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2940 gc_values.line_width = line_width;
2941 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2943 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2944 //mask = foreground ^ background;
2945 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2946 //XSetBackground(DisplayHandle, gc, background);
2947 //XSetFunction(DisplayHandle, gc, GXxor);
2948 //XSetPlaneMask(DisplayHandle, gc, mask);
2951 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2956 control = Control.FromHandle(handle);
2958 XColor xcolor = new XColor();
2960 xcolor.red = (ushort)(control.ForeColor.R * 257);
2961 xcolor.green = (ushort)(control.ForeColor.G * 257);
2962 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2963 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2964 foreground = (uint)xcolor.pixel.ToInt32();
2966 xcolor.red = (ushort)(control.BackColor.R * 257);
2967 xcolor.green = (ushort)(control.BackColor.G * 257);
2968 xcolor.blue = (ushort)(control.BackColor.B * 257);
2969 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2970 background = (uint)xcolor.pixel.ToInt32();
2972 uint mask = foreground ^ background;
2974 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2975 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2976 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2977 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2979 if ((rect.Width > 0) && (rect.Height > 0)) {
2980 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2982 if (rect.Width > 0) {
2983 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2985 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2988 XFreeGC(DisplayHandle, gc);
2991 internal override void DoEvents() {
2992 MSG msg = new MSG ();
2995 if (OverrideCursorHandle != IntPtr.Zero) {
2996 OverrideCursorHandle = IntPtr.Zero;
2999 queue = ThreadQueue(Thread.CurrentThread);
3001 queue.DispatchIdle = false;
3003 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3004 TranslateMessage (ref msg);
3005 DispatchMessage (ref msg);
3008 queue.DispatchIdle = true;
3011 internal override void EnableWindow(IntPtr handle, bool Enable) {
3014 hwnd = Hwnd.ObjectFromHandle(handle);
3016 hwnd.Enabled = Enable;
3020 internal override void EndLoop(Thread thread) {
3021 // This is where we one day will shut down the loop for the thread
3025 internal override IntPtr GetActive() {
3030 IntPtr prop = IntPtr.Zero;
3031 IntPtr active = IntPtr.Zero;
3033 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);
3034 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3035 active = (IntPtr)Marshal.ReadInt32(prop);
3039 if (active != IntPtr.Zero) {
3042 hwnd = Hwnd.GetObjectFromWindow(active);
3044 active = hwnd.Handle;
3046 active = IntPtr.Zero;
3052 internal override Region GetClipRegion(IntPtr handle) {
3055 hwnd = Hwnd.ObjectFromHandle(handle);
3057 return hwnd.UserClip;
3063 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3070 internal override void GetDisplaySize(out Size size) {
3071 XWindowAttributes attributes=new XWindowAttributes();
3074 // FIXME - use _NET_WM messages instead?
3075 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3078 size = new Size(attributes.width, attributes.height);
3081 internal override SizeF GetAutoScaleSize(Font font) {
3084 string magic_string = "The quick brown fox jumped over the lazy dog.";
3085 double magic_number = 44.549996948242189;
3087 g = Graphics.FromHwnd(FosterParent);
3089 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3090 return new SizeF(width, font.Height);
3093 internal override IntPtr GetParent(IntPtr handle) {
3096 hwnd = Hwnd.ObjectFromHandle(handle);
3097 if (hwnd != null && hwnd.parent != null) {
3098 return hwnd.parent.Handle;
3103 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3113 if (handle != IntPtr.Zero) {
3114 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3116 use_handle = RootWindow;
3120 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3123 if (handle != IntPtr.Zero) {
3132 internal override IntPtr GetFocus() {
3137 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3138 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3141 internal override Point GetMenuOrigin(IntPtr handle) {
3144 hwnd = Hwnd.ObjectFromHandle(handle);
3147 return hwnd.MenuOrigin;
3152 [MonoTODO("Implement filtering")]
3153 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3160 if (((XEventQueue)queue_id).Count > 0) {
3161 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3163 UpdateMessageQueue ((XEventQueue)queue_id);
3165 if (((XEventQueue)queue_id).Count > 0) {
3166 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3167 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3168 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3170 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3171 msg.hwnd= IntPtr.Zero;
3172 msg.message = Msg.WM_ENTERIDLE;
3176 // We reset ourselves so GetMessage can be called again
3177 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3183 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3185 // Handle messages for windows that are already or are about to be destroyed.
3187 // we need a special block for this because unless we remove the hwnd from the paint
3188 // queue it will always stay there (since we don't handle the expose), and we'll
3189 // effectively loop infinitely trying to repaint a non-existant window.
3190 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3191 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3192 hwnd.Queue.Paint.Remove (hwnd);
3193 goto ProcessNextMessage;
3196 // We need to make sure we only allow DestroyNotify events through for zombie
3197 // hwnds, since much of the event handling code makes requests using the hwnd's
3198 // client_window, and that'll result in BadWindow errors if there's some lag
3199 // between the XDestroyWindow call and the DestroyNotify event.
3200 if (hwnd == null || hwnd.zombie) {
3201 #if DriverDebug || DriverDebugDestroy
3202 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3204 goto ProcessNextMessage;
3207 if (hwnd.client_window == xevent.AnyEvent.window) {
3209 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3212 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3215 msg.hwnd = hwnd.Handle;
3218 // If you add a new event to this switch make sure to add it in
3219 // UpdateMessage also unless it is not coming through the X event system.
3221 switch(xevent.type) {
3222 case XEventName.KeyPress: {
3223 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3227 case XEventName.KeyRelease: {
3228 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3232 case XEventName.ButtonPress: {
3233 switch(xevent.ButtonEvent.button) {
3235 MouseState |= MouseButtons.Left;
3237 msg.message = Msg.WM_LBUTTONDOWN;
3239 msg.message = Msg.WM_NCLBUTTONDOWN;
3240 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3242 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3243 msg.wParam=GetMousewParam(0);
3248 MouseState |= MouseButtons.Middle;
3250 msg.message = Msg.WM_MBUTTONDOWN;
3252 msg.message = Msg.WM_NCMBUTTONDOWN;
3253 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3255 msg.wParam=GetMousewParam(0);
3260 MouseState |= MouseButtons.Right;
3262 msg.message = Msg.WM_RBUTTONDOWN;
3264 msg.message = Msg.WM_NCRBUTTONDOWN;
3265 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3267 msg.wParam=GetMousewParam(0);
3272 msg.hwnd = FocusWindow;
3273 msg.message=Msg.WM_MOUSEWHEEL;
3274 msg.wParam=GetMousewParam(120);
3279 msg.hwnd = FocusWindow;
3280 msg.message=Msg.WM_MOUSEWHEEL;
3281 msg.wParam=GetMousewParam(-120);
3287 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3288 MousePosition.X = xevent.ButtonEvent.x;
3289 MousePosition.Y = xevent.ButtonEvent.y;
3291 if (!hwnd.Enabled) {
3294 msg.hwnd = hwnd.EnabledHwnd;
3295 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);
3296 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3299 if (Grab.Hwnd != IntPtr.Zero) {
3300 msg.hwnd = Grab.Hwnd;
3303 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3304 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3305 switch(xevent.ButtonEvent.button) {
3307 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3312 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3317 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3321 ClickPending.Pending = false;
3323 ClickPending.Pending = true;
3324 ClickPending.Hwnd = msg.hwnd;
3325 ClickPending.Message = msg.message;
3326 ClickPending.wParam = msg.wParam;
3327 ClickPending.lParam = msg.lParam;
3328 ClickPending.Time = (long)xevent.ButtonEvent.time;
3334 case XEventName.ButtonRelease: {
3336 Dnd.HandleButtonRelease (ref xevent);
3340 switch(xevent.ButtonEvent.button) {
3343 msg.message = Msg.WM_LBUTTONUP;
3345 msg.message = Msg.WM_NCLBUTTONUP;
3346 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3348 MouseState &= ~MouseButtons.Left;
3349 msg.wParam=GetMousewParam(0);
3355 msg.message = Msg.WM_MBUTTONUP;
3357 msg.message = Msg.WM_NCMBUTTONUP;
3358 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3360 MouseState &= ~MouseButtons.Middle;
3361 msg.wParam=GetMousewParam(0);
3367 msg.message = Msg.WM_RBUTTONUP;
3369 msg.message = Msg.WM_NCRBUTTONUP;
3370 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3372 MouseState &= ~MouseButtons.Right;
3373 msg.wParam=GetMousewParam(0);
3378 goto ProcessNextMessage;
3382 goto ProcessNextMessage;
3386 if (!hwnd.Enabled) {
3389 msg.hwnd = hwnd.EnabledHwnd;
3390 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);
3391 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3394 if (Grab.Hwnd != IntPtr.Zero) {
3395 msg.hwnd = Grab.Hwnd;
3398 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3399 MousePosition.X = xevent.ButtonEvent.x;
3400 MousePosition.Y = xevent.ButtonEvent.y;
3404 case XEventName.MotionNotify: {
3406 #if DriverDebugExtra
3407 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);
3410 if (Dnd.HandleMotionNotify (ref xevent))
3411 goto ProcessNextMessage;
3412 if (Grab.Hwnd != IntPtr.Zero) {
3413 msg.hwnd = Grab.Hwnd;
3415 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3418 msg.message = Msg.WM_MOUSEMOVE;
3419 msg.wParam = GetMousewParam(0);
3420 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3422 if (!hwnd.Enabled) {
3425 msg.hwnd = hwnd.EnabledHwnd;
3426 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);
3427 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3430 MousePosition.X = xevent.MotionEvent.x;
3431 MousePosition.Y = xevent.MotionEvent.y;
3433 if ((HoverState.Timer.Enabled) &&
3434 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3435 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3436 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3437 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3438 HoverState.Timer.Stop();
3439 HoverState.Timer.Start();
3440 HoverState.X = MousePosition.X;
3441 HoverState.Y = MousePosition.Y;
3451 #if DriverDebugExtra
3452 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);
3454 msg.message = Msg.WM_NCMOUSEMOVE;
3456 if (!hwnd.Enabled) {
3457 msg.hwnd = hwnd.EnabledHwnd;
3458 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);
3459 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3462 // The hit test is sent in screen coordinates
3463 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3464 xevent.MotionEvent.x, xevent.MotionEvent.y,
3465 out screen_x, out screen_y, out dummy);
3467 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3468 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3469 IntPtr.Zero, msg.lParam).ToInt32 ();
3470 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3472 MousePosition.X = xevent.MotionEvent.x;
3473 MousePosition.Y = xevent.MotionEvent.y;
3479 case XEventName.EnterNotify: {
3480 if (!hwnd.Enabled) {
3481 goto ProcessNextMessage;
3483 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3484 goto ProcessNextMessage;
3486 msg.message = Msg.WM_MOUSE_ENTER;
3487 HoverState.X = xevent.CrossingEvent.x;
3488 HoverState.Y = xevent.CrossingEvent.y;
3489 HoverState.Timer.Enabled = true;
3490 HoverState.Window = xevent.CrossingEvent.window;
3494 case XEventName.LeaveNotify: {
3495 if (!hwnd.Enabled) {
3496 goto ProcessNextMessage;
3498 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3499 goto ProcessNextMessage;
3501 msg.message=Msg.WM_MOUSE_LEAVE;
3502 HoverState.Timer.Enabled = false;
3503 HoverState.Window = IntPtr.Zero;
3508 case XEventName.CreateNotify: {
3509 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3510 msg.message = WM_CREATE;
3511 // Set up CreateStruct
3513 goto ProcessNextMessage;
3520 case XEventName.ReparentNotify: {
3521 if (hwnd.parent == null) { // Toplevel
3522 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3523 // We need to adjust x/y
3524 // This sucks ass, part 2
3525 // Every WM does the reparenting of toplevel windows different, so there's
3526 // no standard way of getting our adjustment considering frames/decorations
3527 // The code below is needed for metacity. KDE doesn't works just fine without this
3535 hwnd.Reparented = true;
3537 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);
3538 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3539 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3542 hwnd.whacky_wm = true;
3545 if (hwnd.opacity != 0xffffffff) {
3548 opacity = (IntPtr)(Int32)hwnd.opacity;
3549 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3551 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3552 goto ProcessNextMessage;
3554 hwnd.Reparented = false;
3555 goto ProcessNextMessage;
3558 goto ProcessNextMessage;
3561 case XEventName.ConfigureNotify: {
3562 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3563 #if DriverDebugExtra
3564 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);
3566 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3567 lock (hwnd.configure_lock) {
3568 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3569 hwnd.configure_pending = false;
3572 // We need to adjust our client window to track the resize of whole_window
3573 if (hwnd.whole_window != hwnd.client_window)
3574 PerformNCCalc(hwnd);
3577 goto ProcessNextMessage;
3580 case XEventName.FocusIn: {
3581 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3582 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3583 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3584 // about it having focus again
3585 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3586 goto ProcessNextMessage;
3589 if (FocusWindow == IntPtr.Zero) {
3590 Control c = Control.FromHandle (hwnd.client_window);
3592 goto ProcessNextMessage;
3593 Form form = c.FindForm ();
3595 goto ProcessNextMessage;
3596 ActiveWindow = form.Handle;
3597 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3598 goto ProcessNextMessage;
3600 Keyboard.FocusIn(FocusWindow);
3601 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3602 goto ProcessNextMessage;
3605 case XEventName.FocusOut: {
3606 // Se the comment for our FocusIn handler
3607 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3608 goto ProcessNextMessage;
3610 Keyboard.FocusOut(FocusWindow);
3612 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3613 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3616 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3617 goto ProcessNextMessage;
3620 case XEventName.Expose: {
3621 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3623 hwnd.expose_pending = false;
3625 hwnd.nc_expose_pending = false;
3627 goto ProcessNextMessage;
3631 if (!hwnd.expose_pending) {
3632 goto ProcessNextMessage;
3635 if (!hwnd.nc_expose_pending) {
3636 goto ProcessNextMessage;
3639 switch (hwnd.border_style) {
3640 case FormBorderStyle.Fixed3D: {
3643 g = Graphics.FromHwnd(hwnd.whole_window);
3644 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3649 case FormBorderStyle.FixedSingle: {
3652 g = Graphics.FromHwnd(hwnd.whole_window);
3653 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3658 #if DriverDebugExtra
3659 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);
3662 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3663 Region region = new Region (rect);
3664 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3665 msg.message = Msg.WM_NCPAINT;
3666 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3667 msg.refobject = region;
3670 #if DriverDebugExtra
3671 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);
3673 if (Caret.Visible == true) {
3674 Caret.Paused = true;
3678 if (Caret.Visible == true) {
3680 Caret.Paused = false;
3682 msg.message = Msg.WM_PAINT;
3686 case XEventName.DestroyNotify: {
3688 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3689 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3691 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3692 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3693 CleanupCachedWindows (hwnd);
3695 #if DriverDebugDestroy
3696 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3699 msg.hwnd = hwnd.client_window;
3700 msg.message=Msg.WM_DESTROY;
3703 goto ProcessNextMessage;
3709 case XEventName.ClientMessage: {
3710 if (Dnd.HandleClientMessage (ref xevent)) {
3711 goto ProcessNextMessage;
3714 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3715 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3716 goto ProcessNextMessage;
3719 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3720 msg.message = Msg.WM_MOUSEHOVER;
3721 msg.wParam = GetMousewParam(0);
3722 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3726 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3727 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3728 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3729 msg.wParam = xevent.ClientMessageEvent.ptr3;
3730 msg.lParam = xevent.ClientMessageEvent.ptr4;
3734 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3735 #if DriverDebugXEmbed
3736 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3739 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3740 XSizeHints hints = new XSizeHints();
3743 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3745 hwnd.width = hints.max_width;
3746 hwnd.height = hints.max_height;
3747 hwnd.ClientRect = Rectangle.Empty;
3748 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3752 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3753 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3754 msg.message = Msg.WM_CLOSE;
3758 // We should not get this, but I'll leave the code in case we need it in the future
3759 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3760 goto ProcessNextMessage;
3763 goto ProcessNextMessage;
3767 goto ProcessNextMessage;
3774 internal override bool GetText(IntPtr handle, out string text) {
3781 IntPtr prop = IntPtr.Zero;
3783 XGetWindowProperty(DisplayHandle, handle,
3784 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
3785 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3787 if ((long)nitems > 0 && prop != IntPtr.Zero) {
3788 text = Marshal.PtrToStringUni (prop, (int)nitems);
3793 // fallback on the non-_NET property
3796 textptr = IntPtr.Zero;
3798 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3799 if (textptr != IntPtr.Zero) {
3800 text = Marshal.PtrToStringAnsi(textptr);
3811 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) {
3814 hwnd = Hwnd.ObjectFromHandle(handle);
3820 height = hwnd.height;
3822 PerformNCCalc(hwnd);
3824 client_width = hwnd.ClientRect.Width;
3825 client_height = hwnd.ClientRect.Height;
3830 // Should we throw an exception or fail silently?
3831 // throw new ArgumentException("Called with an invalid window handle", "handle");
3841 internal override FormWindowState GetWindowState(IntPtr handle) {
3846 IntPtr prop = IntPtr.Zero;
3850 XWindowAttributes attributes;
3853 hwnd = Hwnd.ObjectFromHandle(handle);
3857 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);
3858 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3859 for (int i = 0; i < (long)nitems; i++) {
3860 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3861 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3863 } else if (atom == _NET_WM_STATE_HIDDEN) {
3871 return FormWindowState.Minimized;
3872 } else if (maximized == 2) {
3873 return FormWindowState.Maximized;
3876 attributes = new XWindowAttributes();
3877 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3878 if (attributes.map_state == MapState.IsUnmapped) {
3879 return (FormWindowState)(-1);
3883 return FormWindowState.Normal;
3886 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3888 GrabConfined = Grab.Confined;
3889 GrabArea = Grab.Area;
3892 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3894 IntPtr confine_to_window;
3896 confine_to_window = IntPtr.Zero;
3898 if (confine_to_handle != IntPtr.Zero) {
3899 XWindowAttributes attributes = new XWindowAttributes();
3901 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3904 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3906 Grab.Area.X = attributes.x;
3907 Grab.Area.Y = attributes.y;
3908 Grab.Area.Width = attributes.width;
3909 Grab.Area.Height = attributes.height;
3910 Grab.Confined = true;
3911 confine_to_window = hwnd.client_window;
3916 hwnd = Hwnd.ObjectFromHandle(handle);
3919 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3920 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3921 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3922 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3926 internal override void UngrabWindow(IntPtr hwnd) {
3928 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3929 XFlush(DisplayHandle);
3931 Grab.Hwnd = IntPtr.Zero;
3932 Grab.Confined = false;
3935 internal override void HandleException(Exception e) {
3936 StackTrace st = new StackTrace(e, true);
3937 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3938 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3941 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3944 hwnd = Hwnd.ObjectFromHandle(handle);
3947 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3949 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3953 internal override void InvalidateNC (IntPtr handle) {
3956 hwnd = Hwnd.ObjectFromHandle(handle);
3958 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
3961 internal override bool IsEnabled(IntPtr handle) {
3962 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3963 return (hwnd != null && hwnd.Enabled);
3966 internal override bool IsVisible(IntPtr handle) {
3967 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3968 return (hwnd != null && hwnd.visible);
3971 internal override void KillTimer(Timer timer) {
3972 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3974 if (queue == null) {
3975 // This isn't really an error, MS doesn't start the timer if
3976 // it has no assosciated queue
3979 queue.timer_list.Remove (timer);
3982 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3988 hwnd = Hwnd.ObjectFromHandle(handle);
3991 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3998 internal override void OverrideCursor(IntPtr cursor) {
3999 OverrideCursorHandle = cursor;
4002 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
4003 PaintEventArgs paint_event;
4006 hwnd = Hwnd.ObjectFromHandle(handle);
4008 if (Caret.Visible == true) {
4009 Caret.Paused = true;
4016 dc = Graphics.FromHwnd (hwnd.client_window);
4018 Region clip_region = new Region ();
4019 clip_region.MakeEmpty();
4021 foreach (Rectangle r in hwnd.ClipRectangles) {
4022 clip_region.Union (r);
4025 if (hwnd.UserClip != null) {
4026 clip_region.Intersect(hwnd.UserClip);
4029 dc.Clip = clip_region;
4030 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4031 hwnd.expose_pending = false;
4033 hwnd.ClearInvalidArea();
4035 hwnd.drawing_stack.Push (paint_event);
4036 hwnd.drawing_stack.Push (dc);
4040 dc = Graphics.FromHwnd (hwnd.whole_window);
4042 if (!hwnd.nc_invalid.IsEmpty) {
4043 dc.SetClip (hwnd.nc_invalid);
4044 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4046 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4048 hwnd.nc_expose_pending = false;
4050 hwnd.ClearNcInvalidArea ();
4052 hwnd.drawing_stack.Push (paint_event);
4053 hwnd.drawing_stack.Push (dc);
4059 internal override void PaintEventEnd(IntPtr handle, bool client) {
4062 hwnd = Hwnd.ObjectFromHandle(handle);
4064 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4068 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4069 pe.SetGraphics (null);
4072 if (Caret.Visible == true) {
4074 Caret.Paused = false;
4078 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4079 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4080 XEventQueue queue = (XEventQueue) queue_id;
4083 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4084 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
4088 if (queue.Count > 0) {
4091 // Only call UpdateMessageQueue if real events are pending
4092 // otherwise we go to sleep on the socket
4093 if (XPending(DisplayHandle) != 0) {
4094 UpdateMessageQueue((XEventQueue)queue_id);
4096 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4101 CheckTimers(queue.timer_list, DateTime.UtcNow);
4106 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4109 // FIXME - I think this should just enqueue directly
4110 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4111 XEvent xevent = new XEvent ();
4112 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4114 xevent.type = XEventName.ClientMessage;
4115 xevent.ClientMessageEvent.display = DisplayHandle;
4118 xevent.ClientMessageEvent.window = hwnd.whole_window;
4120 xevent.ClientMessageEvent.window = IntPtr.Zero;
4123 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4124 xevent.ClientMessageEvent.format = 32;
4125 xevent.ClientMessageEvent.ptr1 = handle;
4126 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4127 xevent.ClientMessageEvent.ptr3 = wparam;
4128 xevent.ClientMessageEvent.ptr4 = lparam;
4130 hwnd.Queue.EnqueueLocked (xevent);
4135 internal override void PostQuitMessage(int exitCode) {
4137 XFlush(DisplayHandle);
4138 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4141 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4146 internal override void RequestNCRecalc(IntPtr handle) {
4149 hwnd = Hwnd.ObjectFromHandle(handle);
4155 PerformNCCalc(hwnd);
4156 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4157 InvalidateNC(handle);
4160 internal override void ResetMouseHover(IntPtr handle) {
4163 hwnd = Hwnd.ObjectFromHandle(handle);
4168 HoverState.Timer.Enabled = true;
4169 HoverState.X = MousePosition.X;
4170 HoverState.Y = MousePosition.Y;
4171 HoverState.Window = handle;
4175 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4181 hwnd = Hwnd.ObjectFromHandle(handle);
4184 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4191 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4197 hwnd = Hwnd.ObjectFromHandle(handle);
4200 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4207 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4210 XGCValues gc_values;
4212 hwnd = Hwnd.ObjectFromHandle(handle);
4214 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4216 /* We have an invalid area in the window we're scrolling.
4217 Adjust our stored invalid rectangle to to match the scrolled amount */
4232 if (area.Contains (hwnd.Invalid))
4233 hwnd.ClearInvalidArea ();
4234 hwnd.AddInvalidArea(r);
4237 gc_values = new XGCValues();
4239 if (with_children) {
4240 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4243 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4251 height = area.Height - YAmount;
4252 dest_y = area.Y + YAmount;
4255 src_y = area.Y - YAmount;
4256 height = area.Height + YAmount;
4262 width = area.Width - XAmount;
4263 dest_x = area.X + XAmount;
4266 src_x = area.X - XAmount;
4267 width = area.Width + XAmount;
4271 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4273 // Generate an expose for the area exposed by the horizontal scroll
4274 // We don't use AddExpose since we're
4276 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4277 } else if (XAmount < 0) {
4278 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4281 // Generate an expose for the area exposed by the vertical scroll
4283 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4284 } else if (YAmount < 0) {
4285 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4287 XFreeGC(DisplayHandle, gc);
4290 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4294 hwnd = Hwnd.GetObjectFromWindow(handle);
4296 rect = hwnd.ClientRect;
4299 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4302 internal override void SendAsyncMethod (AsyncMethodData method) {
4304 XEvent xevent = new XEvent ();
4306 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4308 xevent.type = XEventName.ClientMessage;
4309 xevent.ClientMessageEvent.display = DisplayHandle;
4310 xevent.ClientMessageEvent.window = method.Handle;
4311 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4312 xevent.ClientMessageEvent.format = 32;
4313 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4315 hwnd.Queue.EnqueueLocked (xevent);
4320 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4322 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4325 h = Hwnd.ObjectFromHandle(hwnd);
4327 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4328 AsyncMethodResult result;
4329 AsyncMethodData data;
4331 result = new AsyncMethodResult ();
4332 data = new AsyncMethodData ();
4335 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4336 data.Args = new object[] { hwnd, message, wParam, lParam };
4337 data.Result = result;
4339 SendAsyncMethod (data);
4340 #if DriverDebug || DriverDebugThreads
4341 Console.WriteLine ("Sending {0} message across.", message);
4346 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4349 internal override void SetAllowDrop (IntPtr handle, bool value)
4351 // We allow drop on all windows
4354 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4355 DragDropEffects allowed_effects)
4357 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4360 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4362 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4365 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4368 hwnd = Hwnd.ObjectFromHandle(handle);
4370 Form form = Control.FromHandle (handle) as Form;
4371 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4372 border_style == FormBorderStyle.SizableToolWindow)) {
4373 form.window_manager = new InternalWindowManager (form);
4376 hwnd.border_style = border_style;
4377 RequestNCRecalc(handle);
4380 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4381 if (Caret.Hwnd == handle) {
4388 if (Caret.Visible == true) {
4390 Caret.Timer.Start();
4395 internal override void SetClipRegion(IntPtr handle, Region region) {
4398 hwnd = Hwnd.ObjectFromHandle(handle);
4403 hwnd.UserClip = region;
4404 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4407 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4410 if (OverrideCursorHandle == IntPtr.Zero) {
4411 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4415 LastCursorHandle = cursor;
4416 LastCursorWindow = handle;
4418 hwnd = Hwnd.ObjectFromHandle(handle);
4420 if (cursor != IntPtr.Zero) {
4421 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4423 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4425 XFlush(DisplayHandle);
4430 hwnd = Hwnd.ObjectFromHandle(handle);
4432 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4436 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4437 out int root_x, out int root_y, out int child_x, out int child_y,
4440 /* this code was written with the help of
4441 glance at gdk. I never would have realized we
4442 needed a loop in order to traverse down in the
4443 hierarchy. I would have assumed you'd get the
4444 most deeply nested child and have to do
4445 XQueryTree to move back up the hierarchy..
4446 stupid me, of course. */
4449 XGrabServer (display);
4451 XQueryPointer(display, w, out root, out c,
4452 out root_x, out root_y, out child_x, out child_y,
4458 IntPtr child_last = IntPtr.Zero;
4459 while (c != IntPtr.Zero) {
4461 XQueryPointer(display, c, out root, out c,
4462 out root_x, out root_y, out child_x, out child_y,
4465 XUngrabServer (display);
4470 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4471 if (handle == IntPtr.Zero) {
4474 int root_x, root_y, child_x, child_y, mask;
4477 * QueryPointer before warping
4478 * because if the warp is on
4479 * the RootWindow, the x/y are
4480 * relative to the current
4483 QueryPointer (DisplayHandle, RootWindow,
4486 out root_x, out root_y,
4487 out child_x, out child_y,
4490 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4492 XFlush (DisplayHandle);
4494 /* then we need to a
4495 * QueryPointer after warping
4496 * to manually generate a
4497 * motion event for the window
4500 QueryPointer (DisplayHandle, RootWindow,
4503 out root_x, out root_y,
4504 out child_x, out child_y,
4507 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4508 if (child_hwnd == null) {
4512 XEvent xevent = new XEvent ();
4514 xevent.type = XEventName.MotionNotify;
4515 xevent.MotionEvent.display = DisplayHandle;
4516 xevent.MotionEvent.window = child_hwnd.client_window;
4517 xevent.MotionEvent.root = RootWindow;
4518 xevent.MotionEvent.x = child_x;
4519 xevent.MotionEvent.y = child_y;
4520 xevent.MotionEvent.x_root = root_x;
4521 xevent.MotionEvent.y_root = root_y;
4522 xevent.MotionEvent.state = mask;
4524 child_hwnd.Queue.EnqueueLocked (xevent);
4529 hwnd = Hwnd.ObjectFromHandle(handle);
4531 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4536 internal override void SetFocus(IntPtr handle) {
4538 IntPtr prev_focus_window;
4540 hwnd = Hwnd.ObjectFromHandle(handle);
4542 if (hwnd.client_window == FocusWindow) {
4546 prev_focus_window = FocusWindow;
4547 FocusWindow = hwnd.client_window;
4549 if (prev_focus_window != IntPtr.Zero) {
4550 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4552 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4554 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4557 internal override void SetIcon(IntPtr handle, Icon icon) {
4560 hwnd = Hwnd.ObjectFromHandle(handle);
4562 SetIcon(hwnd, icon);
4566 internal override void SetMenu(IntPtr handle, Menu menu) {
4569 hwnd = Hwnd.ObjectFromHandle(handle);
4572 RequestNCRecalc(handle);
4575 internal override void SetModal(IntPtr handle, bool Modal) {
4577 ModalWindows.Push(handle);
4579 if (ModalWindows.Contains(handle)) {
4582 if (ModalWindows.Count > 0) {
4583 Activate((IntPtr)ModalWindows.Peek());
4588 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4591 hwnd = Hwnd.ObjectFromHandle(handle);
4592 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4595 #if DriverDebug || DriverDebugParent
4596 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4598 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4604 internal override void SetTimer (Timer timer) {
4605 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4607 if (queue == null) {
4608 // This isn't really an error, MS doesn't start the timer if
4609 // it has no assosciated queue
4612 queue.timer_list.Add (timer);
4616 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4620 hwnd = Hwnd.ObjectFromHandle(handle);
4622 if (handle_owner != IntPtr.Zero) {
4623 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4634 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4635 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4637 if (hwnd_owner != null) {
4638 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4640 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4645 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4651 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4654 hwnd = Hwnd.ObjectFromHandle(handle);
4655 hwnd.visible = visible;
4659 if (Control.FromHandle(handle) is Form) {
4662 s = ((Form)Control.FromHandle(handle)).WindowState;
4664 MapWindow(hwnd, WindowType.Both);
4667 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4668 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4672 MapWindow(hwnd, WindowType.Both);
4674 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4676 UnmapWindow(hwnd, WindowType.Whole);
4682 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4687 hwnd = Hwnd.ObjectFromHandle(handle);
4692 hints = new XSizeHints();
4694 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4695 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4696 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4697 hints.min_width = min.Width;
4698 hints.min_height = min.Height;
4701 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4702 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4703 hints.max_width = max.Width;
4704 hints.max_height = max.Height;
4707 if (hints.flags != IntPtr.Zero) {
4708 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4711 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4712 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4713 hints.x = maximized.X;
4714 hints.y = maximized.Y;
4715 hints.width = maximized.Width;
4716 hints.height = maximized.Height;
4718 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4719 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4724 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4727 hwnd = Hwnd.ObjectFromHandle(handle);
4733 // Win32 automatically changes negative width/height to 0.
4739 // X requires a sanity check for width & height; otherwise it dies
4740 if (hwnd.zero_sized && width > 0 && height > 0) {
4742 MapWindow(hwnd, WindowType.Whole);
4744 hwnd.zero_sized = false;
4747 if ((width < 1) || (height < 1)) {
4748 hwnd.zero_sized = true;
4749 UnmapWindow(hwnd, WindowType.Whole);
4752 // Save a server roundtrip (and prevent a feedback loop)
4753 if ((hwnd.x == x) && (hwnd.y == y) &&
4754 (hwnd.width == width) && (hwnd.height == height)) {
4758 if (!hwnd.zero_sized) {
4763 hwnd.height = height;
4764 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4766 if (hwnd.fixed_size) {
4767 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4771 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4772 PerformNCCalc(hwnd);
4776 // Update our position/size immediately, so
4777 // that future calls to SetWindowPos aren't
4778 // kept from calling XMoveResizeWindow (by the
4779 // "Save a server roundtrip" block above).
4783 hwnd.height = height;
4784 hwnd.ClientRect = Rectangle.Empty;
4787 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4788 FormWindowState current_state;
4791 hwnd = Hwnd.ObjectFromHandle(handle);
4793 current_state = GetWindowState(handle);
4795 if (current_state == state) {
4800 case FormWindowState.Normal: {
4802 if (current_state == FormWindowState.Minimized) {
4803 MapWindow(hwnd, WindowType.Both);
4804 } else if (current_state == FormWindowState.Maximized) {
4805 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4812 case FormWindowState.Minimized: {
4814 if (current_state == FormWindowState.Maximized) {
4815 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4817 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4822 case FormWindowState.Maximized: {
4824 if (current_state == FormWindowState.Minimized) {
4825 MapWindow(hwnd, WindowType.Both);
4828 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4836 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4839 hwnd = Hwnd.ObjectFromHandle(handle);
4840 SetHwndStyles(hwnd, cp);
4841 SetWMStyles(hwnd, cp);
4844 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4848 hwnd = Hwnd.ObjectFromHandle(handle);
4854 hwnd.opacity = (uint)(0xffffffff * transparency);
4855 opacity = (IntPtr)((int)hwnd.opacity);
4857 IntPtr w = hwnd.whole_window;
4858 if (hwnd.reparented)
4859 w = XGetParent (hwnd.whole_window);
4860 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4863 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4864 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4872 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4875 } else if (!bottom) {
4876 Hwnd after_hwnd = null;
4878 if (after_handle != IntPtr.Zero) {
4879 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4882 XWindowChanges values = new XWindowChanges();
4884 if (after_hwnd == null) {
4885 // Work around metacity 'issues'
4889 atoms[0] = unixtime();
4890 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4892 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4893 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4895 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4898 values.sibling = after_hwnd.whole_window;
4899 values.stack_mode = StackMode.Below;
4902 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4907 XLowerWindow(DisplayHandle, hwnd.whole_window);
4914 internal override void ShowCursor(bool show) {
4915 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4918 internal override object StartLoop(Thread thread) {
4919 return (Object) ThreadQueue(thread);
4922 internal override bool SupportsTransparency() {
4923 // We need to check if the x compositing manager is running
4927 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4928 GetSystrayManagerWindow();
4930 if (SystrayMgrWindow != IntPtr.Zero) {
4931 XSizeHints size_hints;
4934 hwnd = Hwnd.ObjectFromHandle(handle);
4936 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4940 if (hwnd.client_window != hwnd.whole_window) {
4941 XDestroyWindow(DisplayHandle, hwnd.client_window);
4942 hwnd.client_window = hwnd.whole_window;
4944 /* by virtue of the way the tests are ordered when determining if it's PAINT
4945 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
4946 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4947 there's a pending expose). */
4948 if (hwnd.nc_expose_pending) {
4949 hwnd.nc_expose_pending = false;
4950 if (!hwnd.expose_pending)
4951 hwnd.Queue.Paint.Remove (hwnd);
4955 size_hints = new XSizeHints();
4957 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4959 size_hints.min_width = 24;
4960 size_hints.min_height = 24;
4961 size_hints.max_width = 24;
4962 size_hints.max_height = 24;
4963 size_hints.base_width = 24;
4964 size_hints.base_height = 24;
4966 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4968 int[] atoms = new int[2];
4969 atoms [0] = 1; // Version 1
4970 atoms [1] = 1; // we want to be mapped
4972 // This line cost me 3 days...
4973 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4975 // Need to pick some reasonable defaults
4977 tt.AutomaticDelay = 100;
4978 tt.InitialDelay = 250;
4979 tt.ReshowDelay = 250;
4980 tt.ShowAlways = true;
4982 if ((tip != null) && (tip != string.Empty)) {
4983 tt.SetToolTip(Control.FromHandle(handle), tip);
4989 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4997 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5000 control = Control.FromHandle(handle);
5001 if (control != null && tt != null) {
5002 tt.SetToolTip(control, tip);
5010 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5012 #if GTKSOCKET_SUPPORTS_REPARENTING
5015 hwnd = Hwnd.ObjectFromHandle(handle);
5017 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
5018 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
5019 * 2. The client can reparent its window out of the embedder window.
5020 * 3. The client can destroy its window.
5022 * this call to SetParent is case 2, but in
5023 * the spec it also mentions that gtk doesn't
5024 * support this at present. Looking at HEAD
5025 * gtksocket-x11.c jives with this statement.
5027 * so we can't reparent. we have to destroy.
5029 SetParent(hwnd.whole_window, FosterParent);
5031 Control control = Control.FromHandle(handle);
5032 if (control is NotifyIcon.NotifyIconWindow)
5033 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
5036 // The caller can now re-dock it later...
5043 internal override bool Text(IntPtr handle, string text) {
5046 hwnd = Hwnd.ObjectFromHandle(handle);
5049 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5050 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5052 // XXX this has problems with UTF8.
5053 // we need to either use the actual
5054 // text if it's latin-1, or convert it
5055 // to compound text if it's in a
5056 // different charset.
5057 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5062 internal override bool TranslateMessage(ref MSG msg) {
5063 return Keyboard.TranslateMessage (ref msg);
5066 internal override void UpdateWindow(IntPtr handle) {
5069 hwnd = Hwnd.ObjectFromHandle(handle);
5071 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5075 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5076 hwnd.Queue.Paint.Remove(hwnd);
5079 #endregion // Public Static Methods
5082 internal override event EventHandler Idle;
5083 #endregion // Events
5086 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5087 internal extern static IntPtr XOpenDisplay(IntPtr display);
5088 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5089 internal extern static int XCloseDisplay(IntPtr display);
5090 [DllImport ("libX11", EntryPoint="XSynchronize")]
5091 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5093 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5094 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);
5095 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5096 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5097 [DllImport ("libX11", EntryPoint="XMapWindow")]
5098 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5099 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5100 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5101 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5102 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5103 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5104 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5105 [DllImport ("libX11", EntryPoint="XRootWindow")]
5106 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5107 [DllImport ("libX11", EntryPoint="XNextEvent")]
5108 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5109 [DllImport ("libX11")]
5110 internal extern static int XConnectionNumber (IntPtr diplay);
5111 [DllImport ("libX11")]
5112 internal extern static int XPending (IntPtr diplay);
5113 [DllImport ("libX11", EntryPoint="XSelectInput")]
5114 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5116 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5117 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5119 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5120 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5121 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5122 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5124 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5125 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5127 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5128 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5130 [DllImport ("libX11", EntryPoint="XFlush")]
5131 internal extern static int XFlush(IntPtr display);
5133 [DllImport ("libX11", EntryPoint="XSetWMName")]
5134 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5136 [DllImport ("libX11", EntryPoint="XStoreName")]
5137 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5139 [DllImport ("libX11", EntryPoint="XFetchName")]
5140 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5142 [DllImport ("libX11", EntryPoint="XSendEvent")]
5143 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5145 [DllImport ("libX11", EntryPoint="XQueryTree")]
5146 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);
5148 [DllImport ("libX11", EntryPoint="XFree")]
5149 internal extern static int XFree(IntPtr data);
5151 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5152 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5154 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5155 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5157 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5158 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5160 [DllImport ("libX11", EntryPoint="XInternAtom")]
5161 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5163 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5164 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5166 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5167 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5169 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5170 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);
5172 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5173 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5175 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5176 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);
5178 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5179 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);
5181 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5182 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);
5184 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5185 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);
5187 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5188 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);
5190 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5191 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);
5193 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5194 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);
5196 [DllImport ("libX11", EntryPoint="XClearWindow")]
5197 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5199 [DllImport ("libX11", EntryPoint="XClearArea")]
5200 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5203 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5204 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5206 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5207 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5209 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5210 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5212 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5213 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5215 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5216 internal extern static int XDefaultScreen(IntPtr display);
5218 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5219 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5221 [DllImport ("libX11", EntryPoint="XLookupColor")]
5222 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5224 [DllImport ("libX11", EntryPoint="XAllocColor")]
5225 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5227 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5228 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5230 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5231 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5233 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5234 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5236 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5237 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5239 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5240 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5242 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5243 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5245 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5246 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5248 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5249 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5251 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5252 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5254 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5255 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5257 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5258 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5261 [DllImport ("libX11", EntryPoint="XCreateGC")]
5262 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5264 [DllImport ("libX11", EntryPoint="XFreeGC")]
5265 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5267 [DllImport ("libX11", EntryPoint="XSetFunction")]
5268 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5270 [DllImport ("libX11", EntryPoint="XDrawLine")]
5271 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5273 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5274 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5276 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5277 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5279 [DllImport ("libX11", EntryPoint="XCopyArea")]
5280 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);
5282 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5283 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);
5285 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5286 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5288 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5289 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5291 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5292 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5294 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5295 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5297 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5298 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5300 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5301 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5303 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5304 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);
5306 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5307 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5309 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5310 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5312 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5313 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5315 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5316 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5318 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5319 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5321 [DllImport ("libX11", EntryPoint="XGrabServer")]
5322 internal extern static void XGrabServer(IntPtr display);
5324 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5325 internal extern static void XUngrabServer(IntPtr display);
5327 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5328 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5330 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5331 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5333 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5334 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5336 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5337 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5339 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5340 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5342 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5343 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5345 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5346 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5348 [DllImport ("libX11", EntryPoint="XInitThreads")]
5349 internal extern static int XInitThreads();
5351 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5352 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5354 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5355 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5357 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5358 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5360 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5361 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5363 [DllImport ("libX11", EntryPoint="XSetForeground")]
5364 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5366 [DllImport ("libX11", EntryPoint="XSetBackground")]
5367 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5369 [DllImport ("libX11", EntryPoint="XBell")]
5370 internal extern static int XBell(IntPtr display, int percent);
5372 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5373 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5375 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5376 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5378 [DllImport ("libX11")]
5379 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5381 [DllImport ("libX11")]
5382 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);