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 Point mouse_position; // 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 mouse_position = 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)");
509 #endregion // Internal Methods
511 #region Private Methods
512 private int unixtime() {
513 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
515 return (int) t.TotalSeconds;
518 private static void SetupAtoms() {
519 // make sure this array stays in sync with the statements below
520 string [] atom_names = new string[] {
525 //"_NET_CLIENT_LIST",
526 //"_NET_NUMBER_OF_DESKTOPS",
527 //"_NET_DESKTOP_GEOMETRY",
528 //"_NET_DESKTOP_VIEWPORT",
529 "_NET_CURRENT_DESKTOP",
530 //"_NET_DESKTOP_NAMES",
531 "_NET_ACTIVE_WINDOW",
533 //"_NET_SUPPORTING_WM_CHECK",
534 //"_NET_VIRTUAL_ROOTS",
535 //"_NET_DESKTOP_LAYOUT",
536 //"_NET_SHOWING_DESKTOP",
537 //"_NET_CLOSE_WINDOW",
538 //"_NET_MOVERESIZE_WINDOW",
539 //"_NET_WM_MOVERESIZE",
540 //"_NET_RESTACK_WINDOW",
541 //"_NET_REQUEST_FRAME_EXTENTS",
543 //"_NET_WM_VISIBLE_NAME",
544 //"_NET_WM_ICON_NAME",
545 //"_NET_WM_VISIBLE_ICON_NAME",
547 "_NET_WM_WINDOW_TYPE",
549 //"_NET_WM_ALLOWED_ACTIONS",
551 //"_NET_WM_STRUT_PARTIAL",
552 //"_NET_WM_ICON_GEOMETRY",
555 //"_NET_WM_HANDLED_ICONS",
557 "_NET_FRAME_EXTENTS",
559 //"_NET_WM_SYNC_REQUEST",
560 "_NET_SYSTEM_TRAY_OPCODE",
561 //"_NET_SYSTEM_TRAY_ORIENTATION",
562 "_NET_WM_STATE_MAXIMIZED_HORZ",
563 "_NET_WM_STATE_MAXIMIZED_VERT",
564 "_NET_WM_STATE_HIDDEN",
568 "_NET_WM_STATE_SKIP_TASKBAR",
569 //"_NET_WM_STATE_ABOVE",
570 //"_NET_WM_STATE_MODAL",
571 "_NET_WM_CONTEXT_HELP",
572 "_NET_WM_WINDOW_OPACITY",
573 //"_NET_WM_WINDOW_TYPE_DESKTOP",
574 //"_NET_WM_WINDOW_TYPE_DOCK",
575 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
576 //"_NET_WM_WINDOW_TYPE_MENU",
577 "_NET_WM_WINDOW_TYPE_UTILITY",
578 //"_NET_WM_WINDOW_TYPE_DIALOG",
579 //"_NET_WM_WINDOW_TYPE_SPLASH",
580 "_NET_WM_WINDOW_TYPE_NORMAL",
587 "_SWF_PostMessageAtom",
590 IntPtr[] atoms = new IntPtr [atom_names.Length];;
592 XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
595 WM_PROTOCOLS = atoms [off++];
596 WM_DELETE_WINDOW = atoms [off++];
597 WM_TAKE_FOCUS = atoms [off++];
598 //_NET_SUPPORTED = atoms [off++];
599 //_NET_CLIENT_LIST = atoms [off++];
600 //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
601 //_NET_DESKTOP_GEOMETRY = atoms [off++];
602 //_NET_DESKTOP_VIEWPORT = atoms [off++];
603 _NET_CURRENT_DESKTOP = atoms [off++];
604 //_NET_DESKTOP_NAMES = atoms [off++];
605 _NET_ACTIVE_WINDOW = atoms [off++];
606 _NET_WORKAREA = atoms [off++];
607 //_NET_SUPPORTING_WM_CHECK = atoms [off++];
608 //_NET_VIRTUAL_ROOTS = atoms [off++];
609 //_NET_DESKTOP_LAYOUT = atoms [off++];
610 //_NET_SHOWING_DESKTOP = atoms [off++];
611 //_NET_CLOSE_WINDOW = atoms [off++];
612 //_NET_MOVERESIZE_WINDOW = atoms [off++];
613 //_NET_WM_MOVERESIZE = atoms [off++];
614 //_NET_RESTACK_WINDOW = atoms [off++];
615 //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
616 _NET_WM_NAME = atoms [off++];
617 //_NET_WM_VISIBLE_NAME = atoms [off++];
618 //_NET_WM_ICON_NAME = atoms [off++];
619 //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
620 //_NET_WM_DESKTOP = atoms [off++];
621 _NET_WM_WINDOW_TYPE = atoms [off++];
622 _NET_WM_STATE = atoms [off++];
623 //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
624 //_NET_WM_STRUT = atoms [off++];
625 //_NET_WM_STRUT_PARTIAL = atoms [off++];
626 //_NET_WM_ICON_GEOMETRY = atoms [off++];
627 _NET_WM_ICON = atoms [off++];
628 //_NET_WM_PID = atoms [off++];
629 //_NET_WM_HANDLED_ICONS = atoms [off++];
630 _NET_WM_USER_TIME = atoms [off++];
631 _NET_FRAME_EXTENTS = atoms [off++];
632 //_NET_WM_PING = atoms [off++];
633 //_NET_WM_SYNC_REQUEST = atoms [off++];
634 _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
635 //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
636 _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
637 _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
638 _NET_WM_STATE_HIDDEN = atoms [off++];
639 _XEMBED = atoms [off++];
640 _XEMBED_INFO = atoms [off++];
641 _MOTIF_WM_HINTS = atoms [off++];
642 _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
643 //_NET_WM_STATE_ABOVE = atoms [off++];
644 //_NET_WM_STATE_MODAL = atoms [off++];
645 _NET_WM_CONTEXT_HELP = atoms [off++];
646 _NET_WM_WINDOW_OPACITY = atoms [off++];
647 //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
648 //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
649 //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
650 //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
651 _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
652 //_NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
653 //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
654 _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
655 CLIPBOARD = atoms [off++];
656 PRIMARY = atoms [off++];
657 OEMTEXT = atoms [off++];
658 UNICODETEXT = atoms [off++];
659 TARGETS = atoms [off++];
660 AsyncAtom = atoms [off++];
661 PostAtom = atoms [off++];
662 HoverState.Atom = atoms [off++];
664 //DIB = (IntPtr)Atom.XA_PIXMAP;
665 _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
668 private void GetSystrayManagerWindow() {
669 XGrabServer(DisplayHandle);
670 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
671 XUngrabServer(DisplayHandle);
672 XFlush(DisplayHandle);
675 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
679 xev.ClientMessageEvent.type = XEventName.ClientMessage;
680 xev.ClientMessageEvent.send_event = true;
681 xev.ClientMessageEvent.window = window;
682 xev.ClientMessageEvent.message_type = message_type;
683 xev.ClientMessageEvent.format = 32;
684 xev.ClientMessageEvent.ptr1 = l0;
685 xev.ClientMessageEvent.ptr2 = l1;
686 xev.ClientMessageEvent.ptr3 = l2;
687 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
690 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
694 xev.ClientMessageEvent.type = XEventName.ClientMessage;
695 xev.ClientMessageEvent.send_event = true;
696 xev.ClientMessageEvent.window = window;
697 xev.ClientMessageEvent.message_type = message_type;
698 xev.ClientMessageEvent.format = 32;
699 xev.ClientMessageEvent.ptr1 = l0;
700 xev.ClientMessageEvent.ptr2 = l1;
701 xev.ClientMessageEvent.ptr3 = l2;
702 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
705 bool StyleSet (int s, WindowStyles ws)
707 return (s & (int)ws) == (int)ws;
710 bool ExStyleSet (int ex, WindowExStyles exws)
712 return (ex & (int)exws) == (int)exws;
715 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
717 // Only MDI windows get caption_heights
719 tool_caption_height = 19;
721 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
722 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
723 border_style = FormBorderStyle.Fixed3D;
724 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
725 border_style = FormBorderStyle.None;
727 border_style = FormBorderStyle.FixedSingle;
729 title_style = TitleStyle.None;
731 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
734 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
735 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
736 title_style = TitleStyle.Tool;
738 title_style = TitleStyle.Normal;
742 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
743 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
744 border_style = (FormBorderStyle) 0xFFFF;
746 border_style = FormBorderStyle.None;
751 title_style = TitleStyle.None;
752 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
753 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
754 title_style = TitleStyle.Tool;
756 title_style = TitleStyle.Normal;
760 border_style = FormBorderStyle.None;
762 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
763 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
764 border_style = FormBorderStyle.SizableToolWindow;
766 border_style = FormBorderStyle.Sizable;
769 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
770 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
771 border_style = FormBorderStyle.Fixed3D;
772 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
773 border_style = FormBorderStyle.FixedDialog;
774 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
775 border_style = FormBorderStyle.FixedToolWindow;
776 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
777 border_style = FormBorderStyle.FixedSingle;
780 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
781 border_style = FormBorderStyle.FixedSingle;
788 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
789 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
792 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
793 MotifWmHints mwmHints;
794 MotifFunctions functions;
795 MotifDecorations decorations;
798 Rectangle client_rect;
800 // Child windows don't need WM window styles
801 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) {
806 mwmHints = new MotifWmHints();
810 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
811 mwmHints.functions = (IntPtr)0;
812 mwmHints.decorations = (IntPtr)0;
814 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
815 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
816 /* tool windows get no window manager
817 decorations, and neither do windows
818 which lack CAPTION/BORDER/DLGFRAME
822 /* just because the window doesn't get any decorations doesn't
823 mean we should disable the functions. for instance, without
824 MotifFunctions.Maximize, changing the windowstate to Maximized
825 is ignored by metacity. */
826 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
829 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
830 functions |= MotifFunctions.Move;
831 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
834 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
835 functions |= MotifFunctions.Move | MotifFunctions.Resize;
836 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
839 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
840 functions |= MotifFunctions.Minimize;
841 decorations |= MotifDecorations.Minimize;
844 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
845 functions |= MotifFunctions.Maximize;
846 decorations |= MotifDecorations.Maximize;
849 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
850 functions |= MotifFunctions.Resize;
851 decorations |= MotifDecorations.ResizeH;
854 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
855 decorations |= MotifDecorations.Border;
858 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
859 decorations |= MotifDecorations.Border;
862 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
863 decorations |= MotifDecorations.Border;
866 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
867 functions |= MotifFunctions.Close;
870 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
871 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
872 if (cp.Caption == "") {
873 functions &= ~MotifFunctions.Move;
874 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
879 if ((functions & MotifFunctions.Resize) == 0) {
880 hwnd.fixed_size = true;
881 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));
883 hwnd.fixed_size = false;
886 mwmHints.functions = (IntPtr)functions;
887 mwmHints.decorations = (IntPtr)decorations;
889 FormWindowState current_state = GetWindowState (hwnd.Handle);
890 if (current_state == (FormWindowState)(-1))
891 current_state = FormWindowState.Normal;
893 client_rect = hwnd.ClientRect;
897 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
898 // and get those windows in front of their parents
899 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
900 atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
901 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE,
902 (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
904 Form f = Control.FromHandle(hwnd.Handle) as Form;
905 if (f != null && !hwnd.reparented) {
906 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
907 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
908 if (owner_hwnd != null)
909 XSetTransientForHint(DisplayHandle, hwnd.whole_window,
910 owner_hwnd.whole_window);
915 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
916 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
917 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
918 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
920 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
921 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
922 /* this line keeps the window from showing up in gnome's taskbar */
923 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
925 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
926 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
928 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
931 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
932 atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
934 /* we need to add these atoms in the
935 * event we're maximized, since we're
936 * replacing the existing
937 * _NET_WM_STATE here. If we don't
938 * add them, future calls to
939 * GetWindowState will return Normal
940 * for a window which is maximized. */
941 if (current_state == FormWindowState.Maximized) {
942 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
943 atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
945 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
948 IntPtr[] atom_ptrs = new IntPtr[2];
949 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
950 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
951 atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
954 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
958 private void SetIcon(Hwnd hwnd, Icon icon) {
964 bitmap = icon.ToBitmap();
966 size = bitmap.Width * bitmap.Height + 2;
967 data = new IntPtr[size];
969 data[index++] = (IntPtr)bitmap.Width;
970 data[index++] = (IntPtr)bitmap.Height;
972 for (int y = 0; y < bitmap.Height; y++) {
973 for (int x = 0; x < bitmap.Width; x++) {
974 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
978 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
981 private void WakeupMain () {
982 wake.Send (new byte [] { 0xFF });
985 private XEventQueue ThreadQueue(Thread thread) {
988 queue = (XEventQueue)MessageQueues[thread];
990 queue = new XEventQueue(thread);
991 MessageQueues[thread] = queue;
997 private void TranslatePropertyToClipboard(IntPtr property) {
1002 IntPtr prop = IntPtr.Zero;
1004 Clipboard.Item = null;
1006 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);
1008 if ((long)nitems > 0) {
1009 if (property == (IntPtr)Atom.XA_STRING) {
1010 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1011 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1012 // FIXME - convert bitmap to image
1013 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1014 // FIXME - convert pixmap to image
1015 } else if (property == OEMTEXT) {
1016 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1017 } else if (property == UNICODETEXT) {
1018 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1025 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1027 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1031 // Keep the invalid area as small as needed
1032 if ((x + width) > hwnd.width) {
1033 width = hwnd.width - x;
1036 if ((y + height) > hwnd.height) {
1037 height = hwnd.height - y;
1041 hwnd.AddInvalidArea(x, y, width, height);
1042 if (!hwnd.expose_pending) {
1043 if (!hwnd.nc_expose_pending) {
1044 hwnd.Queue.Paint.Enqueue(hwnd);
1046 hwnd.expose_pending = true;
1049 hwnd.AddNcInvalidArea (x, y, width, height);
1051 if (!hwnd.nc_expose_pending) {
1052 if (!hwnd.expose_pending) {
1053 hwnd.Queue.Paint.Enqueue(hwnd);
1055 hwnd.nc_expose_pending = true;
1060 private void FrameExtents(IntPtr window, out int left, out int top) {
1065 IntPtr prop = IntPtr.Zero;
1067 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);
1068 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
1069 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
1070 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
1071 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
1072 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
1078 if (prop != IntPtr.Zero) {
1084 private void AddConfigureNotify (XEvent xevent) {
1087 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1094 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1095 if (!hwnd.reparented) {
1096 hwnd.x = xevent.ConfigureEvent.x;
1097 hwnd.y = xevent.ConfigureEvent.y;
1099 // This sucks ass, part 1
1100 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1101 // no standard way of getting our adjustment.
1102 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1103 // Several other WMs do their decorations different yet again and we fail to deal
1104 // with that, since I couldn't find any frigging commonality between them.
1105 // The only sane WM seems to be KDE
1107 if (!xevent.ConfigureEvent.send_event) {
1110 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1112 // This is a synthetic event, coordinates are in root space
1113 hwnd.x = xevent.ConfigureEvent.x;
1114 hwnd.y = xevent.ConfigureEvent.y;
1115 if (hwnd.whacky_wm) {
1119 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1120 hwnd.x -= frame_left;
1121 hwnd.y -= frame_top;
1126 // XXX this sucks. this isn't thread safe
1127 hwnd.width = xevent.ConfigureEvent.width;
1128 hwnd.height = xevent.ConfigureEvent.height;
1129 hwnd.ClientRect = Rectangle.Empty;
1131 lock (hwnd.configure_lock) {
1132 if (!hwnd.configure_pending) {
1133 hwnd.Queue.EnqueueLocked (xevent);
1134 hwnd.configure_pending = true;
1138 // We drop configure events for Client windows
1141 private void ShowCaret() {
1142 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1148 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1152 private void HideCaret() {
1153 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1159 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1163 private int NextTimeout (ArrayList timers, DateTime now) {
1164 int timeout = Int32.MaxValue;
1166 foreach (Timer timer in timers) {
1167 int next = (int) (timer.Expires - now).TotalMilliseconds;
1169 return 0; // Have a timer that has already expired
1172 if (next < timeout) {
1176 if (timeout < Timer.Minimum) {
1177 timeout = Timer.Minimum;
1185 private void CheckTimers (ArrayList timers, DateTime now) {
1188 count = timers.Count;
1193 for (int i = 0; i < timers.Count; i++) {
1196 timer = (Timer) timers [i];
1198 if (timer.Enabled && timer.Expires <= now) {
1205 private void MapWindow(Hwnd hwnd, WindowType windows) {
1207 if ((windows & WindowType.Whole) != 0) {
1208 XMapWindow(DisplayHandle, hwnd.whole_window);
1210 if ((windows & WindowType.Client) != 0) {
1211 XMapWindow(DisplayHandle, hwnd.client_window);
1215 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1216 hwnd.mapped = false;
1217 if ((windows & WindowType.Whole) != 0) {
1218 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1220 if ((windows & WindowType.Client) != 0) {
1221 XUnmapWindow(DisplayHandle, hwnd.client_window);
1225 private void UpdateMessageQueue (XEventQueue queue) {
1230 now = DateTime.UtcNow;
1233 pending = XPending (DisplayHandle);
1237 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1238 Idle (this, EventArgs.Empty);
1242 pending = XPending (DisplayHandle);
1249 if (queue != null) {
1250 if (queue.Paint.Count > 0)
1253 timeout = NextTimeout (queue.timer_list, now);
1258 int length = pollfds.Length - 1;
1259 lock (wake_waiting_lock) {
1260 if (wake_waiting == false) {
1262 wake_waiting = true;
1266 Syscall.poll (pollfds, (uint)length, timeout);
1267 // Clean out buffer, so we're not busy-looping on the same data
1268 if (pollfds[1].revents != 0) {
1269 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1270 wake_waiting = false;
1274 pending = XPending (DisplayHandle);
1280 CheckTimers (queue.timer_list, now);
1283 XEvent xevent = new XEvent ();
1286 if (XPending (DisplayHandle) == 0)
1289 XNextEvent (DisplayHandle, ref xevent);
1291 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1292 if (XFilterEvent(ref xevent, FosterParent)) {
1298 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1302 switch (xevent.type) {
1303 case XEventName.Expose:
1304 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1307 case XEventName.SelectionClear: {
1308 // Should we do something?
1312 case XEventName.SelectionRequest: {
1313 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1317 sel_event = new XEvent();
1318 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1319 sel_event.SelectionEvent.send_event = true;
1320 sel_event.SelectionEvent.display = DisplayHandle;
1321 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1322 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1323 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1324 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1325 sel_event.SelectionEvent.property = IntPtr.Zero;
1327 // Seems that some apps support asking for supported types
1328 if (xevent.SelectionEvent.target == TARGETS) {
1335 if (Clipboard.Item is String) {
1336 atoms[atom_count++] = (int)Atom.XA_STRING;
1337 atoms[atom_count++] = (int)OEMTEXT;
1338 atoms[atom_count++] = (int)UNICODETEXT;
1339 } else if (Clipboard.Item is Image) {
1340 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1341 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1343 // FIXME - handle other types
1346 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1347 } else if (Clipboard.Item is string) {
1353 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1356 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1357 buffer = Marshal.AllocHGlobal(bytes.Length);
1358 buflen = bytes.Length;
1360 for (int i = 0; i < buflen; i++) {
1361 Marshal.WriteByte(buffer, i, bytes[i]);
1363 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1364 // FIXME - this should encode into ISO2022
1365 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1366 while (Marshal.ReadByte(buffer, buflen) != 0) {
1369 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1370 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1371 while (Marshal.ReadByte(buffer, buflen) != 0) {
1375 buffer = IntPtr.Zero;
1378 if (buffer != IntPtr.Zero) {
1379 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1380 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1381 Marshal.FreeHGlobal(buffer);
1383 } else if (Clipboard.Item is Image) {
1384 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1385 // FIXME - convert image and store as property
1386 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1387 // FIXME - convert image and store as property
1391 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1395 case XEventName.SelectionNotify: {
1396 if (Clipboard.Enumerating) {
1397 Clipboard.Enumerating = false;
1398 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1399 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1400 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1401 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1402 #if DriverDebugExtra
1403 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1407 } else if (Clipboard.Retrieving) {
1408 Clipboard.Retrieving = false;
1409 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1410 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1412 Clipboard.Item = null;
1415 Dnd.HandleSelectionNotifyEvent (ref xevent);
1420 case XEventName.MapNotify: {
1421 if (hwnd.client_window == xevent.MapEvent.window) {
1427 case XEventName.UnmapNotify: {
1428 if (hwnd.client_window == xevent.MapEvent.window) {
1429 hwnd.mapped = false;
1434 case XEventName.KeyRelease:
1435 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1436 XEvent nextevent = new XEvent ();
1438 XPeekEvent (DisplayHandle, ref nextevent);
1440 if (nextevent.type == XEventName.KeyPress &&
1441 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1442 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1446 goto case XEventName.KeyPress;
1448 case XEventName.MotionNotify: {
1451 /* we can't do motion compression across threads, so just punt if we don't match up */
1452 if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1453 peek = hwnd.Queue.Peek();
1454 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1458 goto case XEventName.KeyPress;
1461 case XEventName.KeyPress:
1462 case XEventName.ButtonPress:
1463 case XEventName.ButtonRelease:
1464 case XEventName.EnterNotify:
1465 case XEventName.LeaveNotify:
1466 case XEventName.CreateNotify:
1467 case XEventName.DestroyNotify:
1468 case XEventName.FocusIn:
1469 case XEventName.FocusOut:
1470 case XEventName.ClientMessage:
1471 case XEventName.ReparentNotify:
1472 hwnd.Queue.EnqueueLocked (xevent);
1475 case XEventName.ConfigureNotify:
1476 AddConfigureNotify(xevent);
1479 case XEventName.PropertyNotify:
1480 if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1485 IntPtr prop = IntPtr.Zero;
1488 prev_active = ActiveWindow;
1489 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);
1490 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1491 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1494 if (prev_active != ActiveWindow) {
1495 if (prev_active != IntPtr.Zero) {
1496 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1498 if (ActiveWindow != IntPtr.Zero) {
1499 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1502 if (ModalWindows.Count == 0) {
1505 // Modality handling, if we are modal and the new active window is one
1506 // of ours but not the modal one, switch back to the modal window
1508 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1509 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1510 Activate((IntPtr)ModalWindows.Peek());
1523 private IntPtr GetMousewParam(int Delta) {
1526 if ((MouseState & MouseButtons.Left) != 0) {
1527 result |= (int)MsgButtons.MK_LBUTTON;
1530 if ((MouseState & MouseButtons.Middle) != 0) {
1531 result |= (int)MsgButtons.MK_MBUTTON;
1534 if ((MouseState & MouseButtons.Right) != 0) {
1535 result |= (int)MsgButtons.MK_RBUTTON;
1538 Keys mods = ModifierKeys;
1539 if ((mods & Keys.Control) != 0) {
1540 result |= (int)MsgButtons.MK_CONTROL;
1543 if ((mods & Keys.Shift) != 0) {
1544 result |= (int)MsgButtons.MK_SHIFT;
1547 result |= Delta << 16;
1549 return (IntPtr)result;
1551 private IntPtr XGetParent(IntPtr handle) {
1558 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1561 if (Children!=IntPtr.Zero) {
1569 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1570 if (ErrorExceptions) {
1571 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1573 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), Environment.StackTrace);
1578 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1581 Control[] controls = c.Controls.GetAllControls ();
1583 if (c.IsHandleCreated && !c.IsDisposed) {
1584 Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1586 #if DriverDebug || DriverDebugDestroy
1587 Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1588 Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1592 CleanupCachedWindows (hwnd);
1596 for (int i = 0; i < controls.Length; i ++) {
1597 AccumulateDestroyedHandles (controls[i], list);
1603 void CleanupCachedWindows (Hwnd hwnd)
1605 if (ActiveWindow == hwnd.Handle) {
1606 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1607 ActiveWindow = IntPtr.Zero;
1610 if (FocusWindow == hwnd.Handle) {
1611 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1612 FocusWindow = IntPtr.Zero;
1615 if (Grab.Hwnd == hwnd.Handle) {
1616 Grab.Hwnd = IntPtr.Zero;
1617 Grab.Confined = false;
1620 DestroyCaret (hwnd.Handle);
1623 private void PerformNCCalc(Hwnd hwnd) {
1624 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1628 rect = hwnd.DefaultClientRect;
1630 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1631 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1633 ncp.rgrc1.left = rect.Left;
1634 ncp.rgrc1.top = rect.Top;
1635 ncp.rgrc1.right = rect.Right;
1636 ncp.rgrc1.bottom = rect.Bottom;
1638 Marshal.StructureToPtr(ncp, ptr, true);
1639 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1640 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1641 Marshal.FreeHGlobal(ptr);
1643 // FIXME - debug this with Menus
1645 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1646 hwnd.ClientRect = rect;
1649 if ((rect.Width < 1) || (rect.Height < 1)) {
1650 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1652 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1656 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
1658 #endregion // Private Methods
1661 private void MouseHover(object sender, EventArgs e) {
1665 HoverState.Timer.Enabled = false;
1667 if (HoverState.Window != IntPtr.Zero) {
1668 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1670 xevent = new XEvent ();
1672 xevent.type = XEventName.ClientMessage;
1673 xevent.ClientMessageEvent.display = DisplayHandle;
1674 xevent.ClientMessageEvent.window = HoverState.Window;
1675 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1676 xevent.ClientMessageEvent.format = 32;
1677 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1679 hwnd.Queue.EnqueueLocked (xevent);
1686 private void CaretCallback(object sender, EventArgs e) {
1690 Caret.On = !Caret.On;
1692 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1694 #endregion // Callbacks
1696 #region Public Properties
1698 internal override int Caption {
1704 internal override Size CursorSize {
1709 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1710 return new Size(x, y);
1712 return new Size(16, 16);
1717 internal override bool DragFullWindows {
1723 internal override Size DragSize {
1725 return new Size(4, 4);
1729 internal override Size FrameBorderSize {
1731 throw new NotImplementedException();
1735 internal override Size IconSize {
1741 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1745 current = (long)list;
1748 size = new XIconSize();
1750 for (int i = 0; i < count; i++) {
1751 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1752 current += Marshal.SizeOf(size);
1754 // Look for our preferred size
1755 if (size.min_width == 32) {
1757 return new Size(32, 32);
1760 if (size.max_width == 32) {
1762 return new Size(32, 32);
1765 if (size.min_width < 32 && size.max_width > 32) {
1768 // check if we can fit one
1770 while (x < size.max_width) {
1771 x += size.width_inc;
1774 return new Size(32, 32);
1779 if (largest < size.max_width) {
1780 largest = size.max_width;
1784 // We didn't find a match or we wouldn't be here
1785 return new Size(largest, largest);
1788 return new Size(32, 32);
1793 internal override int KeyboardSpeed {
1796 // A lot harder: need to do:
1797 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1798 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1799 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1801 // And from that we can tell the repetition rate
1803 // Notice, the values must map to:
1804 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1810 internal override int KeyboardDelay {
1813 // Return values must range from 0 to 4, 0 meaning 250ms,
1814 // and 4 meaning 1000 ms.
1816 return 1; // ie, 500 ms
1820 internal override Size MaxWindowTrackSize {
1822 return new Size (WorkingArea.Width, WorkingArea.Height);
1826 internal override Size MinimizedWindowSize {
1828 return new Size(1, 1);
1832 internal override Size MinimizedWindowSpacingSize {
1834 return new Size(1, 1);
1838 internal override Size MinimumWindowSize {
1840 return new Size(1, 1);
1844 internal override Size MinWindowTrackSize {
1846 return new Size(1, 1);
1850 internal override Keys ModifierKeys {
1852 return Keyboard.ModifierKeys;
1856 internal override Size SmallIconSize {
1862 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1866 current = (long)list;
1869 size = new XIconSize();
1871 for (int i = 0; i < count; i++) {
1872 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1873 current += Marshal.SizeOf(size);
1875 // Look for our preferred size
1876 if (size.min_width == 16) {
1878 return new Size(16, 16);
1881 if (size.max_width == 16) {
1883 return new Size(16, 16);
1886 if (size.min_width < 16 && size.max_width > 16) {
1889 // check if we can fit one
1891 while (x < size.max_width) {
1892 x += size.width_inc;
1895 return new Size(16, 16);
1900 if (smallest == 0 || smallest > size.min_width) {
1901 smallest = size.min_width;
1905 // We didn't find a match or we wouldn't be here
1906 return new Size(smallest, smallest);
1909 return new Size(16, 16);
1914 internal override int MouseButtonCount {
1920 internal override bool MouseButtonsSwapped {
1922 return false; // FIXME - how to detect?
1926 internal override Point MousePosition {
1928 return mouse_position;
1932 internal override Size MouseHoverSize {
1934 return new Size (1, 1);
1938 internal override int MouseHoverTime {
1940 return HoverState.Interval;
1946 internal override bool MouseWheelPresent {
1948 return true; // FIXME - how to detect?
1952 internal override Rectangle VirtualScreen {
1958 internal override Rectangle WorkingArea {
1964 IntPtr prop = IntPtr.Zero;
1967 int current_desktop;
1971 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);
1972 if ((long)nitems < 1) {
1976 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
1979 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);
1980 if ((long)nitems < 4 * current_desktop) {
1984 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
1985 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
1986 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
1987 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
1990 return new Rectangle(x, y, width, height);
1993 XWindowAttributes attributes=new XWindowAttributes();
1996 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1999 return new Rectangle(0, 0, attributes.width, attributes.height);
2003 internal override bool ThemesEnabled {
2005 return XplatUIX11.themes_enabled;
2010 #endregion // Public properties
2012 #region Public Static Methods
2013 internal override IntPtr InitializeDriver() {
2015 if (DisplayHandle==IntPtr.Zero) {
2016 SetDisplay(XOpenDisplay(IntPtr.Zero));
2022 internal override void ShutdownDriver(IntPtr token) {
2024 if (DisplayHandle!=IntPtr.Zero) {
2025 XCloseDisplay(DisplayHandle);
2026 DisplayHandle=IntPtr.Zero;
2031 internal override void EnableThemes() {
2032 themes_enabled = true;
2036 internal override void Activate(IntPtr handle) {
2039 hwnd = Hwnd.ObjectFromHandle(handle);
2043 if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2044 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2047 // XRaiseWindow(DisplayHandle, handle);
2053 internal override void AudibleAlert() {
2054 XBell(DisplayHandle, 0);
2059 internal override void CaretVisible(IntPtr handle, bool visible) {
2060 if (Caret.Hwnd == handle) {
2062 if (!Caret.Visible) {
2063 Caret.Visible = true;
2065 Caret.Timer.Start();
2068 Caret.Visible = false;
2075 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2076 FormBorderStyle border_style;
2077 TitleStyle title_style;
2079 int tool_caption_height;
2081 DeriveStyles(Style, ExStyle, out border_style, out title_style,
2082 out caption_height, out tool_caption_height);
2084 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2085 caption_height, tool_caption_height,
2090 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2096 hwnd = Hwnd.ObjectFromHandle(handle);
2099 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2106 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2107 DataFormats.Format f;
2110 f = DataFormats.Format.List;
2112 if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2116 Clipboard.Formats = new ArrayList();
2119 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2121 Clipboard.Enumerating = true;
2122 while (Clipboard.Enumerating) {
2123 UpdateMessageQueue(null);
2128 result = new int[Clipboard.Formats.Count];
2130 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2131 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2134 Clipboard.Formats = null;
2138 internal override void ClipboardClose(IntPtr handle) {
2139 if (handle != ClipMagic) {
2140 throw new ArgumentException("handle is not a valid clipboard handle");
2145 internal override int ClipboardGetID(IntPtr handle, string format) {
2146 if (handle != ClipMagic) {
2147 throw new ArgumentException("handle is not a valid clipboard handle");
2150 if (format == "Text" ) return (int)Atom.XA_STRING;
2151 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2152 //else if (format == "MetaFilePict" ) return 3;
2153 //else if (format == "SymbolicLink" ) return 4;
2154 //else if (format == "DataInterchangeFormat" ) return 5;
2155 //else if (format == "Tiff" ) return 6;
2156 else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2157 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2158 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2159 //else if (format == "PenData" ) return 10;
2160 //else if (format == "RiffAudio" ) return 11;
2161 //else if (format == "WaveAudio" ) return 12;
2162 else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2163 //else if (format == "EnhancedMetafile" ) return 14;
2164 //else if (format == "FileDrop" ) return 15;
2165 //else if (format == "Locale" ) return 16;
2167 return XInternAtom(DisplayHandle, format, false).ToInt32();
2170 internal override IntPtr ClipboardOpen(bool primary_selection) {
2171 if (!primary_selection)
2172 ClipMagic = CLIPBOARD;
2174 ClipMagic = PRIMARY;
2178 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2179 XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2181 Clipboard.Retrieving = true;
2182 while (Clipboard.Retrieving) {
2183 UpdateMessageQueue(null);
2186 return Clipboard.Item;
2189 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2190 Clipboard.Item = obj;
2191 Clipboard.Type = type;
2192 Clipboard.Converter = converter;
2195 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2197 // Clearing the selection
2198 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2202 internal override void CreateCaret(IntPtr handle, int width, int height) {
2203 XGCValues gc_values;
2206 hwnd = Hwnd.ObjectFromHandle(handle);
2208 if (Caret.Hwnd != IntPtr.Zero) {
2209 DestroyCaret(Caret.Hwnd);
2212 Caret.Hwnd = handle;
2213 Caret.Window = hwnd.client_window;
2214 Caret.Width = width;
2215 Caret.Height = height;
2216 Caret.Visible = false;
2219 gc_values = new XGCValues();
2220 gc_values.line_width = width;
2222 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2223 if (Caret.gc == IntPtr.Zero) {
2224 Caret.Hwnd = IntPtr.Zero;
2228 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2231 internal override IntPtr CreateWindow(CreateParams cp) {
2232 XSetWindowAttributes Attributes;
2238 IntPtr ParentHandle;
2240 IntPtr ClientWindow;
2241 Rectangle ClientRect;
2242 SetWindowValuemask ValueMask;
2247 Attributes = new XSetWindowAttributes();
2253 if (Width<1) Width=1;
2254 if (Height<1) Height=1;
2256 if (cp.Parent != IntPtr.Zero) {
2257 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2259 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2260 // We need to use our foster parent window until this poor child gets it's parent assigned
2261 ParentHandle=FosterParent;
2262 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2263 ParentHandle=RootWindow;
2265 // Default position on screen, if window manager doesn't place us somewhere else
2268 ParentHandle=RootWindow;
2272 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2274 Attributes.bit_gravity = Gravity.NorthWestGravity;
2275 Attributes.win_gravity = Gravity.NorthWestGravity;
2277 // Save what's under the toolwindow
2278 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2279 Attributes.save_under = true;
2280 ValueMask |= SetWindowValuemask.SaveUnder;
2284 // If we're a popup without caption we override the WM
2285 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2286 Attributes.override_redirect = true;
2287 ValueMask |= SetWindowValuemask.OverrideRedirect;
2293 hwnd.height = Height;
2294 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2296 if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2297 hwnd.enabled = false;
2300 ClientRect = hwnd.ClientRect;
2301 ClientWindow = IntPtr.Zero;
2304 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2305 if (WholeWindow != IntPtr.Zero) {
2306 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2308 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2309 ValueMask = SetWindowValuemask.ColorMap;
2310 Attributes.colormap = CustomColormap;
2312 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);
2316 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2317 throw new Exception("Could not create X11 windows");
2320 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2321 hwnd.WholeWindow = WholeWindow;
2322 hwnd.ClientWindow = ClientWindow;
2324 #if DriverDebug || DriverDebugCreate
2325 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);
2328 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2329 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2332 hints = new XSizeHints();
2335 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2336 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2341 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2342 if (hwnd.whole_window != hwnd.client_window)
2343 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2345 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2346 MapWindow(hwnd, WindowType.Both);
2347 hwnd.visible = true;
2351 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2353 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2354 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2356 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2359 SetWMStyles(hwnd, cp);
2361 // set the group leader
2362 XWMHints wm_hints = new XWMHints ();
2364 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2365 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2366 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2368 if (ParentHandle != RootWindow) {
2369 wm_hints.window_group = hwnd.whole_window;
2371 wm_hints.window_group = ParentHandle;
2375 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2378 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2379 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2380 } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2381 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2384 // for now make all windows dnd enabled
2385 Dnd.SetAllowDrop (hwnd, true);
2387 // Set caption/window title
2388 Text(hwnd.Handle, cp.Caption);
2393 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2394 CreateParams create_params = new CreateParams();
2396 create_params.Caption = "";
2397 create_params.X = X;
2398 create_params.Y = Y;
2399 create_params.Width = Width;
2400 create_params.Height = Height;
2402 create_params.ClassName=XplatUI.DefaultClassName;
2403 create_params.ClassStyle = 0;
2404 create_params.ExStyle=0;
2405 create_params.Parent=IntPtr.Zero;
2406 create_params.Param=0;
2408 return CreateWindow(create_params);
2411 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2413 Bitmap cursor_bitmap;
2421 IntPtr cursor_pixmap;
2428 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2432 // Win32 only allows creation cursors of a certain size
2433 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2434 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2435 cursor_mask = new Bitmap(mask, new Size(width, height));
2437 cursor_bitmap = bitmap;
2441 width = cursor_bitmap.Width;
2442 height = cursor_bitmap.Height;
2444 cursor_bits = new Byte[(width / 8) * height];
2445 mask_bits = new Byte[(width / 8) * height];
2447 for (int y = 0; y < height; y++) {
2448 for (int x = 0; x < width; x++) {
2449 c_pixel = cursor_bitmap.GetPixel(x, y);
2450 m_pixel = cursor_mask.GetPixel(x, y);
2452 and = c_pixel == cursor_pixel;
2453 xor = m_pixel == mask_pixel;
2457 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2458 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2459 } else if (and && !xor) {
2461 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2462 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2464 } else if (and && !xor) {
2466 } else if (and && xor) {
2469 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2470 // we want both to be 0 so nothing to be done
2471 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2472 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2478 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2479 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2483 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2484 fg.red = (ushort)65535;
2485 fg.green = (ushort)65535;
2486 fg.blue = (ushort)65535;
2488 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2490 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2492 XFreePixmap(DisplayHandle, cursor_pixmap);
2493 XFreePixmap(DisplayHandle, mask_pixmap);
2498 internal override IntPtr DefineStdCursor(StdCursor id) {
2499 CursorFontShape shape;
2502 // FIXME - define missing shapes
2505 case StdCursor.AppStarting: {
2506 shape = CursorFontShape.XC_watch;
2510 case StdCursor.Arrow: {
2511 shape = CursorFontShape.XC_top_left_arrow;
2515 case StdCursor.Cross: {
2516 shape = CursorFontShape.XC_crosshair;
2520 case StdCursor.Default: {
2521 shape = CursorFontShape.XC_top_left_arrow;
2525 case StdCursor.Hand: {
2526 shape = CursorFontShape.XC_hand1;
2530 case StdCursor.Help: {
2531 shape = CursorFontShape.XC_question_arrow;
2535 case StdCursor.HSplit: {
2536 shape = CursorFontShape.XC_sb_v_double_arrow;
2540 case StdCursor.IBeam: {
2541 shape = CursorFontShape.XC_xterm;
2545 case StdCursor.No: {
2546 shape = CursorFontShape.XC_circle;
2550 case StdCursor.NoMove2D: {
2551 shape = CursorFontShape.XC_fleur;
2555 case StdCursor.NoMoveHoriz: {
2556 shape = CursorFontShape.XC_fleur;
2560 case StdCursor.NoMoveVert: {
2561 shape = CursorFontShape.XC_fleur;
2565 case StdCursor.PanEast: {
2566 shape = CursorFontShape.XC_fleur;
2570 case StdCursor.PanNE: {
2571 shape = CursorFontShape.XC_fleur;
2575 case StdCursor.PanNorth: {
2576 shape = CursorFontShape.XC_fleur;
2580 case StdCursor.PanNW: {
2581 shape = CursorFontShape.XC_fleur;
2585 case StdCursor.PanSE: {
2586 shape = CursorFontShape.XC_fleur;
2590 case StdCursor.PanSouth: {
2591 shape = CursorFontShape.XC_fleur;
2595 case StdCursor.PanSW: {
2596 shape = CursorFontShape.XC_fleur;
2600 case StdCursor.PanWest: {
2601 shape = CursorFontShape.XC_sizing;
2605 case StdCursor.SizeAll: {
2606 shape = CursorFontShape.XC_fleur;
2610 case StdCursor.SizeNESW: {
2611 shape = CursorFontShape.XC_top_right_corner;
2615 case StdCursor.SizeNS: {
2616 shape = CursorFontShape.XC_sb_v_double_arrow;
2620 case StdCursor.SizeNWSE: {
2621 shape = CursorFontShape.XC_top_left_corner;
2625 case StdCursor.SizeWE: {
2626 shape = CursorFontShape.XC_sb_h_double_arrow;
2630 case StdCursor.UpArrow: {
2631 shape = CursorFontShape.XC_center_ptr;
2635 case StdCursor.VSplit: {
2636 shape = CursorFontShape.XC_sb_h_double_arrow;
2640 case StdCursor.WaitCursor: {
2641 shape = CursorFontShape.XC_watch;
2651 cursor = XCreateFontCursor(DisplayHandle, shape);
2656 internal override IntPtr DefWndProc(ref Message msg) {
2657 switch ((Msg)msg.Msg) {
2658 case Msg.WM_PAINT: {
2661 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2663 hwnd.expose_pending = false;
2669 case Msg.WM_NCPAINT: {
2672 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2674 hwnd.nc_expose_pending = false;
2680 case Msg.WM_CONTEXTMENU: {
2683 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2685 if ((hwnd != null) && (hwnd.parent != null)) {
2686 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2691 case Msg.WM_MOUSEWHEEL: {
2694 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2696 if ((hwnd != null) && (hwnd.parent != null)) {
2697 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2698 if (msg.Result == IntPtr.Zero) {
2705 case Msg.WM_SETCURSOR: {
2708 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2710 break; // not sure how this happens, but it does
2712 // Pass to parent window first
2713 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2715 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2718 if (msg.Result == IntPtr.Zero) {
2721 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2722 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2723 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2724 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2725 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2726 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2729 handle = Cursors.Default.handle;
2732 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2733 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2734 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2735 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2736 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2737 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2740 case HitTest.HTGROWBOX:
2741 case HitTest.HTSIZE:
2742 case HitTest.HTZOOM:
2743 case HitTest.HTVSCROLL:
2744 case HitTest.HTSYSMENU:
2745 case HitTest.HTREDUCE:
2746 case HitTest.HTNOWHERE:
2747 case HitTest.HTMAXBUTTON:
2748 case HitTest.HTMINBUTTON:
2749 case HitTest.HTMENU:
2750 case HitTest.HSCROLL:
2751 case HitTest.HTBOTTOM:
2752 case HitTest.HTCAPTION:
2753 case HitTest.HTCLIENT:
2754 case HitTest.HTCLOSE:
2756 default: handle = Cursors.Default.handle; break;
2758 SetCursor(msg.HWnd, handle);
2766 internal override void DestroyCaret(IntPtr handle) {
2767 if (Caret.Hwnd == handle) {
2768 if (Caret.Visible == true) {
2771 if (Caret.gc != IntPtr.Zero) {
2772 XFreeGC(DisplayHandle, Caret.gc);
2773 Caret.gc = IntPtr.Zero;
2775 Caret.Hwnd = IntPtr.Zero;
2776 Caret.Visible = false;
2781 internal override void DestroyCursor(IntPtr cursor) {
2783 XFreeCursor(DisplayHandle, cursor);
2787 internal override void DestroyWindow(IntPtr handle) {
2790 hwnd = Hwnd.ObjectFromHandle(handle);
2793 #if DriverDebug || DriverDebugDestroy
2794 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2799 #if DriverDebug || DriverDebugDestroy
2800 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2803 CleanupCachedWindows (hwnd);
2805 ArrayList windows = new ArrayList ();
2807 AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2810 if (hwnd.whole_window != IntPtr.Zero) {
2811 #if DriverDebug || DriverDebugDestroy
2812 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2814 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2816 else if (hwnd.client_window != IntPtr.Zero) {
2817 #if DriverDebug || DriverDebugDestroy
2818 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2820 XDestroyWindow(DisplayHandle, hwnd.client_window);
2825 foreach (Hwnd h in windows) {
2826 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2830 internal override IntPtr DispatchMessage(ref MSG msg) {
2831 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2834 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2836 XGCValues gc_values;
2839 hwnd = Hwnd.ObjectFromHandle(handle);
2841 gc_values = new XGCValues();
2843 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2844 gc_values.line_width = line_width;
2845 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2847 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2848 //mask = foreground ^ background;
2849 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2850 //XSetBackground(DisplayHandle, gc, background);
2851 //XSetFunction(DisplayHandle, gc, GXxor);
2852 //XSetPlaneMask(DisplayHandle, gc, mask);
2855 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2860 control = Control.FromHandle(handle);
2862 XColor xcolor = new XColor();
2864 xcolor.red = (ushort)(control.ForeColor.R * 257);
2865 xcolor.green = (ushort)(control.ForeColor.G * 257);
2866 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2867 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2868 foreground = (uint)xcolor.pixel.ToInt32();
2870 xcolor.red = (ushort)(control.BackColor.R * 257);
2871 xcolor.green = (ushort)(control.BackColor.G * 257);
2872 xcolor.blue = (ushort)(control.BackColor.B * 257);
2873 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2874 background = (uint)xcolor.pixel.ToInt32();
2876 uint mask = foreground ^ background;
2878 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2879 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2880 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2881 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2883 if ((rect.Width > 0) && (rect.Height > 0)) {
2884 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2886 if (rect.Width > 0) {
2887 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2889 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2892 XFreeGC(DisplayHandle, gc);
2895 internal override void DoEvents() {
2896 MSG msg = new MSG ();
2899 if (OverrideCursorHandle != IntPtr.Zero) {
2900 OverrideCursorHandle = IntPtr.Zero;
2903 queue = ThreadQueue(Thread.CurrentThread);
2905 queue.DispatchIdle = false;
2907 while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2908 TranslateMessage (ref msg);
2909 DispatchMessage (ref msg);
2912 queue.DispatchIdle = true;
2915 internal override void EnableWindow(IntPtr handle, bool Enable) {
2918 hwnd = Hwnd.ObjectFromHandle(handle);
2920 hwnd.Enabled = Enable;
2924 internal override void EndLoop(Thread thread) {
2925 // This is where we one day will shut down the loop for the thread
2929 internal override IntPtr GetActive() {
2934 IntPtr prop = IntPtr.Zero;
2935 IntPtr active = IntPtr.Zero;
2937 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);
2938 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2939 active = (IntPtr)Marshal.ReadInt32(prop);
2943 if (active != IntPtr.Zero) {
2946 hwnd = Hwnd.GetObjectFromWindow(active);
2948 active = hwnd.Handle;
2950 active = IntPtr.Zero;
2956 internal override Region GetClipRegion(IntPtr handle) {
2959 hwnd = Hwnd.ObjectFromHandle(handle);
2961 return hwnd.UserClip;
2967 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2974 internal override void GetDisplaySize(out Size size) {
2975 XWindowAttributes attributes=new XWindowAttributes();
2978 // FIXME - use _NET_WM messages instead?
2979 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2982 size = new Size(attributes.width, attributes.height);
2985 internal override SizeF GetAutoScaleSize(Font font) {
2988 string magic_string = "The quick brown fox jumped over the lazy dog.";
2989 double magic_number = 44.549996948242189;
2991 g = Graphics.FromHwnd(FosterParent);
2993 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2994 return new SizeF(width, font.Height);
2997 internal override IntPtr GetParent(IntPtr handle) {
3000 hwnd = Hwnd.ObjectFromHandle(handle);
3001 if (hwnd != null && hwnd.parent != null) {
3002 return hwnd.parent.Handle;
3007 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3017 if (handle != IntPtr.Zero) {
3018 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3020 use_handle = RootWindow;
3024 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3027 if (handle != IntPtr.Zero) {
3036 internal override IntPtr GetFocus() {
3041 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3042 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3045 internal override Point GetMenuOrigin(IntPtr handle) {
3048 hwnd = Hwnd.ObjectFromHandle(handle);
3051 return hwnd.MenuOrigin;
3056 [MonoTODO("Implement filtering")]
3057 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3064 if (((XEventQueue)queue_id).Count > 0) {
3065 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3067 UpdateMessageQueue ((XEventQueue)queue_id);
3069 if (((XEventQueue)queue_id).Count > 0) {
3070 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3071 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3072 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3074 if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3075 msg.hwnd= IntPtr.Zero;
3076 msg.message = Msg.WM_ENTERIDLE;
3080 // We reset ourselves so GetMessage can be called again
3081 ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3087 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3089 // Handle messages for windows that are already or are about to be destroyed.
3091 // we need a special block for this because unless we remove the hwnd from the paint
3092 // queue it will always stay there (since we don't handle the expose), and we'll
3093 // effectively loop infinitely trying to repaint a non-existant window.
3094 if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3095 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3096 hwnd.Queue.Paint.Remove (hwnd);
3097 goto ProcessNextMessage;
3100 // We need to make sure we only allow DestroyNotify events through for zombie
3101 // hwnds, since much of the event handling code makes requests using the hwnd's
3102 // client_window, and that'll result in BadWindow errors if there's some lag
3103 // between the XDestroyWindow call and the DestroyNotify event.
3104 if (hwnd == null || hwnd.zombie) {
3105 #if DriverDebug || DriverDebugDestroy
3106 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3108 goto ProcessNextMessage;
3111 if (hwnd.client_window == xevent.AnyEvent.window) {
3113 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3116 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3119 msg.hwnd = hwnd.Handle;
3122 // If you add a new event to this switch make sure to add it in
3123 // UpdateMessage also unless it is not coming through the X event system.
3125 switch(xevent.type) {
3126 case XEventName.KeyPress: {
3127 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3131 case XEventName.KeyRelease: {
3132 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3136 case XEventName.ButtonPress: {
3137 switch(xevent.ButtonEvent.button) {
3139 MouseState |= MouseButtons.Left;
3141 msg.message = Msg.WM_LBUTTONDOWN;
3143 msg.message = Msg.WM_NCLBUTTONDOWN;
3144 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3146 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3147 msg.wParam=GetMousewParam(0);
3152 MouseState |= MouseButtons.Middle;
3154 msg.message = Msg.WM_MBUTTONDOWN;
3156 msg.message = Msg.WM_NCMBUTTONDOWN;
3157 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3159 msg.wParam=GetMousewParam(0);
3164 MouseState |= MouseButtons.Right;
3166 msg.message = Msg.WM_RBUTTONDOWN;
3168 msg.message = Msg.WM_NCRBUTTONDOWN;
3169 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3171 msg.wParam=GetMousewParam(0);
3176 msg.hwnd = FocusWindow;
3177 msg.message=Msg.WM_MOUSEWHEEL;
3178 msg.wParam=GetMousewParam(120);
3183 msg.hwnd = FocusWindow;
3184 msg.message=Msg.WM_MOUSEWHEEL;
3185 msg.wParam=GetMousewParam(-120);
3191 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3192 mouse_position.X = xevent.ButtonEvent.x;
3193 mouse_position.Y = xevent.ButtonEvent.y;
3195 if (!hwnd.Enabled) {
3198 msg.hwnd = hwnd.EnabledHwnd;
3199 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);
3200 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3203 if (Grab.Hwnd != IntPtr.Zero) {
3204 msg.hwnd = Grab.Hwnd;
3207 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3208 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3209 switch(xevent.ButtonEvent.button) {
3211 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3216 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3221 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3225 ClickPending.Pending = false;
3227 ClickPending.Pending = true;
3228 ClickPending.Hwnd = msg.hwnd;
3229 ClickPending.Message = msg.message;
3230 ClickPending.wParam = msg.wParam;
3231 ClickPending.lParam = msg.lParam;
3232 ClickPending.Time = (long)xevent.ButtonEvent.time;
3238 case XEventName.ButtonRelease: {
3240 Dnd.HandleButtonRelease (ref xevent);
3244 switch(xevent.ButtonEvent.button) {
3247 msg.message = Msg.WM_LBUTTONUP;
3249 msg.message = Msg.WM_NCLBUTTONUP;
3250 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3252 MouseState &= ~MouseButtons.Left;
3253 msg.wParam=GetMousewParam(0);
3259 msg.message = Msg.WM_MBUTTONUP;
3261 msg.message = Msg.WM_NCMBUTTONUP;
3262 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3264 MouseState &= ~MouseButtons.Middle;
3265 msg.wParam=GetMousewParam(0);
3271 msg.message = Msg.WM_RBUTTONUP;
3273 msg.message = Msg.WM_NCRBUTTONUP;
3274 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3276 MouseState &= ~MouseButtons.Right;
3277 msg.wParam=GetMousewParam(0);
3282 goto ProcessNextMessage;
3286 goto ProcessNextMessage;
3290 if (!hwnd.Enabled) {
3293 msg.hwnd = hwnd.EnabledHwnd;
3294 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);
3295 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3298 if (Grab.Hwnd != IntPtr.Zero) {
3299 msg.hwnd = Grab.Hwnd;
3302 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3303 mouse_position.X = xevent.ButtonEvent.x;
3304 mouse_position.Y = xevent.ButtonEvent.y;
3308 case XEventName.MotionNotify: {
3310 #if DriverDebugExtra
3311 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);
3314 if (Dnd.HandleMotionNotify (ref xevent))
3315 goto ProcessNextMessage;
3316 if (Grab.Hwnd != IntPtr.Zero) {
3317 msg.hwnd = Grab.Hwnd;
3319 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3322 msg.message = Msg.WM_MOUSEMOVE;
3323 msg.wParam = GetMousewParam(0);
3324 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3326 if (!hwnd.Enabled) {
3329 msg.hwnd = hwnd.EnabledHwnd;
3330 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);
3331 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3334 mouse_position.X = xevent.MotionEvent.x;
3335 mouse_position.Y = xevent.MotionEvent.y;
3337 if ((HoverState.Timer.Enabled) &&
3338 (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3339 ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3340 ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3341 ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3342 HoverState.Timer.Stop();
3343 HoverState.Timer.Start();
3344 HoverState.X = mouse_position.X;
3345 HoverState.Y = mouse_position.Y;
3355 #if DriverDebugExtra
3356 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);
3358 msg.message = Msg.WM_NCMOUSEMOVE;
3360 if (!hwnd.Enabled) {
3361 msg.hwnd = hwnd.EnabledHwnd;
3362 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);
3363 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3366 // The hit test is sent in screen coordinates
3367 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3368 xevent.MotionEvent.x, xevent.MotionEvent.y,
3369 out screen_x, out screen_y, out dummy);
3371 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3372 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3373 IntPtr.Zero, msg.lParam).ToInt32 ();
3374 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3376 mouse_position.X = xevent.MotionEvent.x;
3377 mouse_position.Y = xevent.MotionEvent.y;
3383 case XEventName.EnterNotify: {
3384 if (!hwnd.Enabled) {
3385 goto ProcessNextMessage;
3387 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3388 goto ProcessNextMessage;
3390 msg.message = Msg.WM_MOUSE_ENTER;
3391 HoverState.X = xevent.CrossingEvent.x;
3392 HoverState.Y = xevent.CrossingEvent.y;
3393 HoverState.Timer.Enabled = true;
3394 HoverState.Window = xevent.CrossingEvent.window;
3398 case XEventName.LeaveNotify: {
3399 if (!hwnd.Enabled) {
3400 goto ProcessNextMessage;
3402 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3403 goto ProcessNextMessage;
3405 msg.message=Msg.WM_MOUSE_LEAVE;
3406 HoverState.Timer.Enabled = false;
3407 HoverState.Window = IntPtr.Zero;
3412 case XEventName.CreateNotify: {
3413 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3414 msg.message = WM_CREATE;
3415 // Set up CreateStruct
3417 goto ProcessNextMessage;
3424 case XEventName.ReparentNotify: {
3425 if (hwnd.parent == null) { // Toplevel
3426 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3427 // We need to adjust x/y
3428 // This sucks ass, part 2
3429 // Every WM does the reparenting of toplevel windows different, so there's
3430 // no standard way of getting our adjustment considering frames/decorations
3431 // The code below is needed for metacity. KDE doesn't works just fine without this
3439 hwnd.Reparented = true;
3441 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);
3442 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3443 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3446 hwnd.whacky_wm = true;
3449 if (hwnd.opacity != 0xffffffff) {
3452 opacity = (IntPtr)(Int32)hwnd.opacity;
3453 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3455 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3456 goto ProcessNextMessage;
3458 hwnd.Reparented = false;
3459 goto ProcessNextMessage;
3462 goto ProcessNextMessage;
3465 case XEventName.ConfigureNotify: {
3466 if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3467 #if DriverDebugExtra
3468 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);
3470 // if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3471 lock (hwnd.configure_lock) {
3472 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3473 hwnd.configure_pending = false;
3476 // We need to adjust our client window to track the resize of whole_window
3477 if (hwnd.whole_window != hwnd.client_window)
3478 PerformNCCalc(hwnd);
3481 goto ProcessNextMessage;
3484 case XEventName.FocusIn: {
3485 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3486 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3487 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3488 // about it having focus again
3489 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3490 goto ProcessNextMessage;
3493 if (FocusWindow == IntPtr.Zero) {
3494 Control c = Control.FromHandle (hwnd.client_window);
3496 goto ProcessNextMessage;
3497 Form form = c.FindForm ();
3499 goto ProcessNextMessage;
3500 ActiveWindow = form.Handle;
3501 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3502 goto ProcessNextMessage;
3504 Keyboard.FocusIn(FocusWindow);
3505 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3506 goto ProcessNextMessage;
3509 case XEventName.FocusOut: {
3510 // Se the comment for our FocusIn handler
3511 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3512 goto ProcessNextMessage;
3514 Keyboard.FocusOut(FocusWindow);
3516 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3517 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3520 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3521 goto ProcessNextMessage;
3524 case XEventName.Expose: {
3525 if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3527 hwnd.expose_pending = false;
3529 hwnd.nc_expose_pending = false;
3531 goto ProcessNextMessage;
3535 if (!hwnd.expose_pending) {
3536 goto ProcessNextMessage;
3539 if (!hwnd.nc_expose_pending) {
3540 goto ProcessNextMessage;
3543 switch (hwnd.border_style) {
3544 case FormBorderStyle.Fixed3D: {
3547 g = Graphics.FromHwnd(hwnd.whole_window);
3548 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3553 case FormBorderStyle.FixedSingle: {
3556 g = Graphics.FromHwnd(hwnd.whole_window);
3557 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3562 #if DriverDebugExtra
3563 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);
3566 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3567 Region region = new Region (rect);
3568 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3569 msg.message = Msg.WM_NCPAINT;
3570 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3571 msg.refobject = region;
3574 #if DriverDebugExtra
3575 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);
3577 if (Caret.Visible == true) {
3578 Caret.Paused = true;
3582 if (Caret.Visible == true) {
3584 Caret.Paused = false;
3586 msg.message = Msg.WM_PAINT;
3590 case XEventName.DestroyNotify: {
3592 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3593 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3595 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3596 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3597 CleanupCachedWindows (hwnd);
3599 #if DriverDebugDestroy
3600 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3603 msg.hwnd = hwnd.client_window;
3604 msg.message=Msg.WM_DESTROY;
3607 goto ProcessNextMessage;
3613 case XEventName.ClientMessage: {
3614 if (Dnd.HandleClientMessage (ref xevent)) {
3615 goto ProcessNextMessage;
3618 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3619 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3620 goto ProcessNextMessage;
3623 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3624 msg.message = Msg.WM_MOUSEHOVER;
3625 msg.wParam = GetMousewParam(0);
3626 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3630 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3631 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3632 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3633 msg.wParam = xevent.ClientMessageEvent.ptr3;
3634 msg.lParam = xevent.ClientMessageEvent.ptr4;
3638 if (xevent.ClientMessageEvent.message_type == _XEMBED) {
3639 #if DriverDebugXEmbed
3640 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
3643 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
3644 XSizeHints hints = new XSizeHints();
3647 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
3649 hwnd.width = hints.max_width;
3650 hwnd.height = hints.max_height;
3651 hwnd.ClientRect = Rectangle.Empty;
3652 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3656 if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3657 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3658 msg.message = Msg.WM_CLOSE;
3662 // We should not get this, but I'll leave the code in case we need it in the future
3663 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3664 goto ProcessNextMessage;
3667 goto ProcessNextMessage;
3671 goto ProcessNextMessage;
3678 internal override bool GetText(IntPtr handle, out string text) {
3685 IntPtr prop = IntPtr.Zero;
3687 XGetWindowProperty(DisplayHandle, handle,
3688 _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
3689 UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3691 if ((long)nitems > 0 && prop != IntPtr.Zero) {
3692 text = Marshal.PtrToStringUni (prop, (int)nitems);
3697 // fallback on the non-_NET property
3700 textptr = IntPtr.Zero;
3702 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3703 if (textptr != IntPtr.Zero) {
3704 text = Marshal.PtrToStringAnsi(textptr);
3715 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) {
3718 hwnd = Hwnd.ObjectFromHandle(handle);
3724 height = hwnd.height;
3726 PerformNCCalc(hwnd);
3728 client_width = hwnd.ClientRect.Width;
3729 client_height = hwnd.ClientRect.Height;
3734 // Should we throw an exception or fail silently?
3735 // throw new ArgumentException("Called with an invalid window handle", "handle");
3745 internal override FormWindowState GetWindowState(IntPtr handle) {
3750 IntPtr prop = IntPtr.Zero;
3754 XWindowAttributes attributes;
3757 hwnd = Hwnd.ObjectFromHandle(handle);
3761 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);
3762 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3763 for (int i = 0; i < (long)nitems; i++) {
3764 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3765 if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3767 } else if (atom == _NET_WM_STATE_HIDDEN) {
3775 return FormWindowState.Minimized;
3776 } else if (maximized == 2) {
3777 return FormWindowState.Maximized;
3780 attributes = new XWindowAttributes();
3781 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3782 if (attributes.map_state == MapState.IsUnmapped) {
3783 return (FormWindowState)(-1);
3787 return FormWindowState.Normal;
3790 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3792 GrabConfined = Grab.Confined;
3793 GrabArea = Grab.Area;
3796 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3798 IntPtr confine_to_window;
3800 confine_to_window = IntPtr.Zero;
3802 if (confine_to_handle != IntPtr.Zero) {
3803 XWindowAttributes attributes = new XWindowAttributes();
3805 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3808 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3810 Grab.Area.X = attributes.x;
3811 Grab.Area.Y = attributes.y;
3812 Grab.Area.Width = attributes.width;
3813 Grab.Area.Height = attributes.height;
3814 Grab.Confined = true;
3815 confine_to_window = hwnd.client_window;
3820 hwnd = Hwnd.ObjectFromHandle(handle);
3823 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3824 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3825 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3826 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3830 internal override void UngrabWindow(IntPtr hwnd) {
3832 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3833 XFlush(DisplayHandle);
3835 Grab.Hwnd = IntPtr.Zero;
3836 Grab.Confined = false;
3839 internal override void HandleException(Exception e) {
3840 StackTrace st = new StackTrace(e, true);
3841 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3842 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3845 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3848 hwnd = Hwnd.ObjectFromHandle(handle);
3851 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3853 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3857 internal override void InvalidateNC (IntPtr handle) {
3860 hwnd = Hwnd.ObjectFromHandle(handle);
3862 AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
3865 internal override bool IsEnabled(IntPtr handle) {
3866 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3867 return (hwnd != null && hwnd.Enabled);
3870 internal override bool IsVisible(IntPtr handle) {
3871 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3872 return (hwnd != null && hwnd.visible);
3875 internal override void KillTimer(Timer timer) {
3876 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3878 if (queue == null) {
3879 // This isn't really an error, MS doesn't start the timer if
3880 // it has no assosciated queue
3883 queue.timer_list.Remove (timer);
3886 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3892 hwnd = Hwnd.ObjectFromHandle(handle);
3895 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3902 internal override void OverrideCursor(IntPtr cursor) {
3903 OverrideCursorHandle = cursor;
3906 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3907 PaintEventArgs paint_event;
3910 hwnd = Hwnd.ObjectFromHandle(handle);
3912 if (Caret.Visible == true) {
3913 Caret.Paused = true;
3920 dc = Graphics.FromHwnd (hwnd.client_window);
3922 Region clip_region = new Region ();
3923 clip_region.MakeEmpty();
3925 foreach (Rectangle r in hwnd.ClipRectangles) {
3926 clip_region.Union (r);
3929 if (hwnd.UserClip != null) {
3930 clip_region.Intersect(hwnd.UserClip);
3933 dc.Clip = clip_region;
3934 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
3935 hwnd.expose_pending = false;
3937 hwnd.ClearInvalidArea();
3939 hwnd.drawing_stack.Push (paint_event);
3940 hwnd.drawing_stack.Push (dc);
3944 dc = Graphics.FromHwnd (hwnd.whole_window);
3946 if (!hwnd.nc_invalid.IsEmpty) {
3947 dc.SetClip (hwnd.nc_invalid);
3948 paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
3950 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3952 hwnd.nc_expose_pending = false;
3954 hwnd.ClearNcInvalidArea ();
3956 hwnd.drawing_stack.Push (paint_event);
3957 hwnd.drawing_stack.Push (dc);
3963 internal override void PaintEventEnd(IntPtr handle, bool client) {
3966 hwnd = Hwnd.ObjectFromHandle(handle);
3968 Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
3972 PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
3973 pe.SetGraphics (null);
3976 if (Caret.Visible == true) {
3978 Caret.Paused = false;
3982 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3983 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3984 XEventQueue queue = (XEventQueue) queue_id;
3987 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3988 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3992 if (queue.Count > 0) {
3995 // Only call UpdateMessageQueue if real events are pending
3996 // otherwise we go to sleep on the socket
3997 if (XPending(DisplayHandle) != 0) {
3998 UpdateMessageQueue((XEventQueue)queue_id);
4000 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4005 CheckTimers(queue.timer_list, DateTime.UtcNow);
4010 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4013 // FIXME - I think this should just enqueue directly
4014 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4015 XEvent xevent = new XEvent ();
4016 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4018 xevent.type = XEventName.ClientMessage;
4019 xevent.ClientMessageEvent.display = DisplayHandle;
4022 xevent.ClientMessageEvent.window = hwnd.whole_window;
4024 xevent.ClientMessageEvent.window = IntPtr.Zero;
4027 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4028 xevent.ClientMessageEvent.format = 32;
4029 xevent.ClientMessageEvent.ptr1 = handle;
4030 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4031 xevent.ClientMessageEvent.ptr3 = wparam;
4032 xevent.ClientMessageEvent.ptr4 = lparam;
4034 hwnd.Queue.EnqueueLocked (xevent);
4039 internal override void PostQuitMessage(int exitCode) {
4041 XFlush(DisplayHandle);
4042 ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4045 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4050 internal override void RequestNCRecalc(IntPtr handle) {
4053 hwnd = Hwnd.ObjectFromHandle(handle);
4059 PerformNCCalc(hwnd);
4060 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4061 InvalidateNC(handle);
4064 internal override void ResetMouseHover(IntPtr handle) {
4067 hwnd = Hwnd.ObjectFromHandle(handle);
4072 HoverState.Timer.Enabled = true;
4073 HoverState.X = mouse_position.X;
4074 HoverState.Y = mouse_position.Y;
4075 HoverState.Window = handle;
4079 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4085 hwnd = Hwnd.ObjectFromHandle(handle);
4088 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4095 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4101 hwnd = Hwnd.ObjectFromHandle(handle);
4104 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4111 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4114 XGCValues gc_values;
4116 hwnd = Hwnd.ObjectFromHandle(handle);
4118 Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4120 /* We have an invalid area in the window we're scrolling.
4121 Adjust our stored invalid rectangle to to match the scrolled amount */
4136 if (area.Contains (hwnd.Invalid))
4137 hwnd.ClearInvalidArea ();
4138 hwnd.AddInvalidArea(r);
4141 gc_values = new XGCValues();
4143 if (with_children) {
4144 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4147 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4155 height = area.Height - YAmount;
4156 dest_y = area.Y + YAmount;
4159 src_y = area.Y - YAmount;
4160 height = area.Height + YAmount;
4166 width = area.Width - XAmount;
4167 dest_x = area.X + XAmount;
4170 src_x = area.X - XAmount;
4171 width = area.Width + XAmount;
4175 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4177 // Generate an expose for the area exposed by the horizontal scroll
4178 // We don't use AddExpose since we're
4180 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4181 } else if (XAmount < 0) {
4182 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4185 // Generate an expose for the area exposed by the vertical scroll
4187 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4188 } else if (YAmount < 0) {
4189 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4191 XFreeGC(DisplayHandle, gc);
4194 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4198 hwnd = Hwnd.GetObjectFromWindow(handle);
4200 rect = hwnd.ClientRect;
4203 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4206 internal override void SendAsyncMethod (AsyncMethodData method) {
4208 XEvent xevent = new XEvent ();
4210 hwnd = Hwnd.ObjectFromHandle(method.Handle);
4212 xevent.type = XEventName.ClientMessage;
4213 xevent.ClientMessageEvent.display = DisplayHandle;
4214 xevent.ClientMessageEvent.window = method.Handle;
4215 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4216 xevent.ClientMessageEvent.format = 32;
4217 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4219 hwnd.Queue.EnqueueLocked (xevent);
4224 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4226 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4229 h = Hwnd.ObjectFromHandle(hwnd);
4231 if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4232 AsyncMethodResult result;
4233 AsyncMethodData data;
4235 result = new AsyncMethodResult ();
4236 data = new AsyncMethodData ();
4239 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4240 data.Args = new object[] { hwnd, message, wParam, lParam };
4241 data.Result = result;
4243 SendAsyncMethod (data);
4244 #if DriverDebug || DriverDebugThreads
4245 Console.WriteLine ("Sending {0} message across.", message);
4250 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4253 internal override void SetAllowDrop (IntPtr handle, bool value)
4255 // We allow drop on all windows
4258 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4259 DragDropEffects allowed_effects)
4261 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4264 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4266 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4269 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4272 hwnd = Hwnd.ObjectFromHandle(handle);
4274 Form form = Control.FromHandle (handle) as Form;
4275 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4276 border_style == FormBorderStyle.SizableToolWindow)) {
4277 form.window_manager = new InternalWindowManager (form);
4280 hwnd.border_style = border_style;
4281 RequestNCRecalc(handle);
4284 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4285 if (Caret.Hwnd == handle) {
4292 if (Caret.Visible == true) {
4294 Caret.Timer.Start();
4299 internal override void SetClipRegion(IntPtr handle, Region region) {
4302 hwnd = Hwnd.ObjectFromHandle(handle);
4307 hwnd.UserClip = region;
4308 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4311 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4314 if (OverrideCursorHandle == IntPtr.Zero) {
4315 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4319 LastCursorHandle = cursor;
4320 LastCursorWindow = handle;
4322 hwnd = Hwnd.ObjectFromHandle(handle);
4324 if (cursor != IntPtr.Zero) {
4325 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4327 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4329 XFlush(DisplayHandle);
4334 hwnd = Hwnd.ObjectFromHandle(handle);
4336 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4340 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4341 out int root_x, out int root_y, out int child_x, out int child_y,
4344 /* this code was written with the help of
4345 glance at gdk. I never would have realized we
4346 needed a loop in order to traverse down in the
4347 hierarchy. I would have assumed you'd get the
4348 most deeply nested child and have to do
4349 XQueryTree to move back up the hierarchy..
4350 stupid me, of course. */
4353 XGrabServer (display);
4355 XQueryPointer(display, w, out root, out c,
4356 out root_x, out root_y, out child_x, out child_y,
4362 IntPtr child_last = IntPtr.Zero;
4363 while (c != IntPtr.Zero) {
4365 XQueryPointer(display, c, out root, out c,
4366 out root_x, out root_y, out child_x, out child_y,
4369 XUngrabServer (display);
4374 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4375 if (handle == IntPtr.Zero) {
4378 int root_x, root_y, child_x, child_y, mask;
4381 * QueryPointer before warping
4382 * because if the warp is on
4383 * the RootWindow, the x/y are
4384 * relative to the current
4387 QueryPointer (DisplayHandle, RootWindow,
4390 out root_x, out root_y,
4391 out child_x, out child_y,
4394 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4396 XFlush (DisplayHandle);
4398 /* then we need to a
4399 * QueryPointer after warping
4400 * to manually generate a
4401 * motion event for the window
4404 QueryPointer (DisplayHandle, RootWindow,
4407 out root_x, out root_y,
4408 out child_x, out child_y,
4411 Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4412 if (child_hwnd == null) {
4416 XEvent xevent = new XEvent ();
4418 xevent.type = XEventName.MotionNotify;
4419 xevent.MotionEvent.display = DisplayHandle;
4420 xevent.MotionEvent.window = child_hwnd.client_window;
4421 xevent.MotionEvent.root = RootWindow;
4422 xevent.MotionEvent.x = child_x;
4423 xevent.MotionEvent.y = child_y;
4424 xevent.MotionEvent.x_root = root_x;
4425 xevent.MotionEvent.y_root = root_y;
4426 xevent.MotionEvent.state = mask;
4428 child_hwnd.Queue.EnqueueLocked (xevent);
4433 hwnd = Hwnd.ObjectFromHandle(handle);
4435 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4440 internal override void SetFocus(IntPtr handle) {
4442 IntPtr prev_focus_window;
4444 hwnd = Hwnd.ObjectFromHandle(handle);
4446 if (hwnd.client_window == FocusWindow) {
4450 prev_focus_window = FocusWindow;
4451 FocusWindow = hwnd.client_window;
4453 if (prev_focus_window != IntPtr.Zero) {
4454 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4456 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4458 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4461 internal override void SetIcon(IntPtr handle, Icon icon) {
4464 hwnd = Hwnd.ObjectFromHandle(handle);
4466 SetIcon(hwnd, icon);
4470 internal override void SetMenu(IntPtr handle, Menu menu) {
4473 hwnd = Hwnd.ObjectFromHandle(handle);
4476 RequestNCRecalc(handle);
4479 internal override void SetModal(IntPtr handle, bool Modal) {
4481 ModalWindows.Push(handle);
4483 if (ModalWindows.Contains(handle)) {
4486 if (ModalWindows.Count > 0) {
4487 Activate((IntPtr)ModalWindows.Peek());
4492 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4495 hwnd = Hwnd.ObjectFromHandle(handle);
4496 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4499 #if DriverDebug || DriverDebugParent
4500 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4502 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4508 internal override void SetTimer (Timer timer) {
4509 XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4511 if (queue == null) {
4512 // This isn't really an error, MS doesn't start the timer if
4513 // it has no assosciated queue
4516 queue.timer_list.Add (timer);
4520 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4524 hwnd = Hwnd.ObjectFromHandle(handle);
4526 if (handle_owner != IntPtr.Zero) {
4527 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4538 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4539 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4541 if (hwnd_owner != null) {
4542 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4544 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4549 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4555 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4558 hwnd = Hwnd.ObjectFromHandle(handle);
4559 hwnd.visible = visible;
4563 if (Control.FromHandle(handle) is Form) {
4566 s = ((Form)Control.FromHandle(handle)).WindowState;
4568 MapWindow(hwnd, WindowType.Both);
4571 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4572 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4576 MapWindow(hwnd, WindowType.Both);
4578 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4580 UnmapWindow(hwnd, WindowType.Whole);
4586 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4591 hwnd = Hwnd.ObjectFromHandle(handle);
4596 hints = new XSizeHints();
4598 XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4599 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4600 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4601 hints.min_width = min.Width;
4602 hints.min_height = min.Height;
4605 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4606 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4607 hints.max_width = max.Width;
4608 hints.max_height = max.Height;
4611 if (hints.flags != IntPtr.Zero) {
4612 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4615 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4616 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4617 hints.x = maximized.X;
4618 hints.y = maximized.Y;
4619 hints.width = maximized.Width;
4620 hints.height = maximized.Height;
4622 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4623 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4628 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4631 hwnd = Hwnd.ObjectFromHandle(handle);
4637 // Win32 automatically changes negative width/height to 0.
4643 // X requires a sanity check for width & height; otherwise it dies
4644 if (hwnd.zero_sized && width > 0 && height > 0) {
4646 MapWindow(hwnd, WindowType.Whole);
4648 hwnd.zero_sized = false;
4651 if ((width < 1) || (height < 1)) {
4652 hwnd.zero_sized = true;
4653 UnmapWindow(hwnd, WindowType.Whole);
4656 // Save a server roundtrip (and prevent a feedback loop)
4657 if ((hwnd.x == x) && (hwnd.y == y) &&
4658 (hwnd.width == width) && (hwnd.height == height)) {
4662 if (!hwnd.zero_sized) {
4667 hwnd.height = height;
4668 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4670 if (hwnd.fixed_size) {
4671 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4675 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4676 PerformNCCalc(hwnd);
4680 // Update our position/size immediately, so
4681 // that future calls to SetWindowPos aren't
4682 // kept from calling XMoveResizeWindow (by the
4683 // "Save a server roundtrip" block above).
4687 hwnd.height = height;
4688 hwnd.ClientRect = Rectangle.Empty;
4691 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4692 FormWindowState current_state;
4695 hwnd = Hwnd.ObjectFromHandle(handle);
4697 current_state = GetWindowState(handle);
4699 if (current_state == state) {
4704 case FormWindowState.Normal: {
4706 if (current_state == FormWindowState.Minimized) {
4707 MapWindow(hwnd, WindowType.Both);
4708 } else if (current_state == FormWindowState.Maximized) {
4709 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4716 case FormWindowState.Minimized: {
4718 if (current_state == FormWindowState.Maximized) {
4719 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4721 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4726 case FormWindowState.Maximized: {
4728 if (current_state == FormWindowState.Minimized) {
4729 MapWindow(hwnd, WindowType.Both);
4732 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4740 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4743 hwnd = Hwnd.ObjectFromHandle(handle);
4744 SetHwndStyles(hwnd, cp);
4745 SetWMStyles(hwnd, cp);
4748 internal override double GetWindowTransparency(IntPtr handle)
4753 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4757 hwnd = Hwnd.ObjectFromHandle(handle);
4763 hwnd.opacity = (uint)(0xffffffff * transparency);
4764 opacity = (IntPtr)((int)hwnd.opacity);
4766 IntPtr w = hwnd.whole_window;
4767 if (hwnd.reparented)
4768 w = XGetParent (hwnd.whole_window);
4769 XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4772 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4773 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4781 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4784 } else if (!bottom) {
4785 Hwnd after_hwnd = null;
4787 if (after_handle != IntPtr.Zero) {
4788 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4791 XWindowChanges values = new XWindowChanges();
4793 if (after_hwnd == null) {
4794 // Work around metacity 'issues'
4798 atoms[0] = unixtime();
4799 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4801 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4802 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4804 //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4807 values.sibling = after_hwnd.whole_window;
4808 values.stack_mode = StackMode.Below;
4811 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4816 XLowerWindow(DisplayHandle, hwnd.whole_window);
4823 internal override void ShowCursor(bool show) {
4824 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4827 internal override object StartLoop(Thread thread) {
4828 return (Object) ThreadQueue(thread);
4831 internal override TransparencySupport SupportsTransparency() {
4832 // We need to check if the x compositing manager is running
4833 return TransparencySupport.Set;
4836 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4837 GetSystrayManagerWindow();
4839 if (SystrayMgrWindow != IntPtr.Zero) {
4840 XSizeHints size_hints;
4843 hwnd = Hwnd.ObjectFromHandle(handle);
4845 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4849 if (hwnd.client_window != hwnd.whole_window) {
4850 XDestroyWindow(DisplayHandle, hwnd.client_window);
4851 hwnd.client_window = hwnd.whole_window;
4853 /* by virtue of the way the tests are ordered when determining if it's PAINT
4854 or NCPAINT, client_window == whole_window will always be PAINT. So, if we're
4855 waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4856 there's a pending expose). */
4857 if (hwnd.nc_expose_pending) {
4858 hwnd.nc_expose_pending = false;
4859 if (!hwnd.expose_pending)
4860 hwnd.Queue.Paint.Remove (hwnd);
4864 size_hints = new XSizeHints();
4866 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4868 size_hints.min_width = 24;
4869 size_hints.min_height = 24;
4870 size_hints.max_width = 24;
4871 size_hints.max_height = 24;
4872 size_hints.base_width = 24;
4873 size_hints.base_height = 24;
4875 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4877 int[] atoms = new int[2];
4878 atoms [0] = 1; // Version 1
4879 atoms [1] = 1; // we want to be mapped
4881 // This line cost me 3 days...
4882 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4884 // Need to pick some reasonable defaults
4886 tt.AutomaticDelay = 100;
4887 tt.InitialDelay = 250;
4888 tt.ReshowDelay = 250;
4889 tt.ShowAlways = true;
4891 if ((tip != null) && (tip != string.Empty)) {
4892 tt.SetToolTip(Control.FromHandle(handle), tip);
4898 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4906 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4909 control = Control.FromHandle(handle);
4910 if (control != null && tt != null) {
4911 tt.SetToolTip(control, tip);
4919 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4921 #if GTKSOCKET_SUPPORTS_REPARENTING
4924 hwnd = Hwnd.ObjectFromHandle(handle);
4926 /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4927 * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4928 * 2. The client can reparent its window out of the embedder window.
4929 * 3. The client can destroy its window.
4931 * this call to SetParent is case 2, but in
4932 * the spec it also mentions that gtk doesn't
4933 * support this at present. Looking at HEAD
4934 * gtksocket-x11.c jives with this statement.
4936 * so we can't reparent. we have to destroy.
4938 SetParent(hwnd.whole_window, FosterParent);
4940 Control control = Control.FromHandle(handle);
4941 if (control is NotifyIcon.NotifyIconWindow)
4942 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
4945 // The caller can now re-dock it later...
4952 internal override bool Text(IntPtr handle, string text) {
4955 hwnd = Hwnd.ObjectFromHandle(handle);
4958 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
4959 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
4961 // XXX this has problems with UTF8.
4962 // we need to either use the actual
4963 // text if it's latin-1, or convert it
4964 // to compound text if it's in a
4965 // different charset.
4966 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4971 internal override bool TranslateMessage(ref MSG msg) {
4972 return Keyboard.TranslateMessage (ref msg);
4975 internal override void UpdateWindow(IntPtr handle) {
4978 hwnd = Hwnd.ObjectFromHandle(handle);
4980 if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
4984 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4985 hwnd.Queue.Paint.Remove(hwnd);
4988 internal override void CreateOffscreenDrawable (IntPtr handle,
4989 int width, int height,
4990 out object offscreen_drawable,
4991 out Graphics offscreen_dc)
4994 int x_out, y_out, width_out, height_out, border_width_out, depth_out;
4996 XGetGeometry (DisplayHandle, handle,
4998 out x_out, out y_out,
4999 out width_out, out height_out,
5000 out border_width_out, out depth_out);
5002 IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5004 offscreen_drawable = pixmap;
5006 offscreen_dc = Graphics.FromHwnd (pixmap);
5009 internal override void DestroyOffscreenDrawable (object offscreen_drawable,
5010 Graphics offscreen_dc)
5012 XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5013 offscreen_dc.Dispose ();
5016 internal override void BlitFromOffscreen (IntPtr dest_handle,
5018 object offscreen_drawable,
5019 Graphics offscreen_dc,
5022 XGCValues gc_values;
5025 gc_values = new XGCValues();
5027 gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5029 XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5030 gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5032 XFreeGC (DisplayHandle, gc);
5035 #endregion // Public Static Methods
5038 internal override event EventHandler Idle;
5039 #endregion // Events
5042 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5043 internal extern static IntPtr XOpenDisplay(IntPtr display);
5044 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5045 internal extern static int XCloseDisplay(IntPtr display);
5046 [DllImport ("libX11", EntryPoint="XSynchronize")]
5047 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5049 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5050 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);
5051 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5052 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5053 [DllImport ("libX11", EntryPoint="XMapWindow")]
5054 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5055 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5056 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5057 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5058 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5059 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5060 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5061 [DllImport ("libX11", EntryPoint="XRootWindow")]
5062 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5063 [DllImport ("libX11", EntryPoint="XNextEvent")]
5064 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5065 [DllImport ("libX11")]
5066 internal extern static int XConnectionNumber (IntPtr diplay);
5067 [DllImport ("libX11")]
5068 internal extern static int XPending (IntPtr diplay);
5069 [DllImport ("libX11", EntryPoint="XSelectInput")]
5070 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
5072 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
5073 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
5075 [DllImport ("libX11", EntryPoint="XReparentWindow")]
5076 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
5077 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
5078 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
5080 [DllImport ("libX11", EntryPoint="XResizeWindow")]
5081 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
5083 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
5084 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
5086 [DllImport ("libX11", EntryPoint="XFlush")]
5087 internal extern static int XFlush(IntPtr display);
5089 [DllImport ("libX11", EntryPoint="XSetWMName")]
5090 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
5092 [DllImport ("libX11", EntryPoint="XStoreName")]
5093 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
5095 [DllImport ("libX11", EntryPoint="XFetchName")]
5096 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5098 [DllImport ("libX11", EntryPoint="XSendEvent")]
5099 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5101 [DllImport ("libX11", EntryPoint="XQueryTree")]
5102 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);
5104 [DllImport ("libX11", EntryPoint="XFree")]
5105 internal extern static int XFree(IntPtr data);
5107 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5108 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5110 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5111 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5113 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5114 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5116 [DllImport ("libX11", EntryPoint="XInternAtom")]
5117 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5119 [DllImport ("libX11", EntryPoint="XInternAtoms")]
5120 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
5122 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5123 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5125 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5126 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);
5128 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5129 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5131 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5132 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);
5134 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5135 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);
5137 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5138 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);
5140 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5141 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);
5143 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5144 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);
5146 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5147 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);
5149 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5150 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);
5152 [DllImport ("libX11", EntryPoint="XClearWindow")]
5153 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5155 [DllImport ("libX11", EntryPoint="XClearArea")]
5156 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5159 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5160 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5162 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5163 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5165 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5166 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5168 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5169 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5171 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5172 internal extern static int XDefaultScreen(IntPtr display);
5174 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5175 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5177 [DllImport ("libX11", EntryPoint="XLookupColor")]
5178 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5180 [DllImport ("libX11", EntryPoint="XAllocColor")]
5181 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5183 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5184 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5186 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5187 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5189 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5190 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5192 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5193 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5195 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5196 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5198 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5199 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5201 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5202 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5204 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5205 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5207 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5208 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5210 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5211 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5213 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5214 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5217 [DllImport ("libX11", EntryPoint="XCreateGC")]
5218 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5220 [DllImport ("libX11", EntryPoint="XFreeGC")]
5221 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5223 [DllImport ("libX11", EntryPoint="XSetFunction")]
5224 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5226 [DllImport ("libX11", EntryPoint="XDrawLine")]
5227 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5229 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5230 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5232 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5233 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5235 [DllImport ("libX11", EntryPoint="XCopyArea")]
5236 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);
5238 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5239 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);
5241 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5242 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5244 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5245 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5247 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5248 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5250 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5251 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5253 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5254 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5256 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5257 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5259 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5260 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);
5262 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5263 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5265 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
5266 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
5268 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5269 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5271 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5272 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5274 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5275 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5277 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5278 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5280 [DllImport ("libX11", EntryPoint="XGrabServer")]
5281 internal extern static void XGrabServer(IntPtr display);
5283 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5284 internal extern static void XUngrabServer(IntPtr display);
5286 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5287 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5289 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5290 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5292 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5293 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5295 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5296 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5298 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5299 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5301 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5302 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5304 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5305 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5307 [DllImport ("libX11", EntryPoint="XInitThreads")]
5308 internal extern static int XInitThreads();
5310 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5311 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5313 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5314 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5316 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5317 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5319 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5320 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5322 [DllImport ("libX11", EntryPoint="XSetForeground")]
5323 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5325 [DllImport ("libX11", EntryPoint="XSetBackground")]
5326 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5328 [DllImport ("libX11", EntryPoint="XBell")]
5329 internal extern static int XBell(IntPtr display, int percent);
5331 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5332 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5334 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5335 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5337 [DllImport ("libX11")]
5338 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5340 [DllImport ("libX11")]
5341 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);