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
49 using System.ComponentModel;
50 using System.Collections;
51 using System.Diagnostics;
53 using System.Drawing.Drawing2D;
54 using System.Drawing.Imaging;
57 using System.Net.Sockets;
58 using System.Reflection;
59 using System.Runtime.InteropServices;
61 using System.Threading;
63 // Only do the poll when building with mono for now
65 using Mono.Unix.Native;
69 namespace System.Windows.Forms {
70 internal class XplatUIX11 : XplatUIDriver {
71 #region Local Variables
73 static volatile XplatUIX11 Instance;
74 private static int RefCount;
75 private static object XlibLock; // Our locking object
76 private static bool ThemesEnabled;
79 private static IntPtr DisplayHandle; // X11 handle to display
80 private static int ScreenNo; // Screen number used
81 private static IntPtr DefaultColormap; // Colormap for screen
82 private static IntPtr CustomVisual; // Visual for window creation
83 private static IntPtr CustomColormap; // Colormap for window creation
84 private static IntPtr RootWindow; // Handle of the root window for the screen/display
85 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
86 private static XErrorHandler ErrorHandler; // Error handler delegate
87 private static bool ErrorExceptions; // Throw exceptions on X errors
88 private static bool PostQuitState; // True if we've got an pending exit
91 private static IntPtr ClipMagic = new IntPtr(27051977);
92 private static ClipboardStruct Clipboard; // Our clipboard
95 private static IntPtr PostAtom; // PostMessage atom
96 private static IntPtr AsyncAtom; // Support for async messages
99 private static XEventQueue MessageQueue; // Holds our queued up events
101 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static X11Keyboard Keyboard; //
104 private static X11Dnd Dnd;
105 private static Socket listen; //
106 private static Socket wake; //
107 private static Socket wake_receive; //
108 private static byte[] network_buffer; //
112 private static IntPtr ActiveWindow; // Handle of the active window
113 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
116 private static Stack ModalWindows; // Stack of our modal windows
119 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
122 private static IntPtr LastCursorWindow; // The last window we set the cursor on
123 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
124 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
127 private static CaretStruct Caret; //
129 // Support for Window Styles
130 private static IntPtr[] NetAtoms; // All atoms we know
132 // mouse hover message generation
133 private static HoverStruct HoverState; //
135 // double click message generation
136 private static ClickStruct ClickPending; //
138 // Support for mouse grab
139 private static GrabStruct Grab; //
142 private static Point MousePosition; // Last position of mouse, in screen coords
143 internal static MouseButtons MouseState; // Last state of mouse buttons
146 private static ArrayList TimerList; // Holds SWF.Timers
149 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
151 const EventMask SelectInputMask = EventMask.ButtonPressMask |
152 EventMask.ButtonReleaseMask |
153 EventMask.KeyPressMask |
154 EventMask.KeyReleaseMask |
155 EventMask.EnterWindowMask |
156 EventMask.LeaveWindowMask |
157 EventMask.ExposureMask |
158 EventMask.FocusChangeMask |
159 EventMask.PointerMotionMask |
160 EventMask.VisibilityChangeMask |
161 EventMask.SubstructureNotifyMask |
162 EventMask.StructureNotifyMask;
164 static readonly object lockobj = new object ();
166 #endregion // Local Variables
168 private XplatUIX11() {
169 // Handle singleton stuff first
172 // Now regular initialization
173 XlibLock = new object ();
174 MessageQueue = new XEventQueue ();
175 TimerList = new ArrayList ();
178 ErrorExceptions = false;
180 // X11 Initialization
181 SetDisplay(XOpenDisplay(IntPtr.Zero));
182 X11DesktopColors.Initialize();
184 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
185 ErrorHandler = new XErrorHandler(HandleError);
186 XSetErrorHandler(ErrorHandler);
188 #endregion // Constructors
190 #region Singleton Specific Code
191 public static XplatUIX11 GetInstance() {
193 if (Instance == null) {
194 Instance=new XplatUIX11();
201 public int Reference {
208 #region Internal Properties
209 internal static IntPtr Display {
211 return DisplayHandle;
215 XplatUIX11.GetInstance().SetDisplay(value);
219 internal static int Screen {
229 internal static IntPtr RootWindowHandle {
239 internal static IntPtr Visual {
245 CustomVisual = value;
249 internal static IntPtr ColorMap {
251 return CustomColormap;
255 CustomColormap = value;
260 #region XExceptionClass
261 internal class XException : ApplicationException {
265 XRequest RequestCode;
269 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
270 this.Display = Display;
271 this.ResourceID = ResourceID;
272 this.Serial = Serial;
273 this.RequestCode = RequestCode;
274 this.ErrorCode = ErrorCode;
275 this.MinorCode = MinorCode;
278 public override string Message {
280 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
284 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
293 sb = new StringBuilder(160);
294 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
295 x_error_text = sb.ToString();
296 hwnd = Hwnd.ObjectFromHandle(ResourceID);
298 hwnd_text = hwnd.ToString();
299 c = Control.FromHandle(hwnd.Handle);
301 control_text = c.ToString();
303 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
306 hwnd_text = "<null>";
307 control_text = "<null>";
311 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);
315 #endregion // XExceptionClass
317 #region Internal Methods
318 internal void SetDisplay(IntPtr display_handle) {
319 if (display_handle != IntPtr.Zero) {
322 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
323 hwnd = Hwnd.ObjectFromHandle(FosterParent);
324 XDestroyWindow(DisplayHandle, FosterParent);
328 if (DisplayHandle != IntPtr.Zero) {
329 XCloseDisplay(DisplayHandle);
332 DisplayHandle=display_handle;
334 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
335 // been hacked to do this for us.
336 Graphics.FromHdcInternal (DisplayHandle);
339 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
340 XSynchronize(DisplayHandle, true);
343 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
344 ErrorExceptions = true;
348 ScreenNo = XDefaultScreen(DisplayHandle);
349 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
350 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
352 // Create the foster parent
353 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
354 if (FosterParent==IntPtr.Zero) {
355 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
359 hwnd.WholeWindow = FosterParent;
360 hwnd.ClientWindow = FosterParent;
362 // For sleeping on the X11 socket
363 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
364 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
368 // To wake up when a timer is ready
369 network_buffer = new byte[10];
371 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
372 wake.Connect(listen.LocalEndPoint);
373 wake_receive = listen.Accept();
376 pollfds = new Pollfd [2];
377 pollfds [0] = new Pollfd ();
378 pollfds [0].fd = XConnectionNumber (DisplayHandle);
379 pollfds [0].events = PollEvents.POLLIN;
381 pollfds [1] = new Pollfd ();
382 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
383 pollfds [1].events = PollEvents.POLLIN;
386 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
387 Dnd = new X11Dnd (DisplayHandle);
389 PostQuitState = false;
391 DoubleClickInterval = 500;
393 HoverState.Interval = 500;
394 HoverState.Timer = new Timer();
395 HoverState.Timer.Enabled = false;
396 HoverState.Timer.Interval = HoverState.Interval;
397 HoverState.Timer.Tick += new EventHandler(MouseHover);
398 HoverState.Size = new Size(4, 4);
402 ActiveWindow = IntPtr.Zero;
403 FocusWindow = IntPtr.Zero;
404 ModalWindows = new Stack(3);
406 MouseState = MouseButtons.None;
407 MousePosition = new Point(0, 0);
409 Caret.Timer = new Timer();
410 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
411 Caret.Timer.Tick += new EventHandler(CaretCallback);
415 // Grab atom changes off the root window to catch certain WM events
416 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
418 // Handle any upcoming errors
419 ErrorHandler = new XErrorHandler(HandleError);
420 XSetErrorHandler(ErrorHandler);
422 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
426 internal static void Where() {
427 Console.WriteLine("Here: {0}\n", WhereString());
430 internal static string WhereString() {
438 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
439 unknown = Locale.GetText("<unknown method>");
440 sb = new StringBuilder();
441 stack = new StackTrace(true);
443 for (int i = 0; i < stack.FrameCount; i++) {
444 frame = stack.GetFrame(i);
447 method = frame.GetMethod();
448 if (method != null) {
450 sb.AppendFormat(frame.ToString());
452 if (frame.GetFileLineNumber() != 0) {
453 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
455 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
461 return sb.ToString();
463 #endregion // Internal Methods
465 #region Private Methods
466 private static void SetupAtoms() {
467 NetAtoms = new IntPtr[(int)NA.LAST_NET_ATOM];
469 NetAtoms[(int)NA.WM_PROTOCOLS] = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
470 NetAtoms[(int)NA.WM_DELETE_WINDOW] = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
471 NetAtoms[(int)NA.WM_TAKE_FOCUS] = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
473 NetAtoms[(int)NA._NET_SUPPORTED] = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
474 NetAtoms[(int)NA._NET_CLIENT_LIST] = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
475 NetAtoms[(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
476 NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
477 NetAtoms[(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
478 NetAtoms[(int)NA._NET_CURRENT_DESKTOP] = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
479 NetAtoms[(int)NA._NET_DESKTOP_NAMES] = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
480 NetAtoms[(int)NA._NET_ACTIVE_WINDOW] = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
481 NetAtoms[(int)NA._NET_WORKAREA] = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
482 NetAtoms[(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
483 NetAtoms[(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
484 NetAtoms[(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
485 NetAtoms[(int)NA._NET_SHOWING_DESKTOP] = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
487 NetAtoms[(int)NA._NET_CLOSE_WINDOW] = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
488 NetAtoms[(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
489 NetAtoms[(int)NA._NET_WM_MOVERESIZE] = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
490 NetAtoms[(int)NA._NET_RESTACK_WINDOW] = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
491 NetAtoms[(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
493 NetAtoms[(int)NA._NET_WM_NAME] = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
494 NetAtoms[(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
495 NetAtoms[(int)NA._NET_WM_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
496 NetAtoms[(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
497 NetAtoms[(int)NA._NET_WM_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
498 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
499 NetAtoms[(int)NA._NET_WM_STATE] = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
500 NetAtoms[(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
501 NetAtoms[(int)NA._NET_WM_STRUT] = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
502 NetAtoms[(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
503 NetAtoms[(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
504 NetAtoms[(int)NA._NET_WM_ICON] = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
505 NetAtoms[(int)NA._NET_WM_PID] = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
506 NetAtoms[(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
507 NetAtoms[(int)NA._NET_WM_USER_TIME] = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
508 NetAtoms[(int)NA._NET_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
510 NetAtoms[(int)NA._NET_WM_PING] = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
511 NetAtoms[(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
513 NetAtoms[(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
514 NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
515 NetAtoms[(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
517 NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
518 NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
519 NetAtoms[(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
521 NetAtoms[(int)NA._XEMBED] = XInternAtom(DisplayHandle, "_XEMBED", false);
522 NetAtoms[(int)NA._XEMBED_INFO] = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
524 NetAtoms[(int)NA._MOTIF_WM_HINTS] = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
526 NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
527 NetAtoms[(int)NA._NET_WM_STATE_ABOVE] = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
528 NetAtoms[(int)NA._NET_WM_STATE_MODAL] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
529 NetAtoms[(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
530 NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
533 NetAtoms[(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
534 NetAtoms[(int)NA.DIB] = (IntPtr)Atom.XA_PIXMAP;
535 NetAtoms[(int)NA.OEMTEXT] = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
536 NetAtoms[(int)NA.UNICODETEXT] = XInternAtom(DisplayHandle, "UTF8_STRING", false);
537 NetAtoms[(int)NA.TARGETS] = XInternAtom(DisplayHandle, "TARGETS", false);
540 AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
541 PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
542 HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
545 private void GetSystrayManagerWindow() {
546 XGrabServer(DisplayHandle);
547 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA._NET_SYSTEM_TRAY_S]);
548 XUngrabServer(DisplayHandle);
549 XFlush(DisplayHandle);
552 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
556 xev.ClientMessageEvent.type = XEventName.ClientMessage;
557 xev.ClientMessageEvent.send_event = true;
558 xev.ClientMessageEvent.window = window;
559 xev.ClientMessageEvent.message_type = message_type;
560 xev.ClientMessageEvent.format = 32;
561 xev.ClientMessageEvent.ptr1 = l0;
562 xev.ClientMessageEvent.ptr2 = l1;
563 xev.ClientMessageEvent.ptr3 = l2;
564 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
567 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
571 xev.ClientMessageEvent.type = XEventName.ClientMessage;
572 xev.ClientMessageEvent.send_event = true;
573 xev.ClientMessageEvent.window = window;
574 xev.ClientMessageEvent.message_type = message_type;
575 xev.ClientMessageEvent.format = 32;
576 xev.ClientMessageEvent.ptr1 = l0;
577 xev.ClientMessageEvent.ptr2 = l1;
578 xev.ClientMessageEvent.ptr3 = l2;
579 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
582 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
584 // Only MDI windows get caption_heights
586 tool_caption_height = 19;
588 if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
589 if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
590 border_style = FormBorderStyle.None;
591 } else if ((ExStyle & (int) WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
592 border_style = FormBorderStyle.Fixed3D;
594 border_style = FormBorderStyle.FixedSingle;
596 title_style = TitleStyle.None;
598 if ((ExStyle & (int) WindowExStyles.WS_EX_MDICHILD) != 0) {
601 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
602 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
603 title_style = TitleStyle.Tool;
605 title_style = TitleStyle.Normal;
609 if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
610 (ExStyle & (int) WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
611 border_style = (FormBorderStyle) 0xFFFF;
613 border_style = FormBorderStyle.None;
618 title_style = TitleStyle.None;
619 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
620 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
621 title_style = TitleStyle.Tool;
623 title_style = TitleStyle.Normal;
627 border_style = FormBorderStyle.None;
629 if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
630 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
631 border_style = FormBorderStyle.SizableToolWindow;
633 border_style = FormBorderStyle.Sizable;
636 if ((ExStyle & (int)WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
637 border_style = FormBorderStyle.Fixed3D;
638 } else if ((ExStyle & (int)WindowExStyles.WS_EX_DLGMODALFRAME) != 0) {
639 border_style = FormBorderStyle.FixedDialog;
640 } else if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
641 border_style = FormBorderStyle.FixedToolWindow;
642 } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
643 border_style = FormBorderStyle.Sizable;
645 border_style = FormBorderStyle.None;
651 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
652 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
655 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
656 MotifWmHints mwmHints;
657 MotifFunctions functions;
658 MotifDecorations decorations;
660 Rectangle client_rect;
662 // Child windows don't need WM window styles
663 if ((cp.Style & (int)WindowStyles.WS_CHILDWINDOW) != 0) {
667 mwmHints = new MotifWmHints();
671 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
672 mwmHints.functions = (IntPtr)0;
673 mwmHints.decorations = (IntPtr)0;
675 if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
676 functions |= MotifFunctions.Move;
677 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
680 if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
681 functions |= MotifFunctions.Move | MotifFunctions.Resize;
682 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
684 if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
685 functions |= MotifFunctions.Minimize;
686 decorations |= MotifDecorations.Minimize;
689 if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
690 functions |= MotifFunctions.Maximize;
691 decorations |= MotifDecorations.Maximize;
694 if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
695 functions |= MotifFunctions.Close;
698 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_DLGMODALFRAME)) != 0) {
699 decorations |= MotifDecorations.Border;
702 if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
703 decorations |= MotifDecorations.Border;
706 if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
707 decorations |= MotifDecorations.Border;
710 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
715 if ((functions & MotifFunctions.Resize) == 0) {
716 hwnd.fixed_size = true;
717 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));
719 hwnd.fixed_size = false;
722 mwmHints.functions = (IntPtr)functions;
723 mwmHints.decorations = (IntPtr)decorations;
725 client_rect = hwnd.ClientRect;
727 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._MOTIF_WM_HINTS], NetAtoms[(int)NA._MOTIF_WM_HINTS], 32, PropertyMode.Replace, ref mwmHints, 5);
729 if (((cp.Style & (int)WindowStyles.WS_POPUP) != 0) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
730 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
732 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
734 int[] atoms = new int[8];
737 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
738 atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR].ToInt32();
740 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
743 IntPtr[] atom_ptrs = new IntPtr[2];
745 atom_ptrs[atom_count++] = NetAtoms[(int)NA.WM_DELETE_WINDOW];
746 if ((cp.ExStyle & (int)WindowExStyles.WS_EX_CONTEXTHELP) != 0) {
747 atom_ptrs[atom_count++] = NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
750 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
754 private void SetIcon(Hwnd hwnd, Icon icon) {
760 bitmap = icon.ToBitmap();
762 size = bitmap.Width * bitmap.Height + 2;
763 data = new uint[size];
765 data[index++] = (uint)bitmap.Width;
766 data[index++] = (uint)bitmap.Height;
768 for (int y = 0; y < bitmap.Height; y++) {
769 for (int x = 0; x < bitmap.Width; x++) {
770 data[index++] = (uint)bitmap.GetPixel(x, y).ToArgb();
773 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
776 private IntPtr ImageToPixmap(Image image) {
780 private void WakeupMain () {
781 wake.Send (new byte [] { 0xFF });
784 private void TranslatePropertyToClipboard(IntPtr property) {
789 IntPtr prop = IntPtr.Zero;
791 Clipboard.Item = null;
793 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);
795 if ((long)nitems > 0) {
796 if (property == (IntPtr)Atom.XA_STRING) {
797 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
798 } else if (property == (IntPtr)Atom.XA_BITMAP) {
799 // FIXME - convert bitmap to image
800 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
801 // FIXME - convert pixmap to image
802 } else if (property == NetAtoms[(int)NA.OEMTEXT]) {
803 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
804 } else if (property == NetAtoms[(int)NA.UNICODETEXT]) {
805 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
812 private void AddExpose (XEvent xevent) {
815 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
822 if (xevent.AnyEvent.window == hwnd.client_window) {
823 hwnd.AddInvalidArea(xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
824 if (!hwnd.expose_pending) {
825 MessageQueue.Enqueue(xevent);
826 hwnd.expose_pending = true;
829 hwnd.AddNcInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
831 if (!hwnd.nc_expose_pending) {
832 MessageQueue.Enqueue(xevent);
833 hwnd.nc_expose_pending = true;
838 private void InvalidateWholeWindow(IntPtr handle) {
841 hwnd = Hwnd.ObjectFromHandle(handle);
843 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
846 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
850 hwnd = Hwnd.ObjectFromHandle(handle);
853 xevent = new XEvent ();
854 xevent.type = XEventName.Expose;
855 xevent.ExposeEvent.display = DisplayHandle;
856 xevent.ExposeEvent.window = hwnd.whole_window;
858 xevent.ExposeEvent.x = rectangle.X;
859 xevent.ExposeEvent.y = rectangle.Y;
860 xevent.ExposeEvent.width = rectangle.Width;
861 xevent.ExposeEvent.height = rectangle.Height;
866 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
872 hwnd = Hwnd.ObjectFromHandle(handle);
875 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
882 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
903 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
910 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
914 if (children != IntPtr.Zero) {
918 } while (win != root);
923 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
926 private void FrameExtents(IntPtr window, out int left, out int top) {
931 IntPtr prop = IntPtr.Zero;
933 XGetWindowProperty(DisplayHandle, window, NetAtoms[(int)NA._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);
934 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
935 left = Marshal.ReadInt32(prop, 0);
936 //right = Marshal.ReadInt32(prop, 4);
937 top = Marshal.ReadInt32(prop, 8);
938 //bottom = Marshal.ReadInt32(prop, 12);
944 if (prop != IntPtr.Zero) {
950 private void AddConfigureNotify (XEvent xevent) {
953 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
960 if (xevent.ConfigureEvent.window == hwnd.whole_window) {
961 if (!hwnd.reparented) {
962 hwnd.x = xevent.ConfigureEvent.x;
963 hwnd.y = xevent.ConfigureEvent.y;
965 // This sucks ass, part 1
966 // Every WM does the ConfigureEvents of toplevel windows different, so there's
967 // no standard way of getting our adjustment.
968 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
969 // Several other WMs do their decorations different yet again and we fail to deal
970 // with that, since I couldn't find any frigging commonality between them.
971 // The only sane WM seems to be KDE
973 if (!xevent.ConfigureEvent.send_event) {
976 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
978 // This is a synthetic event, coordinates are in root space
979 hwnd.x = xevent.ConfigureEvent.x;
980 hwnd.y = xevent.ConfigureEvent.y;
981 if (hwnd.whacky_wm) {
985 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
986 hwnd.x -= frame_left;
991 hwnd.width = xevent.ConfigureEvent.width;
992 hwnd.height = xevent.ConfigureEvent.height;
994 if (!hwnd.configure_pending) {
995 MessageQueue.Enqueue(xevent);
996 hwnd.configure_pending = true;
999 // We drop configure events for Client windows
1002 private void ShowCaret() {
1003 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1009 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1013 private void HideCaret() {
1014 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1020 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1024 private int NextTimeout (DateTime now) {
1025 int timeout = Int32.MaxValue;
1027 foreach (Timer timer in TimerList) {
1028 int next = (int) (timer.Expires - now).TotalMilliseconds;
1030 return 0; // Have a timer that has already expired
1033 if (next < timeout) {
1038 if (timeout < Timer.Minimum) {
1039 timeout = Timer.Minimum;
1045 private void CheckTimers (DateTime now) {
1049 count = TimerList.Count;
1055 for (int i = 0; i < TimerList.Count; i++) {
1058 timer = (Timer) TimerList[i];
1060 if (timer.Enabled && timer.Expires <= now) {
1068 private void UpdateMessageQueue () {
1075 pending = XPending (DisplayHandle);
1080 Idle (this, EventArgs.Empty);
1084 pending = XPending (DisplayHandle);
1091 timeout = NextTimeout (now);
1094 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1095 // Clean out buffer, so we're not busy-looping on the same data
1096 if (pollfds[1].revents != 0) {
1097 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1101 pending = XPending (DisplayHandle);
1110 pending = XPending (DisplayHandle);
1114 while (pending > 0) {
1115 XEvent xevent = new XEvent ();
1118 XNextEvent (DisplayHandle, ref xevent);
1120 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1121 if (XFilterEvent(ref xevent, FosterParent)) {
1126 //Console.WriteLine("Got x event {0}", xevent);
1127 switch (xevent.type) {
1128 case XEventName.Expose:
1132 case XEventName.SelectionClear: {
1133 // Should we do something?
1137 case XEventName.SelectionRequest: {
1138 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1142 sel_event = new XEvent();
1143 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1144 sel_event.SelectionEvent.send_event = true;
1145 sel_event.SelectionEvent.display = DisplayHandle;
1146 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1147 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1148 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1149 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1150 sel_event.SelectionEvent.property = IntPtr.Zero;
1152 // Seems that some apps support asking for supported types
1153 if (xevent.SelectionEvent.target == NetAtoms[(int)NA.TARGETS]) {
1160 if (Clipboard.Item is String) {
1161 atoms[atom_count++] = (int)Atom.XA_STRING;
1162 atoms[atom_count++] = (int)NetAtoms[(int)NA.OEMTEXT];
1163 atoms[atom_count++] = (int)NetAtoms[(int)NA.UNICODETEXT];
1164 } else if (Clipboard.Item is Image) {
1165 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1166 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1168 // FIXME - handle other types
1171 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1172 } else if (Clipboard.Item is string) {
1178 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1181 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1182 buffer = Marshal.AllocHGlobal(bytes.Length);
1183 buflen = bytes.Length;
1185 for (int i = 0; i < buflen; i++) {
1186 Marshal.WriteByte(buffer, i, bytes[i]);
1188 } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.OEMTEXT]) {
1189 // FIXME - this should encode into ISO2022
1190 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1191 while (Marshal.ReadByte(buffer, buflen) != 0) {
1194 } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.UNICODETEXT]) {
1195 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1196 while (Marshal.ReadByte(buffer, buflen) != 0) {
1200 buffer = IntPtr.Zero;
1203 if (buffer != IntPtr.Zero) {
1204 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1205 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1206 Marshal.FreeHGlobal(buffer);
1208 } else if (Clipboard.Item is Image) {
1209 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1210 // FIXME - convert image and store as property
1211 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1212 // FIXME - convert image and store as property
1216 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1220 case XEventName.SelectionNotify: {
1221 if (Clipboard.Enumerating) {
1222 Clipboard.Enumerating = false;
1223 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1224 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1225 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1226 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1227 #if DriverDebugExtra
1228 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1232 } else if (Clipboard.Retrieving) {
1233 Clipboard.Retrieving = false;
1234 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1235 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1237 Clipboard.Item = null;
1240 Dnd.HandleSelectionNotifyEvent (ref xevent);
1245 case XEventName.KeyPress:
1246 case XEventName.KeyRelease:
1247 case XEventName.ButtonPress:
1248 case XEventName.ButtonRelease:
1249 case XEventName.MotionNotify:
1250 case XEventName.EnterNotify:
1251 case XEventName.LeaveNotify:
1252 case XEventName.CreateNotify:
1253 case XEventName.DestroyNotify:
1254 case XEventName.FocusIn:
1255 case XEventName.FocusOut:
1256 case XEventName.ClientMessage:
1257 case XEventName.ReparentNotify:
1258 MessageQueue.Enqueue (xevent);
1261 case XEventName.ConfigureNotify:
1262 AddConfigureNotify(xevent);
1265 case XEventName.PropertyNotify:
1266 if (xevent.PropertyEvent.atom == NetAtoms[(int)NA._NET_ACTIVE_WINDOW]) {
1271 IntPtr prop = IntPtr.Zero;
1272 IntPtr prev_active;;
1274 prev_active = ActiveWindow;
1275 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._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);
1276 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1277 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1280 if (prev_active != ActiveWindow) {
1281 if (prev_active != IntPtr.Zero) {
1282 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1284 if (ActiveWindow != IntPtr.Zero) {
1285 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1288 if (ModalWindows.Count == 0) {
1291 // Modality handling, if we are modal and the new active window is one
1292 // of ours but not the modal one, switch back to the modal window
1294 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1295 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1296 Activate((IntPtr)ModalWindows.Peek());
1308 pending = XPending (DisplayHandle);
1313 private IntPtr GetMousewParam(int Delta) {
1316 if ((MouseState & MouseButtons.Left) != 0) {
1317 result |= (int)MsgButtons.MK_LBUTTON;
1320 if ((MouseState & MouseButtons.Middle) != 0) {
1321 result |= (int)MsgButtons.MK_MBUTTON;
1324 if ((MouseState & MouseButtons.Right) != 0) {
1325 result |= (int)MsgButtons.MK_RBUTTON;
1328 Keys mods = ModifierKeys;
1329 if ((mods & Keys.Control) != 0) {
1330 result |= (int)MsgButtons.MK_CONTROL;
1333 if ((mods & Keys.Shift) != 0) {
1334 result |= (int)MsgButtons.MK_SHIFT;
1337 result |= Delta << 16;
1339 return (IntPtr)result;
1341 private IntPtr XGetParent(IntPtr handle) {
1348 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1351 if (Children!=IntPtr.Zero) {
1359 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1360 if (ErrorExceptions) {
1361 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1363 Console.WriteLine("X11 Error encountered: {0}{1}\n", XException.GetMessage(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), WhereString());
1368 private void DestroyChildWindow(Control c) {
1374 controls = c.child_controls.GetAllControls ();
1376 for (i = 0; i < controls.Length; i++) {
1377 if (controls[i].IsHandleCreated) {
1378 hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
1379 #if DriverDebugDestroy
1380 Console.WriteLine("Destroying {0} [Child of {1}]", XplatUI.Window(controls[i].Handle), XplatUI.Window(controls[i].parent.Handle));
1382 SendMessage(controls[i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1385 DestroyChildWindow(controls[i]);
1390 private void PerformNCCalc(Hwnd hwnd) {
1391 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1395 rect = hwnd.DefaultClientRect;
1397 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1398 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1400 ncp.rgrc1.left = rect.Left;
1401 ncp.rgrc1.top = rect.Top;
1402 ncp.rgrc1.right = rect.Right;
1403 ncp.rgrc1.bottom = rect.Bottom;
1405 Marshal.StructureToPtr(ncp, ptr, true);
1406 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1407 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1408 Marshal.FreeHGlobal(ptr);
1410 // FIXME - debug this with Menus, need to set hwnd.ClientRect
1412 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1415 c = Control.FromHandle(hwnd.Handle);
1418 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1421 #endregion // Private Methods
1424 private void MouseHover(object sender, EventArgs e) {
1426 HoverState.Timer.Enabled = false;
1428 if (HoverState.Window != IntPtr.Zero) {
1429 xevent = new XEvent ();
1431 xevent.type = XEventName.ClientMessage;
1432 xevent.ClientMessageEvent.display = DisplayHandle;
1433 xevent.ClientMessageEvent.window = HoverState.Window;
1434 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1435 xevent.ClientMessageEvent.format = 32;
1436 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1438 MessageQueue.EnqueueLocked (xevent);
1444 private void CaretCallback(object sender, EventArgs e) {
1448 Caret.On = !Caret.On;
1450 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1452 #endregion // Callbacks
1454 #region Public Properties
1456 internal override int Caption {
1462 internal override Size CursorSize {
1467 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1468 return new Size(x, y);
1470 return new Size(16, 16);
1475 internal override bool DragFullWindows {
1481 internal override Size DragSize {
1483 return new Size(4, 4);
1487 internal override Size FrameBorderSize {
1489 throw new NotImplementedException();
1493 internal override Size IconSize {
1499 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1503 current = (long)list;
1506 size = new XIconSize();
1508 for (int i = 0; i < count; i++) {
1509 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1510 current += Marshal.SizeOf(size);
1512 // Look for our preferred size
1513 if (size.min_width == 32) {
1515 return new Size(32, 32);
1518 if (size.max_width == 32) {
1520 return new Size(32, 32);
1523 if (size.min_width < 32 && size.max_width > 32) {
1526 // check if we can fit one
1528 while (x < size.max_width) {
1529 x += size.width_inc;
1532 return new Size(32, 32);
1537 if (largest < size.max_width) {
1538 largest = size.max_width;
1542 // We didn't find a match or we wouldn't be here
1543 return new Size(largest, largest);
1546 return new Size(32, 32);
1551 internal override int KeyboardSpeed {
1554 // A lot harder: need to do:
1555 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1556 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1557 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1559 // And from that we can tell the repetition rate
1561 // Notice, the values must map to:
1562 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1568 internal override int KeyboardDelay {
1571 // Return values must range from 0 to 4, 0 meaning 250ms,
1572 // and 4 meaning 1000 ms.
1574 return 1; // ie, 500 ms
1578 internal override Size MaxWindowTrackSize {
1580 return new Size (WorkingArea.Width, WorkingArea.Height);
1584 internal override Size MinimizedWindowSize {
1586 return new Size(1, 1);
1590 internal override Size MinimizedWindowSpacingSize {
1592 return new Size(1, 1);
1596 internal override Size MinimumWindowSize {
1598 return new Size(1, 1);
1602 internal override Size MinWindowTrackSize {
1604 return new Size(1, 1);
1608 internal override Keys ModifierKeys {
1610 return Keyboard.ModifierKeys;
1614 internal override Size SmallIconSize {
1620 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1624 current = (long)list;
1627 size = new XIconSize();
1629 for (int i = 0; i < count; i++) {
1630 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1631 current += Marshal.SizeOf(size);
1633 // Look for our preferred size
1634 if (size.min_width == 16) {
1636 return new Size(16, 16);
1639 if (size.max_width == 16) {
1641 return new Size(16, 16);
1644 if (size.min_width < 16 && size.max_width > 16) {
1647 // check if we can fit one
1649 while (x < size.max_width) {
1650 x += size.width_inc;
1653 return new Size(16, 16);
1658 if (smallest == 0 || smallest > size.min_width) {
1659 smallest = size.min_width;
1663 // We didn't find a match or we wouldn't be here
1664 return new Size(smallest, smallest);
1667 return new Size(16, 16);
1672 internal override int MouseButtonCount {
1678 internal override bool MouseButtonsSwapped {
1680 return false; // FIXME - how to detect?
1684 internal override Size MouseHoverSize {
1686 return new Size (1, 1);
1690 internal override int MouseHoverTime {
1692 return HoverState.Interval;
1698 internal override bool MouseWheelPresent {
1700 return true; // FIXME - how to detect?
1704 internal override Rectangle VirtualScreen {
1710 internal override Rectangle WorkingArea {
1716 IntPtr prop = IntPtr.Zero;
1720 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY], IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1721 if (((long)nitems == 2) && (prop != IntPtr.Zero) && IntPtr.Size == 4) {
1722 width = Marshal.ReadInt32(prop, 0);
1723 height = Marshal.ReadInt32(prop, 4);
1726 return new Rectangle(0, 0, width, height);
1728 XWindowAttributes attributes=new XWindowAttributes();
1731 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1734 return new Rectangle(0, 0, attributes.width, attributes.height);
1738 #endregion // Public properties
1740 #region Public Static Methods
1741 internal override IntPtr InitializeDriver() {
1743 if (DisplayHandle==IntPtr.Zero) {
1744 SetDisplay(XOpenDisplay(IntPtr.Zero));
1750 internal override void ShutdownDriver(IntPtr token) {
1752 if (DisplayHandle!=IntPtr.Zero) {
1753 XCloseDisplay(DisplayHandle);
1754 DisplayHandle=IntPtr.Zero;
1759 internal override void EnableThemes() {
1760 ThemesEnabled = true;
1764 internal override void Activate(IntPtr handle) {
1767 hwnd = Hwnd.ObjectFromHandle(handle);
1769 if (hwnd != null) lock (XlibLock) {
1770 SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
1771 //XRaiseWindow(DisplayHandle, handle);
1776 internal override void AudibleAlert() {
1777 XBell(DisplayHandle, 0);
1782 internal override void CaretVisible(IntPtr handle, bool visible) {
1783 // Visible is cumulative; two hides require two shows before the caret is visible again
1784 if (Caret.Hwnd == handle) {
1786 if (!Caret.Visible) {
1787 Caret.Visible = true;
1789 Caret.Timer.Start();
1792 Caret.Visible = false;
1799 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
1800 FormBorderStyle border_style;
1801 TitleStyle title_style;
1803 int tool_caption_height;
1805 DeriveStyles(Style, ExStyle, out border_style, out title_style,
1806 out caption_height, out tool_caption_height);
1808 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
1809 caption_height, tool_caption_height,
1815 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
1821 hwnd = Hwnd.ObjectFromHandle(handle);
1824 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1831 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
1832 DataFormats.Format f;
1835 f = DataFormats.Format.List;
1837 if (XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD]) == IntPtr.Zero) {
1841 Clipboard.Formats = new ArrayList();
1844 XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
1846 Clipboard.Enumerating = true;
1847 while (Clipboard.Enumerating) {
1848 UpdateMessageQueue();
1853 result = new int[Clipboard.Formats.Count];
1855 for (int i = 0; i < Clipboard.Formats.Count; i++) {
1856 result[i] = (int)Clipboard.Formats[i];
1859 Clipboard.Formats = null;
1863 internal override void ClipboardClose(IntPtr handle) {
1864 if (handle != ClipMagic) {
1865 throw new ArgumentException("handle is not a valid clipboard handle");
1870 internal override int ClipboardGetID(IntPtr handle, string format) {
1871 if (handle != ClipMagic) {
1872 throw new ArgumentException("handle is not a valid clipboard handle");
1875 if (format == "Text" ) return (int)Atom.XA_STRING;
1876 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
1877 //else if (format == "MetaFilePict" ) return 3;
1878 //else if (format == "SymbolicLink" ) return 4;
1879 //else if (format == "DataInterchangeFormat" ) return 5;
1880 //else if (format == "Tiff" ) return 6;
1881 else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
1882 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
1883 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
1884 //else if (format == "PenData" ) return 10;
1885 //else if (format == "RiffAudio" ) return 11;
1886 //else if (format == "WaveAudio" ) return 12;
1887 else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
1888 //else if (format == "EnhancedMetafile" ) return 14;
1889 //else if (format == "FileDrop" ) return 15;
1890 //else if (format == "Locale" ) return 16;
1892 return XInternAtom(DisplayHandle, format, false).ToInt32();
1895 internal override IntPtr ClipboardOpen() {
1899 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
1900 XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
1902 Clipboard.Retrieving = true;
1903 while (Clipboard.Retrieving) {
1904 UpdateMessageQueue();
1907 return Clipboard.Item;
1910 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
1911 Clipboard.Item = obj;
1912 Clipboard.Type = type;
1913 Clipboard.Converter = converter;
1916 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], FosterParent, IntPtr.Zero);
1918 // Clearing the selection
1919 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], IntPtr.Zero, IntPtr.Zero);
1923 internal override void CreateCaret(IntPtr handle, int width, int height) {
1924 XGCValues gc_values;
1927 hwnd = Hwnd.ObjectFromHandle(handle);
1929 if (Caret.Hwnd != IntPtr.Zero) {
1930 DestroyCaret(Caret.Hwnd);
1933 Caret.Hwnd = handle;
1934 Caret.Window = hwnd.client_window;
1935 Caret.Width = width;
1936 Caret.Height = height;
1937 Caret.Visible = false;
1940 gc_values = new XGCValues();
1941 gc_values.line_width = width;
1943 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
1944 if (Caret.gc == IntPtr.Zero) {
1945 Caret.Hwnd = IntPtr.Zero;
1949 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
1952 internal override IntPtr CreateWindow(CreateParams cp) {
1953 XSetWindowAttributes Attributes;
1959 IntPtr ParentHandle;
1961 IntPtr ClientWindow;
1962 Rectangle ClientRect;
1963 SetWindowValuemask ValueMask;
1968 Attributes = new XSetWindowAttributes();
1974 if (Width<1) Width=1;
1975 if (Height<1) Height=1;
1977 if (cp.Parent != IntPtr.Zero) {
1978 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
1980 if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
1981 // We need to use our foster parent window until this poor child gets it's parent assigned
1982 ParentHandle=FosterParent;
1983 } else if ((cp.Style & (int)WindowStyles.WS_POPUP) != 0) {
1984 ParentHandle=RootWindow;
1986 // Default position on screen, if window manager doesn't place us somewhere else
1989 ParentHandle=RootWindow;
1993 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
1995 Attributes.bit_gravity = Gravity.NorthWestGravity;
1996 Attributes.win_gravity = Gravity.NorthWestGravity;
1998 // Save what's under the toolwindow
1999 if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
2000 Attributes.save_under = true;
2001 ValueMask |= SetWindowValuemask.SaveUnder;
2005 // If we're a popup without caption we override the WM
2006 if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
2007 if ((cp.Style & (int)WindowStyles.WS_CAPTION) == 0) {
2008 Attributes.override_redirect = true;
2009 ValueMask |= SetWindowValuemask.OverrideRedirect;
2016 hwnd.height = Height;
2017 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2019 if ((cp.Style & ((int)WindowStyles.WS_DISABLED)) != 0) {
2020 hwnd.enabled = false;
2023 ClientRect = hwnd.ClientRect;
2024 ClientWindow = IntPtr.Zero;
2027 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2028 if (WholeWindow != IntPtr.Zero) {
2029 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2031 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2032 ValueMask = SetWindowValuemask.ColorMap;
2033 Attributes.colormap = CustomColormap;
2035 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);
2039 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2040 throw new Exception("Could not create X11 windows");
2043 hwnd.WholeWindow = WholeWindow;
2044 hwnd.ClientWindow = ClientWindow;
2046 #if DriverDebug || DriverDebugCreate
2047 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);
2051 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)SelectInputMask));
2052 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2054 if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
2055 XMapWindow(DisplayHandle, hwnd.whole_window);
2056 XMapWindow(DisplayHandle, hwnd.client_window);
2057 hwnd.visible = true;
2061 if ((cp.ExStyle & (int) WindowExStyles.WS_EX_TOPMOST) != 0) {
2062 Console.WriteLine ("Setting transient: " + XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow));
2065 SetWMStyles(hwnd, cp);
2067 if ((cp.Style & (int)WindowStyles.WS_MINIMIZE) != 0) {
2068 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2069 } else if ((cp.Style & (int)WindowStyles.WS_MAXIMIZE) != 0) {
2070 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2073 // for now make all windows dnd enabled
2074 Dnd.SetAllowDrop (hwnd, true);
2076 // Set caption/window title
2077 Text(hwnd.Handle, cp.Caption);
2082 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2083 CreateParams create_params = new CreateParams();
2085 create_params.Caption = "";
2086 create_params.X = X;
2087 create_params.Y = Y;
2088 create_params.Width = Width;
2089 create_params.Height = Height;
2091 create_params.ClassName=XplatUI.DefaultClassName;
2092 create_params.ClassStyle = 0;
2093 create_params.ExStyle=0;
2094 create_params.Parent=IntPtr.Zero;
2095 create_params.Param=0;
2097 return CreateWindow(create_params);
2100 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2102 Bitmap cursor_bitmap;
2110 IntPtr cursor_pixmap;
2117 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2121 // Win32 only allows creation cursors of a certain size
2122 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2123 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2124 cursor_mask = new Bitmap(mask, new Size(width, height));
2126 cursor_bitmap = bitmap;
2130 width = cursor_bitmap.Width;
2131 height = cursor_bitmap.Height;
2133 cursor_bits = new Byte[(width / 8) * height];
2134 mask_bits = new Byte[(width / 8) * height];
2136 for (int y = 0; y < height; y++) {
2137 for (int x = 0; x < width; x++) {
2138 c_pixel = cursor_bitmap.GetPixel(x, y);
2139 m_pixel = cursor_mask.GetPixel(x, y);
2141 and = c_pixel == cursor_pixel;
2142 xor = m_pixel == mask_pixel;
2146 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2147 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2148 } else if (and && !xor) {
2150 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2151 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2153 } else if (and && !xor) {
2155 } else if (and && xor) {
2158 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2159 // we want both to be 0 so nothing to be done
2160 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2161 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2167 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2168 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2172 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2173 fg.red = (ushort)65535;
2174 fg.green = (ushort)65535;
2175 fg.blue = (ushort)65535;
2177 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2179 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2181 XFreePixmap(DisplayHandle, cursor_pixmap);
2182 XFreePixmap(DisplayHandle, mask_pixmap);
2187 internal override IntPtr DefineStdCursor(StdCursor id) {
2188 CursorFontShape shape;
2191 // FIXME - define missing shapes
2194 case StdCursor.AppStarting: {
2195 shape = CursorFontShape.XC_watch;
2199 case StdCursor.Arrow: {
2203 case StdCursor.Cross: {
2204 shape = CursorFontShape.XC_crosshair;
2208 case StdCursor.Default: {
2212 case StdCursor.Hand: {
2213 shape = CursorFontShape.XC_hand1;
2217 case StdCursor.Help: {
2218 shape = CursorFontShape.XC_question_arrow;
2222 case StdCursor.HSplit: {
2223 shape = CursorFontShape.XC_sb_v_double_arrow;
2227 case StdCursor.IBeam: {
2228 shape = CursorFontShape.XC_xterm;
2232 case StdCursor.No: {
2233 shape = CursorFontShape.XC_circle;
2237 case StdCursor.NoMove2D: {
2238 shape = CursorFontShape.XC_fleur;
2242 case StdCursor.NoMoveHoriz: {
2243 shape = CursorFontShape.XC_fleur;
2247 case StdCursor.NoMoveVert: {
2248 shape = CursorFontShape.XC_fleur;
2252 case StdCursor.PanEast: {
2253 shape = CursorFontShape.XC_fleur;
2257 case StdCursor.PanNE: {
2258 shape = CursorFontShape.XC_fleur;
2262 case StdCursor.PanNorth: {
2263 shape = CursorFontShape.XC_fleur;
2267 case StdCursor.PanNW: {
2268 shape = CursorFontShape.XC_fleur;
2272 case StdCursor.PanSE: {
2273 shape = CursorFontShape.XC_fleur;
2277 case StdCursor.PanSouth: {
2278 shape = CursorFontShape.XC_fleur;
2282 case StdCursor.PanSW: {
2283 shape = CursorFontShape.XC_fleur;
2287 case StdCursor.PanWest: {
2288 shape = CursorFontShape.XC_sizing;
2292 case StdCursor.SizeAll: {
2293 shape = CursorFontShape.XC_fleur;
2297 case StdCursor.SizeNESW: {
2298 shape = CursorFontShape.XC_top_right_corner;
2302 case StdCursor.SizeNS: {
2303 shape = CursorFontShape.XC_sb_v_double_arrow;
2307 case StdCursor.SizeNWSE: {
2308 shape = CursorFontShape.XC_top_left_corner;
2312 case StdCursor.SizeWE: {
2313 shape = CursorFontShape.XC_sb_h_double_arrow;
2317 case StdCursor.UpArrow: {
2318 shape = CursorFontShape.XC_center_ptr;
2322 case StdCursor.VSplit: {
2323 shape = CursorFontShape.XC_sb_h_double_arrow;
2327 case StdCursor.WaitCursor: {
2328 shape = CursorFontShape.XC_watch;
2338 cursor = XCreateFontCursor(DisplayHandle, shape);
2343 internal override IntPtr DefWndProc(ref Message msg) {
2344 switch ((Msg)msg.Msg) {
2345 case Msg.WM_SETCURSOR: {
2347 // Pass to parent window first
2348 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2349 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2351 NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2354 if (msg.Result == IntPtr.Zero) {
2357 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2358 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2359 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2360 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2361 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2362 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2365 handle = Cursors.Default.handle;
2368 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2369 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2370 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2371 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2372 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2373 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2376 case HitTest.HTGROWBOX:
2377 case HitTest.HTSIZE:
2378 case HitTest.HTZOOM:
2379 case HitTest.HTVSCROLL:
2380 case HitTest.HTSYSMENU:
2381 case HitTest.HTREDUCE:
2382 case HitTest.HTNOWHERE:
2383 case HitTest.HTMAXBUTTON:
2384 case HitTest.HTMINBUTTON:
2385 case HitTest.HTMENU:
2386 case HitTest.HSCROLL:
2387 case HitTest.HTBOTTOM:
2388 case HitTest.HTCAPTION:
2389 case HitTest.HTCLIENT:
2390 case HitTest.HTCLOSE:
2392 default: handle = Cursors.Default.handle; break;
2394 SetCursor(msg.HWnd, handle);
2402 internal override void DestroyCaret(IntPtr handle) {
2403 if (Caret.Hwnd == handle) {
2404 if (Caret.Visible == true) {
2408 if (Caret.gc != IntPtr.Zero) {
2409 XFreeGC(DisplayHandle, Caret.gc);
2410 Caret.gc = IntPtr.Zero;
2412 Caret.Hwnd = IntPtr.Zero;
2413 Caret.Visible = false;
2418 internal override void DestroyCursor(IntPtr cursor) {
2420 XFreeCursor(DisplayHandle, cursor);
2424 internal override void DestroyWindow(IntPtr handle) {
2427 hwnd = Hwnd.ObjectFromHandle(handle);
2430 #if DriverDebug || DriverDebugDestroy
2431 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2436 #if DriverDebug || DriverDebugDestroy
2437 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2440 // Make sure if the caret is in the window, that we destroy the caret, too
2441 if (Caret.Hwnd == hwnd.client_window) {
2442 DestroyCaret(handle);
2445 // Send destroy message
2446 SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2448 // Mark our children as gone as well
2449 DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
2452 if (hwnd.client_window != IntPtr.Zero) {
2453 XDestroyWindow(DisplayHandle, hwnd.client_window);
2456 if ((hwnd.whole_window != IntPtr.Zero) && (hwnd.whole_window != hwnd.client_window)) {
2457 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2463 internal override IntPtr DispatchMessage(ref MSG msg) {
2464 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2467 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2469 XGCValues gc_values;
2472 hwnd = Hwnd.ObjectFromHandle(handle);
2474 gc_values = new XGCValues();
2476 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2477 gc_values.line_width = line_width;
2478 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2480 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2481 //mask = foreground ^ background;
2482 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2483 //XSetBackground(DisplayHandle, gc, background);
2484 //XSetFunction(DisplayHandle, gc, GXxor);
2485 //XSetPlaneMask(DisplayHandle, gc, mask);
2488 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2493 control = Control.FromHandle(handle);
2495 XColor xcolor = new XColor();
2497 xcolor.red = (ushort)(control.ForeColor.R * 257);
2498 xcolor.green = (ushort)(control.ForeColor.G * 257);
2499 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2500 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2501 foreground = (uint)xcolor.pixel.ToInt32();
2503 xcolor.red = (ushort)(control.BackColor.R * 257);
2504 xcolor.green = (ushort)(control.BackColor.G * 257);
2505 xcolor.blue = (ushort)(control.BackColor.B * 257);
2506 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2507 background = (uint)xcolor.pixel.ToInt32();
2509 uint mask = foreground ^ background;
2511 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2512 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2513 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2514 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2516 if ((rect.Width > 0) && (rect.Height > 0)) {
2517 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2519 if (rect.Width > 0) {
2520 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2522 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2525 XFreeGC(DisplayHandle, gc);
2528 internal override void DoEvents() {
2529 MSG msg = new MSG ();
2531 if (OverrideCursorHandle != IntPtr.Zero) {
2532 OverrideCursorHandle = IntPtr.Zero;
2535 while (PeekMessage(ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2536 TranslateMessage (ref msg);
2537 DispatchMessage (ref msg);
2541 internal override void EnableWindow(IntPtr handle, bool Enable) {
2544 hwnd = Hwnd.ObjectFromHandle(handle);
2546 hwnd.Enabled = Enable;
2550 internal override void EndLoop(Thread thread) {
2551 // This is where we one day will shut down the loop for the thread
2555 internal override IntPtr GetActive() {
2560 IntPtr prop = IntPtr.Zero;
2561 IntPtr active = IntPtr.Zero;
2563 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._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);
2564 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2565 active = (IntPtr)Marshal.ReadInt32(prop);
2569 if (active != IntPtr.Zero) {
2572 hwnd = Hwnd.GetObjectFromWindow(active);
2574 active = hwnd.Handle;
2576 active = IntPtr.Zero;
2582 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2583 throw new NotImplementedException ();
2586 internal override void GetDisplaySize(out Size size) {
2587 XWindowAttributes attributes=new XWindowAttributes();
2590 // FIXME - use _NET_WM messages instead?
2591 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2594 size = new Size(attributes.width, attributes.height);
2597 internal override SizeF GetAutoScaleSize(Font font) {
2600 string magic_string = "The quick brown fox jumped over the lazy dog.";
2601 double magic_number = 44.549996948242189;
2603 g = Graphics.FromHwnd(FosterParent);
2605 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2606 return new SizeF(width, font.Height);
2609 internal override IntPtr GetParent(IntPtr handle) {
2612 hwnd = Hwnd.ObjectFromHandle(handle);
2613 if (hwnd != null && hwnd.parent != null) {
2614 return hwnd.parent.Handle;
2619 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
2629 if (handle != IntPtr.Zero) {
2630 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
2632 use_handle = RootWindow;
2636 XQueryPointer(DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
2639 if (handle != IntPtr.Zero) {
2648 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
2649 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
2652 internal override Point GetMenuOrigin(IntPtr handle) {
2655 hwnd = Hwnd.ObjectFromHandle(handle);
2658 return hwnd.MenuOrigin;
2663 internal override bool GetMessage(ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
2670 if (MessageQueue.Count > 0) {
2671 xevent = (XEvent) MessageQueue.Dequeue ();
2673 UpdateMessageQueue ();
2675 if (MessageQueue.Count > 0) {
2676 xevent = (XEvent) MessageQueue.Dequeue ();
2678 if (!PostQuitState) {
2679 msg.hwnd= IntPtr.Zero;
2680 msg.message = Msg.WM_ENTERIDLE;
2684 // We reset ourselves so GetMessage can be called again
2685 PostQuitState = false;
2691 // FIXME - handle filtering
2693 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
2695 // Handle messages for windows that are already or are about to be destroyed
2698 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
2700 goto ProcessNextMessage;
2703 if (hwnd.client_window == xevent.AnyEvent.window) {
2705 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2708 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2711 msg.hwnd = hwnd.Handle;
2714 // If you add a new event to this switch make sure to add it in
2715 // UpdateMessage also unless it is not coming through the X event system.
2717 switch(xevent.type) {
2718 case XEventName.KeyPress: {
2719 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2723 case XEventName.KeyRelease: {
2724 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2728 case XEventName.ButtonPress: {
2729 switch(xevent.ButtonEvent.button) {
2731 MouseState |= MouseButtons.Left;
2733 msg.message = Msg.WM_LBUTTONDOWN;
2735 msg.message = Msg.WM_NCLBUTTONDOWN;
2736 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2738 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
2739 msg.wParam=GetMousewParam(0);
2744 MouseState |= MouseButtons.Middle;
2746 msg.message = Msg.WM_MBUTTONDOWN;
2748 msg.message = Msg.WM_NCMBUTTONDOWN;
2749 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2751 msg.wParam=GetMousewParam(0);
2756 MouseState |= MouseButtons.Right;
2758 msg.message = Msg.WM_RBUTTONDOWN;
2760 msg.message = Msg.WM_NCRBUTTONDOWN;
2761 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2763 msg.wParam=GetMousewParam(0);
2768 msg.message=Msg.WM_MOUSEWHEEL;
2769 msg.wParam=GetMousewParam(120);
2774 msg.message=Msg.WM_MOUSEWHEEL;
2775 msg.wParam=GetMousewParam(-120);
2781 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2782 MousePosition.X = xevent.ButtonEvent.x;
2783 MousePosition.Y = xevent.ButtonEvent.y;
2785 if (!hwnd.Enabled) {
2788 msg.hwnd = hwnd.EnabledHwnd;
2789 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);
2790 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2793 if (Grab.Hwnd != IntPtr.Zero) {
2794 msg.hwnd = Grab.Hwnd;
2797 if (!ClickPending.Pending) {
2798 ClickPending.Pending = true;
2799 ClickPending.Hwnd = msg.hwnd;
2800 ClickPending.Message = msg.message;
2801 ClickPending.wParam = msg.wParam;
2802 ClickPending.lParam = msg.lParam;
2803 ClickPending.Time = (long)xevent.ButtonEvent.time;
2805 if ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message)) {
2806 // Looks like a genuine double click, clicked twice on the same spot with the same keys
2807 switch(xevent.ButtonEvent.button) {
2809 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
2814 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
2819 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
2824 ClickPending.Pending = false;
2830 case XEventName.ButtonRelease: {
2831 Dnd.HandleButtonRelease (ref xevent);
2832 switch(xevent.ButtonEvent.button) {
2834 MouseState &= ~MouseButtons.Left;
2836 msg.message = Msg.WM_LBUTTONUP;
2838 msg.message = Msg.WM_NCLBUTTONUP;
2839 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2841 msg.wParam=GetMousewParam(0);
2846 MouseState &= ~MouseButtons.Middle;
2848 msg.message = Msg.WM_MBUTTONUP;
2850 msg.message = Msg.WM_NCMBUTTONUP;
2851 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2853 msg.wParam=GetMousewParam(0);
2858 MouseState &= ~MouseButtons.Right;
2860 msg.message = Msg.WM_RBUTTONUP;
2862 msg.message = Msg.WM_NCRBUTTONUP;
2863 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2865 msg.wParam=GetMousewParam(0);
2870 goto ProcessNextMessage;
2874 goto ProcessNextMessage;
2878 if (!hwnd.Enabled) {
2881 msg.hwnd = hwnd.EnabledHwnd;
2882 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);
2883 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2886 if (Grab.Hwnd != IntPtr.Zero) {
2887 msg.hwnd = Grab.Hwnd;
2890 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2891 MousePosition.X = xevent.ButtonEvent.x;
2892 MousePosition.Y = xevent.ButtonEvent.y;
2896 case XEventName.MotionNotify: {
2898 #if DriverDebugExtra
2899 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);
2902 if (Dnd.HandleMotionNotify (ref xevent))
2903 goto ProcessNextMessage;
2904 if (Grab.Hwnd != IntPtr.Zero) {
2905 msg.hwnd = Grab.Hwnd;
2907 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
2910 msg.message = Msg.WM_MOUSEMOVE;
2911 msg.wParam = GetMousewParam(0);
2912 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
2914 if (!hwnd.Enabled) {
2917 msg.hwnd = hwnd.EnabledHwnd;
2918 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);
2919 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2922 MousePosition.X = xevent.MotionEvent.x;
2923 MousePosition.Y = xevent.MotionEvent.y;
2925 if ((HoverState.Timer.Enabled) &&
2926 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
2927 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
2928 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
2929 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
2930 HoverState.Timer.Stop();
2931 HoverState.Timer.Start();
2932 HoverState.X = MousePosition.X;
2933 HoverState.Y = MousePosition.Y;
2943 #if DriverDebugExtra
2944 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);
2946 msg.message = Msg.WM_NCMOUSEMOVE;
2948 if (!hwnd.Enabled) {
2949 msg.hwnd = hwnd.EnabledHwnd;
2950 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);
2951 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2954 // The hit test is sent in screen coordinates
2955 XTranslateCoordinates (DisplayHandle, hwnd.client_window, RootWindow,
2956 xevent.MotionEvent.x, xevent.MotionEvent.y,
2957 out screen_x, out screen_y, out dummy);
2959 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
2960 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
2961 IntPtr.Zero, msg.lParam).ToInt32 ();
2962 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
2964 MousePosition.X = xevent.MotionEvent.x;
2965 MousePosition.Y = xevent.MotionEvent.y;
2971 case XEventName.EnterNotify: {
2972 if (!hwnd.Enabled) {
2973 goto ProcessNextMessage;
2975 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2976 goto ProcessNextMessage;
2978 msg.message = Msg.WM_MOUSE_ENTER;
2979 HoverState.X = xevent.CrossingEvent.x;
2980 HoverState.Y = xevent.CrossingEvent.y;
2981 HoverState.Timer.Enabled = true;
2982 HoverState.Window = xevent.CrossingEvent.window;
2986 case XEventName.LeaveNotify: {
2987 if (!hwnd.Enabled) {
2988 goto ProcessNextMessage;
2990 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2991 goto ProcessNextMessage;
2993 msg.message=Msg.WM_MOUSE_LEAVE;
2994 HoverState.Timer.Enabled = false;
2995 HoverState.Window = IntPtr.Zero;
3000 case XEventName.CreateNotify: {
3001 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3002 msg.message = WM_CREATE;
3003 // Set up CreateStruct
3005 goto ProcessNextMessage;
3012 case XEventName.ReparentNotify: {
3013 if (hwnd.parent == null) { // Toplevel
3014 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3015 // We need to adjust x/y
3016 // This sucks ass, part 2
3017 // Every WM does the reparenting of toplevel windows different, so there's
3018 // no standard way of getting our adjustment considering frames/decorations
3019 // The code below is needed for metacity. KDE doesn't works just fine without this
3027 hwnd.Reparented = true;
3029 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);
3030 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3031 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3034 hwnd.whacky_wm = true;
3037 msg.message = Msg.WM_WINDOWPOSCHANGED;
3038 if (hwnd.opacity != 0xffffffff) {
3041 opacity = hwnd.opacity;
3042 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3045 hwnd.Reparented = false;
3046 goto ProcessNextMessage;
3052 case XEventName.ConfigureNotify: {
3053 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3054 #if DriverDebugExtra
3055 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);
3057 msg.message = Msg.WM_WINDOWPOSCHANGED;
3058 hwnd.configure_pending = false;
3060 // We need to adjust our client window to track the resize of whole_window
3061 PerformNCCalc(hwnd);
3063 goto ProcessNextMessage;
3066 msg.lParam=IntPtr.Zero; // FIXME - Generate LPWINDOWPOS structure and pass on
3070 case XEventName.FocusIn: {
3071 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3072 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3073 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3074 // about it having focus again
3075 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3076 goto ProcessNextMessage;
3078 Keyboard.FocusIn(FocusWindow);
3079 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3080 goto ProcessNextMessage;
3083 case XEventName.FocusOut: {
3084 // Se the comment for our FocusIn handler
3085 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3086 goto ProcessNextMessage;
3088 Keyboard.FocusOut(FocusWindow);
3090 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3091 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3094 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3095 goto ProcessNextMessage;
3098 case XEventName.Expose: {
3099 if (PostQuitState) {
3100 goto ProcessNextMessage;
3105 if (!hwnd.expose_pending) {
3106 goto ProcessNextMessage;
3109 if (!hwnd.nc_expose_pending) {
3110 goto ProcessNextMessage;
3113 switch (hwnd.border_style) {
3114 case FormBorderStyle.Fixed3D: {
3117 g = Graphics.FromHwnd(hwnd.whole_window);
3118 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
3123 case FormBorderStyle.FixedSingle: {
3126 g = Graphics.FromHwnd(hwnd.whole_window);
3127 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3132 #if DriverDebugExtra
3133 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);
3136 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3137 Region region = new Region (rect);
3138 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3139 msg.message = Msg.WM_NCPAINT;
3141 hwnd.nc_expose_pending = false;
3144 #if DriverDebugExtra
3145 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);
3147 if (Caret.Visible == true) {
3148 Caret.Paused = true;
3152 if (Caret.Visible == true) {
3154 Caret.Paused = false;
3156 msg.message = Msg.WM_PAINT;
3160 case XEventName.DestroyNotify: {
3162 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3163 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3165 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3166 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3167 msg.hwnd = hwnd.client_window;
3168 msg.message=Msg.WM_DESTROY;
3172 Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
3175 goto ProcessNextMessage;
3181 case XEventName.ClientMessage: {
3182 if (Dnd.HandleClientMessage (ref xevent)) {
3183 goto ProcessNextMessage;
3186 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3187 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3191 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3192 msg.message = Msg.WM_MOUSEHOVER;
3193 msg.wParam = GetMousewParam(0);
3194 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3198 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3199 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3200 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3201 msg.wParam = xevent.ClientMessageEvent.ptr3;
3202 msg.lParam = xevent.ClientMessageEvent.ptr4;
3207 if (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA._XEMBED]) {
3208 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3213 if (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA.WM_PROTOCOLS]) {
3214 if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
3215 msg.message = Msg.WM_CLOSE;
3216 Graphics.FromHdcInternal (IntPtr.Zero);
3220 // We should not get this, but I'll leave the code in case we need it in the future
3221 if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
3222 goto ProcessNextMessage;
3228 case XEventName.TimerNotify: {
3229 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3234 goto ProcessNextMessage;
3241 internal override bool GetText(IntPtr handle, out string text) {
3244 textptr = IntPtr.Zero;
3247 // FIXME - use _NET properties
3248 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3250 if (textptr != IntPtr.Zero) {
3251 text = Marshal.PtrToStringAnsi(textptr);
3260 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) {
3264 hwnd = Hwnd.ObjectFromHandle(handle);
3270 height = hwnd.height;
3272 rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
3274 client_width = rect.Width;
3275 client_height = rect.Height;
3280 // Should we throw an exception or fail silently?
3281 // throw new ArgumentException("Called with an invalid window handle", "handle");
3291 internal override FormWindowState GetWindowState(IntPtr handle) {
3296 IntPtr prop = IntPtr.Zero;
3300 XWindowAttributes attributes;
3303 hwnd = Hwnd.ObjectFromHandle(handle);
3307 XGetWindowProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._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);
3308 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3309 for (int i = 0; i < (long)nitems; i++) {
3310 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3311 if ((atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
3313 } else if (atom == NetAtoms[(int)NA._NET_WM_STATE_HIDDEN]) {
3321 return FormWindowState.Minimized;
3322 } else if (maximized == 2) {
3323 return FormWindowState.Maximized;
3326 attributes = new XWindowAttributes();
3327 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
3328 if (attributes.map_state == MapState.IsUnmapped) {
3329 throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
3333 return FormWindowState.Normal;
3336 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3338 GrabConfined = Grab.Confined;
3339 GrabArea = Grab.Area;
3342 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3344 IntPtr confine_to_window;
3346 confine_to_window = IntPtr.Zero;
3348 if (confine_to_handle != IntPtr.Zero) {
3349 XWindowAttributes attributes = new XWindowAttributes();
3351 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3354 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3356 Grab.Area.X = attributes.x;
3357 Grab.Area.Y = attributes.y;
3358 Grab.Area.Width = attributes.width;
3359 Grab.Area.Height = attributes.height;
3360 Grab.Confined = true;
3361 confine_to_window = hwnd.client_window;
3366 hwnd = Hwnd.ObjectFromHandle(handle);
3369 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3370 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3371 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3372 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3376 internal override void UngrabWindow(IntPtr hwnd) {
3378 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3379 XFlush(DisplayHandle);
3381 Grab.Hwnd = IntPtr.Zero;
3382 Grab.Confined = false;
3385 internal override void HandleException(Exception e) {
3386 StackTrace st = new StackTrace(e, true);
3387 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3388 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3391 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3395 hwnd = Hwnd.ObjectFromHandle(handle);
3398 xevent = new XEvent ();
3399 xevent.type = XEventName.Expose;
3400 xevent.ExposeEvent.display = DisplayHandle;
3401 xevent.ExposeEvent.window = hwnd.client_window;
3404 xevent.ExposeEvent.x = hwnd.X;
3405 xevent.ExposeEvent.y = hwnd.Y;
3406 xevent.ExposeEvent.width = hwnd.Width;
3407 xevent.ExposeEvent.height = hwnd.Height;
3409 xevent.ExposeEvent.x = rc.X;
3410 xevent.ExposeEvent.y = rc.Y;
3411 xevent.ExposeEvent.width = rc.Width;
3412 xevent.ExposeEvent.height = rc.Height;
3418 internal override bool IsEnabled(IntPtr handle) {
3419 return Hwnd.ObjectFromHandle(handle).Enabled;
3422 internal override bool IsVisible(IntPtr handle) {
3423 return Hwnd.ObjectFromHandle(handle).visible;
3426 internal override void KillTimer(Timer timer) {
3428 TimerList.Remove(timer);
3432 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3438 hwnd = Hwnd.ObjectFromHandle(handle);
3441 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3448 internal override void OverrideCursor(IntPtr cursor) {
3449 OverrideCursorHandle = cursor;
3452 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3453 PaintEventArgs paint_event;
3456 hwnd = Hwnd.ObjectFromHandle(handle);
3458 if (Caret.Visible == true) {
3459 Caret.Paused = true;
3464 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3465 hwnd.client_dc.SetClip(hwnd.invalid);
3466 paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.invalid);
3467 hwnd.expose_pending = false;
3471 hwnd.non_client_dc = Graphics.FromHwnd (hwnd.whole_window);
3472 hwnd.non_client_dc.SetClip (hwnd.nc_invalid);
3473 paint_event = new PaintEventArgs(hwnd.non_client_dc, hwnd.nc_invalid);
3474 hwnd.nc_expose_pending = false;
3480 internal override void PaintEventEnd(IntPtr handle, bool client) {
3483 hwnd = Hwnd.ObjectFromHandle(handle);
3486 hwnd.ClearInvalidArea();
3488 hwnd.client_dc.Flush();
3489 hwnd.client_dc.Dispose();
3490 hwnd.client_dc = null;
3492 hwnd.ClearNcInvalidArea ();
3494 hwnd.non_client_dc.Flush ();
3495 hwnd.non_client_dc.Dispose ();
3496 hwnd.non_client_dc = null;
3501 if (Caret.Visible == true) {
3503 Caret.Paused = false;
3507 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3510 // FIXME - imlement filtering
3512 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3513 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3517 if (MessageQueue.Count > 0) {
3520 // Only call UpdateMessageQueue if real events are pending
3521 // otherwise we go to sleep on the socket
3522 if (XPending(DisplayHandle) != 0) {
3523 UpdateMessageQueue();
3528 CheckTimers(DateTime.Now);
3533 return GetMessage(ref msg, hWnd, wFilterMin, wFilterMax);
3536 // FIXME - I think this should just enqueue directly
3537 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3538 XEvent xevent = new XEvent ();
3539 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
3541 xevent.type = XEventName.ClientMessage;
3542 xevent.ClientMessageEvent.display = DisplayHandle;
3545 xevent.ClientMessageEvent.window = hwnd.whole_window;
3547 xevent.ClientMessageEvent.window = IntPtr.Zero;
3550 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
3551 xevent.ClientMessageEvent.format = 32;
3552 xevent.ClientMessageEvent.ptr1 = handle;
3553 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
3554 xevent.ClientMessageEvent.ptr3 = wparam;
3555 xevent.ClientMessageEvent.ptr4 = lparam;
3557 MessageQueue.Enqueue (xevent);
3562 internal override void PostQuitMessage(int exitCode) {
3563 XFlush(DisplayHandle);
3564 PostQuitState = true;
3566 // Remove our display handle from S.D
3567 Graphics.FromHdcInternal (IntPtr.Zero);
3570 internal override void RequestNCRecalc(IntPtr handle) {
3573 hwnd = Hwnd.ObjectFromHandle(handle);
3579 PerformNCCalc(hwnd);
3580 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3581 InvalidateWholeWindow(handle);
3584 internal override void ResetMouseHover(IntPtr handle) {
3587 hwnd = Hwnd.ObjectFromHandle(handle);
3592 HoverState.Timer.Enabled = true;
3593 HoverState.X = MousePosition.X;
3594 HoverState.Y = MousePosition.Y;
3595 HoverState.Window = handle;
3599 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
3605 hwnd = Hwnd.ObjectFromHandle(handle);
3608 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
3615 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
3621 hwnd = Hwnd.ObjectFromHandle(handle);
3624 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
3631 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
3634 XGCValues gc_values;
3636 hwnd = Hwnd.ObjectFromHandle(handle);
3638 if (hwnd.invalid != Rectangle.Empty) {
3639 // BIG FAT WARNING. This only works with how we use this function right now
3640 // where we basically still scroll the whole window, but work around areas
3641 // that are covered by our children
3643 hwnd.invalid.X += XAmount;
3644 hwnd.invalid.Y += YAmount;
3646 if (hwnd.invalid.X < 0) {
3647 hwnd.invalid.Width += hwnd.invalid.X;
3651 if (hwnd.invalid.Y < 0) {
3652 hwnd.invalid.Height += hwnd.invalid.Y;
3657 gc_values = new XGCValues();
3659 if (with_children) {
3660 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3663 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
3665 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
3667 // Generate an expose for the area exposed by the horizontal scroll
3669 hwnd.AddInvalidArea (area.X, area.Y, XAmount, area.Height);
3670 } else if (XAmount < 0) {
3671 hwnd.AddInvalidArea (XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
3674 // Generate an expose for the area exposed by the vertical scroll
3676 hwnd.AddInvalidArea (area.X, area.Y, area.Width, YAmount);
3677 } else if (YAmount < 0) {
3678 hwnd.AddInvalidArea (area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
3680 XFreeGC(DisplayHandle, gc);
3682 UpdateWindow(handle);
3685 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
3688 hwnd = Hwnd.GetObjectFromWindow(handle);
3690 ScrollWindow(handle, hwnd.ClientRect, XAmount, YAmount, with_children);
3693 internal override void SendAsyncMethod (AsyncMethodData method) {
3694 XEvent xevent = new XEvent ();
3696 xevent.type = XEventName.ClientMessage;
3697 xevent.ClientMessageEvent.display = DisplayHandle;
3698 xevent.ClientMessageEvent.window = FosterParent;
3699 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
3700 xevent.ClientMessageEvent.format = 32;
3701 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
3703 MessageQueue.EnqueueLocked (xevent);
3708 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam) {
3709 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
3712 internal override void SetAllowDrop (IntPtr handle, bool value)
3714 // We allow drop on all windows
3717 internal override DragDropEffects StartDrag (IntPtr handle, object data,
3718 DragDropEffects allowed_effects)
3720 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3723 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
3725 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
3728 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
3731 hwnd = Hwnd.ObjectFromHandle(handle);
3733 hwnd.border_style = border_style;
3734 RequestNCRecalc(handle);
3737 internal override void SetCaretPos(IntPtr handle, int x, int y) {
3738 if (Caret.Hwnd == handle) {
3745 if (Caret.Visible == true) {
3747 Caret.Timer.Start();
3752 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
3755 if (OverrideCursorHandle == IntPtr.Zero) {
3756 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
3760 LastCursorHandle = cursor;
3761 LastCursorWindow = handle;
3763 hwnd = Hwnd.ObjectFromHandle(handle);
3765 if (cursor != IntPtr.Zero) {
3766 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
3768 XUndefineCursor(DisplayHandle, hwnd.whole_window);
3774 hwnd = Hwnd.ObjectFromHandle(handle);
3776 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
3780 internal override void SetCursorPos(IntPtr handle, int x, int y) {
3781 if (handle == IntPtr.Zero) {
3783 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x, y);
3789 hwnd = Hwnd.ObjectFromHandle(handle);
3791 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
3797 internal override void SetFocus(IntPtr handle) {
3800 hwnd = Hwnd.ObjectFromHandle(handle);
3802 if (hwnd.client_window == FocusWindow) {
3806 SendMessage(hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
3807 if (FocusWindow != IntPtr.Zero) {
3808 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
3810 FocusWindow = hwnd.client_window;
3812 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
3815 internal override void SetIcon(IntPtr handle, Icon icon) {
3818 hwnd = Hwnd.ObjectFromHandle(handle);
3820 SetIcon(hwnd, icon);
3824 internal override void SetMenu(IntPtr handle, Menu menu) {
3827 hwnd = Hwnd.ObjectFromHandle(handle);
3830 RequestNCRecalc(handle);
3833 internal override void SetModal(IntPtr handle, bool Modal) {
3835 ModalWindows.Push(handle);
3837 if (ModalWindows.Contains(handle)) {
3840 if (ModalWindows.Count > 0) {
3841 Activate((IntPtr)ModalWindows.Peek());
3846 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
3849 hwnd = Hwnd.ObjectFromHandle(handle);
3850 hwnd.parent = Hwnd.ObjectFromHandle(parent);
3853 #if DriverDebug || DriverDebugParent
3854 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
3856 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
3862 internal override void SetTimer (Timer timer) {
3864 TimerList.Add(timer);
3869 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
3873 hwnd = Hwnd.ObjectFromHandle(handle);
3875 if (handle_owner != IntPtr.Zero) {
3876 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
3883 if (hwnd_owner != null) {
3884 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
3886 XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
3891 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
3897 internal override bool SetVisible(IntPtr handle, bool visible) {
3900 hwnd = Hwnd.ObjectFromHandle(handle);
3901 hwnd.visible = visible;
3905 if (Control.FromHandle(handle) is Form) {
3908 s = ((Form)Control.FromHandle(handle)).WindowState;
3910 XMapWindow(DisplayHandle, hwnd.whole_window);
3911 XMapWindow(DisplayHandle, hwnd.client_window);
3914 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
3915 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
3918 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3920 XMapWindow(DisplayHandle, hwnd.whole_window);
3921 XMapWindow(DisplayHandle, hwnd.client_window);
3924 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3930 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
3934 hwnd = Hwnd.ObjectFromHandle(handle);
3939 hints = new XSizeHints();
3941 if (min != Size.Empty) {
3942 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
3943 hints.min_width = min.Width;
3944 hints.min_height = min.Height;
3947 if (max != Size.Empty) {
3948 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
3949 hints.max_width = max.Width;
3950 hints.max_height = max.Height;
3953 if (hints.flags != IntPtr.Zero) {
3954 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
3957 if (maximized != Rectangle.Empty) {
3958 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
3959 hints.x = maximized.X;
3960 hints.y = maximized.Y;
3961 hints.width = maximized.Width;
3962 hints.height = maximized.Height;
3964 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
3965 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
3970 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
3972 Rectangle client_rect;
3974 hwnd = Hwnd.ObjectFromHandle(handle);
3976 // X requires a sanity check for width & height; otherwise it dies
3977 if (hwnd.zero_sized && width > 0 && height > 0) {
3979 XMapWindow(DisplayHandle, hwnd.whole_window);
3981 hwnd.zero_sized = false;
3985 hwnd.zero_sized = true;
3986 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3990 hwnd.zero_sized = true;
3991 XUnmapWindow(DisplayHandle, hwnd.whole_window);
3994 client_rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
3996 // Save a server roundtrip (and prevent a feedback loop)
3997 if ((hwnd.x == x) && (hwnd.y == y) &&
3998 (hwnd.width == width) && (hwnd.height == height) &&
3999 (hwnd.ClientRect == client_rect)) {
4003 if (!hwnd.zero_sized) {
4005 if (hwnd.fixed_size) {
4006 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4010 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4011 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
4015 // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
4017 hwnd.height = height;
4020 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4021 FormWindowState current_state;
4024 hwnd = Hwnd.ObjectFromHandle(handle);
4027 current_state = GetWindowState(handle);
4029 catch (NotSupportedException) {
4030 current_state = (FormWindowState)(-1);
4033 if (current_state == state) {
4038 case FormWindowState.Normal: {
4040 if (current_state == FormWindowState.Minimized) {
4041 XMapWindow(DisplayHandle, hwnd.whole_window);
4042 XMapWindow(DisplayHandle, hwnd.client_window);
4043 } else if (current_state == FormWindowState.Maximized) {
4044 SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4051 case FormWindowState.Minimized: {
4053 if (current_state == FormWindowState.Maximized) {
4054 SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4056 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4061 case FormWindowState.Maximized: {
4063 if (current_state == FormWindowState.Minimized) {
4064 XMapWindow(DisplayHandle, hwnd.whole_window);
4065 XMapWindow(DisplayHandle, hwnd.client_window);
4068 SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4076 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4079 hwnd = Hwnd.ObjectFromHandle(handle);
4080 SetHwndStyles(hwnd, cp);
4081 SetWMStyles(hwnd, cp);
4084 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4088 hwnd = Hwnd.ObjectFromHandle(handle);
4094 hwnd.opacity = (uint)(0xffffffff * transparency);
4095 opacity = hwnd.opacity;
4097 if (hwnd.reparented) {
4098 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4102 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4103 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4107 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4110 } else if (!bottom) {
4111 Hwnd after_hwnd = null;
4113 if (after_handle != IntPtr.Zero) {
4114 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4117 XWindowChanges values = new XWindowChanges();
4119 if (after_hwnd == null) {
4120 throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4122 values.sibling = after_hwnd.whole_window;
4123 values.stack_mode = StackMode.Below;
4126 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4131 XLowerWindow(DisplayHandle, hwnd.whole_window);
4138 internal override void ShowCursor(bool show) {
4139 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4142 internal override void StartLoop(Thread thread) {
4143 // Future place for prepping a new queue for this specific thread
4146 internal override bool SupportsTransparency() {
4147 // We need to check if the x compositing manager is running
4151 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4152 GetSystrayManagerWindow();
4154 if (SystrayMgrWindow != IntPtr.Zero) {
4155 XSizeHints size_hints;
4158 hwnd = Hwnd.ObjectFromHandle(handle);
4160 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4163 XUnmapWindow(DisplayHandle, hwnd.whole_window);
4164 XUnmapWindow(DisplayHandle, hwnd.client_window);
4167 XDestroyWindow(DisplayHandle, hwnd.client_window);
4168 hwnd.client_window = hwnd.whole_window;
4170 size_hints = new XSizeHints();
4172 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4173 size_hints.min_width = icon.Width;
4174 size_hints.min_height = icon.Height;
4176 size_hints.max_width = icon.Width;
4177 size_hints.max_height = icon.Height;
4179 size_hints.base_width = icon.Width;
4180 size_hints.base_height = icon.Height;
4181 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4183 int[] atoms = new int[2];
4184 atoms [0] = 1; // Version 1
4185 atoms [1] = 0; // We're not mapped
4187 // This line cost me 3 days...
4188 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._XEMBED_INFO], NetAtoms[(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
4190 // Need to pick some reasonable defaults
4192 tt.AutomaticDelay = 100;
4193 tt.InitialDelay = 250;
4194 tt.ReshowDelay = 250;
4195 tt.ShowAlways = true;
4197 if ((tip != null) && (tip != string.Empty)) {
4198 tt.SetToolTip(Control.FromHandle(handle), tip);
4204 // Make sure the window exists
4205 XSync(DisplayHandle, hwnd.whole_window);
4207 SendNetClientMessage(SystrayMgrWindow, NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4214 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4217 control = Control.FromHandle(handle);
4218 if (control != null && tt != null) {
4219 tt.SetToolTip(control, tip);
4227 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4230 hwnd = Hwnd.ObjectFromHandle(handle);
4232 XUnmapWindow(DisplayHandle, hwnd.whole_window);
4233 SetParent(hwnd.whole_window, FosterParent);
4235 // The caller can now re-dock it later...
4242 internal override bool Text(IntPtr handle, string text) {
4244 // FIXME - use _NET properties
4245 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4250 internal override bool TranslateMessage(ref MSG msg) {
4251 return Keyboard.TranslateMessage (ref msg);
4254 internal override void UpdateWindow(IntPtr handle) {
4258 hwnd = Hwnd.ObjectFromHandle(handle);
4260 if (!hwnd.visible || hwnd.expose_pending) {
4265 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4267 xevent = new XEvent();
4268 xevent.type = XEventName.Expose;
4269 xevent.ExposeEvent.display = DisplayHandle;
4270 xevent.ExposeEvent.window = hwnd.client_window;
4272 MessageQueue.Enqueue(xevent);
4273 hwnd.expose_pending = true;
4277 private bool WindowIsMapped(IntPtr handle) {
4278 XWindowAttributes attributes;
4280 attributes = new XWindowAttributes();
4281 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
4282 if (attributes.map_state == MapState.IsUnmapped) {
4288 #endregion // Public Static Methods
4291 internal override event EventHandler Idle;
4292 #endregion // Events
4295 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4296 internal extern static IntPtr XOpenDisplay(IntPtr display);
4297 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4298 internal extern static int XCloseDisplay(IntPtr display);
4299 [DllImport ("libX11", EntryPoint="XSynchronize")]
4300 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4302 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4303 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);
4304 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4305 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4306 [DllImport ("libX11", EntryPoint="XMapWindow")]
4307 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4308 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4309 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4310 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4311 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4312 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4313 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4314 [DllImport ("libX11", EntryPoint="XRootWindow")]
4315 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4316 [DllImport ("libX11", EntryPoint="XNextEvent")]
4317 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4318 [DllImport ("libX11")]
4319 internal extern static int XConnectionNumber (IntPtr diplay);
4320 [DllImport ("libX11")]
4321 internal extern static int XPending (IntPtr diplay);
4322 [DllImport ("libX11", EntryPoint="XSelectInput")]
4323 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4325 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4326 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4328 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4329 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4330 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4331 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4333 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4334 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4336 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4337 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4339 [DllImport ("libX11", EntryPoint="XFlush")]
4340 internal extern static int XFlush(IntPtr display);
4342 [DllImport ("libX11", EntryPoint="XSetWMName")]
4343 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4345 [DllImport ("libX11", EntryPoint="XStoreName")]
4346 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
4348 [DllImport ("libX11", EntryPoint="XFetchName")]
4349 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
4351 [DllImport ("libX11", EntryPoint="XSendEvent")]
4352 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
4354 [DllImport ("libX11", EntryPoint="XQueryTree")]
4355 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);
4357 [DllImport ("libX11", EntryPoint="XFree")]
4358 internal extern static int XFree(IntPtr data);
4360 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
4361 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
4363 [DllImport ("libX11", EntryPoint="XLowerWindow")]
4364 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
4366 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
4367 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
4369 [DllImport ("libX11", EntryPoint="XInternAtom")]
4370 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
4372 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
4373 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
4375 [DllImport ("libX11", EntryPoint="XGrabPointer")]
4376 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);
4378 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
4379 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
4381 [DllImport ("libX11", EntryPoint="XQueryPointer")]
4382 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);
4384 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
4385 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);
4387 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4388 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);
4390 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4391 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);
4393 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4394 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);
4396 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4397 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);
4399 [DllImport ("libX11", EntryPoint="XWarpPointer")]
4400 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);
4402 [DllImport ("libX11", EntryPoint="XClearWindow")]
4403 internal extern static int XClearWindow(IntPtr display, IntPtr window);
4405 [DllImport ("libX11", EntryPoint="XClearArea")]
4406 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
4409 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
4410 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
4412 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
4413 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
4415 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
4416 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
4418 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
4419 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
4421 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
4422 internal extern static int XDefaultScreen(IntPtr display);
4424 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
4425 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
4427 [DllImport ("libX11", EntryPoint="XLookupColor")]
4428 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
4430 [DllImport ("libX11", EntryPoint="XAllocColor")]
4431 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
4433 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
4434 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
4436 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4437 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
4439 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4440 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
4442 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4443 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
4445 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4446 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
4448 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4449 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
4451 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
4452 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
4454 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
4455 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
4457 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
4458 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
4461 [DllImport ("libX11", EntryPoint="XCreateGC")]
4462 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
4464 [DllImport ("libX11", EntryPoint="XFreeGC")]
4465 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
4467 [DllImport ("libX11", EntryPoint="XSetFunction")]
4468 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
4470 [DllImport ("libX11", EntryPoint="XDrawLine")]
4471 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
4473 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
4474 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
4476 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
4477 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
4479 [DllImport ("libX11", EntryPoint="XCopyArea")]
4480 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);
4482 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
4483 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);
4485 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
4486 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
4488 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
4489 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
4491 [DllImport ("libX11", EntryPoint="XDefineCursor")]
4492 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
4494 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
4495 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
4497 [DllImport ("libX11", EntryPoint="XFreeCursor")]
4498 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
4500 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
4501 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
4503 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
4504 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);
4506 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
4507 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
4509 [DllImport ("libX11", EntryPoint="XFreePixmap")]
4510 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
4512 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
4513 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
4515 [DllImport ("libX11", EntryPoint="XWhitePixel")]
4516 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
4518 [DllImport ("libX11", EntryPoint="XBlackPixel")]
4519 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
4521 [DllImport ("libX11", EntryPoint="XGrabServer")]
4522 internal extern static void XGrabServer(IntPtr display);
4524 [DllImport ("libX11", EntryPoint="XUngrabServer")]
4525 internal extern static void XUngrabServer(IntPtr display);
4527 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
4528 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4530 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
4531 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4533 [DllImport ("libX11", EntryPoint="XSetWMHints")]
4534 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
4536 [DllImport ("libX11", EntryPoint="XSync")]
4537 internal extern static void XSync(IntPtr display, IntPtr window);
4539 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
4540 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
4542 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
4543 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
4545 [DllImport ("libX11", EntryPoint="XGetErrorText")]
4546 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
4548 [DllImport ("libX11", EntryPoint="XInitThreads")]
4549 internal extern static int XInitThreads();
4551 [DllImport ("libX11", EntryPoint="XConvertSelection")]
4552 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
4554 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
4555 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
4557 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
4558 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
4560 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
4561 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
4563 [DllImport ("libX11", EntryPoint="XSetForeground")]
4564 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
4566 [DllImport ("libX11", EntryPoint="XSetBackground")]
4567 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
4569 [DllImport ("libX11", EntryPoint="XBell")]
4570 internal extern static int XBell(IntPtr display, int percent);
4572 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
4573 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
4575 [DllImport ("libX11", EntryPoint="XFilterEvent")]
4576 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);