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 themes_enabled;
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 Hashtable MessageQueues; // Holds our thread-specific XEventQueues
101 private static Pollfd[] pollfds; // For watching the X11 socket
103 private static X11Keyboard Keyboard; //
104 private static X11Dnd Dnd;
105 private static Socket listen; //
106 private static Socket wake; //
107 private static Socket wake_receive; //
108 private static byte[] network_buffer; //
109 private static bool detectable_key_auto_repeat;
112 private static IntPtr ActiveWindow; // Handle of the active window
113 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
116 private static Stack ModalWindows; // Stack of our modal windows
119 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
122 private static IntPtr LastCursorWindow; // The last window we set the cursor on
123 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
124 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
127 private static CaretStruct Caret; //
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 MessageQueues = new Hashtable(7);
175 TimerList = new ArrayList ();
178 ErrorExceptions = false;
180 // X11 Initialization
181 SetDisplay(XOpenDisplay(IntPtr.Zero));
182 X11DesktopColors.Initialize();
185 // Disable keyboard autorepeat
187 XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
188 detectable_key_auto_repeat = true;
190 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
191 detectable_key_auto_repeat = false;
194 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
195 ErrorHandler = new XErrorHandler(HandleError);
196 XSetErrorHandler(ErrorHandler);
198 #endregion // Constructors
200 #region Singleton Specific Code
201 public static XplatUIX11 GetInstance() {
203 if (Instance == null) {
204 Instance=new XplatUIX11();
211 public int Reference {
218 #region Internal Properties
219 internal static IntPtr Display {
221 return DisplayHandle;
225 XplatUIX11.GetInstance().SetDisplay(value);
229 internal static int Screen {
239 internal static IntPtr RootWindowHandle {
249 internal static IntPtr Visual {
255 CustomVisual = value;
259 internal static IntPtr ColorMap {
261 return CustomColormap;
265 CustomColormap = value;
270 #region XExceptionClass
271 internal class XException : ApplicationException {
275 XRequest RequestCode;
279 public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
280 this.Display = Display;
281 this.ResourceID = ResourceID;
282 this.Serial = Serial;
283 this.RequestCode = RequestCode;
284 this.ErrorCode = ErrorCode;
285 this.MinorCode = MinorCode;
288 public override string Message {
290 return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
294 public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
303 sb = new StringBuilder(160);
304 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
305 x_error_text = sb.ToString();
306 hwnd = Hwnd.ObjectFromHandle(ResourceID);
308 hwnd_text = hwnd.ToString();
309 c = Control.FromHandle(hwnd.Handle);
311 control_text = c.ToString();
313 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
316 hwnd_text = "<null>";
317 control_text = "<null>";
321 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);
325 #endregion // XExceptionClass
327 #region Internal Methods
328 internal void SetDisplay(IntPtr display_handle) {
329 if (display_handle != IntPtr.Zero) {
332 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
333 hwnd = Hwnd.ObjectFromHandle(FosterParent);
334 XDestroyWindow(DisplayHandle, FosterParent);
338 if (DisplayHandle != IntPtr.Zero) {
339 XCloseDisplay(DisplayHandle);
342 DisplayHandle=display_handle;
344 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
345 // been hacked to do this for us.
346 Graphics.FromHdcInternal (DisplayHandle);
349 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
350 XSynchronize(DisplayHandle, true);
353 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
354 ErrorExceptions = true;
358 ScreenNo = XDefaultScreen(DisplayHandle);
359 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
360 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
362 // Create the foster parent
363 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
364 if (FosterParent==IntPtr.Zero) {
365 Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
369 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
370 hwnd.WholeWindow = FosterParent;
371 hwnd.ClientWindow = FosterParent;
373 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
375 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
376 hwnd.whole_window = RootWindow;
377 hwnd.ClientWindow = RootWindow;
379 // For sleeping on the X11 socket
380 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
381 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
385 // To wake up when a timer is ready
386 network_buffer = new byte[10];
388 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
389 wake.Connect(listen.LocalEndPoint);
390 wake_receive = listen.Accept();
393 pollfds = new Pollfd [2];
394 pollfds [0] = new Pollfd ();
395 pollfds [0].fd = XConnectionNumber (DisplayHandle);
396 pollfds [0].events = PollEvents.POLLIN;
398 pollfds [1] = new Pollfd ();
399 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
400 pollfds [1].events = PollEvents.POLLIN;
403 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
404 Dnd = new X11Dnd (DisplayHandle);
406 PostQuitState = false;
408 DoubleClickInterval = 500;
410 HoverState.Interval = 500;
411 HoverState.Timer = new Timer();
412 HoverState.Timer.Enabled = false;
413 HoverState.Timer.Interval = HoverState.Interval;
414 HoverState.Timer.Tick += new EventHandler(MouseHover);
415 HoverState.Size = new Size(4, 4);
419 ActiveWindow = IntPtr.Zero;
420 FocusWindow = IntPtr.Zero;
421 ModalWindows = new Stack(3);
423 MouseState = MouseButtons.None;
424 MousePosition = new Point(0, 0);
426 Caret.Timer = new Timer();
427 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
428 Caret.Timer.Tick += new EventHandler(CaretCallback);
432 // Grab atom changes off the root window to catch certain WM events
433 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
435 // Handle any upcoming errors
436 ErrorHandler = new XErrorHandler(HandleError);
437 XSetErrorHandler(ErrorHandler);
439 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
443 internal static void Where() {
444 Console.WriteLine("Here: {0}\n", WhereString());
447 internal static string WhereString() {
455 newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
456 unknown = Locale.GetText("<unknown method>");
457 sb = new StringBuilder();
458 stack = new StackTrace(true);
460 for (int i = 0; i < stack.FrameCount; i++) {
461 frame = stack.GetFrame(i);
464 method = frame.GetMethod();
465 if (method != null) {
467 sb.AppendFormat(frame.ToString());
469 if (frame.GetFileLineNumber() != 0) {
470 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
472 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
478 return sb.ToString();
480 #endregion // Internal Methods
482 #region Private Methods
483 private static void SetupAtoms() {
484 NetAtoms = new IntPtr[(int)NA.LAST_NET_ATOM];
486 NetAtoms[(int)NA.WM_PROTOCOLS] = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
487 NetAtoms[(int)NA.WM_DELETE_WINDOW] = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
488 NetAtoms[(int)NA.WM_TAKE_FOCUS] = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
490 NetAtoms[(int)NA._NET_SUPPORTED] = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
491 NetAtoms[(int)NA._NET_CLIENT_LIST] = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
492 NetAtoms[(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
493 NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
494 NetAtoms[(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
495 NetAtoms[(int)NA._NET_CURRENT_DESKTOP] = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
496 NetAtoms[(int)NA._NET_DESKTOP_NAMES] = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
497 NetAtoms[(int)NA._NET_ACTIVE_WINDOW] = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
498 NetAtoms[(int)NA._NET_WORKAREA] = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
499 NetAtoms[(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
500 NetAtoms[(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
501 NetAtoms[(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
502 NetAtoms[(int)NA._NET_SHOWING_DESKTOP] = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
504 NetAtoms[(int)NA._NET_CLOSE_WINDOW] = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
505 NetAtoms[(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
506 NetAtoms[(int)NA._NET_WM_MOVERESIZE] = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
507 NetAtoms[(int)NA._NET_RESTACK_WINDOW] = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
508 NetAtoms[(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
510 NetAtoms[(int)NA._NET_WM_NAME] = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
511 NetAtoms[(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
512 NetAtoms[(int)NA._NET_WM_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
513 NetAtoms[(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
514 NetAtoms[(int)NA._NET_WM_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
515 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
516 NetAtoms[(int)NA._NET_WM_STATE] = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
517 NetAtoms[(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
518 NetAtoms[(int)NA._NET_WM_STRUT] = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
519 NetAtoms[(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
520 NetAtoms[(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
521 NetAtoms[(int)NA._NET_WM_ICON] = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
522 NetAtoms[(int)NA._NET_WM_PID] = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
523 NetAtoms[(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
524 NetAtoms[(int)NA._NET_WM_USER_TIME] = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
525 NetAtoms[(int)NA._NET_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
527 NetAtoms[(int)NA._NET_WM_PING] = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
528 NetAtoms[(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
530 NetAtoms[(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
531 NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
532 NetAtoms[(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
534 NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
535 NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
536 NetAtoms[(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
538 NetAtoms[(int)NA._XEMBED] = XInternAtom(DisplayHandle, "_XEMBED", false);
539 NetAtoms[(int)NA._XEMBED_INFO] = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
541 NetAtoms[(int)NA._MOTIF_WM_HINTS] = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
543 NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
544 NetAtoms[(int)NA._NET_WM_STATE_ABOVE] = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
545 NetAtoms[(int)NA._NET_WM_STATE_MODAL] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
546 NetAtoms[(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
547 NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
549 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DESKTOP", false);
550 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DOCK] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DOCK", false);
551 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_TOOLBAR] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_TOOLBAR", false);
552 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_MENU] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_MENU", false);
553 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_UTILITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_UTILITY", false);
554 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DIALOG] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DIALOG", false);
555 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_SPLASH] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_SPLASH", false);
556 NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_NORMAL] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_NORMAL", false);
559 NetAtoms[(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
560 NetAtoms[(int)NA.DIB] = (IntPtr)Atom.XA_PIXMAP;
561 NetAtoms[(int)NA.OEMTEXT] = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
562 NetAtoms[(int)NA.UNICODETEXT] = XInternAtom(DisplayHandle, "UTF8_STRING", false);
563 NetAtoms[(int)NA.TARGETS] = XInternAtom(DisplayHandle, "TARGETS", false);
566 AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
567 PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
568 HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
571 private void GetSystrayManagerWindow() {
572 XGrabServer(DisplayHandle);
573 SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA._NET_SYSTEM_TRAY_S]);
574 XUngrabServer(DisplayHandle);
575 XFlush(DisplayHandle);
578 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
582 xev.ClientMessageEvent.type = XEventName.ClientMessage;
583 xev.ClientMessageEvent.send_event = true;
584 xev.ClientMessageEvent.window = window;
585 xev.ClientMessageEvent.message_type = message_type;
586 xev.ClientMessageEvent.format = 32;
587 xev.ClientMessageEvent.ptr1 = l0;
588 xev.ClientMessageEvent.ptr2 = l1;
589 xev.ClientMessageEvent.ptr3 = l2;
590 XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
593 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
597 xev.ClientMessageEvent.type = XEventName.ClientMessage;
598 xev.ClientMessageEvent.send_event = true;
599 xev.ClientMessageEvent.window = window;
600 xev.ClientMessageEvent.message_type = message_type;
601 xev.ClientMessageEvent.format = 32;
602 xev.ClientMessageEvent.ptr1 = l0;
603 xev.ClientMessageEvent.ptr2 = l1;
604 xev.ClientMessageEvent.ptr3 = l2;
605 XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
608 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
610 // Only MDI windows get caption_heights
612 tool_caption_height = 19;
614 if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
615 if ((ExStyle & (int) WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
616 border_style = FormBorderStyle.Fixed3D;
617 } else if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
618 border_style = FormBorderStyle.None;
620 border_style = FormBorderStyle.FixedSingle;
622 title_style = TitleStyle.None;
624 if ((ExStyle & (int) WindowExStyles.WS_EX_MDICHILD) != 0) {
627 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
628 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
629 title_style = TitleStyle.Tool;
631 title_style = TitleStyle.Normal;
635 if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
636 (ExStyle & (int) WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
637 border_style = (FormBorderStyle) 0xFFFF;
639 border_style = FormBorderStyle.None;
644 title_style = TitleStyle.None;
645 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
646 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
647 title_style = TitleStyle.Tool;
649 title_style = TitleStyle.Normal;
653 border_style = FormBorderStyle.None;
655 if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
656 if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
657 border_style = FormBorderStyle.SizableToolWindow;
659 border_style = FormBorderStyle.Sizable;
662 if ((Style & (int)WindowStyles.WS_CAPTION) == (int)WindowStyles.WS_CAPTION) {
663 if ((ExStyle & (int)WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
664 border_style = FormBorderStyle.Fixed3D;
665 } else if ((ExStyle & (int)WindowExStyles.WS_EX_DLGMODALFRAME) != 0) {
666 border_style = FormBorderStyle.FixedDialog;
667 } else if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
668 border_style = FormBorderStyle.FixedToolWindow;
669 } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
670 border_style = FormBorderStyle.FixedSingle;
673 if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
674 border_style = FormBorderStyle.FixedSingle;
681 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
682 DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
685 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
686 MotifWmHints mwmHints;
687 MotifFunctions functions;
688 MotifDecorations decorations;
690 Rectangle client_rect;
693 // Child windows don't need WM window styles
694 if ((cp.Style & (int)WindowStyles.WS_CHILDWINDOW) != 0) {
700 mwmHints = new MotifWmHints();
704 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
705 mwmHints.functions = (IntPtr)0;
706 mwmHints.decorations = (IntPtr)0;
708 if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
709 functions |= MotifFunctions.Move;
710 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
713 if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
714 functions |= MotifFunctions.Move | MotifFunctions.Resize;
715 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
717 if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
718 functions |= MotifFunctions.Minimize;
719 decorations |= MotifDecorations.Minimize;
722 if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
723 functions |= MotifFunctions.Maximize;
724 decorations |= MotifDecorations.Maximize;
727 if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
728 functions |= MotifFunctions.Close;
731 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_DLGMODALFRAME)) != 0) {
732 decorations |= MotifDecorations.Border;
735 if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
736 decorations |= MotifDecorations.Border;
739 if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
740 decorations |= MotifDecorations.Border;
743 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
748 if ((functions & MotifFunctions.Resize) == 0) {
749 hwnd.fixed_size = true;
750 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));
752 hwnd.fixed_size = false;
755 mwmHints.functions = (IntPtr)functions;
756 mwmHints.decorations = (IntPtr)decorations;
758 client_rect = hwnd.ClientRect;
760 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._MOTIF_WM_HINTS], NetAtoms[(int)NA._MOTIF_WM_HINTS], 32, PropertyMode.Replace, ref mwmHints, 5);
761 if (((cp.Style & (int)WindowStyles.WS_POPUP) != 0) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
763 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
764 } else if ((cp.ExStyle & (int)WindowExStyles.WS_EX_APPWINDOW) == 0) {
766 // XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
768 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
769 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
771 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
774 int[] atoms = new int[8];
777 if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
778 atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR].ToInt32();
780 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
783 IntPtr[] atom_ptrs = new IntPtr[2];
784 atom_ptrs[atom_count++] = NetAtoms[(int)NA.WM_DELETE_WINDOW];
785 if ((cp.ExStyle & (int)WindowExStyles.WS_EX_CONTEXTHELP) != 0) {
786 atom_ptrs[atom_count++] = NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
789 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
793 private void SetIcon(Hwnd hwnd, Icon icon) {
799 bitmap = icon.ToBitmap();
801 size = bitmap.Width * bitmap.Height + 2;
802 data = new IntPtr[size];
804 data[index++] = (IntPtr)bitmap.Width;
805 data[index++] = (IntPtr)bitmap.Height;
807 for (int y = 0; y < bitmap.Height; y++) {
808 for (int x = 0; x < bitmap.Width; x++) {
809 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
813 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
816 private IntPtr ImageToPixmap(Image image) {
820 private void WakeupMain () {
821 wake.Send (new byte [] { 0xFF });
824 private XEventQueue ThreadQueue(Thread thread) {
827 queue = (XEventQueue)MessageQueues[thread];
829 queue = new XEventQueue(thread);
830 MessageQueues[thread] = queue;
836 private void TranslatePropertyToClipboard(IntPtr property) {
841 IntPtr prop = IntPtr.Zero;
843 Clipboard.Item = null;
845 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);
847 if ((long)nitems > 0) {
848 if (property == (IntPtr)Atom.XA_STRING) {
849 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
850 } else if (property == (IntPtr)Atom.XA_BITMAP) {
851 // FIXME - convert bitmap to image
852 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
853 // FIXME - convert pixmap to image
854 } else if (property == NetAtoms[(int)NA.OEMTEXT]) {
855 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
856 } else if (property == NetAtoms[(int)NA.UNICODETEXT]) {
857 Clipboard.Item = Marshal.PtrToStringAnsi(prop);
864 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
866 if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
870 // Keep the invalid area as small as needed
871 if ((x + width) > hwnd.width) {
872 width = hwnd.width - x;
875 if ((y + height) > hwnd.height) {
876 height = hwnd.height - y;
880 hwnd.AddInvalidArea(x, y, width, height);
881 if (!hwnd.expose_pending) {
882 if (!hwnd.nc_expose_pending) {
883 hwnd.Queue.Paint.Enqueue(hwnd);
885 hwnd.expose_pending = true;
888 hwnd.AddNcInvalidArea (x, y, width, height);
890 if (!hwnd.nc_expose_pending) {
891 if (!hwnd.expose_pending) {
892 hwnd.Queue.Paint.Enqueue(hwnd);
894 hwnd.nc_expose_pending = true;
899 private void InvalidateWholeWindow(IntPtr handle) {
902 hwnd = Hwnd.ObjectFromHandle(handle);
904 InvalidateWholeWindow(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
907 private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
910 hwnd = Hwnd.ObjectFromHandle(handle);
912 AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
915 private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
921 hwnd = Hwnd.ObjectFromHandle(handle);
924 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
931 private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
952 XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
959 if (XQueryTree(DisplayHandle, win, out root, out parent, out children, out nchildren) == 0) {
963 if (children != IntPtr.Zero) {
967 } while (win != root);
972 //Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
975 private void FrameExtents(IntPtr window, out int left, out int top) {
980 IntPtr prop = IntPtr.Zero;
982 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);
983 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
984 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
985 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
986 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
987 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
993 if (prop != IntPtr.Zero) {
999 private void AddConfigureNotify (XEvent xevent) {
1002 hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1009 if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
1010 if (!hwnd.reparented) {
1011 hwnd.x = xevent.ConfigureEvent.x;
1012 hwnd.y = xevent.ConfigureEvent.y;
1014 // This sucks ass, part 1
1015 // Every WM does the ConfigureEvents of toplevel windows different, so there's
1016 // no standard way of getting our adjustment.
1017 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
1018 // Several other WMs do their decorations different yet again and we fail to deal
1019 // with that, since I couldn't find any frigging commonality between them.
1020 // The only sane WM seems to be KDE
1022 if (!xevent.ConfigureEvent.send_event) {
1025 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
1027 // This is a synthetic event, coordinates are in root space
1028 hwnd.x = xevent.ConfigureEvent.x;
1029 hwnd.y = xevent.ConfigureEvent.y;
1030 if (hwnd.whacky_wm) {
1034 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
1035 hwnd.x -= frame_left;
1036 hwnd.y -= frame_top;
1040 hwnd.width = xevent.ConfigureEvent.width;
1041 hwnd.height = xevent.ConfigureEvent.height;
1042 hwnd.ClientRect = Rectangle.Empty;
1044 if (!hwnd.configure_pending) {
1045 hwnd.Queue.Enqueue(xevent);
1046 hwnd.configure_pending = true;
1049 // We drop configure events for Client windows
1052 private void ShowCaret() {
1053 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1059 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1063 private void HideCaret() {
1064 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1070 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1074 private int NextTimeout (DateTime now) {
1075 int timeout = Int32.MaxValue;
1077 foreach (Timer timer in TimerList) {
1078 int next = (int) (timer.Expires - now).TotalMilliseconds;
1080 return 0; // Have a timer that has already expired
1083 if (next < timeout) {
1088 if (timeout < Timer.Minimum) {
1089 timeout = Timer.Minimum;
1097 private void CheckTimers (DateTime now) {
1101 count = TimerList.Count;
1107 for (int i = 0; i < TimerList.Count; i++) {
1110 timer = (Timer) TimerList[i];
1112 if (timer.Enabled && timer.Expires <= now) {
1120 private void MapWindow(Hwnd hwnd, WindowType windows) {
1122 if ((windows & WindowType.Whole) != 0) {
1123 XMapWindow(DisplayHandle, hwnd.whole_window);
1125 if ((windows & WindowType.Client) != 0) {
1126 XMapWindow(DisplayHandle, hwnd.client_window);
1130 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1131 hwnd.mapped = false;
1132 if ((windows & WindowType.Whole) != 0) {
1133 XUnmapWindow(DisplayHandle, hwnd.whole_window);
1135 if ((windows & WindowType.Client) != 0) {
1136 XUnmapWindow(DisplayHandle, hwnd.client_window);
1140 private void UpdateMessageQueue (XEventQueue queue) {
1145 now = DateTime.UtcNow;
1148 pending = XPending (DisplayHandle);
1153 Idle (this, EventArgs.Empty);
1157 pending = XPending (DisplayHandle);
1164 if ((queue != null) && (queue.Paint.Count > 0)) {
1168 timeout = NextTimeout (now);
1171 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1172 // Clean out buffer, so we're not busy-looping on the same data
1173 if (pollfds[1].revents != 0) {
1174 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1178 pending = XPending (DisplayHandle);
1186 XEvent xevent = new XEvent ();
1189 if (XPending (DisplayHandle) == 0)
1192 XNextEvent (DisplayHandle, ref xevent);
1194 if (xevent.AnyEvent.type == XEventName.KeyPress) {
1195 if (XFilterEvent(ref xevent, FosterParent)) {
1200 //Console.WriteLine("Got x event {0}", xevent);
1202 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1204 if (xevent.type == XEventName.Expose) {
1208 switch (xevent.type) {
1209 case XEventName.Expose:
1210 AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1213 case XEventName.SelectionClear: {
1214 // Should we do something?
1218 case XEventName.SelectionRequest: {
1219 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1223 sel_event = new XEvent();
1224 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1225 sel_event.SelectionEvent.send_event = true;
1226 sel_event.SelectionEvent.display = DisplayHandle;
1227 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1228 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1229 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1230 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1231 sel_event.SelectionEvent.property = IntPtr.Zero;
1233 // Seems that some apps support asking for supported types
1234 if (xevent.SelectionEvent.target == NetAtoms[(int)NA.TARGETS]) {
1241 if (Clipboard.Item is String) {
1242 atoms[atom_count++] = (int)Atom.XA_STRING;
1243 atoms[atom_count++] = (int)NetAtoms[(int)NA.OEMTEXT];
1244 atoms[atom_count++] = (int)NetAtoms[(int)NA.UNICODETEXT];
1245 } else if (Clipboard.Item is Image) {
1246 atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1247 atoms[atom_count++] = (int)Atom.XA_BITMAP;
1249 // FIXME - handle other types
1252 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1253 } else if (Clipboard.Item is string) {
1259 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1262 bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1263 buffer = Marshal.AllocHGlobal(bytes.Length);
1264 buflen = bytes.Length;
1266 for (int i = 0; i < buflen; i++) {
1267 Marshal.WriteByte(buffer, i, bytes[i]);
1269 } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.OEMTEXT]) {
1270 // FIXME - this should encode into ISO2022
1271 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1272 while (Marshal.ReadByte(buffer, buflen) != 0) {
1275 } else if (xevent.SelectionRequestEvent.target == NetAtoms[(int)NA.UNICODETEXT]) {
1276 buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1277 while (Marshal.ReadByte(buffer, buflen) != 0) {
1281 buffer = IntPtr.Zero;
1284 if (buffer != IntPtr.Zero) {
1285 XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1286 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1287 Marshal.FreeHGlobal(buffer);
1289 } else if (Clipboard.Item is Image) {
1290 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1291 // FIXME - convert image and store as property
1292 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1293 // FIXME - convert image and store as property
1297 XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1301 case XEventName.SelectionNotify: {
1302 if (Clipboard.Enumerating) {
1303 Clipboard.Enumerating = false;
1304 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1305 XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1306 if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1307 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1308 #if DriverDebugExtra
1309 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1313 } else if (Clipboard.Retrieving) {
1314 Clipboard.Retrieving = false;
1315 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1316 TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1318 Clipboard.Item = null;
1321 Dnd.HandleSelectionNotifyEvent (ref xevent);
1326 case XEventName.MapNotify: {
1327 if (hwnd.client_window == xevent.MapEvent.window) {
1333 case XEventName.UnmapNotify: {
1334 if (hwnd.client_window == xevent.MapEvent.window) {
1335 hwnd.mapped = false;
1340 case XEventName.KeyRelease:
1341 if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1342 XEvent nextevent = new XEvent ();
1344 XPeekEvent (DisplayHandle, ref nextevent);
1346 if (nextevent.type == XEventName.KeyPress &&
1347 nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1348 nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1352 goto case XEventName.KeyPress;
1354 case XEventName.MotionNotify: {
1357 if (hwnd.Queue.Count > 0) {
1358 peek = hwnd.Queue.Peek();
1359 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1363 goto case XEventName.KeyPress;
1366 case XEventName.KeyPress:
1367 case XEventName.ButtonPress:
1368 case XEventName.ButtonRelease:
1369 case XEventName.EnterNotify:
1370 case XEventName.LeaveNotify:
1371 case XEventName.CreateNotify:
1372 case XEventName.DestroyNotify:
1373 case XEventName.FocusIn:
1374 case XEventName.FocusOut:
1375 case XEventName.ClientMessage:
1376 case XEventName.ReparentNotify:
1377 hwnd.Queue.Enqueue (xevent);
1380 case XEventName.ConfigureNotify:
1381 AddConfigureNotify(xevent);
1384 case XEventName.PropertyNotify:
1385 if (xevent.PropertyEvent.atom == NetAtoms[(int)NA._NET_ACTIVE_WINDOW]) {
1390 IntPtr prop = IntPtr.Zero;
1391 IntPtr prev_active;;
1393 prev_active = ActiveWindow;
1394 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);
1395 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1396 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1399 if (prev_active != ActiveWindow) {
1400 if (prev_active != IntPtr.Zero) {
1401 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1403 if (ActiveWindow != IntPtr.Zero) {
1404 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1407 if (ModalWindows.Count == 0) {
1410 // Modality handling, if we are modal and the new active window is one
1411 // of ours but not the modal one, switch back to the modal window
1413 if (NativeWindow.FindWindow(ActiveWindow) != null) {
1414 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1415 Activate((IntPtr)ModalWindows.Peek());
1428 private IntPtr GetMousewParam(int Delta) {
1431 if ((MouseState & MouseButtons.Left) != 0) {
1432 result |= (int)MsgButtons.MK_LBUTTON;
1435 if ((MouseState & MouseButtons.Middle) != 0) {
1436 result |= (int)MsgButtons.MK_MBUTTON;
1439 if ((MouseState & MouseButtons.Right) != 0) {
1440 result |= (int)MsgButtons.MK_RBUTTON;
1443 Keys mods = ModifierKeys;
1444 if ((mods & Keys.Control) != 0) {
1445 result |= (int)MsgButtons.MK_CONTROL;
1448 if ((mods & Keys.Shift) != 0) {
1449 result |= (int)MsgButtons.MK_SHIFT;
1452 result |= Delta << 16;
1454 return (IntPtr)result;
1456 private IntPtr XGetParent(IntPtr handle) {
1463 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1466 if (Children!=IntPtr.Zero) {
1474 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
1475 if (ErrorExceptions) {
1476 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1478 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());
1483 private void SendWMDestroyMessages(Control c) {
1489 controls = c.child_controls.GetAllControls ();
1491 if (c.IsHandleCreated && !c.IsDisposed) {
1492 #if DriverDebugDestroy
1493 Console.WriteLine("Destroying {0}, child of {1}", XplatUI.Window(c.Handle), (c.Parent != null) ? XplatUI.Window(c.Parent.Handle) : "<none>");
1496 hwnd = Hwnd.ObjectFromHandle(c.Handle);
1497 SendMessage(c.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1500 for (i = 0; i < controls.Length; i++) {
1501 SendWMDestroyMessages(controls[i]);
1502 if (controls[i].IsHandleCreated) {
1503 hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
1512 private void PerformNCCalc(Hwnd hwnd) {
1513 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
1517 rect = hwnd.DefaultClientRect;
1519 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1520 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1522 ncp.rgrc1.left = rect.Left;
1523 ncp.rgrc1.top = rect.Top;
1524 ncp.rgrc1.right = rect.Right;
1525 ncp.rgrc1.bottom = rect.Bottom;
1527 Marshal.StructureToPtr(ncp, ptr, true);
1528 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1529 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1530 Marshal.FreeHGlobal(ptr);
1532 // FIXME - debug this with Menus
1534 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1535 hwnd.ClientRect = rect;
1538 if ((rect.Width < 1) || (rect.Height < 1)) {
1539 XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1541 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1545 #endregion // Private Methods
1548 private void MouseHover(object sender, EventArgs e) {
1552 HoverState.Timer.Enabled = false;
1554 if (HoverState.Window != IntPtr.Zero) {
1555 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1557 xevent = new XEvent ();
1559 xevent.type = XEventName.ClientMessage;
1560 xevent.ClientMessageEvent.display = DisplayHandle;
1561 xevent.ClientMessageEvent.window = HoverState.Window;
1562 xevent.ClientMessageEvent.message_type = HoverState.Atom;
1563 xevent.ClientMessageEvent.format = 32;
1564 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1566 hwnd.Queue.EnqueueLocked (xevent);
1573 private void CaretCallback(object sender, EventArgs e) {
1577 Caret.On = !Caret.On;
1579 XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1581 #endregion // Callbacks
1583 #region Public Properties
1585 internal override int Caption {
1591 internal override Size CursorSize {
1596 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1597 return new Size(x, y);
1599 return new Size(16, 16);
1604 internal override bool DragFullWindows {
1610 internal override Size DragSize {
1612 return new Size(4, 4);
1616 internal override Size FrameBorderSize {
1618 throw new NotImplementedException();
1622 internal override Size IconSize {
1628 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1632 current = (long)list;
1635 size = new XIconSize();
1637 for (int i = 0; i < count; i++) {
1638 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1639 current += Marshal.SizeOf(size);
1641 // Look for our preferred size
1642 if (size.min_width == 32) {
1644 return new Size(32, 32);
1647 if (size.max_width == 32) {
1649 return new Size(32, 32);
1652 if (size.min_width < 32 && size.max_width > 32) {
1655 // check if we can fit one
1657 while (x < size.max_width) {
1658 x += size.width_inc;
1661 return new Size(32, 32);
1666 if (largest < size.max_width) {
1667 largest = size.max_width;
1671 // We didn't find a match or we wouldn't be here
1672 return new Size(largest, largest);
1675 return new Size(32, 32);
1680 internal override int KeyboardSpeed {
1683 // A lot harder: need to do:
1684 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1685 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1686 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1688 // And from that we can tell the repetition rate
1690 // Notice, the values must map to:
1691 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1697 internal override int KeyboardDelay {
1700 // Return values must range from 0 to 4, 0 meaning 250ms,
1701 // and 4 meaning 1000 ms.
1703 return 1; // ie, 500 ms
1707 internal override Size MaxWindowTrackSize {
1709 return new Size (WorkingArea.Width, WorkingArea.Height);
1713 internal override Size MinimizedWindowSize {
1715 return new Size(1, 1);
1719 internal override Size MinimizedWindowSpacingSize {
1721 return new Size(1, 1);
1725 internal override Size MinimumWindowSize {
1727 return new Size(1, 1);
1731 internal override Size MinWindowTrackSize {
1733 return new Size(1, 1);
1737 internal override Keys ModifierKeys {
1739 return Keyboard.ModifierKeys;
1743 internal override Size SmallIconSize {
1749 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1753 current = (long)list;
1756 size = new XIconSize();
1758 for (int i = 0; i < count; i++) {
1759 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1760 current += Marshal.SizeOf(size);
1762 // Look for our preferred size
1763 if (size.min_width == 16) {
1765 return new Size(16, 16);
1768 if (size.max_width == 16) {
1770 return new Size(16, 16);
1773 if (size.min_width < 16 && size.max_width > 16) {
1776 // check if we can fit one
1778 while (x < size.max_width) {
1779 x += size.width_inc;
1782 return new Size(16, 16);
1787 if (smallest == 0 || smallest > size.min_width) {
1788 smallest = size.min_width;
1792 // We didn't find a match or we wouldn't be here
1793 return new Size(smallest, smallest);
1796 return new Size(16, 16);
1801 internal override int MouseButtonCount {
1807 internal override bool MouseButtonsSwapped {
1809 return false; // FIXME - how to detect?
1813 internal override Size MouseHoverSize {
1815 return new Size (1, 1);
1819 internal override int MouseHoverTime {
1821 return HoverState.Interval;
1827 internal override bool MouseWheelPresent {
1829 return true; // FIXME - how to detect?
1833 internal override Rectangle VirtualScreen {
1839 internal override Rectangle WorkingArea {
1845 IntPtr prop = IntPtr.Zero;
1848 int current_desktop;
1852 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_CURRENT_DESKTOP], IntPtr.Zero, new IntPtr(1), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1853 if ((long)nitems < 1) {
1857 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
1860 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_WORKAREA], IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1861 if ((long)nitems < 4 * current_desktop) {
1865 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
1866 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
1867 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
1868 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
1871 return new Rectangle(x, y, width, height);
1874 XWindowAttributes attributes=new XWindowAttributes();
1877 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1880 return new Rectangle(0, 0, attributes.width, attributes.height);
1884 internal override bool ThemesEnabled {
1886 return XplatUIX11.themes_enabled;
1891 #endregion // Public properties
1893 #region Public Static Methods
1894 internal override IntPtr InitializeDriver() {
1896 if (DisplayHandle==IntPtr.Zero) {
1897 SetDisplay(XOpenDisplay(IntPtr.Zero));
1903 internal override void ShutdownDriver(IntPtr token) {
1905 if (DisplayHandle!=IntPtr.Zero) {
1906 XCloseDisplay(DisplayHandle);
1907 DisplayHandle=IntPtr.Zero;
1912 internal override void EnableThemes() {
1913 themes_enabled = true;
1917 internal override void Activate(IntPtr handle) {
1920 hwnd = Hwnd.ObjectFromHandle(handle);
1922 if (hwnd != null) lock (XlibLock) {
1923 SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
1924 //XRaiseWindow(DisplayHandle, handle);
1929 internal override void AudibleAlert() {
1930 XBell(DisplayHandle, 0);
1935 internal override void CaretVisible(IntPtr handle, bool visible) {
1936 if (Caret.Hwnd == handle) {
1938 if (!Caret.Visible) {
1939 Caret.Visible = true;
1941 Caret.Timer.Start();
1944 Caret.Visible = false;
1951 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
1952 FormBorderStyle border_style;
1953 TitleStyle title_style;
1955 int tool_caption_height;
1957 DeriveStyles(Style, ExStyle, out border_style, out title_style,
1958 out caption_height, out tool_caption_height);
1960 WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
1961 caption_height, tool_caption_height,
1966 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
1972 hwnd = Hwnd.ObjectFromHandle(handle);
1975 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1982 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
1983 DataFormats.Format f;
1986 f = DataFormats.Format.List;
1988 if (XGetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD]) == IntPtr.Zero) {
1992 Clipboard.Formats = new ArrayList();
1995 XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
1997 Clipboard.Enumerating = true;
1998 while (Clipboard.Enumerating) {
1999 UpdateMessageQueue(null);
2004 result = new int[Clipboard.Formats.Count];
2006 for (int i = 0; i < Clipboard.Formats.Count; i++) {
2007 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2010 Clipboard.Formats = null;
2014 internal override void ClipboardClose(IntPtr handle) {
2015 if (handle != ClipMagic) {
2016 throw new ArgumentException("handle is not a valid clipboard handle");
2021 internal override int ClipboardGetID(IntPtr handle, string format) {
2022 if (handle != ClipMagic) {
2023 throw new ArgumentException("handle is not a valid clipboard handle");
2026 if (format == "Text" ) return (int)Atom.XA_STRING;
2027 else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2028 //else if (format == "MetaFilePict" ) return 3;
2029 //else if (format == "SymbolicLink" ) return 4;
2030 //else if (format == "DataInterchangeFormat" ) return 5;
2031 //else if (format == "Tiff" ) return 6;
2032 else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
2033 else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2034 else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
2035 //else if (format == "PenData" ) return 10;
2036 //else if (format == "RiffAudio" ) return 11;
2037 //else if (format == "WaveAudio" ) return 12;
2038 else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
2039 //else if (format == "EnhancedMetafile" ) return 14;
2040 //else if (format == "FileDrop" ) return 15;
2041 //else if (format == "Locale" ) return 16;
2043 return XInternAtom(DisplayHandle, format, false).ToInt32();
2046 internal override IntPtr ClipboardOpen() {
2050 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2051 XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2053 Clipboard.Retrieving = true;
2054 while (Clipboard.Retrieving) {
2055 UpdateMessageQueue(null);
2058 return Clipboard.Item;
2061 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2062 Clipboard.Item = obj;
2063 Clipboard.Type = type;
2064 Clipboard.Converter = converter;
2067 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], FosterParent, IntPtr.Zero);
2069 // Clearing the selection
2070 XSetSelectionOwner(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], IntPtr.Zero, IntPtr.Zero);
2074 internal override void CreateCaret(IntPtr handle, int width, int height) {
2075 XGCValues gc_values;
2078 hwnd = Hwnd.ObjectFromHandle(handle);
2080 if (Caret.Hwnd != IntPtr.Zero) {
2081 DestroyCaret(Caret.Hwnd);
2084 Caret.Hwnd = handle;
2085 Caret.Window = hwnd.client_window;
2086 Caret.Width = width;
2087 Caret.Height = height;
2088 Caret.Visible = false;
2091 gc_values = new XGCValues();
2092 gc_values.line_width = width;
2094 Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2095 if (Caret.gc == IntPtr.Zero) {
2096 Caret.Hwnd = IntPtr.Zero;
2100 XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2103 internal override IntPtr CreateWindow(CreateParams cp) {
2104 XSetWindowAttributes Attributes;
2110 IntPtr ParentHandle;
2112 IntPtr ClientWindow;
2113 Rectangle ClientRect;
2114 SetWindowValuemask ValueMask;
2119 Attributes = new XSetWindowAttributes();
2125 if (Width<1) Width=1;
2126 if (Height<1) Height=1;
2128 if (cp.Parent != IntPtr.Zero) {
2129 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2131 if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
2132 // We need to use our foster parent window until this poor child gets it's parent assigned
2133 ParentHandle=FosterParent;
2134 } else if ((cp.Style & (int)WindowStyles.WS_POPUP) != 0) {
2135 ParentHandle=RootWindow;
2137 // Default position on screen, if window manager doesn't place us somewhere else
2140 ParentHandle=RootWindow;
2144 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2146 Attributes.bit_gravity = Gravity.NorthWestGravity;
2147 Attributes.win_gravity = Gravity.NorthWestGravity;
2149 // Save what's under the toolwindow
2150 if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
2151 Attributes.save_under = true;
2152 ValueMask |= SetWindowValuemask.SaveUnder;
2156 // If we're a popup without caption we override the WM
2157 if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
2158 if ((cp.Style & (int)WindowStyles.WS_CAPTION) != (int)WindowStyles.WS_CAPTION) {
2159 Attributes.override_redirect = true;
2160 ValueMask |= SetWindowValuemask.OverrideRedirect;
2167 hwnd.height = Height;
2168 hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2170 if ((cp.Style & ((int)WindowStyles.WS_DISABLED)) != 0) {
2171 hwnd.enabled = false;
2174 ClientRect = hwnd.ClientRect;
2175 ClientWindow = IntPtr.Zero;
2178 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2179 if (WholeWindow != IntPtr.Zero) {
2180 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2182 if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2183 ValueMask = SetWindowValuemask.ColorMap;
2184 Attributes.colormap = CustomColormap;
2186 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);
2190 if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2191 throw new Exception("Could not create X11 windows");
2194 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2195 hwnd.WholeWindow = WholeWindow;
2196 hwnd.ClientWindow = ClientWindow;
2198 #if DriverDebug || DriverDebugCreate
2199 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);
2202 if ((cp.Style & (int)WindowStyles.WS_CHILD) == 0) {
2203 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2206 hints = new XSizeHints();
2209 hints.flags = (IntPtr)XSizeHintsFlags.USPosition;
2210 XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2215 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)SelectInputMask));
2216 XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2218 if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
2219 MapWindow(hwnd, WindowType.Both);
2220 hwnd.visible = true;
2224 if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOPMOST) != 0) {
2225 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2226 } else if ((cp.ExStyle & (int)WindowExStyles.WS_EX_APPWINDOW) == 0) {
2227 // XSetTransientForHint (DisplayHandle, hwnd.whole_window, FosterParent);
2230 SetWMStyles(hwnd, cp);
2232 if ((cp.Style & (int)WindowStyles.WS_MINIMIZE) != 0) {
2233 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2234 } else if ((cp.Style & (int)WindowStyles.WS_MAXIMIZE) != 0) {
2235 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2238 // for now make all windows dnd enabled
2239 Dnd.SetAllowDrop (hwnd, true);
2241 // Set caption/window title
2242 Text(hwnd.Handle, cp.Caption);
2247 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2248 CreateParams create_params = new CreateParams();
2250 create_params.Caption = "";
2251 create_params.X = X;
2252 create_params.Y = Y;
2253 create_params.Width = Width;
2254 create_params.Height = Height;
2256 create_params.ClassName=XplatUI.DefaultClassName;
2257 create_params.ClassStyle = 0;
2258 create_params.ExStyle=0;
2259 create_params.Parent=IntPtr.Zero;
2260 create_params.Param=0;
2262 return CreateWindow(create_params);
2265 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2267 Bitmap cursor_bitmap;
2275 IntPtr cursor_pixmap;
2282 if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2286 // Win32 only allows creation cursors of a certain size
2287 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2288 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2289 cursor_mask = new Bitmap(mask, new Size(width, height));
2291 cursor_bitmap = bitmap;
2295 width = cursor_bitmap.Width;
2296 height = cursor_bitmap.Height;
2298 cursor_bits = new Byte[(width / 8) * height];
2299 mask_bits = new Byte[(width / 8) * height];
2301 for (int y = 0; y < height; y++) {
2302 for (int x = 0; x < width; x++) {
2303 c_pixel = cursor_bitmap.GetPixel(x, y);
2304 m_pixel = cursor_mask.GetPixel(x, y);
2306 and = c_pixel == cursor_pixel;
2307 xor = m_pixel == mask_pixel;
2311 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2312 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2313 } else if (and && !xor) {
2315 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2316 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2318 } else if (and && !xor) {
2320 } else if (and && xor) {
2323 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2324 // we want both to be 0 so nothing to be done
2325 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2326 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2332 cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2333 mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2337 fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2338 fg.red = (ushort)65535;
2339 fg.green = (ushort)65535;
2340 fg.blue = (ushort)65535;
2342 bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2344 cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2346 XFreePixmap(DisplayHandle, cursor_pixmap);
2347 XFreePixmap(DisplayHandle, mask_pixmap);
2352 internal override IntPtr DefineStdCursor(StdCursor id) {
2353 CursorFontShape shape;
2356 // FIXME - define missing shapes
2359 case StdCursor.AppStarting: {
2360 shape = CursorFontShape.XC_watch;
2364 case StdCursor.Arrow: {
2365 shape = CursorFontShape.XC_top_left_arrow;
2369 case StdCursor.Cross: {
2370 shape = CursorFontShape.XC_crosshair;
2374 case StdCursor.Default: {
2375 shape = CursorFontShape.XC_top_left_arrow;
2379 case StdCursor.Hand: {
2380 shape = CursorFontShape.XC_hand1;
2384 case StdCursor.Help: {
2385 shape = CursorFontShape.XC_question_arrow;
2389 case StdCursor.HSplit: {
2390 shape = CursorFontShape.XC_sb_v_double_arrow;
2394 case StdCursor.IBeam: {
2395 shape = CursorFontShape.XC_xterm;
2399 case StdCursor.No: {
2400 shape = CursorFontShape.XC_circle;
2404 case StdCursor.NoMove2D: {
2405 shape = CursorFontShape.XC_fleur;
2409 case StdCursor.NoMoveHoriz: {
2410 shape = CursorFontShape.XC_fleur;
2414 case StdCursor.NoMoveVert: {
2415 shape = CursorFontShape.XC_fleur;
2419 case StdCursor.PanEast: {
2420 shape = CursorFontShape.XC_fleur;
2424 case StdCursor.PanNE: {
2425 shape = CursorFontShape.XC_fleur;
2429 case StdCursor.PanNorth: {
2430 shape = CursorFontShape.XC_fleur;
2434 case StdCursor.PanNW: {
2435 shape = CursorFontShape.XC_fleur;
2439 case StdCursor.PanSE: {
2440 shape = CursorFontShape.XC_fleur;
2444 case StdCursor.PanSouth: {
2445 shape = CursorFontShape.XC_fleur;
2449 case StdCursor.PanSW: {
2450 shape = CursorFontShape.XC_fleur;
2454 case StdCursor.PanWest: {
2455 shape = CursorFontShape.XC_sizing;
2459 case StdCursor.SizeAll: {
2460 shape = CursorFontShape.XC_fleur;
2464 case StdCursor.SizeNESW: {
2465 shape = CursorFontShape.XC_top_right_corner;
2469 case StdCursor.SizeNS: {
2470 shape = CursorFontShape.XC_sb_v_double_arrow;
2474 case StdCursor.SizeNWSE: {
2475 shape = CursorFontShape.XC_top_left_corner;
2479 case StdCursor.SizeWE: {
2480 shape = CursorFontShape.XC_sb_h_double_arrow;
2484 case StdCursor.UpArrow: {
2485 shape = CursorFontShape.XC_center_ptr;
2489 case StdCursor.VSplit: {
2490 shape = CursorFontShape.XC_sb_h_double_arrow;
2494 case StdCursor.WaitCursor: {
2495 shape = CursorFontShape.XC_watch;
2505 cursor = XCreateFontCursor(DisplayHandle, shape);
2510 internal override IntPtr DefWndProc(ref Message msg) {
2511 switch ((Msg)msg.Msg) {
2512 case Msg.WM_PAINT: {
2515 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2517 hwnd.expose_pending = false;
2523 case Msg.WM_NCPAINT: {
2526 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2528 hwnd.nc_expose_pending = false;
2534 case Msg.WM_CONTEXTMENU: {
2537 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2539 if ((hwnd != null) && (hwnd.parent != null)) {
2540 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2545 case Msg.WM_MOUSEWHEEL: {
2548 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2550 if ((hwnd != null) && (hwnd.parent != null)) {
2551 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2552 if (msg.Result == IntPtr.Zero) {
2559 case Msg.WM_SETCURSOR: {
2562 hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2564 break; // not sure how this happens, but it does
2566 // Pass to parent window first
2567 while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2569 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2572 if (msg.Result == IntPtr.Zero) {
2575 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2576 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
2577 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
2578 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
2579 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
2580 case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2583 handle = Cursors.Default.handle;
2586 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
2587 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
2588 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
2589 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
2590 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
2591 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
2594 case HitTest.HTGROWBOX:
2595 case HitTest.HTSIZE:
2596 case HitTest.HTZOOM:
2597 case HitTest.HTVSCROLL:
2598 case HitTest.HTSYSMENU:
2599 case HitTest.HTREDUCE:
2600 case HitTest.HTNOWHERE:
2601 case HitTest.HTMAXBUTTON:
2602 case HitTest.HTMINBUTTON:
2603 case HitTest.HTMENU:
2604 case HitTest.HSCROLL:
2605 case HitTest.HTBOTTOM:
2606 case HitTest.HTCAPTION:
2607 case HitTest.HTCLIENT:
2608 case HitTest.HTCLOSE:
2610 default: handle = Cursors.Default.handle; break;
2612 SetCursor(msg.HWnd, handle);
2620 internal override void DestroyCaret(IntPtr handle) {
2621 if (Caret.Hwnd == handle) {
2622 if (Caret.Visible == true) {
2626 if (Caret.gc != IntPtr.Zero) {
2627 XFreeGC(DisplayHandle, Caret.gc);
2628 Caret.gc = IntPtr.Zero;
2630 Caret.Hwnd = IntPtr.Zero;
2631 Caret.Visible = false;
2636 private void DestroyCaretInternal() {
2637 if (Caret.Visible == true) {
2640 if (Caret.gc != IntPtr.Zero) {
2641 XFreeGC(DisplayHandle, Caret.gc);
2642 Caret.gc = IntPtr.Zero;
2644 Caret.Hwnd = IntPtr.Zero;
2645 Caret.Visible = false;
2649 internal override void DestroyCursor(IntPtr cursor) {
2651 XFreeCursor(DisplayHandle, cursor);
2655 internal override void DestroyWindow(IntPtr handle) {
2658 hwnd = Hwnd.ObjectFromHandle(handle);
2661 #if DriverDebug || DriverDebugDestroy
2662 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2667 #if DriverDebug || DriverDebugDestroy
2668 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2671 // Make sure if the caret is in the window, that we destroy the caret, too
2672 if (Caret.Hwnd == hwnd.client_window) {
2673 DestroyCaret(handle);
2676 if (ActiveWindow == handle) {
2677 SendMessage(handle, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
2678 ActiveWindow = IntPtr.Zero;
2681 SendWMDestroyMessages(Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle));
2684 if (hwnd.client_window != IntPtr.Zero) {
2685 XDestroyWindow(DisplayHandle, hwnd.client_window);
2688 if ((hwnd.whole_window != IntPtr.Zero) && (hwnd.whole_window != hwnd.client_window)) {
2689 XDestroyWindow(DisplayHandle, hwnd.whole_window);
2695 internal override IntPtr DispatchMessage(ref MSG msg) {
2696 return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2699 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2701 XGCValues gc_values;
2704 hwnd = Hwnd.ObjectFromHandle(handle);
2706 gc_values = new XGCValues();
2708 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2709 gc_values.line_width = line_width;
2710 gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2712 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2713 //mask = foreground ^ background;
2714 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2715 //XSetBackground(DisplayHandle, gc, background);
2716 //XSetFunction(DisplayHandle, gc, GXxor);
2717 //XSetPlaneMask(DisplayHandle, gc, mask);
2720 gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2725 control = Control.FromHandle(handle);
2727 XColor xcolor = new XColor();
2729 xcolor.red = (ushort)(control.ForeColor.R * 257);
2730 xcolor.green = (ushort)(control.ForeColor.G * 257);
2731 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2732 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2733 foreground = (uint)xcolor.pixel.ToInt32();
2735 xcolor.red = (ushort)(control.BackColor.R * 257);
2736 xcolor.green = (ushort)(control.BackColor.G * 257);
2737 xcolor.blue = (ushort)(control.BackColor.B * 257);
2738 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2739 background = (uint)xcolor.pixel.ToInt32();
2741 uint mask = foreground ^ background;
2743 XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2744 XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2745 XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
2746 XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
2748 if ((rect.Width > 0) && (rect.Height > 0)) {
2749 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2751 if (rect.Width > 0) {
2752 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2754 XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2757 XFreeGC(DisplayHandle, gc);
2760 internal override void DoEvents() {
2761 MSG msg = new MSG ();
2764 if (OverrideCursorHandle != IntPtr.Zero) {
2765 OverrideCursorHandle = IntPtr.Zero;
2768 queue_id = (Object)ThreadQueue(Thread.CurrentThread);
2770 while (PeekMessage(queue_id, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2771 TranslateMessage (ref msg);
2772 DispatchMessage (ref msg);
2776 internal override void EnableWindow(IntPtr handle, bool Enable) {
2779 hwnd = Hwnd.ObjectFromHandle(handle);
2781 hwnd.Enabled = Enable;
2785 internal override void EndLoop(Thread thread) {
2786 // This is where we one day will shut down the loop for the thread
2790 internal override IntPtr GetActive() {
2795 IntPtr prop = IntPtr.Zero;
2796 IntPtr active = IntPtr.Zero;
2798 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);
2799 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2800 active = (IntPtr)Marshal.ReadInt32(prop);
2804 if (active != IntPtr.Zero) {
2807 hwnd = Hwnd.GetObjectFromWindow(active);
2809 active = hwnd.Handle;
2811 active = IntPtr.Zero;
2817 internal override Region GetClipRegion(IntPtr handle) {
2820 hwnd = Hwnd.ObjectFromHandle(handle);
2822 return hwnd.UserClip;
2828 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2835 internal override void GetDisplaySize(out Size size) {
2836 XWindowAttributes attributes=new XWindowAttributes();
2839 // FIXME - use _NET_WM messages instead?
2840 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2843 size = new Size(attributes.width, attributes.height);
2846 internal override SizeF GetAutoScaleSize(Font font) {
2849 string magic_string = "The quick brown fox jumped over the lazy dog.";
2850 double magic_number = 44.549996948242189;
2852 g = Graphics.FromHwnd(FosterParent);
2854 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2855 return new SizeF(width, font.Height);
2858 internal override IntPtr GetParent(IntPtr handle) {
2861 hwnd = Hwnd.ObjectFromHandle(handle);
2862 if (hwnd != null && hwnd.parent != null) {
2863 return hwnd.parent.Handle;
2868 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
2878 if (handle != IntPtr.Zero) {
2879 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
2881 use_handle = RootWindow;
2885 XQueryPointer(DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
2888 if (handle != IntPtr.Zero) {
2897 internal override IntPtr GetFocus() {
2902 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
2903 return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
2906 internal override Point GetMenuOrigin(IntPtr handle) {
2909 hwnd = Hwnd.ObjectFromHandle(handle);
2912 return hwnd.MenuOrigin;
2917 [MonoTODO("Implement filtering")]
2918 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
2925 if (((XEventQueue)queue_id).Count > 0) {
2926 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
2928 UpdateMessageQueue ((XEventQueue)queue_id);
2930 if (((XEventQueue)queue_id).Count > 0) {
2931 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
2932 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
2933 xevent = ((XEventQueue)queue_id).Paint.Dequeue();
2935 if (!PostQuitState) {
2936 msg.hwnd= IntPtr.Zero;
2937 msg.message = Msg.WM_ENTERIDLE;
2941 // We reset ourselves so GetMessage can be called again
2942 PostQuitState = false;
2948 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
2950 // Handle messages for windows that are already or are about to be destroyed
2953 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
2955 goto ProcessNextMessage;
2958 if (hwnd.client_window == xevent.AnyEvent.window) {
2960 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2963 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2966 msg.hwnd = hwnd.Handle;
2969 // If you add a new event to this switch make sure to add it in
2970 // UpdateMessage also unless it is not coming through the X event system.
2972 switch(xevent.type) {
2973 case XEventName.KeyPress: {
2974 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2978 case XEventName.KeyRelease: {
2979 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2983 case XEventName.ButtonPress: {
2984 switch(xevent.ButtonEvent.button) {
2986 MouseState |= MouseButtons.Left;
2988 msg.message = Msg.WM_LBUTTONDOWN;
2990 msg.message = Msg.WM_NCLBUTTONDOWN;
2991 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2993 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
2994 msg.wParam=GetMousewParam(0);
2999 MouseState |= MouseButtons.Middle;
3001 msg.message = Msg.WM_MBUTTONDOWN;
3003 msg.message = Msg.WM_NCMBUTTONDOWN;
3004 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3006 msg.wParam=GetMousewParam(0);
3011 MouseState |= MouseButtons.Right;
3013 msg.message = Msg.WM_RBUTTONDOWN;
3015 msg.message = Msg.WM_NCRBUTTONDOWN;
3016 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3018 msg.wParam=GetMousewParam(0);
3023 msg.message=Msg.WM_MOUSEWHEEL;
3024 msg.wParam=GetMousewParam(120);
3029 msg.message=Msg.WM_MOUSEWHEEL;
3030 msg.wParam=GetMousewParam(-120);
3036 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3037 MousePosition.X = xevent.ButtonEvent.x;
3038 MousePosition.Y = xevent.ButtonEvent.y;
3040 if (!hwnd.Enabled) {
3043 msg.hwnd = hwnd.EnabledHwnd;
3044 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);
3045 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3048 if (Grab.Hwnd != IntPtr.Zero) {
3049 msg.hwnd = Grab.Hwnd;
3052 if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3053 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3054 switch(xevent.ButtonEvent.button) {
3056 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3061 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3066 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3070 ClickPending.Pending = false;
3072 ClickPending.Pending = true;
3073 ClickPending.Hwnd = msg.hwnd;
3074 ClickPending.Message = msg.message;
3075 ClickPending.wParam = msg.wParam;
3076 ClickPending.lParam = msg.lParam;
3077 ClickPending.Time = (long)xevent.ButtonEvent.time;
3083 case XEventName.ButtonRelease: {
3085 Dnd.HandleButtonRelease (ref xevent);
3089 switch(xevent.ButtonEvent.button) {
3091 MouseState &= ~MouseButtons.Left;
3093 msg.message = Msg.WM_LBUTTONUP;
3095 msg.message = Msg.WM_NCLBUTTONUP;
3096 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3098 msg.wParam=GetMousewParam(0);
3103 MouseState &= ~MouseButtons.Middle;
3105 msg.message = Msg.WM_MBUTTONUP;
3107 msg.message = Msg.WM_NCMBUTTONUP;
3108 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3110 msg.wParam=GetMousewParam(0);
3115 MouseState &= ~MouseButtons.Right;
3117 msg.message = Msg.WM_RBUTTONUP;
3119 msg.message = Msg.WM_NCRBUTTONUP;
3120 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3122 msg.wParam=GetMousewParam(0);
3127 goto ProcessNextMessage;
3131 goto ProcessNextMessage;
3135 if (!hwnd.Enabled) {
3138 msg.hwnd = hwnd.EnabledHwnd;
3139 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);
3140 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3143 if (Grab.Hwnd != IntPtr.Zero) {
3144 msg.hwnd = Grab.Hwnd;
3147 msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3148 MousePosition.X = xevent.ButtonEvent.x;
3149 MousePosition.Y = xevent.ButtonEvent.y;
3153 case XEventName.MotionNotify: {
3155 #if DriverDebugExtra
3156 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);
3159 if (Dnd.HandleMotionNotify (ref xevent))
3160 goto ProcessNextMessage;
3161 if (Grab.Hwnd != IntPtr.Zero) {
3162 msg.hwnd = Grab.Hwnd;
3164 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3167 msg.message = Msg.WM_MOUSEMOVE;
3168 msg.wParam = GetMousewParam(0);
3169 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3171 if (!hwnd.Enabled) {
3174 msg.hwnd = hwnd.EnabledHwnd;
3175 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);
3176 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3179 MousePosition.X = xevent.MotionEvent.x;
3180 MousePosition.Y = xevent.MotionEvent.y;
3182 if ((HoverState.Timer.Enabled) &&
3183 (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3184 ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3185 ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3186 ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3187 HoverState.Timer.Stop();
3188 HoverState.Timer.Start();
3189 HoverState.X = MousePosition.X;
3190 HoverState.Y = MousePosition.Y;
3200 #if DriverDebugExtra
3201 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);
3203 msg.message = Msg.WM_NCMOUSEMOVE;
3205 if (!hwnd.Enabled) {
3206 msg.hwnd = hwnd.EnabledHwnd;
3207 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);
3208 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3211 // The hit test is sent in screen coordinates
3212 XTranslateCoordinates (DisplayHandle, hwnd.client_window, RootWindow,
3213 xevent.MotionEvent.x, xevent.MotionEvent.y,
3214 out screen_x, out screen_y, out dummy);
3216 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3217 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3218 IntPtr.Zero, msg.lParam).ToInt32 ();
3219 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3221 MousePosition.X = xevent.MotionEvent.x;
3222 MousePosition.Y = xevent.MotionEvent.y;
3228 case XEventName.EnterNotify: {
3229 if (!hwnd.Enabled) {
3230 goto ProcessNextMessage;
3232 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3233 goto ProcessNextMessage;
3235 msg.message = Msg.WM_MOUSE_ENTER;
3236 HoverState.X = xevent.CrossingEvent.x;
3237 HoverState.Y = xevent.CrossingEvent.y;
3238 HoverState.Timer.Enabled = true;
3239 HoverState.Window = xevent.CrossingEvent.window;
3243 case XEventName.LeaveNotify: {
3244 if (!hwnd.Enabled) {
3245 goto ProcessNextMessage;
3247 if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3248 goto ProcessNextMessage;
3250 msg.message=Msg.WM_MOUSE_LEAVE;
3251 HoverState.Timer.Enabled = false;
3252 HoverState.Window = IntPtr.Zero;
3257 case XEventName.CreateNotify: {
3258 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3259 msg.message = WM_CREATE;
3260 // Set up CreateStruct
3262 goto ProcessNextMessage;
3269 case XEventName.ReparentNotify: {
3270 if (hwnd.parent == null) { // Toplevel
3271 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3272 // We need to adjust x/y
3273 // This sucks ass, part 2
3274 // Every WM does the reparenting of toplevel windows different, so there's
3275 // no standard way of getting our adjustment considering frames/decorations
3276 // The code below is needed for metacity. KDE doesn't works just fine without this
3284 hwnd.Reparented = true;
3286 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);
3287 FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3288 if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3291 hwnd.whacky_wm = true;
3294 if (hwnd.opacity != 0xffffffff) {
3297 opacity = (IntPtr)(Int32)hwnd.opacity;
3298 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3300 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3301 goto ProcessNextMessage;
3303 hwnd.Reparented = false;
3304 goto ProcessNextMessage;
3307 goto ProcessNextMessage;
3310 case XEventName.ConfigureNotify: {
3311 if (PostQuitState || !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3312 #if DriverDebugExtra
3313 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);
3315 SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3316 hwnd.configure_pending = false;
3318 // We need to adjust our client window to track the resize of whole_window
3319 PerformNCCalc(hwnd);
3321 goto ProcessNextMessage;
3324 case XEventName.FocusIn: {
3325 // We received focus. We use X11 focus only to know if the app window does or does not have focus
3326 // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3327 // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
3328 // about it having focus again
3329 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3330 goto ProcessNextMessage;
3332 Keyboard.FocusIn(FocusWindow);
3333 SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3334 goto ProcessNextMessage;
3337 case XEventName.FocusOut: {
3338 // Se the comment for our FocusIn handler
3339 if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3340 goto ProcessNextMessage;
3342 Keyboard.FocusOut(FocusWindow);
3344 while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3345 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3348 SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3349 goto ProcessNextMessage;
3352 case XEventName.Expose: {
3353 if (PostQuitState || !hwnd.Mapped) {
3355 hwnd.expose_pending = false;
3357 hwnd.nc_expose_pending = false;
3359 goto ProcessNextMessage;
3363 if (!hwnd.expose_pending) {
3364 goto ProcessNextMessage;
3367 if (!hwnd.nc_expose_pending) {
3368 goto ProcessNextMessage;
3371 switch (hwnd.border_style) {
3372 case FormBorderStyle.Fixed3D: {
3375 g = Graphics.FromHwnd(hwnd.whole_window);
3376 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3381 case FormBorderStyle.FixedSingle: {
3384 g = Graphics.FromHwnd(hwnd.whole_window);
3385 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3390 #if DriverDebugExtra
3391 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);
3394 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3395 Region region = new Region (rect);
3396 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3397 msg.message = Msg.WM_NCPAINT;
3398 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3401 #if DriverDebugExtra
3402 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);
3404 if (Caret.Visible == true) {
3405 Caret.Paused = true;
3409 if (Caret.Visible == true) {
3411 Caret.Paused = false;
3413 msg.message = Msg.WM_PAINT;
3417 case XEventName.DestroyNotify: {
3419 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3420 hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3422 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3423 if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3424 if (ActiveWindow == hwnd.client_window) {
3425 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
3426 ActiveWindow = IntPtr.Zero;
3429 if (Caret.Window == hwnd.client_window) {
3430 DestroyCaretInternal();
3433 #if DriverDebugDestroy
3434 Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3437 msg.hwnd = hwnd.client_window;
3438 msg.message=Msg.WM_DESTROY;
3442 Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
3445 goto ProcessNextMessage;
3451 case XEventName.ClientMessage: {
3452 if (Dnd.HandleClientMessage (ref xevent)) {
3453 goto ProcessNextMessage;
3456 if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3457 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3458 goto ProcessNextMessage;
3461 if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3462 msg.message = Msg.WM_MOUSEHOVER;
3463 msg.wParam = GetMousewParam(0);
3464 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3468 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3469 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3470 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3471 msg.wParam = xevent.ClientMessageEvent.ptr3;
3472 msg.lParam = xevent.ClientMessageEvent.ptr4;
3477 if (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA._XEMBED]) {
3478 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3483 if (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA.WM_PROTOCOLS]) {
3484 if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
3485 msg.message = Msg.WM_CLOSE;
3486 Graphics.FromHdcInternal (IntPtr.Zero);
3490 // We should not get this, but I'll leave the code in case we need it in the future
3491 if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
3492 goto ProcessNextMessage;
3495 goto ProcessNextMessage;
3498 case XEventName.TimerNotify: {
3499 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3500 goto ProcessNextMessage;
3504 goto ProcessNextMessage;
3511 internal override bool GetText(IntPtr handle, out string text) {
3514 textptr = IntPtr.Zero;
3517 // FIXME - use _NET properties
3518 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3520 if (textptr != IntPtr.Zero) {
3521 text = Marshal.PtrToStringAnsi(textptr);
3530 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) {
3533 hwnd = Hwnd.ObjectFromHandle(handle);
3539 height = hwnd.height;
3541 PerformNCCalc(hwnd);
3543 client_width = hwnd.ClientRect.Width;
3544 client_height = hwnd.ClientRect.Height;
3549 // Should we throw an exception or fail silently?
3550 // throw new ArgumentException("Called with an invalid window handle", "handle");
3560 internal override FormWindowState GetWindowState(IntPtr handle) {
3565 IntPtr prop = IntPtr.Zero;
3569 XWindowAttributes attributes;
3572 hwnd = Hwnd.ObjectFromHandle(handle);
3576 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);
3577 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3578 for (int i = 0; i < (long)nitems; i++) {
3579 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3580 if ((atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
3582 } else if (atom == NetAtoms[(int)NA._NET_WM_STATE_HIDDEN]) {
3590 return FormWindowState.Minimized;
3591 } else if (maximized == 2) {
3592 return FormWindowState.Maximized;
3595 attributes = new XWindowAttributes();
3596 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
3597 if (attributes.map_state == MapState.IsUnmapped) {
3598 throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
3602 return FormWindowState.Normal;
3605 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3607 GrabConfined = Grab.Confined;
3608 GrabArea = Grab.Area;
3611 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3613 IntPtr confine_to_window;
3615 confine_to_window = IntPtr.Zero;
3617 if (confine_to_handle != IntPtr.Zero) {
3618 XWindowAttributes attributes = new XWindowAttributes();
3620 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3623 XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3625 Grab.Area.X = attributes.x;
3626 Grab.Area.Y = attributes.y;
3627 Grab.Area.Width = attributes.width;
3628 Grab.Area.Height = attributes.height;
3629 Grab.Confined = true;
3630 confine_to_window = hwnd.client_window;
3635 hwnd = Hwnd.ObjectFromHandle(handle);
3638 XGrabPointer(DisplayHandle, hwnd.client_window, false,
3639 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3640 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3641 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3645 internal override void UngrabWindow(IntPtr hwnd) {
3647 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3648 XFlush(DisplayHandle);
3650 Grab.Hwnd = IntPtr.Zero;
3651 Grab.Confined = false;
3654 internal override void HandleException(Exception e) {
3655 StackTrace st = new StackTrace(e, true);
3656 Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3657 Console.WriteLine("{0}{1}", e.Message, st.ToString());
3660 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3663 hwnd = Hwnd.ObjectFromHandle(handle);
3666 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3668 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3672 internal override bool IsEnabled(IntPtr handle) {
3673 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3674 return (hwnd != null && hwnd.Enabled);
3677 internal override bool IsVisible(IntPtr handle) {
3678 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3679 return (hwnd != null && hwnd.visible);
3682 internal override void KillTimer(Timer timer) {
3684 TimerList.Remove(timer);
3688 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3694 hwnd = Hwnd.ObjectFromHandle(handle);
3697 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3704 internal override void OverrideCursor(IntPtr cursor) {
3705 OverrideCursorHandle = cursor;
3708 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3709 PaintEventArgs paint_event;
3712 hwnd = Hwnd.ObjectFromHandle(handle);
3714 if (Caret.Visible == true) {
3715 Caret.Paused = true;
3721 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3723 // Protected against illegal cross-thread painting
3725 if (hwnd.client_dc != null) {
3729 hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
3733 Region clip_region = new Region ();
3734 clip_region.MakeEmpty();
3736 foreach (Rectangle r in hwnd.ClipRectangles) {
3737 clip_region.Union (r);
3740 if (hwnd.UserClip != null) {
3741 clip_region.Intersect(hwnd.UserClip);
3744 hwnd.client_dc.Clip = clip_region;
3745 paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.Invalid);
3746 hwnd.expose_pending = false;
3750 hwnd.non_client_dc = Graphics.FromHwnd (hwnd.whole_window);
3752 if (!hwnd.nc_invalid.IsEmpty) {
3753 hwnd.non_client_dc.SetClip (hwnd.nc_invalid);
3754 paint_event = new PaintEventArgs(hwnd.non_client_dc, hwnd.nc_invalid);
3756 paint_event = new PaintEventArgs(hwnd.non_client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3758 hwnd.nc_expose_pending = false;
3764 internal override void PaintEventEnd(IntPtr handle, bool client) {
3767 hwnd = Hwnd.ObjectFromHandle(handle);
3770 hwnd.ClearInvalidArea();
3773 hwnd.client_dc.Flush();
3774 hwnd.client_dc.Dispose();
3775 hwnd.client_dc = null;
3778 hwnd.client_dc.Flush();
3779 hwnd.client_dc.Dispose();
3780 hwnd.client_dc = null;
3784 hwnd.ClearNcInvalidArea ();
3786 hwnd.non_client_dc.Flush ();
3787 hwnd.non_client_dc.Dispose ();
3788 hwnd.non_client_dc = null;
3793 if (Caret.Visible == true) {
3795 Caret.Paused = false;
3799 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3800 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3803 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3804 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3808 if (((XEventQueue)queue_id).Count > 0) {
3811 // Only call UpdateMessageQueue if real events are pending
3812 // otherwise we go to sleep on the socket
3813 if (XPending(DisplayHandle) != 0) {
3814 UpdateMessageQueue((XEventQueue)queue_id);
3816 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3821 CheckTimers(DateTime.UtcNow);
3826 return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
3829 // FIXME - I think this should just enqueue directly
3830 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3831 XEvent xevent = new XEvent ();
3832 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
3834 xevent.type = XEventName.ClientMessage;
3835 xevent.ClientMessageEvent.display = DisplayHandle;
3838 xevent.ClientMessageEvent.window = hwnd.whole_window;
3840 xevent.ClientMessageEvent.window = IntPtr.Zero;
3843 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
3844 xevent.ClientMessageEvent.format = 32;
3845 xevent.ClientMessageEvent.ptr1 = handle;
3846 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
3847 xevent.ClientMessageEvent.ptr3 = wparam;
3848 xevent.ClientMessageEvent.ptr4 = lparam;
3850 hwnd.Queue.Enqueue (xevent);
3855 internal override void PostQuitMessage(int exitCode) {
3856 XFlush(DisplayHandle);
3857 PostQuitState = true;
3859 // Remove our display handle from S.D
3860 Graphics.FromHdcInternal (IntPtr.Zero);
3863 internal override void RequestNCRecalc(IntPtr handle) {
3866 hwnd = Hwnd.ObjectFromHandle(handle);
3872 PerformNCCalc(hwnd);
3873 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3874 InvalidateWholeWindow(handle);
3877 internal override void ResetMouseHover(IntPtr handle) {
3880 hwnd = Hwnd.ObjectFromHandle(handle);
3885 HoverState.Timer.Enabled = true;
3886 HoverState.X = MousePosition.X;
3887 HoverState.Y = MousePosition.Y;
3888 HoverState.Window = handle;
3892 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
3898 hwnd = Hwnd.ObjectFromHandle(handle);
3901 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
3908 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
3914 hwnd = Hwnd.ObjectFromHandle(handle);
3917 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
3924 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
3927 XGCValues gc_values;
3930 hwnd = Hwnd.ObjectFromHandle(handle);
3933 if (r != Rectangle.Empty) {
3934 /* We have an invalid area in the window we're scrolling.
3935 Adjust our stored invalid rectangle to to match the scrolled amount */
3950 hwnd.ClearInvalidArea();
3951 hwnd.AddInvalidArea(r);
3954 gc_values = new XGCValues();
3956 if (with_children) {
3957 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3960 gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
3968 height = area.Height - YAmount;
3969 dest_y = area.Y + YAmount;
3972 src_y = area.Y - YAmount;
3973 height = area.Height + YAmount;
3979 width = area.Width - XAmount;
3980 dest_x = area.X + XAmount;
3983 src_x = area.X - XAmount;
3984 width = area.Width + XAmount;
3988 XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
3990 // Generate an expose for the area exposed by the horizontal scroll
3991 // We don't use AddExpose since we're
3993 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
3994 } else if (XAmount < 0) {
3995 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
3998 // Generate an expose for the area exposed by the vertical scroll
4000 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4001 } else if (YAmount < 0) {
4002 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4004 XFreeGC(DisplayHandle, gc);
4007 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4011 hwnd = Hwnd.GetObjectFromWindow(handle);
4013 rect = hwnd.ClientRect;
4016 ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4019 internal override void SendAsyncMethod (AsyncMethodData method) {
4021 XEvent xevent = new XEvent ();
4023 hwnd = Hwnd.ObjectFromHandle(FosterParent);
4025 xevent.type = XEventName.ClientMessage;
4026 xevent.ClientMessageEvent.display = DisplayHandle;
4027 xevent.ClientMessageEvent.window = FosterParent;
4028 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4029 xevent.ClientMessageEvent.format = 32;
4030 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4032 hwnd.Queue.EnqueueLocked (xevent);
4037 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam) {
4038 return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4041 internal override void SetAllowDrop (IntPtr handle, bool value)
4043 // We allow drop on all windows
4046 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4047 DragDropEffects allowed_effects)
4049 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4052 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4054 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4057 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4060 hwnd = Hwnd.ObjectFromHandle(handle);
4062 Form form = Control.FromHandle (handle) as Form;
4063 if (form != null && border_style == FormBorderStyle.FixedToolWindow ||
4064 border_style == FormBorderStyle.SizableToolWindow) {
4065 form.window_manager = new InternalWindowManager (form);
4068 hwnd.border_style = border_style;
4069 RequestNCRecalc(handle);
4072 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4073 if (Caret.Hwnd == handle) {
4080 if (Caret.Visible == true) {
4082 Caret.Timer.Start();
4087 internal override void SetClipRegion(IntPtr handle, Region region) {
4090 hwnd = Hwnd.ObjectFromHandle(handle);
4095 hwnd.UserClip = region;
4096 Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4099 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4102 if (OverrideCursorHandle == IntPtr.Zero) {
4103 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4107 LastCursorHandle = cursor;
4108 LastCursorWindow = handle;
4110 hwnd = Hwnd.ObjectFromHandle(handle);
4112 if (cursor != IntPtr.Zero) {
4113 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4115 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4121 hwnd = Hwnd.ObjectFromHandle(handle);
4123 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4127 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4128 if (handle == IntPtr.Zero) {
4130 XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x, y);
4136 hwnd = Hwnd.ObjectFromHandle(handle);
4138 XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4144 internal override void SetFocus(IntPtr handle) {
4146 IntPtr prev_focus_window;
4148 hwnd = Hwnd.ObjectFromHandle(handle);
4150 if (hwnd.client_window == FocusWindow) {
4154 prev_focus_window = FocusWindow;
4155 FocusWindow = hwnd.client_window;
4157 if (prev_focus_window != IntPtr.Zero) {
4158 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4160 SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4162 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4165 internal override void SetIcon(IntPtr handle, Icon icon) {
4168 hwnd = Hwnd.ObjectFromHandle(handle);
4170 SetIcon(hwnd, icon);
4174 internal override void SetMenu(IntPtr handle, Menu menu) {
4177 hwnd = Hwnd.ObjectFromHandle(handle);
4180 RequestNCRecalc(handle);
4183 internal override void SetModal(IntPtr handle, bool Modal) {
4185 ModalWindows.Push(handle);
4187 if (ModalWindows.Contains(handle)) {
4190 if (ModalWindows.Count > 0) {
4191 Activate((IntPtr)ModalWindows.Peek());
4196 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4199 hwnd = Hwnd.ObjectFromHandle(handle);
4200 hwnd.parent = Hwnd.ObjectFromHandle(parent);
4203 #if DriverDebug || DriverDebugParent
4204 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4206 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
4212 internal override void SetTimer (Timer timer) {
4214 TimerList.Add(timer);
4219 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4223 hwnd = Hwnd.ObjectFromHandle(handle);
4225 if (handle_owner != IntPtr.Zero) {
4226 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4233 if (hwnd_owner != null) {
4234 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4236 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4241 XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4247 internal override bool SetVisible(IntPtr handle, bool visible) {
4250 hwnd = Hwnd.ObjectFromHandle(handle);
4251 hwnd.visible = visible;
4255 if (Control.FromHandle(handle) is Form) {
4258 s = ((Form)Control.FromHandle(handle)).WindowState;
4260 MapWindow(hwnd, WindowType.Both);
4263 case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4264 case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4268 MapWindow(hwnd, WindowType.Both);
4270 SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4272 UnmapWindow(hwnd, WindowType.Whole);
4278 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4282 hwnd = Hwnd.ObjectFromHandle(handle);
4287 hints = new XSizeHints();
4288 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4289 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4290 hints.min_width = min.Width;
4291 hints.min_height = min.Height;
4294 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4295 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4296 hints.max_width = max.Width;
4297 hints.max_height = max.Height;
4300 if (hints.flags != IntPtr.Zero) {
4301 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4304 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4305 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4306 hints.x = maximized.X;
4307 hints.y = maximized.Y;
4308 hints.width = maximized.Width;
4309 hints.height = maximized.Height;
4311 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4312 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4317 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4320 hwnd = Hwnd.ObjectFromHandle(handle);
4326 // X requires a sanity check for width & height; otherwise it dies
4327 if (hwnd.zero_sized && width > 0 && height > 0) {
4329 MapWindow(hwnd, WindowType.Whole);
4331 hwnd.zero_sized = false;
4334 if ((width < 1) || (height < 1)) {
4335 hwnd.zero_sized = true;
4336 UnmapWindow(hwnd, WindowType.Whole);
4339 // Save a server roundtrip (and prevent a feedback loop)
4340 if ((hwnd.x == x) && (hwnd.y == y) &&
4341 (hwnd.width == width) && (hwnd.height == height)) {
4345 if (!hwnd.zero_sized) {
4347 if (hwnd.fixed_size) {
4348 SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4352 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4353 PerformNCCalc(hwnd);
4357 // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
4359 hwnd.height = height;
4362 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4363 FormWindowState current_state;
4366 hwnd = Hwnd.ObjectFromHandle(handle);
4369 current_state = GetWindowState(handle);
4371 catch (NotSupportedException) {
4372 current_state = (FormWindowState)(-1);
4375 if (current_state == state) {
4380 case FormWindowState.Normal: {
4382 if (current_state == FormWindowState.Minimized) {
4383 MapWindow(hwnd, WindowType.Both);
4384 } else if (current_state == FormWindowState.Maximized) {
4385 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]);
4392 case FormWindowState.Minimized: {
4394 if (current_state == FormWindowState.Maximized) {
4395 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]);
4397 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4402 case FormWindowState.Maximized: {
4404 if (current_state == FormWindowState.Minimized) {
4405 MapWindow(hwnd, WindowType.Both);
4408 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]);
4416 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4419 hwnd = Hwnd.ObjectFromHandle(handle);
4420 SetHwndStyles(hwnd, cp);
4421 SetWMStyles(hwnd, cp);
4424 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4428 hwnd = Hwnd.ObjectFromHandle(handle);
4434 hwnd.opacity = (uint)(0xffffffff * transparency);
4435 opacity = (IntPtr)((int)hwnd.opacity);
4437 if (hwnd.reparented) {
4438 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4442 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4443 Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4447 XRaiseWindow(DisplayHandle, hwnd.whole_window);
4450 } else if (!bottom) {
4451 Hwnd after_hwnd = null;
4453 if (after_handle != IntPtr.Zero) {
4454 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4457 XWindowChanges values = new XWindowChanges();
4459 if (after_hwnd == null) {
4460 throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4462 values.sibling = after_hwnd.whole_window;
4463 values.stack_mode = StackMode.Below;
4466 XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4471 XLowerWindow(DisplayHandle, hwnd.whole_window);
4478 internal override void ShowCursor(bool show) {
4479 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4482 internal override object StartLoop(Thread thread) {
4483 return (Object) ThreadQueue(thread);
4486 internal override bool SupportsTransparency() {
4487 // We need to check if the x compositing manager is running
4491 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4492 GetSystrayManagerWindow();
4494 if (SystrayMgrWindow != IntPtr.Zero) {
4495 XSizeHints size_hints;
4498 hwnd = Hwnd.ObjectFromHandle(handle);
4500 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4503 UnmapWindow(hwnd, WindowType.Whole);
4506 XDestroyWindow(DisplayHandle, hwnd.client_window);
4507 hwnd.client_window = hwnd.whole_window;
4509 size_hints = new XSizeHints();
4511 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4512 size_hints.min_width = icon.Width;
4513 size_hints.min_height = icon.Height;
4515 size_hints.max_width = icon.Width;
4516 size_hints.max_height = icon.Height;
4518 size_hints.base_width = icon.Width;
4519 size_hints.base_height = icon.Height;
4520 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4522 int[] atoms = new int[2];
4523 atoms [0] = 1; // Version 1
4524 atoms [1] = 0; // We're not mapped
4526 // This line cost me 3 days...
4527 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._XEMBED_INFO], NetAtoms[(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
4529 // Need to pick some reasonable defaults
4531 tt.AutomaticDelay = 100;
4532 tt.InitialDelay = 250;
4533 tt.ReshowDelay = 250;
4534 tt.ShowAlways = true;
4536 if ((tip != null) && (tip != string.Empty)) {
4537 tt.SetToolTip(Control.FromHandle(handle), tip);
4543 // Make sure the window exists
4544 XSync(DisplayHandle, hwnd.whole_window);
4546 SendNetClientMessage(SystrayMgrWindow, NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4553 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4556 control = Control.FromHandle(handle);
4557 if (control != null && tt != null) {
4558 tt.SetToolTip(control, tip);
4566 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4569 hwnd = Hwnd.ObjectFromHandle(handle);
4571 UnmapWindow(hwnd, WindowType.Whole);
4572 SetParent(hwnd.whole_window, FosterParent);
4574 // The caller can now re-dock it later...
4581 internal override bool Text(IntPtr handle, string text) {
4583 // FIXME - use _NET properties
4584 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4589 internal override bool TranslateMessage(ref MSG msg) {
4590 return Keyboard.TranslateMessage (ref msg);
4593 internal override void UpdateWindow(IntPtr handle) {
4596 hwnd = Hwnd.ObjectFromHandle(handle);
4598 if (!hwnd.visible || !hwnd.expose_pending) {
4602 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4603 hwnd.Queue.Paint.Remove(hwnd);
4606 private bool WindowIsMapped(IntPtr handle) {
4607 XWindowAttributes attributes;
4609 attributes = new XWindowAttributes();
4610 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
4611 if (attributes.map_state == MapState.IsUnmapped) {
4617 #endregion // Public Static Methods
4620 internal override event EventHandler Idle;
4621 #endregion // Events
4624 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4625 internal extern static IntPtr XOpenDisplay(IntPtr display);
4626 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4627 internal extern static int XCloseDisplay(IntPtr display);
4628 [DllImport ("libX11", EntryPoint="XSynchronize")]
4629 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4631 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4632 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);
4633 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4634 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4635 [DllImport ("libX11", EntryPoint="XMapWindow")]
4636 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4637 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4638 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4639 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4640 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4641 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4642 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4643 [DllImport ("libX11", EntryPoint="XRootWindow")]
4644 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4645 [DllImport ("libX11", EntryPoint="XNextEvent")]
4646 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4647 [DllImport ("libX11")]
4648 internal extern static int XConnectionNumber (IntPtr diplay);
4649 [DllImport ("libX11")]
4650 internal extern static int XPending (IntPtr diplay);
4651 [DllImport ("libX11", EntryPoint="XSelectInput")]
4652 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4654 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4655 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4657 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4658 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4659 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4660 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4662 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4663 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4665 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4666 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4668 [DllImport ("libX11", EntryPoint="XFlush")]
4669 internal extern static int XFlush(IntPtr display);
4671 [DllImport ("libX11", EntryPoint="XSetWMName")]
4672 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4674 [DllImport ("libX11", EntryPoint="XStoreName")]
4675 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
4677 [DllImport ("libX11", EntryPoint="XFetchName")]
4678 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
4680 [DllImport ("libX11", EntryPoint="XSendEvent")]
4681 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
4683 [DllImport ("libX11", EntryPoint="XQueryTree")]
4684 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);
4686 [DllImport ("libX11", EntryPoint="XFree")]
4687 internal extern static int XFree(IntPtr data);
4689 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
4690 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
4692 [DllImport ("libX11", EntryPoint="XLowerWindow")]
4693 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
4695 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
4696 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
4698 [DllImport ("libX11", EntryPoint="XInternAtom")]
4699 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
4701 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
4702 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
4704 [DllImport ("libX11", EntryPoint="XGrabPointer")]
4705 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);
4707 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
4708 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
4710 [DllImport ("libX11", EntryPoint="XQueryPointer")]
4711 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);
4713 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
4714 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);
4716 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4717 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);
4719 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4720 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);
4722 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4723 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);
4725 [DllImport ("libX11", EntryPoint="XGetGeometry")]
4726 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);
4728 [DllImport ("libX11", EntryPoint="XWarpPointer")]
4729 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);
4731 [DllImport ("libX11", EntryPoint="XClearWindow")]
4732 internal extern static int XClearWindow(IntPtr display, IntPtr window);
4734 [DllImport ("libX11", EntryPoint="XClearArea")]
4735 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
4738 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
4739 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
4741 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
4742 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
4744 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
4745 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
4747 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
4748 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
4750 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
4751 internal extern static int XDefaultScreen(IntPtr display);
4753 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
4754 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
4756 [DllImport ("libX11", EntryPoint="XLookupColor")]
4757 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
4759 [DllImport ("libX11", EntryPoint="XAllocColor")]
4760 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
4762 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
4763 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
4765 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4766 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
4768 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4769 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
4771 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4772 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
4774 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4775 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
4777 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4778 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
4780 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4781 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
4783 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4784 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
4786 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
4787 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
4789 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
4790 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
4792 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
4793 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
4796 [DllImport ("libX11", EntryPoint="XCreateGC")]
4797 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
4799 [DllImport ("libX11", EntryPoint="XFreeGC")]
4800 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
4802 [DllImport ("libX11", EntryPoint="XSetFunction")]
4803 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
4805 [DllImport ("libX11", EntryPoint="XDrawLine")]
4806 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
4808 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
4809 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
4811 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
4812 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
4814 [DllImport ("libX11", EntryPoint="XCopyArea")]
4815 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);
4817 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
4818 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);
4820 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
4821 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
4823 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
4824 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
4826 [DllImport ("libX11", EntryPoint="XDefineCursor")]
4827 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
4829 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
4830 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
4832 [DllImport ("libX11", EntryPoint="XFreeCursor")]
4833 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
4835 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
4836 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
4838 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
4839 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);
4841 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
4842 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
4844 [DllImport ("libX11", EntryPoint="XFreePixmap")]
4845 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
4847 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
4848 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
4850 [DllImport ("libX11", EntryPoint="XWhitePixel")]
4851 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
4853 [DllImport ("libX11", EntryPoint="XBlackPixel")]
4854 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
4856 [DllImport ("libX11", EntryPoint="XGrabServer")]
4857 internal extern static void XGrabServer(IntPtr display);
4859 [DllImport ("libX11", EntryPoint="XUngrabServer")]
4860 internal extern static void XUngrabServer(IntPtr display);
4862 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
4863 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4865 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
4866 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
4868 [DllImport ("libX11", EntryPoint="XSetWMHints")]
4869 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
4871 [DllImport ("libX11", EntryPoint="XSync")]
4872 internal extern static void XSync(IntPtr display, IntPtr window);
4874 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
4875 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
4877 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
4878 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
4880 [DllImport ("libX11", EntryPoint="XGetErrorText")]
4881 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
4883 [DllImport ("libX11", EntryPoint="XInitThreads")]
4884 internal extern static int XInitThreads();
4886 [DllImport ("libX11", EntryPoint="XConvertSelection")]
4887 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
4889 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
4890 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
4892 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
4893 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
4895 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
4896 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
4898 [DllImport ("libX11", EntryPoint="XSetForeground")]
4899 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
4901 [DllImport ("libX11", EntryPoint="XSetBackground")]
4902 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
4904 [DllImport ("libX11", EntryPoint="XBell")]
4905 internal extern static int XBell(IntPtr display, int percent);
4907 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
4908 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
4910 [DllImport ("libX11", EntryPoint="XFilterEvent")]
4911 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
4913 [DllImport ("libX11")]
4914 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
4916 [DllImport ("libX11")]
4917 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);