In Test/System.Windows.Forms:
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11GTK.cs
blob152e9f9e428ceeed9e6d1d4a5b35abeeb545b9cc
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
22 // Authors:
23 // Peter Bartok pbartok@novell.com
24 // Alexander Olk alex.olk@googlemail.com
28 // NOTE:
29 // This driver understands the following environment variables: (Set the var to enable feature)
31 // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
32 // by default a message is displayed but execution continues
34 // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
35 // helps in debugging errors
38 // NOT COMPLETE - WORK IN PROGRESS
40 // One feature of the driver is, that PaintEventstart returns a graphics context created from a offscreen drawable (pixmap)
42 // define to log Window handles and relationships to stdout
43 #undef DriverDebug
45 // Extra detailed debug
46 #undef DriverDebugExtra
48 using System;
49 using System.ComponentModel;
50 using System.Collections;
51 using System.Diagnostics;
52 using System.Drawing;
53 using System.Drawing.Drawing2D;
54 using System.Drawing.Imaging;
55 using System.IO;
56 using System.Net;
57 using System.Net.Sockets;
58 using System.Reflection;
59 using System.Runtime.InteropServices;
60 using System.Text;
61 using System.Threading;
63 // Only do the poll when building with mono for now
64 #if __MonoCS__
65 using Mono.Unix.Native;
66 #endif
68 /// X11 Version
69 namespace System.Windows.Forms {
70 internal class XplatUIX11GTK : XplatUIDriver {
72 internal enum GdkWindowClass {
73 GDK_INPUT_OUTPUT,
74 GDK_INPUT_ONLY
77 internal enum GdkWindowType {
78 GDK_WINDOW_ROOT,
79 GDK_WINDOW_TOPLEVEL,
80 GDK_WINDOW_CHILD,
81 GDK_WINDOW_DIALOG,
82 GDK_WINDOW_TEMP,
83 GDK_WINDOW_FOREIGN
86 internal enum GdkWindowHints {
87 GDK_HINT_POS = 1 << 0,
88 GDK_HINT_MIN_SIZE = 1 << 1,
89 GDK_HINT_MAX_SIZE = 1 << 2,
90 GDK_HINT_BASE_SIZE = 1 << 3,
91 GDK_HINT_ASPECT = 1 << 4,
92 GDK_HINT_RESIZE_INC = 1 << 5,
93 GDK_HINT_WIN_GRAVITY = 1 << 6,
94 GDK_HINT_USER_POS = 1 << 7,
95 GDK_HINT_USER_SIZE = 1 << 8
98 internal enum GdkGravity {
99 GDK_GRAVITY_NORTH_WEST = 1,
100 GDK_GRAVITY_NORTH,
101 GDK_GRAVITY_NORTH_EAST,
102 GDK_GRAVITY_WEST,
103 GDK_GRAVITY_CENTER,
104 GDK_GRAVITY_EAST,
105 GDK_GRAVITY_SOUTH_WEST,
106 GDK_GRAVITY_SOUTH,
107 GDK_GRAVITY_SOUTH_EAST,
108 GDK_GRAVITY_STATIC
111 internal enum GdkWindowEdge {
112 GDK_WINDOW_EDGE_NORTH_WEST,
113 GDK_WINDOW_EDGE_NORTH,
114 GDK_WINDOW_EDGE_NORTH_EAST,
115 GDK_WINDOW_EDGE_WEST,
116 GDK_WINDOW_EDGE_EAST,
117 GDK_WINDOW_EDGE_SOUTH_WEST,
118 GDK_WINDOW_EDGE_SOUTH,
119 GDK_WINDOW_EDGE_SOUTH_EAST
122 internal enum GdkWindowTypeHint {
123 GDK_WINDOW_TYPE_HINT_NORMAL,
124 GDK_WINDOW_TYPE_HINT_DIALOG,
125 GDK_WINDOW_TYPE_HINT_MENU,
126 GDK_WINDOW_TYPE_HINT_TOOLBAR,
127 GDK_WINDOW_TYPE_HINT_SPLASHSCREEN,
128 GDK_WINDOW_TYPE_HINT_UTILITY,
129 GDK_WINDOW_TYPE_HINT_DOCK,
130 GDK_WINDOW_TYPE_HINT_DESKTOP
133 internal enum GdkWindowAttributesType {
134 GDK_WA_TITLE = 1 << 1,
135 GDK_WA_X = 1 << 2,
136 GDK_WA_Y = 1 << 3,
137 GDK_WA_CURSOR = 1 << 4,
138 GDK_WA_COLORMAP = 1 << 5,
139 GDK_WA_VISUAL = 1 << 6,
140 GDK_WA_WMCLASS = 1 << 7,
141 GDK_WA_NOREDIR = 1 << 8
144 internal enum GdkEventMask {
145 GDK_EXPOSURE_MASK = 1 << 1,
146 GDK_POINTER_MOTION_MASK = 1 << 2,
147 GDK_POINTER_MOTION_HINT_MASK = 1 << 3,
148 GDK_BUTTON_MOTION_MASK = 1 << 4,
149 GDK_BUTTON1_MOTION_MASK = 1 << 5,
150 GDK_BUTTON2_MOTION_MASK = 1 << 6,
151 GDK_BUTTON3_MOTION_MASK = 1 << 7,
152 GDK_BUTTON_PRESS_MASK = 1 << 8,
153 GDK_BUTTON_RELEASE_MASK = 1 << 9,
154 GDK_KEY_PRESS_MASK = 1 << 10,
155 GDK_KEY_RELEASE_MASK = 1 << 11,
156 GDK_ENTER_NOTIFY_MASK = 1 << 12,
157 GDK_LEAVE_NOTIFY_MASK = 1 << 13,
158 GDK_FOCUS_CHANGE_MASK = 1 << 14,
159 GDK_STRUCTURE_MASK = 1 << 15,
160 GDK_PROPERTY_CHANGE_MASK = 1 << 16,
161 GDK_VISIBILITY_NOTIFY_MASK = 1 << 17,
162 GDK_PROXIMITY_IN_MASK = 1 << 18,
163 GDK_PROXIMITY_OUT_MASK = 1 << 19,
164 GDK_SUBSTRUCTURE_MASK = 1 << 20,
165 GDK_SCROLL_MASK = 1 << 21,
166 GDK_ALL_EVENTS_MASK = 0x3FFFFE
169 internal enum GdkEventType {
170 GDK_NOTHING = -1,
171 GDK_DELETE = 0,
172 GDK_DESTROY = 1,
173 GDK_EXPOSE = 2,
174 GDK_MOTION_NOTIFY = 3,
175 GDK_BUTTON_PRESS = 4,
176 GDK_2BUTTON_PRESS = 5,
177 GDK_3BUTTON_PRESS = 6,
178 GDK_BUTTON_RELEASE = 7,
179 GDK_KEY_PRESS = 8,
180 GDK_KEY_RELEASE = 9,
181 GDK_ENTER_NOTIFY = 10,
182 GDK_LEAVE_NOTIFY = 11,
183 GDK_FOCUS_CHANGE = 12,
184 GDK_CONFIGURE = 13,
185 GDK_MAP = 14,
186 GDK_UNMAP = 15,
187 GDK_PROPERTY_NOTIFY = 16,
188 GDK_SELECTION_CLEAR = 17,
189 GDK_SELECTION_REQUEST = 18,
190 GDK_SELECTION_NOTIFY = 19,
191 GDK_PROXIMITY_IN = 20,
192 GDK_PROXIMITY_OUT = 21,
193 GDK_DRAG_ENTER = 22,
194 GDK_DRAG_LEAVE = 23,
195 GDK_DRAG_MOTION = 24,
196 GDK_DRAG_STATUS = 25,
197 GDK_DROP_START = 26,
198 GDK_DROP_FINISHED = 27,
199 GDK_CLIENT_EVENT = 28,
200 GDK_VISIBILITY_NOTIFY = 29,
201 GDK_NO_EXPOSE = 30,
202 GDK_SCROLL = 31,
203 GDK_WINDOW_STATE = 32,
204 GDK_SETTING = 33,
205 GDK_OWNER_CHANGE = 34,
206 GDK_GRAB_BROKEN = 35
209 internal enum GdkWMDecoration {
210 GDK_DECOR_ALL = 1 << 0,
211 GDK_DECOR_BORDER = 1 << 1,
212 GDK_DECOR_RESIZEH = 1 << 2,
213 GDK_DECOR_TITLE = 1 << 3,
214 GDK_DECOR_MENU = 1 << 4,
215 GDK_DECOR_MINIMIZE = 1 << 5,
216 GDK_DECOR_MAXIMIZE = 1 << 6
219 internal enum GdkWMFunction {
220 GDK_FUNC_ALL = 1 << 0,
221 GDK_FUNC_RESIZE = 1 << 1,
222 GDK_FUNC_MOVE = 1 << 2,
223 GDK_FUNC_MINIMIZE = 1 << 3,
224 GDK_FUNC_MAXIMIZE = 1 << 4,
225 GDK_FUNC_CLOSE = 1 << 5
228 internal enum GdkCursorType {
229 GDK_X_CURSOR = 0,
230 GDK_ARROW = 2,
231 GDK_BASED_ARROW_DOWN = 4,
232 GDK_BASED_ARROW_UP = 6,
233 GDK_BOAT = 8,
234 GDK_BOGOSITY = 10,
235 GDK_BOTTOM_LEFT_CORNER = 12,
236 GDK_BOTTOM_RIGHT_CORNER = 14,
237 GDK_BOTTOM_SIDE = 16,
238 GDK_BOTTOM_TEE = 18,
239 GDK_BOX_SPIRAL = 20,
240 GDK_CENTER_PTR = 22,
241 GDK_CIRCLE = 24,
242 GDK_CLOCK = 26,
243 GDK_COFFEE_MUG = 28,
244 GDK_CROSS = 30,
245 GDK_CROSS_REVERSE = 32,
246 GDK_CROSSHAIR = 34,
247 GDK_DIAMOND_CROSS = 36,
248 GDK_DOT = 38,
249 GDK_DOTBOX = 40,
250 GDK_DOUBLE_ARROW = 42,
251 GDK_DRAFT_LARGE = 44,
252 GDK_DRAFT_SMALL = 46,
253 GDK_DRAPED_BOX = 48,
254 GDK_EXCHANGE = 50,
255 GDK_FLEUR = 52,
256 GDK_GOBBLER = 54,
257 GDK_GUMBY = 56,
258 GDK_HAND1 = 58,
259 GDK_HAND2 = 60,
260 GDK_HEART = 62,
261 GDK_ICON = 64,
262 GDK_IRON_CROSS = 66,
263 GDK_LEFT_PTR = 68,
264 GDK_LEFT_SIDE = 70,
265 GDK_LEFT_TEE = 72,
266 GDK_LEFTBUTTON = 74,
267 GDK_LL_ANGLE = 76,
268 GDK_LR_ANGLE = 78,
269 GDK_MAN = 80,
270 GDK_MIDDLEBUTTON = 82,
271 GDK_MOUSE = 84,
272 GDK_PENCIL = 86,
273 GDK_PIRATE = 88,
274 GDK_PLUS = 90,
275 GDK_QUESTION_ARROW = 92,
276 GDK_RIGHT_PTR = 94,
277 GDK_RIGHT_SIDE = 96,
278 GDK_RIGHT_TEE = 98,
279 GDK_RIGHTBUTTON = 100,
280 GDK_RTL_LOGO = 102,
281 GDK_SAILBOAT = 104,
282 GDK_SB_DOWN_ARROW = 106,
283 GDK_SB_H_DOUBLE_ARROW = 108,
284 GDK_SB_LEFT_ARROW = 110,
285 GDK_SB_RIGHT_ARROW = 112,
286 GDK_SB_UP_ARROW = 114,
287 GDK_SB_V_DOUBLE_ARROW = 116,
288 GDK_SHUTTLE = 118,
289 GDK_SIZING = 120,
290 GDK_SPIDER = 122,
291 GDK_SPRAYCAN = 124,
292 GDK_STAR = 126,
293 GDK_TARGET = 128,
294 GDK_TCROSS = 130,
295 GDK_TOP_LEFT_ARROW = 132,
296 GDK_TOP_LEFT_CORNER = 134,
297 GDK_TOP_RIGHT_CORNER = 136,
298 GDK_TOP_SIDE = 138,
299 GDK_TOP_TEE = 140,
300 GDK_TREK = 142,
301 GDK_UL_ANGLE = 144,
302 GDK_UMBRELLA = 146,
303 GDK_UR_ANGLE = 148,
304 GDK_WATCH = 150,
305 GDK_XTERM = 152,
306 GDK_LAST_CURSOR,
307 GDK_CURSOR_IS_PIXMAP = -1
310 internal enum GdkPropMode {
311 GDK_PROP_MODE_REPLACE,
312 GDK_PROP_MODE_PREPEND,
313 GDK_PROP_MODE_APPEND
316 [StructLayout (LayoutKind.Sequential)]
317 internal struct GdkGeometry {
318 internal int min_width;
319 internal int min_height;
320 internal int max_width;
321 internal int max_height;
322 internal int base_width;
323 internal int base_height;
324 internal int width_inc;
325 internal int height_inc;
326 internal double min_aspect;
327 internal double max_aspect;
328 internal GdkGravity win_gravity;
331 [StructLayout (LayoutKind.Sequential)]
332 internal struct GdkWindowAttr {
333 internal string title;
334 internal int event_mask;
335 internal int x, y;
336 internal int width;
337 internal int height;
338 internal GdkWindowClass wclass;
339 internal IntPtr visual;
340 internal IntPtr colormap;
341 internal GdkWindowType window_type;
342 internal IntPtr cursor;
343 internal string wmclass_name;
344 internal string wmclass_class;
345 internal bool override_redirect;
348 #region Local Variables
349 // General
350 static volatile XplatUIX11GTK Instance;
351 private static int RefCount;
352 private static object XlibLock; // Our locking object
353 private static bool ThemesEnabled;
355 // General X11
356 private static IntPtr DisplayHandle; // X11 handle to display
357 private static IntPtr GdkDisplayHandle; // gdk handle to display
358 private static int ScreenNo; // Screen number used
359 private static IntPtr GdkScreen;
360 private static IntPtr DefaultColormap; // Colormap for screen
361 private static IntPtr GdkDefaultColormap; // Gdk Colormap for screen
362 private static IntPtr CustomVisual; // Visual for window creation
363 private static IntPtr GdkCustomVisual;
364 private static IntPtr CustomColormap; // Colormap for window creation
365 private static IntPtr GdkCustomColormap;
366 private static int VisualBestDepth;
367 private static IntPtr RootWindow; // Handle of the root window for the screen/display
368 private static IntPtr GdkRootWindow; // Gdk handle of the root window for the screen/display
369 private static IntPtr FosterParent; // Container to hold child windows until their parent exists
370 private static IntPtr GdkFosterParent; // Container to hold child windows until their parent exists
371 private static XErrorHandler ErrorHandler; // Error handler delegate
372 private static bool ErrorExceptions; // Throw exceptions on X errors
373 private static bool PostQuitState; // True if we've got an pending exit
375 // Clipboard
376 private static IntPtr ClipMagic = new IntPtr(27051977);
377 private static ClipboardStruct Clipboard; // Our clipboard
379 // Communication
380 private static int PostAtom; // PostMessage atom
381 private static int AsyncAtom; // Support for async messages
383 // Message Loop
384 private static XEventQueue MessageQueue; // Holds our queued up events
385 #if __MonoCS__ //
386 private static Pollfd[] pollfds; // For watching the X11 socket
387 #endif //
388 private static X11Keyboard Keyboard; //
389 private static X11Dnd Dnd;
390 private static Socket listen; //
391 private static Socket wake; //
392 private static Socket wake_receive; //
393 private static byte[] network_buffer; //
396 // Focus tracking
397 private static IntPtr ActiveWindow; // Handle of the active window
398 private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
400 // Modality support
401 private static Stack ModalWindows; // Stack of our modal windows
403 // Systray
404 private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
406 // Cursors
407 private static IntPtr LastCursorWindow; // The last window we set the cursor on
408 private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
409 private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
411 // Caret
412 private static CaretStruct Caret; //
414 // Support for Window Styles
415 private static int[] NetAtoms; // All atoms we know
417 // mouse hover message generation
418 private static HoverStruct HoverState; //
420 // double click message generation
421 private static ClickStruct ClickPending; //
423 // Support for mouse grab
424 private static GrabStruct Grab; //
426 // State
427 private static Point MousePosition; // Last position of mouse, in screen coords
428 internal static MouseButtons MouseState; // Last state of mouse buttons
430 // Timers
431 private static ArrayList TimerList; // Holds SWF.Timers
433 // 'Constants'
434 private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
436 const GdkEventMask GdkSelectInputMask = GdkEventMask.GDK_BUTTON_PRESS_MASK |
437 GdkEventMask.GDK_BUTTON_RELEASE_MASK |
438 GdkEventMask.GDK_KEY_PRESS_MASK |
439 GdkEventMask.GDK_KEY_RELEASE_MASK |
440 GdkEventMask.GDK_ENTER_NOTIFY_MASK |
441 GdkEventMask.GDK_LEAVE_NOTIFY_MASK |
442 GdkEventMask.GDK_EXPOSURE_MASK |
443 GdkEventMask.GDK_FOCUS_CHANGE_MASK |
444 GdkEventMask.GDK_POINTER_MOTION_MASK |
445 GdkEventMask.GDK_VISIBILITY_NOTIFY_MASK |
446 GdkEventMask.GDK_SUBSTRUCTURE_MASK |
447 GdkEventMask.GDK_STRUCTURE_MASK;
449 static readonly object lockobj = new object ();
451 static Hashtable backing_store = new Hashtable (5);
453 #endregion // Local Variables
454 #region Constructors
455 private XplatUIX11GTK ()
457 Console.WriteLine ("XplatUIX11GTK ctor...");
458 // Handle singleton stuff first
459 RefCount = 0;
461 // init gdk
462 gdk_init_check (IntPtr.Zero, IntPtr.Zero);
464 // Now regular initialization
465 XlibLock = new object ();
466 MessageQueue = new XEventQueue ();
467 TimerList = new ArrayList ();
468 XInitThreads ();
470 ErrorExceptions = false;
472 // X11 Initialization
473 SetDisplay (gdk_x11_display_get_xdisplay (gdk_display_get_default ()));
474 X11DesktopColors.Initialize ();
476 // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
477 ErrorHandler = new XErrorHandler (HandleError);
478 XSetErrorHandler (ErrorHandler);
480 #endregion // Constructors
482 #region Singleton Specific Code
483 public static XplatUIX11GTK GetInstance ()
485 lock (lockobj) {
486 if (Instance == null) {
487 Instance = new XplatUIX11GTK ();
489 RefCount++;
491 return Instance;
494 public int Reference {
495 get {
496 return RefCount;
499 #endregion
501 #region Internal Properties
502 internal static IntPtr Display {
503 get {
504 return DisplayHandle;
507 set {
508 XplatUIX11GTK.GetInstance ().SetDisplay (value);
512 internal static int Screen {
513 get {
514 return ScreenNo;
517 set {
518 ScreenNo = value;
522 internal static IntPtr RootWindowHandle {
523 get {
524 return RootWindow;
527 set {
528 RootWindow = value;
532 internal static IntPtr Visual {
533 get {
534 return CustomVisual;
537 set {
538 CustomVisual = value;
542 internal static IntPtr ColorMap {
543 get {
544 return CustomColormap;
547 set {
548 CustomColormap = value;
551 #endregion
553 #region XExceptionClass
554 internal class XException : ApplicationException {
555 IntPtr Display;
556 IntPtr ResourceID;
557 IntPtr Serial;
558 XRequest RequestCode;
559 byte ErrorCode;
560 byte MinorCode;
562 public XException (IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode)
564 this.Display = Display;
565 this.ResourceID = ResourceID;
566 this.Serial = Serial;
567 this.RequestCode = RequestCode;
568 this.ErrorCode = ErrorCode;
569 this.MinorCode = MinorCode;
572 public override string Message {
573 get {
574 return GetMessage (Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
578 public static string GetMessage (IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode)
580 StringBuilder sb;
581 string x_error_text;
582 string error;
584 sb = new StringBuilder (160);
585 XGetErrorText (Display, ErrorCode, sb, sb.Capacity);
586 x_error_text = sb.ToString ();
588 error = String.Format ("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:x}\n Serial: {4}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32 (), Serial);
589 return error;
592 #endregion // XExceptionClass
594 #region Internal Methods
595 // native X display handle
596 internal void SetDisplay (IntPtr display_handle)
598 if (display_handle != IntPtr.Zero) {
599 Hwnd hwnd;
601 if ((GdkDisplayHandle != IntPtr.Zero) && (GdkFosterParent != IntPtr.Zero)) {
602 hwnd = Hwnd.ObjectFromHandle (gdk_x11_drawable_get_xid (GdkFosterParent));
603 gdk_window_destroy (GdkFosterParent);
604 hwnd.Dispose ();
607 if (GdkDisplayHandle != IntPtr.Zero) {
608 gdk_display_close (GdkDisplayHandle);
611 DisplayHandle = display_handle;
612 GdkDisplayHandle = gdk_x11_lookup_xdisplay (display_handle);
614 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
615 // been hacked to do this for us.
616 Graphics.FromHdcInternal (DisplayHandle);
618 // Debugging support
619 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
620 XSynchronize (DisplayHandle, true);
623 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
624 ErrorExceptions = true;
627 // Generic X11 setup
628 GdkScreen = gdk_screen_get_default ();
629 // or gdk_x11_get_default_screen
630 ScreenNo = gdk_screen_get_number (GdkScreen);
631 GdkRootWindow = gdk_get_default_root_window ();
632 RootWindow = gdk_x11_drawable_get_xid (GdkRootWindow);
633 GdkDefaultColormap = gdk_colormap_get_system ();
634 DefaultColormap = gdk_x11_colormap_get_xcolormap (GdkDefaultColormap);
636 VisualBestDepth = gdk_visual_get_best_depth ();
637 //Console.WriteLine (VisualBestDepth);
639 // Create the foster parent
640 FosterParent = XCreateSimpleWindow (DisplayHandle, RootWindow, 0, 0, 1, 1, 4, 0, 0);
641 GdkFosterParent = gdk_window_foreign_new (FosterParent);
643 if (GdkFosterParent == IntPtr.Zero) {
644 Console.WriteLine ("XplatUIX11GTK Constructor failed to create FosterParent");
647 hwnd = new Hwnd ();
649 hwnd.WholeWindow = FosterParent;
650 hwnd.ClientWindow = FosterParent;
652 // For sleeping on the X11 socket
653 listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
654 IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
655 listen.Bind (ep);
656 listen.Listen (1);
658 // To wake up when a timer is ready
659 network_buffer = new byte [10];
661 wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
662 wake.Connect (listen.LocalEndPoint);
663 wake_receive = listen.Accept ();
665 #if __MonoCS__
666 pollfds = new Pollfd [2];
667 pollfds [0] = new Pollfd ();
668 pollfds [0].fd = XConnectionNumber (DisplayHandle);
669 pollfds [0].events = PollEvents.POLLIN;
671 pollfds [1] = new Pollfd ();
672 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
673 pollfds [1].events = PollEvents.POLLIN;
674 #endif
676 Keyboard = new X11Keyboard (DisplayHandle);
677 Dnd = new X11Dnd (DisplayHandle);
679 PostQuitState = false;
681 DoubleClickInterval = 500;
683 HoverState.Interval = 500;
684 HoverState.Timer = new Timer ();
685 HoverState.Timer.Enabled = false;
686 HoverState.Timer.Interval = HoverState.Interval;
687 HoverState.Timer.Tick += new EventHandler (MouseHover);
688 HoverState.X = -1;
689 HoverState.Y = -1;
691 ActiveWindow = IntPtr.Zero;
692 FocusWindow = IntPtr.Zero;
693 ModalWindows = new Stack (3);
695 MouseState = MouseButtons.None;
696 MousePosition = new Point (0, 0);
698 Caret.Timer = new Timer ();
699 Caret.Timer.Interval = 500; // FIXME - where should this number come from?
700 Caret.Timer.Tick += new EventHandler (CaretCallback);
702 SetupAtoms ();
704 // Grab atom changes off the root window to catch certain WM events
705 gdk_window_set_events (GdkRootWindow, (int)GdkEventMask.GDK_PROPERTY_CHANGE_MASK);
707 // Handle any upcoming errors
708 ErrorHandler = new XErrorHandler (HandleError);
709 XSetErrorHandler (ErrorHandler);
710 } else {
711 throw new ArgumentNullException ("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
714 #endregion // Internal Methods
716 #region Private Methods
717 private static void SetupAtoms ()
719 NetAtoms = new int [(int)NA.LAST_NET_ATOM];
721 NetAtoms [(int)NA.WM_PROTOCOLS] = XInternAtom (DisplayHandle, "WM_PROTOCOLS", false);
722 NetAtoms [(int)NA.WM_DELETE_WINDOW] = XInternAtom (DisplayHandle, "WM_DELETE_WINDOW", false);
723 NetAtoms [(int)NA.WM_TAKE_FOCUS] = XInternAtom (DisplayHandle, "WM_TAKE_FOCUS", false);
725 NetAtoms [(int)NA._NET_SUPPORTED] = XInternAtom (DisplayHandle, "_NET_SUPPORTED", false);
726 NetAtoms [(int)NA._NET_CLIENT_LIST] = XInternAtom (DisplayHandle, "_NET_CLIENT_LIST", false);
727 NetAtoms [(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom (DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
728 NetAtoms [(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom (DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
729 NetAtoms [(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom (DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
730 NetAtoms [(int)NA._NET_CURRENT_DESKTOP] = XInternAtom (DisplayHandle, "_NET_CURRENT_DESKTOP", false);
731 NetAtoms [(int)NA._NET_DESKTOP_NAMES] = XInternAtom (DisplayHandle, "_NET_DESKTOP_NAMES", false);
732 NetAtoms [(int)NA._NET_ACTIVE_WINDOW] = XInternAtom (DisplayHandle, "_NET_ACTIVE_WINDOW", false);
733 NetAtoms [(int)NA._NET_WORKAREA] = XInternAtom (DisplayHandle, "_NET_WORKAREA", false);
734 NetAtoms [(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom (DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
735 NetAtoms [(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom (DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
736 NetAtoms [(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom (DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
737 NetAtoms [(int)NA._NET_SHOWING_DESKTOP] = XInternAtom (DisplayHandle, "_NET_SHOWING_DESKTOP", false);
739 NetAtoms [(int)NA._NET_CLOSE_WINDOW] = XInternAtom (DisplayHandle, "_NET_CLOSE_WINDOW", false);
740 NetAtoms [(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom (DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
741 NetAtoms [(int)NA._NET_WM_MOVERESIZE] = XInternAtom (DisplayHandle, "_NET_WM_MOVERESIZE", false);
742 NetAtoms [(int)NA._NET_RESTACK_WINDOW] = XInternAtom (DisplayHandle, "_NET_RESTACK_WINDOW", false);
743 NetAtoms [(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom (DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
745 NetAtoms [(int)NA._NET_WM_NAME] = XInternAtom (DisplayHandle, "_NET_WM_NAME", false);
746 NetAtoms [(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom (DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
747 NetAtoms [(int)NA._NET_WM_ICON_NAME] = XInternAtom (DisplayHandle, "_NET_WM_ICON_NAME", false);
748 NetAtoms [(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom (DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
749 NetAtoms [(int)NA._NET_WM_DESKTOP] = XInternAtom (DisplayHandle, "_NET_WM_DESKTOP", false);
750 NetAtoms [(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom (DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
751 NetAtoms [(int)NA._NET_WM_STATE] = XInternAtom (DisplayHandle, "_NET_WM_STATE", false);
752 NetAtoms [(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom (DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
753 NetAtoms [(int)NA._NET_WM_STRUT] = XInternAtom (DisplayHandle, "_NET_WM_STRUT", false);
754 NetAtoms [(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom (DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
755 NetAtoms [(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom (DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
756 NetAtoms [(int)NA._NET_WM_ICON] = XInternAtom (DisplayHandle, "_NET_WM_ICON", false);
757 NetAtoms [(int)NA._NET_WM_PID] = XInternAtom (DisplayHandle, "_NET_WM_PID", false);
758 NetAtoms [(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom (DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
759 NetAtoms [(int)NA._NET_WM_USER_TIME] = XInternAtom (DisplayHandle, "_NET_WM_USER_TIME", false);
760 NetAtoms [(int)NA._NET_FRAME_EXTENTS] = XInternAtom (DisplayHandle, "_NET_FRAME_EXTENTS", false);
762 NetAtoms [(int)NA._NET_WM_PING] = XInternAtom (DisplayHandle, "_NET_WM_PING", false);
763 NetAtoms [(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom (DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
765 NetAtoms [(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString (), false);
766 NetAtoms [(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
767 NetAtoms [(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
769 NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
770 NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
771 NetAtoms [(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom (DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
773 NetAtoms [(int)NA._XEMBED] = XInternAtom (DisplayHandle, "_XEMBED", false);
774 NetAtoms [(int)NA._XEMBED_INFO] = XInternAtom (DisplayHandle, "_XEMBED_INFO", false);
776 NetAtoms [(int)NA._MOTIF_WM_HINTS] = XInternAtom (DisplayHandle, "_MOTIF_WM_HINTS", false);
778 NetAtoms [(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom (DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
779 NetAtoms [(int)NA._NET_WM_STATE_ABOVE] = XInternAtom (DisplayHandle, "_NET_WM_STATE_ABOVE", false);
780 NetAtoms [(int)NA._NET_WM_STATE_MODAL] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MODAL", false);
781 NetAtoms [(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom (DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
782 NetAtoms [(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom (DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
784 // Clipboard support
785 NetAtoms [(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
786 NetAtoms [(int)NA.DIB] = (int)Atom.XA_PIXMAP;
787 NetAtoms [(int)NA.OEMTEXT] = XInternAtom (DisplayHandle, "COMPOUND_TEXT", false);
788 NetAtoms [(int)NA.UNICODETEXT] = XInternAtom (DisplayHandle, "UTF8_STRING", false);
789 NetAtoms [(int)NA.TARGETS] = XInternAtom (DisplayHandle, "TARGETS", false);
791 // Special Atoms
792 AsyncAtom = XInternAtom (DisplayHandle, "_SWF_AsyncAtom", false);
793 PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
794 HoverState.Atom = XInternAtom (DisplayHandle, "_SWF_HoverAtom", false);
797 private void GetSystrayManagerWindow ()
799 gdk_x11_grab_server ();
800 SystrayMgrWindow = XGetSelectionOwner (DisplayHandle, NetAtoms [(int)NA._NET_SYSTEM_TRAY_S]);
801 gdk_x11_ungrab_server ();
802 gdk_display_flush (GdkDisplayHandle);
805 private void SendNetWMMessage (IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
807 XEvent xev;
809 xev = new XEvent ();
810 xev.ClientMessageEvent.type = XEventName.ClientMessage;
811 xev.ClientMessageEvent.send_event = true;
812 xev.ClientMessageEvent.window = window;
813 xev.ClientMessageEvent.message_type = message_type;
814 xev.ClientMessageEvent.format = 32;
815 xev.ClientMessageEvent.ptr1 = l0;
816 xev.ClientMessageEvent.ptr2 = l1;
817 xev.ClientMessageEvent.ptr3 = l2;
818 XSendEvent (DisplayHandle, RootWindow, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
821 private void SendNetClientMessage (IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
823 XEvent xev;
825 xev = new XEvent ();
826 xev.ClientMessageEvent.type = XEventName.ClientMessage;
827 xev.ClientMessageEvent.send_event = true;
828 xev.ClientMessageEvent.window = window;
829 xev.ClientMessageEvent.message_type = message_type;
830 xev.ClientMessageEvent.format = 32;
831 xev.ClientMessageEvent.ptr1 = l0;
832 xev.ClientMessageEvent.ptr2 = l1;
833 xev.ClientMessageEvent.ptr3 = l2;
834 XSendEvent (DisplayHandle, window, false, EventMask.NoEventMask, ref xev);
837 private void DeriveStyles (IntPtr handle, int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height)
840 // Only MDI windows get caption_heights
841 caption_height = 0;
842 tool_caption_height = 19;
844 if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
845 if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
846 border_style = FormBorderStyle.None;
847 } else if ((ExStyle & (int) WindowStyles.WS_EX_CLIENTEDGE) != 0) {
848 border_style = FormBorderStyle.Fixed3D;
849 } else {
850 border_style = FormBorderStyle.FixedSingle;
852 title_style = TitleStyle.None;
853 } else {
854 bool is_mdi = false;
856 if ((ExStyle & (int) WindowStyles.WS_EX_MDICHILD) != 0) {
857 caption_height = 26;
858 is_mdi = true;
861 title_style = TitleStyle.None;
862 if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
863 if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
864 title_style = TitleStyle.Tool;
865 } else {
866 title_style = TitleStyle.Normal;
870 if (!is_mdi) {
871 border_style = FormBorderStyle.None;
873 if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
874 if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
875 border_style = FormBorderStyle.SizableToolWindow;
876 } else {
877 border_style = FormBorderStyle.Sizable;
879 } else {
880 if ((ExStyle & (int)WindowStyles.WS_EX_CLIENTEDGE) != 0) {
881 border_style = FormBorderStyle.Fixed3D;
882 } else if ((ExStyle & (int)WindowStyles.WS_EX_DLGMODALFRAME) != 0) {
883 border_style = FormBorderStyle.FixedDialog;
884 } else if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
885 border_style = FormBorderStyle.FixedToolWindow;
886 } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
887 border_style = FormBorderStyle.Sizable;
888 } else {
889 border_style = FormBorderStyle.None;
892 } else {
893 if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
894 (ExStyle & (int) WindowStyles.WS_EX_TOOLWINDOW) != 0) {
895 border_style = (FormBorderStyle) 0xFFFF;
896 } else {
897 border_style = FormBorderStyle.None;
903 private void SetHwndStyles (Hwnd hwnd, CreateParams cp)
905 DeriveStyles (hwnd.Handle, cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
908 private void SetWMStyles (Hwnd hwnd, CreateParams cp)
910 GdkWMDecoration decorations = GdkWMDecoration.GDK_DECOR_ALL;
912 if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
913 decorations |= GdkWMDecoration.GDK_DECOR_TITLE | GdkWMDecoration.GDK_DECOR_MENU;
916 if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
917 decorations |= GdkWMDecoration.GDK_DECOR_BORDER | GdkWMDecoration.GDK_DECOR_RESIZEH;
919 if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
920 decorations |= GdkWMDecoration.GDK_DECOR_MINIMIZE;
923 if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
924 decorations |= GdkWMDecoration.GDK_DECOR_MAXIMIZE;
927 // is this needed ? most window managers do not even honour any MotifFunctions...
928 // if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
929 // functions |= MotifFunctions.Close;
930 // }
932 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
933 decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
936 if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
937 decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
940 if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
941 decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
944 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
945 decorations = 0;
948 gdk_window_set_decorations (gdk_window_foreign_new (hwnd.whole_window), (int)decorations);
951 private void SetIcon (Hwnd hwnd, Icon icon)
953 Bitmap bitmap;
954 int size;
955 uint[] data;
956 int index;
958 bitmap = icon.ToBitmap ();
959 index = 0;
960 size = bitmap.Width * bitmap.Height + 2;
961 data = new uint [size];
963 data [index++] = (uint)bitmap.Width;
964 data [index++] = (uint)bitmap.Height;
966 for (int y = 0; y < bitmap.Height; y++) {
967 for (int x = 0; x < bitmap.Width; x++) {
968 data [index++] = (uint)bitmap.GetPixel (x, y).ToArgb ();
971 XChangeProperty (DisplayHandle, hwnd.whole_window, NetAtoms [(int)NA._NET_WM_ICON], Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
974 private IntPtr ImageToPixmap (Image image)
976 return IntPtr.Zero;
979 private void WakeupMain ()
981 wake.Send (new byte [] { 0xFF });
984 private void TranslatePropertyToClipboard (int property)
986 Atom actual_atom;
987 int actual_format;
988 int nitems;
989 int bytes_after;
990 IntPtr prop = IntPtr.Zero;
992 Clipboard.Item = null;
994 XGetWindowProperty (DisplayHandle, FosterParent, property, 0, 0x7fffffff, true, Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
996 if (nitems > 0) {
997 if (property == (int)Atom.XA_STRING) {
998 Clipboard.Item = Marshal.PtrToStringAnsi (prop);
999 } else if (property == (int)Atom.XA_BITMAP) {
1000 // FIXME - convert bitmap to image
1001 } else if (property == (int)Atom.XA_PIXMAP) {
1002 // FIXME - convert pixmap to image
1003 } else if (property == NetAtoms [(int)NA.OEMTEXT]) {
1004 Clipboard.Item = Marshal.PtrToStringAnsi (prop);
1005 } else if (property == NetAtoms [(int)NA.UNICODETEXT]) {
1006 Clipboard.Item = Marshal.PtrToStringAnsi (prop);
1009 XFree (prop);
1013 private void AddExpose (XEvent xevent)
1015 Hwnd hwnd;
1017 hwnd = Hwnd.GetObjectFromWindow (xevent.AnyEvent.window);
1019 // Don't waste time
1020 if (hwnd == null) {
1021 return;
1024 if (xevent.AnyEvent.window == hwnd.client_window) {
1025 hwnd.AddInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1026 if (!hwnd.expose_pending) {
1027 MessageQueue.Enqueue (xevent);
1028 hwnd.expose_pending = true;
1030 } else {
1031 if (!hwnd.nc_expose_pending) {
1032 MessageQueue.Enqueue (xevent);
1033 hwnd.nc_expose_pending = true;
1038 private void InvalidateWholeWindow (IntPtr handle)
1040 Hwnd hwnd;
1042 hwnd = Hwnd.ObjectFromHandle (handle);
1044 InvalidateWholeWindow (handle, new Rectangle (0, 0, hwnd.Width, hwnd.Height));
1047 private void InvalidateWholeWindow (IntPtr handle, Rectangle rectangle)
1049 Hwnd hwnd;
1050 XEvent xevent;
1052 hwnd = Hwnd.ObjectFromHandle (handle);
1055 xevent = new XEvent ();
1056 xevent.type = XEventName.Expose;
1057 xevent.ExposeEvent.display = DisplayHandle;
1058 xevent.ExposeEvent.window = hwnd.whole_window;
1060 xevent.ExposeEvent.x = rectangle.X;
1061 xevent.ExposeEvent.y = rectangle.Y;
1062 xevent.ExposeEvent.width = rectangle.Width;
1063 xevent.ExposeEvent.height = rectangle.Height;
1065 AddExpose (xevent);
1068 private void WholeToScreen (IntPtr handle, ref int x, ref int y)
1070 int dest_x_return;
1071 int dest_y_return;
1072 Hwnd hwnd;
1074 hwnd = Hwnd.ObjectFromHandle (handle);
1076 lock (XlibLock) {
1077 gdk_window_get_origin (gdk_window_lookup (hwnd.whole_window), out dest_x_return, out dest_y_return);
1080 x = dest_x_return;
1081 y = dest_y_return;
1084 private void AddConfigureNotify (XEvent xevent)
1086 Hwnd hwnd;
1088 hwnd = Hwnd.GetObjectFromWindow (xevent.ConfigureEvent.window);
1090 // Don't waste time
1091 if (hwnd == null) {
1092 return;
1095 if (xevent.ConfigureEvent.window == hwnd.whole_window) {
1096 if (!hwnd.reparented) {
1097 hwnd.x = xevent.ConfigureEvent.x;
1098 hwnd.y = xevent.ConfigureEvent.y;
1099 } else {
1100 int dummy_int;
1102 gdk_window_get_geometry (gdk_window_lookup (hwnd.whole_window), out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int);
1105 hwnd.width = xevent.ConfigureEvent.width;
1106 hwnd.height = xevent.ConfigureEvent.height;
1108 if (!hwnd.configure_pending) {
1109 MessageQueue.Enqueue (xevent);
1110 hwnd.configure_pending = true;
1113 // We drop configure events for Client windows
1116 private void ShowCaret ()
1118 if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1119 return;
1121 Caret.On = true;
1123 // gdk_gc_set_foreground
1124 // gdk_draw_line
1125 lock (XlibLock) {
1126 XDrawLine (DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1130 private void HideCaret ()
1132 if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1133 return;
1135 Caret.On = false;
1137 // gdk_gc_set_foreground
1138 // gdk_draw_text_wc
1139 lock (XlibLock) {
1140 XDrawLine (DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1144 private int NextTimeout (DateTime now)
1146 int timeout = Int32.MaxValue;
1147 lock (TimerList) {
1148 foreach (Timer timer in TimerList) {
1149 int next = (int) (timer.Expires - now).TotalMilliseconds;
1150 if (next < 0) {
1151 return 0; // Have a timer that has already expired
1154 if (next < timeout) {
1155 timeout = next;
1159 if (timeout < Timer.Minimum) {
1160 timeout = Timer.Minimum;
1163 return timeout;
1166 private void CheckTimers (DateTime now)
1168 lock (TimerList) {
1169 int count;
1171 count = TimerList.Count;
1173 if (count == 0) {
1174 return;
1177 for (int i = 0; i < TimerList.Count; i++) {
1178 Timer timer;
1180 timer = (Timer) TimerList [i];
1182 if (timer.Enabled && timer.Expires <= now) {
1183 timer.Update (now);
1184 timer.FireTick ();
1190 private void UpdateMessageQueue ()
1192 DateTime now;
1193 int pending;
1195 now = DateTime.Now;
1197 lock (XlibLock) {
1198 pending = XPending (DisplayHandle);
1201 if (pending == 0) {
1202 if (Idle != null) {
1203 Idle (this, EventArgs.Empty);
1206 lock (XlibLock) {
1207 pending = XPending (DisplayHandle);
1211 if (pending == 0) {
1212 int timeout;
1214 timeout = NextTimeout (now);
1215 if (timeout > 0) {
1216 #if __MonoCS__
1217 Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
1218 // Clean out buffer, so we're not busy-looping on the same data
1219 if (pollfds[1].revents != 0) {
1220 wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1222 #endif
1223 lock (XlibLock) {
1224 pending = XPending (DisplayHandle);
1229 CheckTimers (now);
1231 if (pending == 0) {
1232 lock (XlibLock) {
1233 pending = XPending (DisplayHandle);
1237 while (pending > 0) {
1238 XEvent xevent = new XEvent ();
1240 lock (XlibLock) {
1241 XNextEvent (DisplayHandle, ref xevent);
1243 //Console.WriteLine("Got x event {0}", xevent);
1244 switch (xevent.type) {
1245 case XEventName.Expose:
1246 AddExpose (xevent);
1247 break;
1249 case XEventName.SelectionClear: {
1250 // Should we do something?
1251 break;
1254 case XEventName.SelectionRequest: {
1255 if (Dnd.HandleSelectionRequestEvent (ref xevent))
1256 break;
1257 XEvent sel_event;
1259 sel_event = new XEvent ();
1260 sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1261 sel_event.SelectionEvent.send_event = true;
1262 sel_event.SelectionEvent.display = DisplayHandle;
1263 sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1264 sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1265 sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1266 sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1267 sel_event.SelectionEvent.property = 0;
1269 // Seems that some apps support asking for supported types
1270 if (xevent.SelectionEvent.target == NetAtoms [(int)NA.TARGETS]) {
1271 uint[] atoms;
1272 int atom_count;
1274 atoms = new uint [5];
1275 atom_count = 0;
1277 if (Clipboard.Item is String) {
1278 atoms [atom_count++] = (uint)Atom.XA_STRING;
1279 atoms [atom_count++] = (uint)NetAtoms [(int)NA.OEMTEXT];
1280 atoms [atom_count++] = (uint)NetAtoms [(int)NA.UNICODETEXT];
1281 } else if (Clipboard.Item is Image) {
1282 atoms [atom_count++] = (uint)Atom.XA_PIXMAP;
1283 atoms [atom_count++] = (uint)Atom.XA_BITMAP;
1284 } else {
1285 // FIXME - handle other types
1288 XChangeProperty (DisplayHandle, xevent.SelectionEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1289 } else if (Clipboard.Item is string) {
1290 IntPtr buffer;
1291 int buflen;
1293 buflen = 0;
1295 if (xevent.SelectionRequestEvent.target == (int)Atom.XA_STRING) {
1296 Byte[] bytes;
1298 bytes = new ASCIIEncoding ().GetBytes ((string)Clipboard.Item);
1299 buffer = Marshal.AllocHGlobal (bytes.Length);
1300 buflen = bytes.Length;
1302 for (int i = 0; i < buflen; i++) {
1303 Marshal.WriteByte (buffer, i, bytes [i]);
1305 } else if (xevent.SelectionRequestEvent.target == NetAtoms [(int)NA.OEMTEXT]) {
1306 // FIXME - this should encode into ISO2022
1307 buffer = Marshal.StringToHGlobalAnsi ((string)Clipboard.Item);
1308 while (Marshal.ReadByte (buffer, buflen) != 0) {
1309 buflen++;
1311 } else if (xevent.SelectionRequestEvent.target == NetAtoms [(int)NA.UNICODETEXT]) {
1312 buffer = Marshal.StringToHGlobalAnsi ((string)Clipboard.Item);
1313 while (Marshal.ReadByte (buffer, buflen) != 0) {
1314 buflen++;
1316 } else {
1317 buffer = IntPtr.Zero;
1320 if (buffer != IntPtr.Zero) {
1321 XChangeProperty (DisplayHandle, xevent.SelectionRequestEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1322 sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1323 Marshal.FreeHGlobal (buffer);
1325 } else if (Clipboard.Item is Image) {
1326 if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
1327 // FIXME - convert image and store as property
1328 } else if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
1329 // FIXME - convert image and store as property
1333 XSendEvent (DisplayHandle, xevent.SelectionRequestEvent.requestor, false, EventMask.NoEventMask, ref sel_event);
1334 break;
1337 case XEventName.SelectionNotify: {
1338 if (Clipboard.Enumerating) {
1339 Clipboard.Enumerating = false;
1340 if (xevent.SelectionEvent.property != 0) {
1341 XDeleteProperty (DisplayHandle, FosterParent, xevent.SelectionEvent.property);
1342 if (!Clipboard.Formats.Contains (xevent.SelectionEvent.property)) {
1343 Clipboard.Formats.Add (xevent.SelectionEvent.property);
1344 #if DriverDebugExtra
1345 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1346 #endif
1349 } else if (Clipboard.Retrieving) {
1350 Clipboard.Retrieving = false;
1351 if (xevent.SelectionEvent.property != 0) {
1352 TranslatePropertyToClipboard (xevent.SelectionEvent.property);
1353 } else {
1354 Clipboard.Item = null;
1356 } else {
1357 Dnd.HandleSelectionNotifyEvent (ref xevent);
1359 break;
1362 case XEventName.KeyPress:
1363 case XEventName.KeyRelease:
1364 case XEventName.ButtonPress:
1365 case XEventName.ButtonRelease:
1366 case XEventName.MotionNotify:
1367 case XEventName.EnterNotify:
1368 case XEventName.LeaveNotify:
1369 case XEventName.CreateNotify:
1370 case XEventName.DestroyNotify:
1371 case XEventName.FocusIn:
1372 case XEventName.FocusOut:
1373 case XEventName.ClientMessage:
1374 case XEventName.ReparentNotify:
1375 MessageQueue.Enqueue (xevent);
1376 break;
1378 case XEventName.ConfigureNotify:
1379 AddConfigureNotify (xevent);
1380 break;
1382 case XEventName.PropertyNotify:
1383 if (xevent.PropertyEvent.atom == NetAtoms [(int)NA._NET_ACTIVE_WINDOW]) {
1384 Atom actual_atom;
1385 int actual_format;
1386 int nitems;
1387 int bytes_after;
1388 IntPtr prop = IntPtr.Zero;
1389 IntPtr prev_active;;
1391 prev_active = ActiveWindow;
1392 XGetWindowProperty (DisplayHandle, RootWindow, NetAtoms [(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1393 if ((nitems > 0) && (prop != IntPtr.Zero)) {
1394 ActiveWindow = Hwnd.GetHandleFromWindow ((IntPtr)Marshal.ReadInt32 (prop));
1395 XFree (prop);
1397 if (prev_active != ActiveWindow) {
1398 if (prev_active != IntPtr.Zero) {
1399 PostMessage (prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1401 if (ActiveWindow != IntPtr.Zero) {
1402 PostMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1405 if (ModalWindows.Count == 0) {
1406 break;
1407 } else {
1408 // Modality handling, if we are modal and the new active window is one
1409 // of ours but not the modal one, switch back to the modal window
1411 if (NativeWindow.FindWindow (ActiveWindow) != null) {
1412 if (ActiveWindow != (IntPtr)ModalWindows.Peek ()) {
1413 Activate ((IntPtr)ModalWindows.Peek ());
1416 break;
1420 break;
1424 lock (XlibLock) {
1425 pending = XPending (DisplayHandle);
1430 private IntPtr GetMousewParam (int Delta)
1432 int result = 0;
1434 if ((MouseState & MouseButtons.Left) != 0) {
1435 result |= (int)MsgButtons.MK_LBUTTON;
1438 if ((MouseState & MouseButtons.Middle) != 0) {
1439 result |= (int)MsgButtons.MK_MBUTTON;
1442 if ((MouseState & MouseButtons.Right) != 0) {
1443 result |= (int)MsgButtons.MK_RBUTTON;
1446 Keys mods = ModifierKeys;
1447 if ((mods & Keys.Control) != 0) {
1448 result |= (int)MsgButtons.MK_CONTROL;
1451 if ((mods & Keys.Shift) != 0) {
1452 result |= (int)MsgButtons.MK_SHIFT;
1455 result |= Delta << 16;
1457 return (IntPtr)result;
1459 private IntPtr XGetParent (IntPtr handle)
1461 return gdk_x11_drawable_get_xid (gdk_window_get_parent (gdk_window_lookup (handle)));
1464 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1466 if (ErrorExceptions) {
1467 throw new XException (error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
1468 } else {
1469 Console.WriteLine ("X11 Error encountered: {0}{1}\n", XException.GetMessage (error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), Environment.StackTrace);
1471 return 0;
1474 private void DestroyChildWindow (Control c)
1476 Hwnd hwnd;
1477 int i;
1478 Control[] controls;
1480 if (c != null) {
1481 controls = c.Controls.GetAllControls ();
1483 for (i = 0; i < controls.Length; i++) {
1484 if (controls [i].IsHandleCreated) {
1485 hwnd = Hwnd.ObjectFromHandle (controls [i].Handle);
1486 SendMessage (controls [i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
1487 hwnd.Dispose ();
1489 DestroyChildWindow (controls [i]);
1494 #endregion // Private Methods
1496 #region Callbacks
1497 private void MouseHover (object sender, EventArgs e)
1499 if ((HoverState.X == MousePosition.X) && (HoverState.Y == MousePosition.Y)) {
1500 XEvent xevent;
1502 HoverState.Timer.Enabled = false;
1504 if (HoverState.Window != IntPtr.Zero) {
1505 xevent = new XEvent ();
1507 xevent.type = XEventName.ClientMessage;
1508 xevent.ClientMessageEvent.display = DisplayHandle;
1509 xevent.ClientMessageEvent.window = (IntPtr)HoverState.Window;
1510 xevent.ClientMessageEvent.message_type = (IntPtr)HoverState.Atom;
1511 xevent.ClientMessageEvent.format = 32;
1512 xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1514 MessageQueue.EnqueueLocked (xevent);
1516 WakeupMain ();
1521 private void CaretCallback (object sender, EventArgs e)
1523 if (Caret.Paused) {
1524 return;
1526 Caret.On = !Caret.On;
1528 XDrawLine (DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1530 #endregion // Callbacks
1532 #region Public Properties
1534 internal override int Caption {
1535 get {
1536 return 25;
1540 internal override Size CursorSize {
1541 get {
1542 uint x;
1543 uint y;
1544 gdk_display_get_maximal_cursor_size (GdkDisplayHandle, out x, out y);
1546 return new Size ((int)x, (int)y);
1550 internal override bool DragFullWindows {
1551 get {
1552 return true;
1556 internal override Size DragSize {
1557 get {
1558 return new Size (4, 4);
1562 internal override Size FrameBorderSize {
1563 get {
1564 throw new NotImplementedException ();
1568 internal override Size IconSize {
1569 get {
1570 IntPtr list;
1571 XIconSize size;
1572 int count;
1574 if (XGetIconSizes (DisplayHandle, RootWindow, out list, out count) != 0) {
1575 long current;
1576 int largest;
1578 current = (long)list;
1579 largest = 0;
1581 size = new XIconSize ();
1583 for (int i = 0; i < count; i++) {
1584 size = (XIconSize)Marshal.PtrToStructure ((IntPtr)current, size.GetType ());
1585 current += Marshal.SizeOf (size);
1587 // Look for our preferred size
1588 if (size.min_width == 32) {
1589 XFree (list);
1590 return new Size (32, 32);
1593 if (size.max_width == 32) {
1594 XFree (list);
1595 return new Size (32, 32);
1598 if (size.min_width < 32 && size.max_width > 32) {
1599 int x;
1601 // check if we can fit one
1602 x = size.min_width;
1603 while (x < size.max_width) {
1604 x += size.width_inc;
1605 if (x == 32) {
1606 XFree (list);
1607 return new Size (32, 32);
1612 if (largest < size.max_width) {
1613 largest = size.max_width;
1617 // We didn't find a match or we wouldn't be here
1618 return new Size (largest, largest);
1620 } else {
1621 return new Size (32, 32);
1626 internal override int KeyboardSpeed {
1627 get {
1629 // A lot harder: need to do:
1630 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
1631 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
1632 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
1634 // And from that we can tell the repetition rate
1636 // Notice, the values must map to:
1637 // [0, 31] which maps to 2.5 to 30 repetitions per second.
1639 return 0;
1643 internal override int KeyboardDelay {
1644 get {
1646 // Return values must range from 0 to 4, 0 meaning 250ms,
1647 // and 4 meaning 1000 ms.
1649 return 1; // ie, 500 ms
1653 internal override Size MaxWindowTrackSize {
1654 get {
1655 return new Size (WorkingArea.Width, WorkingArea.Height);
1659 internal override Size MinimizedWindowSize {
1660 get {
1661 return new Size (1, 1);
1665 internal override Size MinimizedWindowSpacingSize {
1666 get {
1667 return new Size (1, 1);
1671 internal override Size MinimumWindowSize {
1672 get {
1673 return new Size (1, 1);
1677 internal override Size MinWindowTrackSize {
1678 get {
1679 return new Size (1, 1);
1683 internal override Keys ModifierKeys {
1684 get {
1685 return Keyboard.ModifierKeys;
1689 internal override Size SmallIconSize {
1690 get {
1691 IntPtr list;
1692 XIconSize size;
1693 int count;
1695 if (XGetIconSizes (DisplayHandle, RootWindow, out list, out count) != 0) {
1696 long current;
1697 int smallest;
1699 current = (long)list;
1700 smallest = 0;
1702 size = new XIconSize ();
1704 for (int i = 0; i < count; i++) {
1705 size = (XIconSize)Marshal.PtrToStructure ((IntPtr)current, size.GetType ());
1706 current += Marshal.SizeOf (size);
1708 // Look for our preferred size
1709 if (size.min_width == 16) {
1710 XFree (list);
1711 return new Size (16, 16);
1714 if (size.max_width == 16) {
1715 XFree (list);
1716 return new Size (16, 16);
1719 if (size.min_width < 16 && size.max_width > 16) {
1720 int x;
1722 // check if we can fit one
1723 x = size.min_width;
1724 while (x < size.max_width) {
1725 x += size.width_inc;
1726 if (x == 16) {
1727 XFree (list);
1728 return new Size (16, 16);
1733 if (smallest == 0 || smallest > size.min_width) {
1734 smallest = size.min_width;
1738 // We didn't find a match or we wouldn't be here
1739 return new Size (smallest, smallest);
1741 } else {
1742 return new Size (16, 16);
1747 internal override int MouseButtonCount {
1748 get {
1749 return 3;
1753 internal override bool MouseButtonsSwapped {
1754 get {
1755 return false; // FIXME - how to detect?
1759 internal override bool MouseWheelPresent {
1760 get {
1761 return true; // FIXME - how to detect?
1765 internal override Rectangle VirtualScreen {
1766 get {
1767 return WorkingArea;
1771 internal override Rectangle WorkingArea {
1772 get {
1773 Atom actual_atom;
1774 int actual_format;
1775 int nitems;
1776 int bytes_after;
1777 IntPtr prop = IntPtr.Zero;
1778 int width;
1779 int height;
1781 XGetWindowProperty (DisplayHandle, RootWindow, NetAtoms [(int)NA._NET_DESKTOP_GEOMETRY], 0, 256, false, Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1782 if ((nitems == 2) && (prop != IntPtr.Zero)) {
1783 width = Marshal.ReadInt32 (prop, 0);
1784 height = Marshal.ReadInt32 (prop, 4);
1786 XFree (prop);
1787 return new Rectangle (0, 0, width, height);
1788 } else {
1789 XWindowAttributes attributes=new XWindowAttributes ();
1791 lock (XlibLock) {
1792 XGetWindowAttributes (DisplayHandle, XRootWindow (DisplayHandle, ScreenNo), ref attributes);
1795 return new Rectangle (0, 0, attributes.width, attributes.height);
1799 #endregion // Public properties
1801 #region Public Static Methods
1802 internal override IntPtr InitializeDriver ()
1804 lock (this) {
1805 if (GdkDisplayHandle == IntPtr.Zero) {
1806 SetDisplay (gdk_x11_display_get_xdisplay (gdk_display_get_default ()));
1809 return IntPtr.Zero;
1812 internal override void ShutdownDriver (IntPtr token)
1814 lock (this) {
1815 if (GdkDisplayHandle != IntPtr.Zero) {
1816 gdk_display_close (GdkDisplayHandle);
1817 DisplayHandle = IntPtr.Zero;
1818 GdkDisplayHandle = IntPtr.Zero;
1823 internal override void EnableThemes ()
1825 ThemesEnabled = true;
1829 internal override void Activate (IntPtr handle)
1831 Hwnd hwnd;
1833 hwnd = Hwnd.ObjectFromHandle (handle);
1835 if (hwnd != null) lock (XlibLock) {
1836 SendNetWMMessage (hwnd.whole_window, (IntPtr)NetAtoms [(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
1837 //XRaiseWindow(DisplayHandle, handle);
1839 return;
1842 internal override void AudibleAlert ()
1844 gdk_display_beep (gdk_x11_lookup_xdisplay (DisplayHandle));
1845 return;
1849 internal override void CaretVisible (IntPtr handle, bool visible)
1851 // Visible is cumulative; two hides require two shows before the caret is visible again
1852 if (Caret.Hwnd == handle) {
1853 if (visible) {
1854 if (Caret.Visible < 1) {
1855 Caret.Visible++;
1856 Caret.On = false;
1857 if (Caret.Visible == 1) {
1858 ShowCaret ();
1859 Caret.Timer.Start ();
1862 } else {
1863 Caret.Visible--;
1864 if (Caret.Visible == 0) {
1865 Caret.Timer.Stop ();
1866 HideCaret ();
1872 internal override bool CalculateWindowRect (IntPtr handle, ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect)
1874 FormBorderStyle border_style;
1875 TitleStyle title_style;
1876 int caption_height;
1877 int tool_caption_height;
1879 DeriveStyles (handle, Style, ExStyle, out border_style, out title_style,
1880 out caption_height, out tool_caption_height);
1882 WindowRect = Hwnd.GetWindowRectangle (border_style, menu, title_style,
1883 caption_height, tool_caption_height,
1884 ClientRect);
1886 return true;
1889 internal override void ClientToScreen (IntPtr handle, ref int x, ref int y)
1891 int dest_x_return;
1892 int dest_y_return;
1893 IntPtr child;
1894 Hwnd hwnd;
1896 hwnd = Hwnd.ObjectFromHandle (handle);
1898 lock (XlibLock) {
1899 XTranslateCoordinates (DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1902 x = dest_x_return;
1903 y = dest_y_return;
1906 internal override int[] ClipboardAvailableFormats (IntPtr handle)
1908 DataFormats.Format f;
1909 int[] result;
1911 f = DataFormats.Format.List;
1913 if (XGetSelectionOwner (DisplayHandle, NetAtoms [(int)NA.CLIPBOARD]) == IntPtr.Zero) {
1914 return null;
1917 Clipboard.Formats = new ArrayList ();
1919 while (f != null) {
1920 XConvertSelection (DisplayHandle, NetAtoms [(int)NA.CLIPBOARD], f.Id, f.Id, FosterParent, IntPtr.Zero);
1922 Clipboard.Enumerating = true;
1923 while (Clipboard.Enumerating) {
1924 UpdateMessageQueue ();
1926 f = f.Next;
1929 result = new int [Clipboard.Formats.Count];
1931 for (int i = 0; i < Clipboard.Formats.Count; i++) {
1932 result [i] = (int)Clipboard.Formats [i];
1935 Clipboard.Formats = null;
1936 return result;
1939 internal override void ClipboardClose (IntPtr handle)
1941 if (handle != ClipMagic) {
1942 throw new ArgumentException ("handle is not a valid clipboard handle");
1944 return;
1947 internal override int ClipboardGetID (IntPtr handle, string format)
1949 if (handle != ClipMagic) {
1950 throw new ArgumentException ("handle is not a valid clipboard handle");
1953 if (format == "Text") return (int)Atom.XA_STRING;
1954 else if (format == "Bitmap") return (int)Atom.XA_BITMAP;
1955 //else if (format == "MetaFilePict" ) return 3;
1956 //else if (format == "SymbolicLink" ) return 4;
1957 //else if (format == "DataInterchangeFormat" ) return 5;
1958 //else if (format == "Tiff" ) return 6;
1959 else if (format == "OEMText") return XInternAtom (DisplayHandle, "COMPOUND_TEXT", false);
1960 else if (format == "DeviceIndependentBitmap") return (int)Atom.XA_PIXMAP;
1961 else if (format == "Palette") return (int)Atom.XA_COLORMAP; // Useless
1962 //else if (format == "PenData" ) return 10;
1963 //else if (format == "RiffAudio" ) return 11;
1964 //else if (format == "WaveAudio" ) return 12;
1965 else if (format == "UnicodeText") return XInternAtom (DisplayHandle, "UTF8_STRING", false);
1966 //else if (format == "EnhancedMetafile" ) return 14;
1967 //else if (format == "FileDrop" ) return 15;
1968 //else if (format == "Locale" ) return 16;
1970 return XInternAtom (DisplayHandle, format, false);
1973 internal override IntPtr ClipboardOpen ()
1975 return ClipMagic;
1978 internal override object ClipboardRetrieve (IntPtr handle, int type, XplatUI.ClipboardToObject converter)
1980 XConvertSelection (DisplayHandle, NetAtoms [(int)NA.CLIPBOARD], type, type, FosterParent, IntPtr.Zero);
1982 Clipboard.Retrieving = true;
1983 while (Clipboard.Retrieving) {
1984 UpdateMessageQueue ();
1987 return Clipboard.Item;
1990 internal override void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter)
1992 Clipboard.Item = obj;
1993 Clipboard.Type = type;
1994 Clipboard.Converter = converter;
1996 if (obj != null) {
1997 XSetSelectionOwner (DisplayHandle, NetAtoms [(int)NA.CLIPBOARD], FosterParent, IntPtr.Zero);
1998 } else {
1999 // Clearing the selection
2000 XSetSelectionOwner (DisplayHandle, NetAtoms [(int)NA.CLIPBOARD], IntPtr.Zero, IntPtr.Zero);
2004 internal override void CreateCaret (IntPtr handle, int width, int height)
2006 XGCValues gc_values;
2007 Hwnd hwnd;
2009 hwnd = Hwnd.ObjectFromHandle (handle);
2011 if (Caret.Hwnd != IntPtr.Zero) {
2012 DestroyCaret (Caret.Hwnd);
2015 Caret.Hwnd = handle;
2016 Caret.Window = hwnd.client_window;
2017 Caret.Width = width;
2018 Caret.Height = height;
2019 Caret.Visible = 0;
2020 Caret.On = false;
2022 gc_values = new XGCValues ();
2023 gc_values.line_width = width;
2025 Caret.gc = XCreateGC (DisplayHandle, Caret.Window, GCFunction.GCLineWidth, ref gc_values);
2026 if (Caret.gc == IntPtr.Zero) {
2027 Caret.Hwnd = IntPtr.Zero;
2028 return;
2031 XSetFunction (DisplayHandle, Caret.gc, GXFunction.GXinvert);
2034 internal override IntPtr CreateWindow (CreateParams cp)
2036 GdkWindowAttr gdk_window_attributes;
2037 GdkWindowAttributesType attributes_mask = 0;
2038 Hwnd hwnd;
2039 int X;
2040 int Y;
2041 int Width;
2042 int Height;
2043 IntPtr GdkParentHandle;
2044 IntPtr GdkWholeWindow;
2045 IntPtr GdkClientWindow;
2046 Rectangle ClientRect;
2047 GdkWindowType gdk_window_type;
2050 hwnd = new Hwnd ();
2052 gdk_window_attributes = new GdkWindowAttr ();
2054 X = cp.X;
2055 Y = cp.Y;
2056 Width = cp.Width;
2057 Height = cp.Height;
2059 if (Width < 1) Width = 1;
2060 if (Height < 1) Height = 1;
2062 gdk_window_type = GdkWindowType.GDK_WINDOW_CHILD;
2064 if (cp.Parent != IntPtr.Zero) {
2065 GdkParentHandle = gdk_window_lookup (Hwnd.ObjectFromHandle (cp.Parent).client_window);
2066 } else {
2067 if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
2068 // We need to use our foster parent window until this poor child gets it's parent assigned
2069 GdkParentHandle = GdkFosterParent;
2070 } else if ((cp.Style & (int)WindowStyles.WS_POPUP) != 0) {
2071 GdkParentHandle = GdkRootWindow;
2072 } else {
2073 // Default position on screen, if window manager doesn't place us somewhere else
2074 if (X < 1) X = 50;
2075 if (Y < 1) Y = 50;
2076 GdkParentHandle = GdkRootWindow;
2080 // ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2082 // Attributes.bit_gravity = Gravity.NorthWestGravity;
2083 // Attributes.win_gravity = Gravity.NorthWestGravity;
2085 // FIXME: does gdk need that ?
2086 // Save what's under the toolwindow
2087 if ((cp.ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
2088 // Attributes.save_under = true;
2089 // ValueMask |= SetWindowValuemask.SaveUnder;
2092 // If we're a popup without caption we override the WM
2093 if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
2094 if ((cp.Style & (int)WindowStyles.WS_CAPTION) == 0) {
2095 gdk_window_attributes.override_redirect = true;
2096 attributes_mask |= GdkWindowAttributesType.GDK_WA_NOREDIR;
2100 hwnd.x = X;
2101 hwnd.y = Y;
2102 hwnd.width = Width;
2103 hwnd.height = Height;
2104 hwnd.parent = Hwnd.ObjectFromHandle (cp.Parent);
2106 if ((cp.Style & ((int)WindowStyles.WS_DISABLED)) != 0) {
2107 hwnd.enabled = false;
2110 ClientRect = hwnd.ClientRect;
2111 GdkClientWindow = IntPtr.Zero;
2113 gdk_window_attributes.x = X;
2114 gdk_window_attributes.y = Y;
2115 gdk_window_attributes.width = Width;
2116 gdk_window_attributes.height = Height;
2117 gdk_window_attributes.window_type = gdk_window_type;
2119 attributes_mask |= GdkWindowAttributesType.GDK_WA_X | GdkWindowAttributesType.GDK_WA_Y;
2121 gdk_window_attributes.wclass = GdkWindowClass.GDK_INPUT_OUTPUT;
2123 lock (XlibLock) {
2124 GdkWholeWindow = gdk_window_new (GdkParentHandle, ref gdk_window_attributes, (int)attributes_mask);
2126 if (GdkWholeWindow != IntPtr.Zero) {
2127 attributes_mask &= ~GdkWindowAttributesType.GDK_WA_NOREDIR;
2129 if (GdkCustomVisual != IntPtr.Zero && GdkCustomColormap != IntPtr.Zero) {
2130 attributes_mask |= GdkWindowAttributesType.GDK_WA_COLORMAP | GdkWindowAttributesType.GDK_WA_VISUAL;
2131 gdk_window_attributes.colormap = GdkCustomColormap;
2132 gdk_window_attributes.visual = GdkCustomVisual;
2135 gdk_window_attributes.x = ClientRect.X;
2136 gdk_window_attributes.y = ClientRect.Y;
2137 gdk_window_attributes.width = ClientRect.Width;
2138 gdk_window_attributes.height = ClientRect.Height;
2140 GdkClientWindow = gdk_window_new (GdkWholeWindow, ref gdk_window_attributes, (int)attributes_mask);
2144 if ((GdkWholeWindow == IntPtr.Zero) || (GdkClientWindow == IntPtr.Zero)) {
2145 throw new Exception ("Could not create X11 Gdk windows");
2148 hwnd.WholeWindow = gdk_x11_drawable_get_xid (GdkWholeWindow);
2149 hwnd.ClientWindow = gdk_x11_drawable_get_xid (GdkClientWindow);
2151 #if DriverDebug
2152 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
2153 #endif
2155 lock (XlibLock) {
2156 gdk_window_set_events (GdkWholeWindow, (int)GdkSelectInputMask);
2157 gdk_window_set_events (GdkClientWindow, (int)GdkSelectInputMask);
2159 if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
2160 gdk_window_show (GdkWholeWindow);
2161 gdk_window_show (GdkClientWindow);
2162 hwnd.visible = true;
2166 SetWMStyles (hwnd, cp);
2168 if ((cp.Style & (int)WindowStyles.WS_MINIMIZE) != 0) {
2169 SetWindowState (hwnd.Handle, FormWindowState.Minimized);
2170 } else if ((cp.Style & (int)WindowStyles.WS_MAXIMIZE) != 0) {
2171 SetWindowState (hwnd.Handle, FormWindowState.Maximized);
2174 // for now make all windows dnd enabled
2175 Dnd.SetAllowDrop (hwnd, true);
2177 // Set caption/window title
2178 Text (hwnd.Handle, cp.Caption);
2180 return hwnd.Handle;
2183 internal override IntPtr CreateWindow (IntPtr Parent, int X, int Y, int Width, int Height)
2185 CreateParams create_params = new CreateParams ();
2187 create_params.Caption = "";
2188 create_params.X = X;
2189 create_params.Y = Y;
2190 create_params.Width = Width;
2191 create_params.Height = Height;
2193 create_params.ClassName = XplatUI.DefaultClassName;
2194 create_params.ClassStyle = 0;
2195 create_params.ExStyle = 0;
2196 create_params.Parent = IntPtr.Zero;
2197 create_params.Param = 0;
2199 return CreateWindow (create_params);
2202 internal override IntPtr DefineCursor (Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot)
2204 IntPtr cursor;
2205 Bitmap cursor_bitmap;
2206 Bitmap cursor_mask;
2207 Byte[] cursor_bits;
2208 Byte[] mask_bits;
2209 Color c_pixel;
2210 Color m_pixel;
2211 int width;
2212 int height;
2213 IntPtr cursor_pixmap;
2214 IntPtr mask_pixmap;
2215 XColor fg;
2216 XColor bg;
2217 bool and;
2218 bool xor;
2220 Size cursor_size = CursorSize;
2221 width = cursor_size.Width;
2222 height = cursor_size.Height;
2224 // Win32 only allows creation cursors of a certain size
2225 if ((bitmap.Width != width) || (bitmap.Width != height)) {
2226 cursor_bitmap = new Bitmap (bitmap, new Size (width, height));
2227 cursor_mask = new Bitmap (mask, new Size (width, height));
2228 } else {
2229 cursor_bitmap = bitmap;
2230 cursor_mask = mask;
2233 width = cursor_bitmap.Width;
2234 height = cursor_bitmap.Height;
2236 cursor_bits = new Byte [(width / 8) * height];
2237 mask_bits = new Byte [(width / 8) * height];
2239 for (int y = 0; y < height; y++) {
2240 for (int x = 0; x < width; x++) {
2241 c_pixel = cursor_bitmap.GetPixel (x, y);
2242 m_pixel = cursor_mask.GetPixel (x, y);
2244 and = c_pixel == cursor_pixel;
2245 xor = m_pixel == mask_pixel;
2247 if (!and && !xor) {
2248 // Black
2249 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
2250 mask_bits [y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2251 } else if (and && !xor) {
2252 // White
2253 cursor_bits [y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2254 mask_bits [y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2255 #if notneeded
2256 } else if (and && !xor) {
2257 // Screen
2258 } else if (and && xor) {
2259 // Inverse Screen
2261 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2262 // we want both to be 0 so nothing to be done
2263 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2264 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2265 #endif
2270 cursor_pixmap = XCreatePixmapFromBitmapData (DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2271 mask_pixmap = XCreatePixmapFromBitmapData (DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2272 fg = new XColor ();
2273 bg = new XColor ();
2275 fg.pixel = XWhitePixel (DisplayHandle, ScreenNo);
2276 fg.red = (ushort)65535;
2277 fg.green = (ushort)65535;
2278 fg.blue = (ushort)65535;
2280 bg.pixel = XBlackPixel (DisplayHandle, ScreenNo);
2282 cursor = XCreatePixmapCursor (DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2284 XFreePixmap (DisplayHandle, cursor_pixmap);
2285 XFreePixmap (DisplayHandle, mask_pixmap);
2287 return cursor;
2290 internal override IntPtr DefineStdCursor (StdCursor id)
2292 CursorFontShape shape;
2293 IntPtr cursor;
2295 // FIXME - define missing shapes
2297 switch (id) {
2298 case StdCursor.AppStarting: {
2299 shape = CursorFontShape.XC_watch;
2300 break;
2303 case StdCursor.Arrow: {
2304 return IntPtr.Zero;
2307 case StdCursor.Cross: {
2308 shape = CursorFontShape.XC_crosshair;
2309 break;
2312 case StdCursor.Default: {
2313 return IntPtr.Zero;
2316 case StdCursor.Hand: {
2317 shape = CursorFontShape.XC_hand1;
2318 break;
2321 case StdCursor.Help: {
2322 shape = CursorFontShape.XC_question_arrow;
2323 break;
2326 case StdCursor.HSplit: {
2327 shape = CursorFontShape.XC_sb_v_double_arrow;
2328 break;
2331 case StdCursor.IBeam: {
2332 shape = CursorFontShape.XC_xterm;
2333 break;
2336 case StdCursor.No: {
2337 shape = CursorFontShape.XC_circle;
2338 break;
2341 case StdCursor.NoMove2D: {
2342 shape = CursorFontShape.XC_fleur;
2343 break;
2346 case StdCursor.NoMoveHoriz: {
2347 shape = CursorFontShape.XC_fleur;
2348 break;
2351 case StdCursor.NoMoveVert: {
2352 shape = CursorFontShape.XC_fleur;
2353 break;
2356 case StdCursor.PanEast: {
2357 shape = CursorFontShape.XC_fleur;
2358 break;
2361 case StdCursor.PanNE: {
2362 shape = CursorFontShape.XC_fleur;
2363 break;
2366 case StdCursor.PanNorth: {
2367 shape = CursorFontShape.XC_fleur;
2368 break;
2371 case StdCursor.PanNW: {
2372 shape = CursorFontShape.XC_fleur;
2373 break;
2376 case StdCursor.PanSE: {
2377 shape = CursorFontShape.XC_fleur;
2378 break;
2381 case StdCursor.PanSouth: {
2382 shape = CursorFontShape.XC_fleur;
2383 break;
2386 case StdCursor.PanSW: {
2387 shape = CursorFontShape.XC_fleur;
2388 break;
2391 case StdCursor.PanWest: {
2392 shape = CursorFontShape.XC_sizing;
2393 break;
2396 case StdCursor.SizeAll: {
2397 shape = CursorFontShape.XC_fleur;
2398 break;
2401 case StdCursor.SizeNESW: {
2402 shape = CursorFontShape.XC_top_right_corner;
2403 break;
2406 case StdCursor.SizeNS: {
2407 shape = CursorFontShape.XC_sb_v_double_arrow;
2408 break;
2411 case StdCursor.SizeNWSE: {
2412 shape = CursorFontShape.XC_top_left_corner;
2413 break;
2416 case StdCursor.SizeWE: {
2417 shape = CursorFontShape.XC_sb_h_double_arrow;
2418 break;
2421 case StdCursor.UpArrow: {
2422 shape = CursorFontShape.XC_center_ptr;
2423 break;
2426 case StdCursor.VSplit: {
2427 shape = CursorFontShape.XC_sb_h_double_arrow;
2428 break;
2431 case StdCursor.WaitCursor: {
2432 shape = CursorFontShape.XC_watch;
2433 break;
2436 default: {
2437 return IntPtr.Zero;
2441 lock (XlibLock) {
2442 cursor = XCreateFontCursor (DisplayHandle, shape);
2444 return cursor;
2447 internal override IntPtr DefWndProc (ref Message msg)
2449 return IntPtr.Zero;
2452 internal override void DestroyCaret (IntPtr handle)
2454 if (Caret.Hwnd == handle) {
2455 if (Caret.Visible == 1) {
2456 Caret.Timer.Stop ();
2457 HideCaret ();
2459 if (Caret.gc != IntPtr.Zero) {
2460 XFreeGC (DisplayHandle, Caret.gc);
2461 Caret.gc = IntPtr.Zero;
2463 Caret.Hwnd = IntPtr.Zero;
2464 Caret.Visible = 0;
2465 Caret.On = false;
2469 internal override void DestroyCursor (IntPtr cursor)
2471 lock (XlibLock) {
2472 XFreeCursor (DisplayHandle, cursor);
2476 internal override void DestroyWindow (IntPtr handle)
2478 Hwnd hwnd;
2480 hwnd = Hwnd.ObjectFromHandle (handle);
2482 if (hwnd == null) {
2483 #if DriverDebug
2484 Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2485 #endif
2486 return;
2489 #if DriverDebug
2490 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
2491 #endif
2493 // Make sure if the caret is in the window, that we destroy the caret, too
2494 if (Caret.Hwnd == hwnd.client_window) {
2495 DestroyCaret (handle);
2498 // Mark our children as gone as well
2499 DestroyChildWindow (Control.ControlNativeWindow.ControlFromHandle (handle));
2501 // Send destroy message
2502 SendMessage (handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2504 lock (XlibLock) {
2505 if (hwnd.client_window != IntPtr.Zero) {
2506 gdk_window_destroy (gdk_window_lookup (hwnd.client_window));
2509 if ((hwnd.whole_window != IntPtr.Zero) && (hwnd.whole_window != hwnd.client_window)) {
2510 gdk_window_destroy (gdk_window_lookup (hwnd.whole_window));
2513 hwnd.Dispose ();
2516 internal override IntPtr DispatchMessage (ref MSG msg)
2518 return NativeWindow.WndProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
2521 internal override void DrawReversibleRectangle (IntPtr handle, Rectangle rect, int line_width)
2523 Hwnd hwnd;
2524 XGCValues gc_values;
2525 IntPtr gc;
2527 hwnd = Hwnd.ObjectFromHandle (handle);
2529 gc_values = new XGCValues ();
2531 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2532 gc_values.line_width = line_width;
2533 gc_values.foreground = XBlackPixel (DisplayHandle, ScreenNo);
2535 // This logic will give us true rubber bands: (libsx, SANE_XOR)
2536 //mask = foreground ^ background;
2537 //XSetForeground(DisplayHandle, gc, 0xffffffff);
2538 //XSetBackground(DisplayHandle, gc, background);
2539 //XSetFunction(DisplayHandle, gc, GXxor);
2540 //XSetPlaneMask(DisplayHandle, gc, mask);
2543 gc = XCreateGC (DisplayHandle, hwnd.client_window, GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground, ref gc_values);
2544 uint foreground;
2545 uint background;
2547 Control control;
2548 control = Control.FromHandle (handle);
2550 XColor xcolor = new XColor ();
2552 xcolor.red = (ushort)(control.ForeColor.R * 257);
2553 xcolor.green = (ushort)(control.ForeColor.G * 257);
2554 xcolor.blue = (ushort)(control.ForeColor.B * 257);
2555 XAllocColor (DisplayHandle, DefaultColormap, ref xcolor);
2556 foreground = (uint)xcolor.pixel.ToInt32 ();
2558 xcolor.red = (ushort)(control.BackColor.R * 257);
2559 xcolor.green = (ushort)(control.BackColor.G * 257);
2560 xcolor.blue = (ushort)(control.BackColor.B * 257);
2561 XAllocColor (DisplayHandle, DefaultColormap, ref xcolor);
2562 background = (uint)xcolor.pixel.ToInt32 ();
2564 uint mask = foreground ^ background;
2566 XSetForeground (DisplayHandle, gc, 0xffffffff);
2567 XSetBackground (DisplayHandle, gc, background);
2568 XSetFunction (DisplayHandle, gc, GXFunction.GXxor);
2569 XSetPlaneMask (DisplayHandle, gc, mask);
2571 if ((rect.Width > 0) && (rect.Height > 0)) {
2572 XDrawRectangle (DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2573 } else {
2574 if (rect.Width > 0) {
2575 XDrawLine (DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2576 } else {
2577 XDrawLine (DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2580 XFreeGC (DisplayHandle, gc);
2583 internal override void DoEvents ()
2585 MSG msg = new MSG ();
2587 if (OverrideCursorHandle != IntPtr.Zero) {
2588 OverrideCursorHandle = IntPtr.Zero;
2591 while (PeekMessage (ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2592 TranslateMessage (ref msg);
2593 DispatchMessage (ref msg);
2597 internal override void EnableWindow (IntPtr handle, bool Enable)
2599 Hwnd hwnd;
2601 hwnd = Hwnd.ObjectFromHandle (handle);
2602 if (hwnd != null) {
2603 hwnd.Enabled = Enable;
2607 internal override void EndLoop (Thread thread)
2609 // This is where we one day will shut down the loop for the thread
2613 internal override IntPtr GetActive ()
2615 Atom actual_atom;
2616 int actual_format;
2617 int nitems;
2618 int bytes_after;
2619 IntPtr prop = IntPtr.Zero;
2620 IntPtr active = IntPtr.Zero;
2622 XGetWindowProperty (DisplayHandle, RootWindow, NetAtoms [(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2623 if ((nitems > 0) && (prop != IntPtr.Zero)) {
2624 active = (IntPtr)Marshal.ReadInt32 (prop);
2625 XFree (prop);
2628 if (active != IntPtr.Zero) {
2629 Hwnd hwnd;
2631 hwnd = Hwnd.GetObjectFromWindow (active);
2632 if (hwnd != null) {
2633 active = hwnd.Handle;
2634 } else {
2635 active = IntPtr.Zero;
2638 return active;
2641 internal override void GetCursorInfo (IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y)
2643 throw new NotImplementedException ();
2646 internal override void GetDisplaySize (out Size size)
2648 XWindowAttributes attributes=new XWindowAttributes ();
2650 lock (XlibLock) {
2651 // FIXME - use _NET_WM messages instead?
2652 XGetWindowAttributes (DisplayHandle, XRootWindow (DisplayHandle, ScreenNo), ref attributes);
2655 size = new Size (attributes.width, attributes.height);
2658 internal override SizeF GetAutoScaleSize (Font font)
2660 Graphics g;
2661 float width;
2662 string magic_string = "The quick brown fox jumped over the lazy dog.";
2663 double magic_number = 44.549996948242189;
2665 g = Graphics.FromHwnd (FosterParent);
2667 width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
2668 return new SizeF (width, font.Height);
2671 internal override IntPtr GetParent (IntPtr handle)
2673 Hwnd hwnd;
2675 hwnd = Hwnd.ObjectFromHandle (handle);
2676 if (hwnd != null && hwnd.parent != null) {
2677 return hwnd.parent.Handle;
2679 return IntPtr.Zero;
2682 internal override void GetCursorPos (IntPtr handle, out int x, out int y)
2684 IntPtr use_handle;
2685 IntPtr root;
2686 IntPtr child;
2687 int root_x;
2688 int root_y;
2689 int win_x;
2690 int win_y;
2691 int keys_buttons;
2693 if (handle != IntPtr.Zero) {
2694 use_handle = Hwnd.ObjectFromHandle (handle).client_window;
2695 } else {
2696 use_handle = RootWindow;
2699 lock (XlibLock) {
2700 XQueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
2703 if (handle != IntPtr.Zero) {
2704 x = win_x;
2705 y = win_y;
2706 } else {
2707 x = root_x;
2708 y = root_y;
2712 internal override bool GetFontMetrics (Graphics g, Font font, out int ascent, out int descent)
2714 return GetFontMetrics (g.GetHdc (), font.ToHfont (), out ascent, out descent);
2717 internal override Point GetMenuOrigin (IntPtr handle)
2719 Hwnd hwnd;
2721 hwnd = Hwnd.ObjectFromHandle (handle);
2723 if (hwnd != null) {
2724 return hwnd.MenuOrigin;
2726 return Point.Empty;
2729 internal override bool GetMessage (ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax)
2731 XEvent xevent;
2732 bool client;
2733 Hwnd hwnd;
2735 ProcessNextMessage:
2737 if (MessageQueue.Count > 0) {
2738 xevent = (XEvent) MessageQueue.Dequeue ();
2739 } else {
2740 UpdateMessageQueue ();
2742 if (MessageQueue.Count > 0) {
2743 xevent = (XEvent) MessageQueue.Dequeue ();
2744 } else {
2745 if (!PostQuitState) {
2746 msg.hwnd = IntPtr.Zero;
2747 msg.message = Msg.WM_ENTERIDLE;
2748 return true;
2751 // We reset ourselves so GetMessage can be called again
2752 PostQuitState = false;
2754 return false;
2758 // FIXME - handle filtering
2760 hwnd = Hwnd.GetObjectFromWindow (xevent.AnyEvent.window);
2762 // Handle messages for windows that are already or are about to be destroyed
2763 if (hwnd == null) {
2764 #if DriverDebug
2765 Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
2766 #endif
2767 goto ProcessNextMessage;
2770 if (hwnd.client_window == xevent.AnyEvent.window) {
2771 client = true;
2772 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2773 } else {
2774 client = false;
2775 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
2778 msg.hwnd = hwnd.Handle;
2781 // If you add a new event to this switch make sure to add it in
2782 // UpdateMessage also unless it is not coming through the X event system.
2784 switch (xevent.type) {
2785 case XEventName.KeyPress: {
2786 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2787 break;
2790 case XEventName.KeyRelease: {
2791 Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
2792 break;
2795 case XEventName.ButtonPress: {
2796 switch (xevent.ButtonEvent.button) {
2797 case 1: {
2798 MouseState |= MouseButtons.Left;
2799 if (client) {
2800 msg.message = Msg.WM_LBUTTONDOWN;
2801 } else {
2802 msg.message = Msg.WM_NCLBUTTONDOWN;
2803 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2805 // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
2806 msg.wParam = GetMousewParam (0);
2807 break;
2810 case 2: {
2811 MouseState |= MouseButtons.Middle;
2812 if (client) {
2813 msg.message = Msg.WM_MBUTTONDOWN;
2814 } else {
2815 msg.message = Msg.WM_NCMBUTTONDOWN;
2816 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2818 msg.wParam = GetMousewParam (0);
2819 break;
2822 case 3: {
2823 MouseState |= MouseButtons.Right;
2824 if (client) {
2825 msg.message = Msg.WM_RBUTTONDOWN;
2826 } else {
2827 msg.message = Msg.WM_NCRBUTTONDOWN;
2828 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2830 msg.wParam = GetMousewParam (0);
2831 break;
2834 case 4: {
2835 msg.message = Msg.WM_MOUSEWHEEL;
2836 msg.wParam = GetMousewParam (120);
2837 break;
2840 case 5: {
2841 msg.message = Msg.WM_MOUSEWHEEL;
2842 msg.wParam = GetMousewParam (-120);
2843 break;
2848 msg.lParam = (IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2849 MousePosition.X = xevent.ButtonEvent.x;
2850 MousePosition.Y = xevent.ButtonEvent.y;
2852 if (!hwnd.Enabled) {
2853 IntPtr dummy;
2855 msg.hwnd = hwnd.EnabledHwnd;
2856 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);
2857 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2860 if (Grab.Hwnd != IntPtr.Zero) {
2861 msg.hwnd = Grab.Hwnd;
2864 if (!ClickPending.Pending) {
2865 ClickPending.Pending = true;
2866 ClickPending.Hwnd = msg.hwnd;
2867 ClickPending.Message = msg.message;
2868 ClickPending.wParam = msg.wParam;
2869 ClickPending.lParam = msg.lParam;
2870 ClickPending.Time = (long)xevent.ButtonEvent.time;
2871 } else {
2872 if ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message)) {
2873 // Looks like a genuine double click, clicked twice on the same spot with the same keys
2874 switch (xevent.ButtonEvent.button) {
2875 case 1: {
2876 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
2877 break;
2880 case 2: {
2881 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
2882 break;
2885 case 3: {
2886 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
2887 break;
2891 ClickPending.Pending = false;
2894 break;
2897 case XEventName.ButtonRelease: {
2898 Dnd.HandleButtonRelease (ref xevent);
2899 switch (xevent.ButtonEvent.button) {
2900 case 1: {
2901 if (client) {
2902 msg.message = Msg.WM_LBUTTONUP;
2903 } else {
2904 msg.message = Msg.WM_NCLBUTTONUP;
2905 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2907 msg.wParam = GetMousewParam (0);
2908 MouseState &= ~MouseButtons.Left;
2909 break;
2912 case 2: {
2913 if (client) {
2914 msg.message = Msg.WM_MBUTTONUP;
2915 } else {
2916 msg.message = Msg.WM_NCMBUTTONUP;
2917 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2919 msg.wParam = GetMousewParam (0);
2920 MouseState &= ~MouseButtons.Middle;
2921 break;
2924 case 3: {
2925 if (client) {
2926 msg.message = Msg.WM_RBUTTONUP;
2927 } else {
2928 msg.message = Msg.WM_NCRBUTTONUP;
2929 WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
2931 msg.wParam = GetMousewParam (0);
2932 MouseState &= ~MouseButtons.Right;
2933 break;
2936 case 4: {
2937 goto ProcessNextMessage;
2940 case 5: {
2941 goto ProcessNextMessage;
2945 if (!hwnd.Enabled) {
2946 IntPtr dummy;
2948 msg.hwnd = hwnd.EnabledHwnd;
2949 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);
2950 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2953 if (Grab.Hwnd != IntPtr.Zero) {
2954 msg.hwnd = Grab.Hwnd;
2957 msg.lParam = (IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2958 MousePosition.X = xevent.ButtonEvent.x;
2959 MousePosition.Y = xevent.ButtonEvent.y;
2960 break;
2963 case XEventName.MotionNotify: {
2964 if (client) {
2965 #if DriverDebugExtra
2966 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);
2967 #endif
2969 if (Dnd.HandleMotionNotify (ref xevent))
2970 goto ProcessNextMessage;
2971 if (Grab.Hwnd != IntPtr.Zero) {
2972 msg.hwnd = Grab.Hwnd;
2973 } else {
2974 NativeWindow.WndProc (msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
2977 msg.message = Msg.WM_MOUSEMOVE;
2978 msg.wParam = GetMousewParam (0);
2979 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
2981 if (!hwnd.Enabled) {
2982 IntPtr dummy;
2984 msg.hwnd = hwnd.EnabledHwnd;
2985 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);
2986 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
2989 HoverState.X = MousePosition.X = xevent.MotionEvent.x;
2990 HoverState.Y = MousePosition.Y = xevent.MotionEvent.y;
2992 break;
2993 } else {
2994 #if DriverDebugExtra
2995 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);
2996 #endif
2997 msg.message = Msg.WM_NCMOUSEMOVE;
2998 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3000 if (!hwnd.Enabled) {
3001 IntPtr dummy;
3003 msg.hwnd = hwnd.EnabledHwnd;
3004 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);
3005 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3008 #if notyet
3009 // Not sure we need this...
3010 HitTest ht;
3011 ht = NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, msg.lParam);
3012 #endif
3014 MousePosition.X = xevent.MotionEvent.x;
3015 MousePosition.Y = xevent.MotionEvent.y;
3018 break;
3021 case XEventName.EnterNotify: {
3022 if (!hwnd.Enabled) {
3023 goto ProcessNextMessage;
3025 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3026 goto ProcessNextMessage;
3028 msg.message = Msg.WM_MOUSE_ENTER;
3029 HoverState.Timer.Enabled = true;
3030 HoverState.Window = xevent.CrossingEvent.window;
3031 break;
3034 case XEventName.LeaveNotify: {
3035 if (!hwnd.Enabled) {
3036 goto ProcessNextMessage;
3038 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3039 goto ProcessNextMessage;
3041 msg.message = Msg.WM_MOUSELEAVE;
3042 HoverState.Timer.Enabled = false;
3043 HoverState.Window = IntPtr.Zero;
3044 break;
3047 #if later
3048 case XEventName.CreateNotify: {
3049 if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3050 msg.message = WM_CREATE;
3051 // Set up CreateStruct
3052 } else {
3053 goto ProcessNextMessage;
3055 break;
3057 #endif
3060 case XEventName.ReparentNotify: {
3061 if (hwnd.parent == null) { // Toplevel
3062 if (xevent.ReparentEvent.parent != IntPtr.Zero) {
3063 // We need to adjust x/y
3064 int dummy_int;
3066 hwnd.Reparented = true;
3068 gdk_window_get_geometry (gdk_window_lookup (hwnd.whole_window), out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int);
3069 msg.message = Msg.WM_WINDOWPOSCHANGED;
3070 if (hwnd.opacity != 0xffffffff) {
3071 uint opacity;
3073 opacity = hwnd.opacity;
3074 XChangeProperty (DisplayHandle, XGetParent (hwnd.whole_window), NetAtoms [(int)NA._NET_WM_WINDOW_OPACITY], Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3076 } else {
3077 hwnd.Reparented = false;
3078 goto ProcessNextMessage;
3081 break;
3084 case XEventName.ConfigureNotify: {
3085 if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
3086 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3087 IntPtr ptr;
3088 Rectangle rect;
3090 #if DriverDebugExtra
3091 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);
3092 #endif
3093 msg.message = Msg.WM_WINDOWPOSCHANGED;
3094 hwnd.configure_pending = false;
3096 // We need to adjust our client window to track the resize of whole_window
3097 rect = hwnd.DefaultClientRect;
3099 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS ();
3100 ptr = Marshal.AllocHGlobal (Marshal.SizeOf (ncp));
3102 ncp.rgrc1.left = rect.Left;
3103 ncp.rgrc1.top = rect.Top;
3104 ncp.rgrc1.right = rect.Right;
3105 ncp.rgrc1.bottom = rect.Bottom;
3107 Marshal.StructureToPtr (ncp, ptr, true);
3108 NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
3109 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
3110 Marshal.FreeHGlobal (ptr);
3112 // FIXME - debug this with Menus, need to set hwnd.ClientRect
3114 rect = new Rectangle (ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
3115 //Console.WriteLine("CreateOffscreenbuffer...");
3116 // CreateOffscreenBuffer (ref hwnd.client_offscreen, rect.Width, rect.Height);
3118 XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
3119 } else {
3120 goto ProcessNextMessage;
3123 msg.lParam = IntPtr.Zero; // FIXME - Generate LPWINDOWPOS structure and pass on
3124 break;
3127 case XEventName.FocusIn: {
3128 if (!hwnd.Enabled) {
3129 goto ProcessNextMessage;
3131 msg.message = Msg.WM_SETFOCUS;
3132 msg.wParam = IntPtr.Zero;
3133 break;
3136 case XEventName.FocusOut: {
3137 if (!hwnd.Enabled) {
3138 goto ProcessNextMessage;
3140 msg.message = Msg.WM_KILLFOCUS;
3141 msg.wParam = IntPtr.Zero;
3142 break;
3145 case XEventName.Expose: {
3146 if (PostQuitState) {
3147 goto ProcessNextMessage;
3151 if (client) {
3152 if (!hwnd.expose_pending) {
3153 goto ProcessNextMessage;
3155 } else {
3156 if (!hwnd.nc_expose_pending) {
3157 goto ProcessNextMessage;
3160 switch (hwnd.border_style) {
3161 case FormBorderStyle.Fixed3D: {
3162 Graphics g;
3164 g = Graphics.FromHwnd (hwnd.whole_window);
3165 ControlPaint.DrawBorder3D (g, new Rectangle (0, 0, hwnd.Width, hwnd.Height));
3166 g.Dispose ();
3167 break;
3170 case FormBorderStyle.FixedSingle: {
3171 Graphics g;
3173 g = Graphics.FromHwnd (hwnd.whole_window);
3174 ControlPaint.DrawBorder (g, new Rectangle (0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3175 g.Dispose ();
3176 break;
3179 #if DriverDebugExtra
3180 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);
3181 #endif
3183 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3184 Region region = new Region (rect);
3185 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3186 msg.message = Msg.WM_NCPAINT;
3187 msg.wParam = hrgn;
3188 hwnd.nc_expose_pending = false;
3189 break;
3191 #if DriverDebugExtra
3192 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);
3193 #endif
3194 if (Caret.Visible == 1) {
3195 Caret.Paused = true;
3196 HideCaret ();
3199 if (Caret.Visible == 1) {
3200 ShowCaret ();
3201 Caret.Paused = false;
3203 msg.message = Msg.WM_PAINT;
3204 break;
3207 case XEventName.DestroyNotify: {
3209 // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3210 hwnd = Hwnd.ObjectFromHandle (xevent.DestroyWindowEvent.window);
3212 // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3213 if (hwnd.client_window == xevent.DestroyWindowEvent.window) {
3214 msg.hwnd = hwnd.client_window;
3215 msg.message = Msg.WM_DESTROY;
3216 hwnd.Dispose ();
3218 #if DriverDebug
3219 Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
3220 #endif
3221 } else {
3222 goto ProcessNextMessage;
3225 break;
3228 case XEventName.ClientMessage: {
3229 if (Dnd.HandleClientMessage (ref xevent)) {
3230 goto ProcessNextMessage;
3233 if (xevent.ClientMessageEvent.message_type == (IntPtr)AsyncAtom) {
3234 XplatUIDriverSupport.ExecuteClientMessage ((GCHandle)xevent.ClientMessageEvent.ptr1);
3235 break;
3238 if (xevent.ClientMessageEvent.message_type == (IntPtr)HoverState.Atom) {
3239 msg.message = Msg.WM_MOUSEHOVER;
3240 msg.wParam = GetMousewParam (0);
3241 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3242 break;
3245 if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3246 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3247 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3248 msg.wParam = xevent.ClientMessageEvent.ptr3;
3249 msg.lParam = xevent.ClientMessageEvent.ptr4;
3250 break;
3253 #if dontcare
3254 if (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA._XEMBED]) {
3255 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3256 break;
3258 #endif
3260 if (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms [(int)NA.WM_PROTOCOLS]) {
3261 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms [(int)NA.WM_DELETE_WINDOW]) {
3262 msg.message = Msg.WM_CLOSE;
3263 Graphics.FromHdcInternal (IntPtr.Zero);
3264 break;
3267 // We should not get this, but I'll leave the code in case we need it in the future
3268 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms [(int)NA.WM_TAKE_FOCUS]) {
3269 goto ProcessNextMessage;
3272 break;
3275 case XEventName.TimerNotify: {
3276 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3277 break;
3280 default: {
3281 goto ProcessNextMessage;
3285 return true;
3288 internal override bool GetText (IntPtr handle, out string text)
3290 IntPtr textptr;
3292 textptr = IntPtr.Zero;
3294 lock (XlibLock) {
3295 // FIXME - use _NET properties
3296 XFetchName (DisplayHandle, Hwnd.ObjectFromHandle (handle).whole_window, ref textptr);
3298 if (textptr != IntPtr.Zero) {
3299 text = Marshal.PtrToStringAnsi (textptr);
3300 XFree (textptr);
3301 return true;
3302 } else {
3303 text = "";
3304 return false;
3308 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)
3310 Hwnd hwnd;
3311 Rectangle rect;
3313 hwnd = Hwnd.ObjectFromHandle (handle);
3315 if (hwnd != null) {
3316 x = hwnd.x;
3317 y = hwnd.y;
3318 width = hwnd.width;
3319 height = hwnd.height;
3321 rect = Hwnd.GetClientRectangle (hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
3323 client_width = rect.Width;
3324 client_height = rect.Height;
3326 return;
3329 // Should we throw an exception or fail silently?
3330 // throw new ArgumentException("Called with an invalid window handle", "handle");
3332 x = 0;
3333 y = 0;
3334 width = 0;
3335 height = 0;
3336 client_width = 0;
3337 client_height = 0;
3340 internal override FormWindowState GetWindowState (IntPtr handle)
3342 Atom actual_atom;
3343 int actual_format;
3344 int nitems;
3345 int bytes_after;
3346 IntPtr prop = IntPtr.Zero;
3347 IntPtr atom;
3348 int maximized;
3349 bool minimized;
3350 XWindowAttributes attributes;
3351 Hwnd hwnd;
3353 hwnd = Hwnd.ObjectFromHandle (handle);
3355 maximized = 0;
3356 minimized = false;
3357 XGetWindowProperty (DisplayHandle, hwnd.whole_window, NetAtoms [(int)NA._NET_WM_STATE], 0, 256, false, Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3358 if ((nitems > 0) && (prop != IntPtr.Zero)) {
3359 for (int i = 0; i < nitems; i++) {
3360 atom = (IntPtr)Marshal.ReadInt32 (prop, i * 4);
3361 if ((atom == (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
3362 maximized++;
3363 } else if (atom == (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_HIDDEN]) {
3364 minimized = true;
3367 XFree (prop);
3370 if (minimized) {
3371 return FormWindowState.Minimized;
3372 } else if (maximized == 2) {
3373 return FormWindowState.Maximized;
3376 attributes = new XWindowAttributes ();
3377 XGetWindowAttributes (DisplayHandle, handle, ref attributes);
3378 if (attributes.map_state == MapState.IsUnmapped) {
3379 throw new NotSupportedException ("Cannot retrieve the state of an unmapped window");
3383 return FormWindowState.Normal;
3386 internal override void GrabInfo (out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea)
3388 handle = Grab.Hwnd;
3389 GrabConfined = Grab.Confined;
3390 GrabArea = Grab.Area;
3393 internal override void GrabWindow (IntPtr handle, IntPtr confine_to_handle)
3395 Hwnd hwnd;
3396 IntPtr confine_to_window;
3398 confine_to_window = IntPtr.Zero;
3400 if (confine_to_handle != IntPtr.Zero) {
3401 XWindowAttributes attributes = new XWindowAttributes ();
3403 hwnd = Hwnd.ObjectFromHandle (confine_to_handle);
3405 lock (XlibLock) {
3406 XGetWindowAttributes (DisplayHandle, hwnd.client_window, ref attributes);
3408 Grab.Area.X = attributes.x;
3409 Grab.Area.Y = attributes.y;
3410 Grab.Area.Width = attributes.width;
3411 Grab.Area.Height = attributes.height;
3412 Grab.Confined = true;
3413 confine_to_window = hwnd.client_window;
3416 Grab.Hwnd = handle;
3418 hwnd = Hwnd.ObjectFromHandle (handle);
3420 lock (XlibLock) {
3421 XGrabPointer (DisplayHandle, hwnd.client_window, false,
3422 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3423 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3424 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, 0, 0);
3428 internal override void UngrabWindow (IntPtr hwnd)
3430 lock (XlibLock) {
3431 XUngrabPointer (DisplayHandle, 0);
3432 XFlush (DisplayHandle);
3434 Grab.Hwnd = IntPtr.Zero;
3435 Grab.Confined = false;
3438 internal override void HandleException (Exception e)
3440 StackTrace st = new StackTrace (e, true);
3441 Console.WriteLine ("Exception '{0}'", e.Message + st.ToString ());
3442 Console.WriteLine ("{0}{1}", e.Message, st.ToString ());
3445 internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear)
3447 Hwnd hwnd;
3448 XEvent xevent;
3450 hwnd = Hwnd.ObjectFromHandle (handle);
3453 xevent = new XEvent ();
3454 xevent.type = XEventName.Expose;
3455 xevent.ExposeEvent.display = DisplayHandle;
3456 xevent.ExposeEvent.window = hwnd.client_window;
3458 if (clear) {
3459 xevent.ExposeEvent.x = hwnd.X;
3460 xevent.ExposeEvent.y = hwnd.Y;
3461 xevent.ExposeEvent.width = hwnd.Width;
3462 xevent.ExposeEvent.height = hwnd.Height;
3463 } else {
3464 xevent.ExposeEvent.x = rc.X;
3465 xevent.ExposeEvent.y = rc.Y;
3466 xevent.ExposeEvent.width = rc.Width;
3467 xevent.ExposeEvent.height = rc.Height;
3470 AddExpose (xevent);
3473 internal override bool IsEnabled (IntPtr handle)
3475 return Hwnd.ObjectFromHandle (handle).Enabled;
3478 internal override bool IsVisible (IntPtr handle)
3480 return Hwnd.ObjectFromHandle (handle).visible;
3483 internal override void KillTimer (Timer timer)
3485 lock (TimerList) {
3486 TimerList.Remove (timer);
3490 internal override void MenuToScreen (IntPtr handle, ref int x, ref int y)
3492 int dest_x_return;
3493 int dest_y_return;
3494 IntPtr child;
3495 Hwnd hwnd;
3497 hwnd = Hwnd.ObjectFromHandle (handle);
3499 lock (XlibLock) {
3500 XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3503 x = dest_x_return;
3504 y = dest_y_return;
3507 internal override void OverrideCursor (IntPtr cursor)
3509 OverrideCursorHandle = cursor;
3512 internal override PaintEventArgs PaintEventStart (IntPtr handle, bool client)
3514 PaintEventArgs paint_event;
3515 Hwnd hwnd;
3517 hwnd = Hwnd.ObjectFromHandle (handle);
3519 if (Caret.Visible == 1) {
3520 Caret.Paused = true;
3521 HideCaret ();
3524 if (client) {
3525 // handle backing store
3526 IntPtr gdk_window = gdk_window_lookup (hwnd.client_window);
3527 IntPtr gdk_pixmap = NewPixmap (gdk_window, hwnd.ClientRect.Width, hwnd.ClientRect.Height);
3529 backing_store [gdk_window] = gdk_pixmap;
3531 hwnd.client_dc = Graphics.FromHwnd (gdk_x11_drawable_get_xid (gdk_pixmap));
3532 hwnd.client_dc.SetClip (hwnd.invalid);
3533 paint_event = new PaintEventArgs (hwnd.client_dc, hwnd.invalid);
3534 hwnd.expose_pending = false;
3536 return paint_event;
3537 } else {
3538 hwnd.client_dc = Graphics.FromHwnd (hwnd.whole_window);
3539 paint_event = new PaintEventArgs (hwnd.client_dc, new Rectangle (0, 0, hwnd.width, hwnd.height));
3540 hwnd.nc_expose_pending = false;
3542 return paint_event;
3546 internal override void PaintEventEnd (IntPtr handle, bool client)
3548 Hwnd hwnd;
3550 hwnd = Hwnd.ObjectFromHandle (handle);
3552 hwnd.client_dc.Flush ();
3554 if (client) {
3555 // clients are already drawn to a backing store pixmap
3556 IntPtr gdk_window = gdk_window_lookup (hwnd.client_window);
3557 IntPtr gdk_pixmap = (IntPtr)backing_store [gdk_window];
3559 BlitOffscreenPixmap (gdk_pixmap, gdk_window, hwnd.Invalid);
3561 g_object_unref (gdk_pixmap);
3562 backing_store.Remove (gdk_pixmap);
3564 hwnd.ClearInvalidArea ();
3567 hwnd.client_dc.Dispose ();
3568 hwnd.client_dc = null;
3570 if (Caret.Visible == 1) {
3571 ShowCaret ();
3572 Caret.Paused = false;
3576 internal override bool PeekMessage (ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags)
3578 bool pending;
3580 // FIXME - imlement filtering
3582 if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3583 throw new NotImplementedException ("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
3586 pending = false;
3587 if (MessageQueue.Count > 0) {
3588 pending = true;
3589 } else {
3590 // Only call UpdateMessageQueue if real events are pending
3591 // otherwise we go to sleep on the socket
3592 if (XPending (DisplayHandle) != 0) {
3593 UpdateMessageQueue ();
3594 pending = true;
3598 CheckTimers (DateTime.Now);
3600 if (!pending) {
3601 return false;
3603 return GetMessage (ref msg, hWnd, wFilterMin, wFilterMax);
3606 // FIXME - I think this should just enqueue directly
3607 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam)
3609 XEvent xevent = new XEvent ();
3610 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3612 xevent.type = XEventName.ClientMessage;
3613 xevent.ClientMessageEvent.display = DisplayHandle;
3615 if (hwnd != null) {
3616 xevent.ClientMessageEvent.window = hwnd.whole_window;
3617 } else {
3618 xevent.ClientMessageEvent.window = IntPtr.Zero;
3621 xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
3622 xevent.ClientMessageEvent.format = 32;
3623 xevent.ClientMessageEvent.ptr1 = handle;
3624 xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
3625 xevent.ClientMessageEvent.ptr3 = wparam;
3626 xevent.ClientMessageEvent.ptr4 = lparam;
3628 MessageQueue.Enqueue (xevent);
3630 return true;
3633 internal override void PostQuitMessage (int exitCode)
3635 XFlush (DisplayHandle);
3636 PostQuitState = true;
3638 // Remove our display handle from S.D
3639 Graphics.FromHdcInternal (IntPtr.Zero);
3642 internal override void ScreenToClient (IntPtr handle, ref int x, ref int y)
3644 int dest_x_return;
3645 int dest_y_return;
3646 IntPtr child;
3647 Hwnd hwnd;
3649 hwnd = Hwnd.ObjectFromHandle (handle);
3651 lock (XlibLock) {
3652 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
3655 x = dest_x_return;
3656 y = dest_y_return;
3659 internal override void ScreenToMenu (IntPtr handle, ref int x, ref int y)
3661 int dest_x_return;
3662 int dest_y_return;
3663 IntPtr child;
3664 Hwnd hwnd;
3666 hwnd = Hwnd.ObjectFromHandle (handle);
3668 lock (XlibLock) {
3669 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
3672 x = dest_x_return;
3673 y = dest_y_return;
3676 internal override void ScrollWindow (IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children)
3678 Hwnd hwnd;
3679 IntPtr gc;
3680 XGCValues gc_values;
3682 hwnd = Hwnd.ObjectFromHandle (handle);
3684 if (hwnd.invalid != Rectangle.Empty) {
3685 // BIG FAT WARNING. This only works with how we use this function right now
3686 // where we basically still scroll the whole window, but work around areas
3687 // that are covered by our children
3689 hwnd.invalid.X += XAmount;
3690 hwnd.invalid.Y += YAmount;
3692 if (hwnd.invalid.X < 0) {
3693 hwnd.invalid.Width += hwnd.invalid.X;
3694 hwnd.invalid.X = 0;
3697 if (hwnd.invalid.Y < 0) {
3698 hwnd.invalid.Height += hwnd.invalid.Y;
3699 hwnd.invalid.Y = 0;
3703 gc_values = new XGCValues ();
3705 if (with_children) {
3706 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3709 gc = XCreateGC (DisplayHandle, hwnd.client_window, 0, ref gc_values);
3711 XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
3713 // Generate an expose for the area exposed by the horizontal scroll
3714 if (XAmount > 0) {
3715 hwnd.AddInvalidArea (area.X, area.Y, XAmount, area.Height);
3716 } else if (XAmount < 0) {
3717 hwnd.AddInvalidArea (XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
3720 // Generate an expose for the area exposed by the vertical scroll
3721 if (YAmount > 0) {
3722 hwnd.AddInvalidArea (area.X, area.Y, area.Width, YAmount);
3723 } else if (YAmount < 0) {
3724 hwnd.AddInvalidArea (area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
3726 XFreeGC (DisplayHandle, gc);
3728 UpdateWindow (handle);
3731 internal override void ScrollWindow (IntPtr handle, int XAmount, int YAmount, bool with_children)
3733 Hwnd hwnd;
3735 hwnd = Hwnd.GetObjectFromWindow (handle);
3737 ScrollWindow (handle, hwnd.ClientRect, XAmount, YAmount, with_children);
3740 internal override void SendAsyncMethod (AsyncMethodData method)
3742 XEvent xevent = new XEvent ();
3744 xevent.type = XEventName.ClientMessage;
3745 xevent.ClientMessageEvent.display = DisplayHandle;
3746 xevent.ClientMessageEvent.window = FosterParent;
3747 xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
3748 xevent.ClientMessageEvent.format = 32;
3749 xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
3751 MessageQueue.EnqueueLocked (xevent);
3753 WakeupMain ();
3756 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
3758 return NativeWindow.WndProc (hwnd, message, wParam, lParam);
3761 internal override void SetAllowDrop (IntPtr handle, bool value)
3763 // We allow drop on all windows
3766 internal override DragDropEffects StartDrag (IntPtr handle, object data,
3767 DragDropEffects allowed_effects)
3769 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3771 if (hwnd == null)
3772 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
3774 return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
3777 internal override void SetBorderStyle (IntPtr handle, FormBorderStyle border_style)
3779 Hwnd hwnd;
3781 hwnd = Hwnd.ObjectFromHandle (handle);
3783 hwnd.border_style = border_style;
3785 XMoveResizeWindow (DisplayHandle, hwnd.client_window, hwnd.ClientRect.X, hwnd.ClientRect.Y, hwnd.ClientRect.Width, hwnd.ClientRect.Height);
3787 InvalidateWholeWindow (handle);
3790 internal override void SetCaretPos (IntPtr handle, int x, int y)
3792 if (Caret.Hwnd == handle) {
3793 Caret.Timer.Stop ();
3794 HideCaret ();
3796 Caret.X = x;
3797 Caret.Y = y;
3799 if (Caret.Visible == 1) {
3800 ShowCaret ();
3801 Caret.Timer.Start ();
3806 internal override void SetCursor (IntPtr handle, IntPtr cursor)
3808 Hwnd hwnd;
3810 if (OverrideCursorHandle == IntPtr.Zero) {
3811 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
3812 return;
3815 LastCursorHandle = cursor;
3816 LastCursorWindow = handle;
3818 hwnd = Hwnd.ObjectFromHandle (handle);
3819 lock (XlibLock) {
3820 if (cursor != IntPtr.Zero) {
3821 XDefineCursor (DisplayHandle, hwnd.whole_window, cursor);
3822 } else {
3823 XUndefineCursor (DisplayHandle, hwnd.whole_window);
3826 return;
3829 hwnd = Hwnd.ObjectFromHandle (handle);
3830 lock (XlibLock) {
3831 XDefineCursor (DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
3835 internal override void SetCursorPos (IntPtr handle, int x, int y)
3837 if (handle == IntPtr.Zero) {
3838 lock (XlibLock) {
3839 XWarpPointer (DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x, y);
3841 return;
3842 } else {
3843 Hwnd hwnd;
3845 hwnd = Hwnd.ObjectFromHandle (handle);
3846 lock (XlibLock) {
3847 XWarpPointer (DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
3849 return;
3853 internal override void SetFocus (IntPtr handle)
3855 Hwnd hwnd;
3857 hwnd = Hwnd.ObjectFromHandle (handle);
3859 if (FocusWindow != IntPtr.Zero) {
3860 PostMessage (FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
3862 PostMessage (hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
3863 FocusWindow = hwnd.client_window;
3865 //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
3868 internal override void SetIcon (IntPtr handle, Icon icon)
3870 Hwnd hwnd;
3872 hwnd = Hwnd.ObjectFromHandle (handle);
3873 if (hwnd != null) {
3874 SetIcon (hwnd, icon);
3878 internal override void SetMenu (IntPtr handle, Menu menu)
3880 Hwnd hwnd;
3882 hwnd = Hwnd.ObjectFromHandle (handle);
3883 hwnd.menu = menu;
3885 // FIXME - do we need to trigger some resize?
3888 internal override void SetModal (IntPtr handle, bool Modal)
3890 if (Modal) {
3891 ModalWindows.Push (handle);
3892 } else {
3893 if (ModalWindows.Contains (handle)) {
3894 ModalWindows.Pop ();
3896 if (ModalWindows.Count > 0) {
3897 Activate ((IntPtr)ModalWindows.Peek ());
3902 internal override IntPtr SetParent (IntPtr handle, IntPtr parent)
3904 Hwnd hwnd;
3906 hwnd = Hwnd.ObjectFromHandle (handle);
3907 hwnd.parent = Hwnd.ObjectFromHandle (parent);
3909 lock (XlibLock) {
3910 #if DriverDebug
3911 Console.WriteLine("Parent for window {0:X} / {1:X} = {2:X} (Handle:{3:X})", hwnd.ClientWindow.ToInt32(), hwnd.WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, parent.ToInt32());
3912 #endif
3913 XReparentWindow (DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
3916 return IntPtr.Zero;
3919 internal override void SetTimer (Timer timer)
3921 lock (TimerList) {
3922 TimerList.Add (timer);
3924 WakeupMain ();
3927 internal override bool SetTopmost (IntPtr handle, IntPtr handle_owner, bool enabled)
3929 Hwnd hwnd;
3930 Hwnd hwnd_owner;
3932 hwnd = Hwnd.ObjectFromHandle (handle);
3934 if (handle_owner != IntPtr.Zero) {
3935 hwnd_owner = Hwnd.ObjectFromHandle (handle_owner);
3936 } else {
3937 hwnd_owner = null;
3940 if (enabled) {
3941 lock (XlibLock) {
3942 if (hwnd_owner != null) {
3943 XSetTransientForHint (DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
3944 } else {
3945 XSetTransientForHint (DisplayHandle, hwnd.whole_window, FosterParent);
3948 } else {
3949 lock (XlibLock) {
3950 XDeleteProperty (DisplayHandle, hwnd.whole_window, (int)Atom.XA_WM_TRANSIENT_FOR);
3953 return true;
3956 internal override bool SetVisible (IntPtr handle, bool visible)
3958 Hwnd hwnd;
3960 hwnd = Hwnd.ObjectFromHandle (handle);
3961 hwnd.visible = visible;
3963 lock (XlibLock) {
3964 if (visible) {
3965 if (Control.FromHandle (handle) is Form) {
3966 FormWindowState s;
3968 s = ((Form)Control.FromHandle (handle)).WindowState;
3970 XMapWindow (DisplayHandle, hwnd.whole_window);
3971 XMapWindow (DisplayHandle, hwnd.client_window);
3973 switch (s) {
3974 case FormWindowState.Minimized: SetWindowState (handle, FormWindowState.Minimized); break;
3975 case FormWindowState.Maximized: SetWindowState (handle, FormWindowState.Maximized); break;
3977 } else {
3978 XMapWindow (DisplayHandle, hwnd.whole_window);
3979 XMapWindow (DisplayHandle, hwnd.client_window);
3981 } else {
3982 XUnmapWindow (DisplayHandle, hwnd.whole_window);
3985 return true;
3988 internal override void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max)
3990 Hwnd hwnd;
3991 XSizeHints hints;
3993 hwnd = Hwnd.ObjectFromHandle (handle);
3994 if (hwnd == null) {
3995 return;
3998 hints = new XSizeHints ();
4000 if (min != Size.Empty) {
4001 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4002 hints.min_width = min.Width;
4003 hints.min_height = min.Height;
4006 if (max != Size.Empty) {
4007 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4008 hints.max_width = max.Width;
4009 hints.max_height = max.Height;
4012 XSetWMNormalHints (DisplayHandle, hwnd.whole_window, ref hints);
4014 if (maximized != Rectangle.Empty) {
4015 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4016 hints.x = maximized.X;
4017 hints.y = maximized.Y;
4018 hints.width = maximized.Width;
4019 hints.height = maximized.Height;
4021 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4022 XSetZoomHints (DisplayHandle, hwnd.whole_window, ref hints);
4027 internal override void SetWindowPos (IntPtr handle, int x, int y, int width, int height)
4029 Hwnd hwnd;
4030 Rectangle client_rect;
4032 hwnd = Hwnd.ObjectFromHandle (handle);
4034 // X requires a sanity check for width & height; otherwise it dies
4035 if (hwnd.zero_sized && width > 0 && height > 0) {
4036 if (hwnd.visible) {
4037 XMapWindow (DisplayHandle, hwnd.whole_window);
4039 hwnd.zero_sized = false;
4042 if (width < 1) {
4043 hwnd.zero_sized = true;
4044 XUnmapWindow (DisplayHandle, hwnd.whole_window);
4047 if (height < 1) {
4048 hwnd.zero_sized = true;
4049 XUnmapWindow (DisplayHandle, hwnd.whole_window);
4052 client_rect = Hwnd.GetClientRectangle (hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
4054 // Save a server roundtrip (and prevent a feedback loop)
4055 if ((hwnd.x == x) && (hwnd.y == y) &&
4056 (hwnd.width == width) && (hwnd.height == height) &&
4057 (hwnd.ClientRect == client_rect)) {
4058 return;
4061 if (!hwnd.zero_sized) {
4062 lock (XlibLock) {
4063 XMoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, width, height);
4064 XMoveResizeWindow (DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
4068 // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
4069 hwnd.width = width;
4070 hwnd.height = height;
4073 internal override void SetWindowState (IntPtr handle, FormWindowState state)
4075 FormWindowState current_state;
4076 Hwnd hwnd;
4078 hwnd = Hwnd.ObjectFromHandle (handle);
4080 current_state = GetWindowState (handle);
4082 if (current_state == state) {
4083 return;
4086 switch (state) {
4087 case FormWindowState.Normal: {
4088 lock (XlibLock) {
4089 if (current_state == FormWindowState.Minimized) {
4090 XMapWindow (DisplayHandle, hwnd.whole_window);
4091 XMapWindow (DisplayHandle, hwnd.client_window);
4092 } else if (current_state == FormWindowState.Maximized) {
4093 SendNetWMMessage (hwnd.whole_window, (IntPtr)(uint)NetAtoms [(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4096 Activate (handle);
4097 return;
4100 case FormWindowState.Minimized: {
4101 lock (XlibLock) {
4102 if (current_state == FormWindowState.Maximized) {
4103 SendNetWMMessage (hwnd.whole_window, (IntPtr)NetAtoms [(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4105 XIconifyWindow (DisplayHandle, hwnd.whole_window, ScreenNo);
4107 return;
4110 case FormWindowState.Maximized: {
4111 lock (XlibLock) {
4112 if (current_state == FormWindowState.Minimized) {
4113 XMapWindow (DisplayHandle, hwnd.whole_window);
4114 XMapWindow (DisplayHandle, hwnd.client_window);
4117 SendNetWMMessage (hwnd.whole_window, (IntPtr)NetAtoms [(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
4119 Activate (handle);
4120 return;
4125 internal override void SetWindowStyle (IntPtr handle, CreateParams cp)
4127 Hwnd hwnd;
4129 hwnd = Hwnd.ObjectFromHandle (handle);
4130 SetHwndStyles (hwnd, cp);
4131 SetWMStyles (hwnd, cp);
4134 internal override void SetWindowTransparency (IntPtr handle, double transparency, Color key)
4136 Hwnd hwnd;
4137 uint opacity;
4139 hwnd = Hwnd.ObjectFromHandle (handle);
4141 if (hwnd == null) {
4142 return;
4145 hwnd.opacity = (uint)(0xffffffff * transparency);
4146 opacity = hwnd.opacity;
4148 if (hwnd.reparented) {
4149 XChangeProperty (DisplayHandle, XGetParent (hwnd.whole_window), NetAtoms [(int)NA._NET_WM_WINDOW_OPACITY], Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4153 internal override bool SetZOrder (IntPtr handle, IntPtr after_handle, bool top, bool bottom)
4155 Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4157 if (top) {
4158 lock (XlibLock) {
4159 XRaiseWindow (DisplayHandle, hwnd.whole_window);
4161 return true;
4162 } else if (!bottom) {
4163 Hwnd after_hwnd = null;
4165 if (after_handle != IntPtr.Zero) {
4166 after_hwnd = Hwnd.ObjectFromHandle (after_handle);
4169 XWindowChanges values = new XWindowChanges ();
4171 if (after_hwnd == null) {
4172 throw new ArgumentNullException ("after_handle", "Need sibling to adjust z-order");
4174 values.sibling = after_hwnd.whole_window;
4175 values.stack_mode = StackMode.Below;
4177 lock (XlibLock) {
4178 XConfigureWindow (DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4180 } else {
4181 // Bottom
4182 lock (XlibLock) {
4183 XLowerWindow (DisplayHandle, hwnd.whole_window);
4185 return true;
4187 return false;
4190 internal override void ShowCursor (bool show)
4192 ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4195 internal override void StartLoop (Thread thread)
4197 // Future place for prepping a new queue for this specific thread
4200 internal override bool SupportsTransparency ()
4202 // We need to check if the x compositing manager is running
4203 return true;
4206 internal override bool SystrayAdd (IntPtr handle, string tip, Icon icon, out ToolTip tt)
4208 GetSystrayManagerWindow ();
4210 if (SystrayMgrWindow != IntPtr.Zero) {
4211 uint[] atoms;
4212 XSizeHints size_hints;
4213 Hwnd hwnd;
4215 hwnd = Hwnd.ObjectFromHandle (handle);
4216 #if DriverDebug
4217 Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4218 #endif
4220 XUnmapWindow (DisplayHandle, hwnd.whole_window);
4221 XUnmapWindow (DisplayHandle, hwnd.client_window);
4223 // Oh boy.
4224 gdk_window_destroy (gdk_window_lookup (hwnd.client_window));
4225 hwnd.client_window = hwnd.whole_window;
4227 size_hints = new XSizeHints ();
4229 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4230 size_hints.min_width = icon.Width;
4231 size_hints.min_height = icon.Height;
4233 size_hints.max_width = icon.Width;
4234 size_hints.max_height = icon.Height;
4236 size_hints.base_width = icon.Width;
4237 size_hints.base_height = icon.Height;
4238 XSetWMNormalHints (DisplayHandle, hwnd.whole_window, ref size_hints);
4240 atoms = new uint [2];
4241 atoms [0] = 1; // Version 1
4242 atoms [1] = 0; // We're not mapped
4244 // This line cost me 3 days...
4245 XChangeProperty (DisplayHandle, hwnd.whole_window, NetAtoms [(int)NA._XEMBED_INFO], NetAtoms [(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
4247 // Need to pick some reasonable defaults
4248 tt = new ToolTip ();
4249 tt.AutomaticDelay = 100;
4250 tt.InitialDelay = 250;
4251 tt.ReshowDelay = 250;
4252 tt.ShowAlways = true;
4254 if ((tip != null) && (tip != string.Empty)) {
4255 tt.SetToolTip (Control.FromHandle (handle), tip);
4256 tt.Active = true;
4257 } else {
4258 tt.Active = false;
4261 // Make sure the window exists
4262 XSync (DisplayHandle, hwnd.whole_window);
4264 SendNetClientMessage (SystrayMgrWindow, (IntPtr)NetAtoms [(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4265 return true;
4268 tt = null;
4269 return false;
4272 internal override bool SystrayChange (IntPtr handle, string tip, Icon icon, ref ToolTip tt)
4274 Control control;
4276 control = Control.FromHandle (handle);
4277 if (control != null && tt != null) {
4278 tt.SetToolTip (control, tip);
4279 tt.Active = true;
4280 return true;
4281 } else {
4282 return false;
4286 internal override void SystrayRemove (IntPtr handle, ref ToolTip tt)
4288 Hwnd hwnd;
4290 hwnd = Hwnd.ObjectFromHandle (handle);
4292 XUnmapWindow (DisplayHandle, hwnd.whole_window);
4293 SetParent (hwnd.whole_window, FosterParent);
4295 // The caller can now re-dock it later...
4296 if (tt != null) {
4297 tt.Dispose ();
4298 tt = null;
4302 internal override bool Text (IntPtr handle, string text)
4304 lock (XlibLock) {
4305 gdk_window_set_title (gdk_window_lookup (Hwnd.ObjectFromHandle (handle).whole_window), text);
4307 return true;
4310 internal override bool TranslateMessage (ref MSG msg)
4312 return Keyboard.TranslateMessage (ref msg);
4315 internal override void UpdateWindow (IntPtr handle)
4317 XEvent xevent;
4318 Hwnd hwnd;
4320 hwnd = Hwnd.ObjectFromHandle (handle);
4322 if (!hwnd.visible || hwnd.expose_pending) {
4323 return;
4326 #if not
4327 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4328 #else
4329 xevent = new XEvent ();
4330 xevent.type = XEventName.Expose;
4331 xevent.ExposeEvent.display = DisplayHandle;
4332 xevent.ExposeEvent.window = hwnd.client_window;
4334 MessageQueue.Enqueue (xevent);
4335 hwnd.expose_pending = true;
4336 #endif
4339 internal static IntPtr NewPixmap (IntPtr gdk_window, int width, int height)
4341 return gdk_pixmap_new (gdk_window, width, height, 24); // FIXME: instead of 24, get the correct display depth
4344 internal static void BlitOffscreenPixmap (IntPtr gdk_pixmap, IntPtr dest_drawable, Rectangle area)
4346 IntPtr gdk_gc = gdk_gc_new (gdk_pixmap);
4348 gdk_draw_drawable (dest_drawable, gdk_gc, gdk_pixmap, area.X, area.Y, area.X, area.Y, area.Width, area.Height);
4350 g_object_unref (gdk_gc);
4352 #endregion // Public Static Methods
4354 #region Events
4355 internal override event EventHandler Idle;
4356 #endregion // Events
4358 #region X11 Imports
4359 [DllImport ("libX11", EntryPoint="XSynchronize")]
4360 internal extern static IntPtr XSynchronize (IntPtr display, bool onoff);
4362 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4363 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, SetWindowValuemask valuemask, ref XSetWindowAttributes attributes);
4364 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4365 internal extern static IntPtr XCreateSimpleWindow (IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
4366 [DllImport ("libX11", EntryPoint="XMapWindow")]
4367 internal extern static int XMapWindow (IntPtr display, IntPtr window);
4368 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4369 internal extern static int XUnmapWindow (IntPtr display, IntPtr window);
4370 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4371 internal extern static int XMapSubindows (IntPtr display, IntPtr window);
4372 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4373 internal extern static int XUnmapSubwindows (IntPtr display, IntPtr window);
4374 [DllImport ("libX11", EntryPoint="XRootWindow")]
4375 internal extern static IntPtr XRootWindow (IntPtr display, int screen_number);
4376 [DllImport ("libX11", EntryPoint="XNextEvent")]
4377 internal extern static IntPtr XNextEvent (IntPtr display, ref XEvent xevent);
4378 [DllImport ("libX11")]
4379 internal extern static int XConnectionNumber (IntPtr diplay);
4380 [DllImport ("libX11")]
4381 internal extern static int XPending (IntPtr diplay);
4382 [DllImport ("libX11")]
4383 internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
4384 [DllImport ("libX11")]
4385 internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
4386 [DllImport ("libX11", EntryPoint="XSelectInput")]
4387 internal extern static IntPtr XSelectInput (IntPtr display, IntPtr window, EventMask mask);
4389 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4390 internal extern static int XReparentWindow (IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4391 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4392 internal extern static int XMoveResizeWindow (IntPtr display, IntPtr window, int x, int y, int width, int height);
4394 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4395 internal extern static int XResizeWindow (IntPtr display, IntPtr window, int width, int height);
4397 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4398 internal extern static int XGetWindowAttributes (IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4400 [DllImport ("libX11", EntryPoint="XFlush")]
4401 internal extern static int XFlush (IntPtr display);
4403 [DllImport ("libX11", EntryPoint="XSetWMName")]
4404 internal extern static int XSetWMName (IntPtr display, IntPtr window, ref XTextProperty text_prop);
4406 [DllImport ("libX11", EntryPoint="XStoreName")]
4407 internal extern static int XStoreName (IntPtr display, IntPtr window, string window_name);
4409 [DllImport ("libX11", EntryPoint="XFetchName")]
4410 internal extern static int XFetchName (IntPtr display, IntPtr window, ref IntPtr window_name);
4412 [DllImport ("libX11", EntryPoint="XSendEvent")]
4413 internal extern static int XSendEvent (IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
4415 [DllImport ("libX11", EntryPoint="XQueryTree")]
4416 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);
4418 [DllImport ("libX11", EntryPoint="XFree")]
4419 internal extern static int XFree (IntPtr data);
4421 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
4422 internal extern static int XRaiseWindow (IntPtr display, IntPtr window);
4424 [DllImport ("libX11", EntryPoint="XLowerWindow")]
4425 internal extern static uint XLowerWindow (IntPtr display, IntPtr window);
4427 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
4428 internal extern static uint XConfigureWindow (IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
4430 [DllImport ("libX11", EntryPoint="XInternAtom")]
4431 internal extern static int XInternAtom (IntPtr display, string atom_name, bool only_if_exists);
4433 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
4434 internal extern static int XSetWMProtocols (IntPtr display, IntPtr window, uint[] protocols, int count);
4436 [DllImport ("libX11", EntryPoint="XGrabPointer")]
4437 internal extern static int XGrabPointer (IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, uint cursor, uint timestamp);
4439 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
4440 internal extern static int XUngrabPointer (IntPtr display, uint timestamp);
4442 [DllImport ("libX11", EntryPoint="XQueryPointer")]
4443 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);
4445 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
4446 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);
4448 [DllImport ("libX11", EntryPoint="XWarpPointer")]
4449 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);
4451 [DllImport ("libX11", EntryPoint="XClearWindow")]
4452 internal extern static int XClearWindow (IntPtr display, IntPtr window);
4454 [DllImport ("libX11", EntryPoint="XClearArea")]
4455 internal extern static int XClearArea (IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
4457 // Colormaps
4458 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
4459 internal extern static IntPtr XDefaultScreenOfDisplay (IntPtr display);
4461 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
4462 internal extern static int XScreenNumberOfScreen (IntPtr display, IntPtr Screen);
4464 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
4465 internal extern static IntPtr XDefaultVisual (IntPtr display, int screen_number);
4467 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
4468 internal extern static uint XDefaultDepth (IntPtr display, int screen_number);
4470 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
4471 internal extern static IntPtr XDefaultColormap (IntPtr display, int screen_number);
4473 [DllImport ("libX11", EntryPoint="XLookupColor")]
4474 internal extern static int XLookupColor (IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
4476 [DllImport ("libX11", EntryPoint="XAllocColor")]
4477 internal extern static int XAllocColor (IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
4479 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
4480 internal extern static int XSetTransientForHint (IntPtr display, IntPtr window, IntPtr prop_window);
4482 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4483 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, int type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
4485 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4486 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode mode, uint[] atoms, int nelements);
4488 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4489 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode mode, ref uint value, int nelements);
4491 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4492 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, int format, int type, PropertyMode mode, uint[] atoms, int nelements);
4494 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4495 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, int format, int type, PropertyMode mode, IntPtr atoms, int nelements);
4497 [DllImport ("libX11", EntryPoint="XChangeProperty")]
4498 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode mode, IntPtr atoms, int nelements);
4500 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
4501 internal extern static int XChangeProperty (IntPtr display, IntPtr window, int property, int type, int format, PropertyMode mode, string text, int text_length);
4503 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
4504 internal extern static int XDeleteProperty (IntPtr display, IntPtr window, int property);
4506 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
4507 internal extern static bool GetFontMetrics (IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
4509 // Drawing
4510 [DllImport ("libX11", EntryPoint="XCreateGC")]
4511 internal extern static IntPtr XCreateGC (IntPtr display, IntPtr window, GCFunction valuemask, ref XGCValues values);
4513 [DllImport ("libX11", EntryPoint="XFreeGC")]
4514 internal extern static int XFreeGC (IntPtr display, IntPtr gc);
4516 [DllImport ("libX11", EntryPoint="XSetFunction")]
4517 internal extern static int XSetFunction (IntPtr display, IntPtr gc, GXFunction function);
4519 [DllImport ("libX11", EntryPoint="XDrawLine")]
4520 internal extern static int XDrawLine (IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
4522 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
4523 internal extern static int XDrawRectangle (IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
4525 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
4526 internal extern static int XSetWindowBackground (IntPtr display, IntPtr window, IntPtr background);
4528 [DllImport ("libX11", EntryPoint="XCopyArea")]
4529 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);
4531 [DllImport ("libX11", EntryPoint="XGetAtomName")]
4532 internal extern static string XGetAtomName (IntPtr display, int atom);
4534 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
4535 internal extern static int XGetWindowProperty (IntPtr display, IntPtr window, int atom, int long_offset, int long_length, bool delete, Atom req_type, out Atom actual_type, out int actual_format, out int nitems, out int bytes_after, ref IntPtr prop);
4537 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
4538 internal extern static int XSetInputFocus (IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
4540 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
4541 internal extern static int XIconifyWindow (IntPtr display, IntPtr window, int screen_number);
4543 [DllImport ("libX11", EntryPoint="XDefineCursor")]
4544 internal extern static int XDefineCursor (IntPtr display, IntPtr window, IntPtr cursor);
4546 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
4547 internal extern static int XUndefineCursor (IntPtr display, IntPtr window);
4549 [DllImport ("libX11", EntryPoint="XFreeCursor")]
4550 internal extern static int XFreeCursor (IntPtr display, IntPtr cursor);
4552 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
4553 internal extern static IntPtr XCreateFontCursor (IntPtr display, CursorFontShape shape);
4555 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
4556 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);
4558 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
4559 internal extern static IntPtr XCreatePixmapFromBitmapData (IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
4561 [DllImport ("libX11", EntryPoint="XFreePixmap")]
4562 internal extern static IntPtr XFreePixmap (IntPtr display, IntPtr pixmap);
4564 [DllImport ("libX11", EntryPoint="XWhitePixel")]
4565 internal extern static IntPtr XWhitePixel (IntPtr display, int screen_no);
4567 [DllImport ("libX11", EntryPoint="XBlackPixel")]
4568 internal extern static IntPtr XBlackPixel (IntPtr display, int screen_no);
4570 [DllImport ("libX11", EntryPoint="XGrabServer")]
4571 internal extern static void XGrabServer (IntPtr display);
4573 [DllImport ("libX11", EntryPoint="XUngrabServer")]
4574 internal extern static void XUngrabServer (IntPtr display);
4576 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
4577 internal extern static void XSetWMNormalHints (IntPtr display, IntPtr window, ref XSizeHints hints);
4579 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
4580 internal extern static void XSetZoomHints (IntPtr display, IntPtr window, ref XSizeHints hints);
4582 [DllImport ("libX11", EntryPoint="XSetWMHints")]
4583 internal extern static void XSetWMHints (IntPtr display, IntPtr window, ref XWMHints wmhints);
4585 [DllImport ("libX11", EntryPoint="XSync")]
4586 internal extern static void XSync (IntPtr display, IntPtr window);
4588 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
4589 internal extern static int XGetIconSizes (IntPtr display, IntPtr window, out IntPtr size_list, out int count);
4591 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
4592 internal extern static IntPtr XSetErrorHandler (XErrorHandler error_handler);
4594 [DllImport ("libX11", EntryPoint="XGetErrorText")]
4595 internal extern static IntPtr XGetErrorText (IntPtr display, byte code, StringBuilder buffer, int length);
4597 [DllImport ("libX11", EntryPoint="XInitThreads")]
4598 internal extern static int XInitThreads ();
4600 [DllImport ("libX11", EntryPoint="XConvertSelection")]
4601 internal extern static int XConvertSelection (IntPtr display, int selection, int target, int property, IntPtr requestor, IntPtr time);
4603 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
4604 internal extern static IntPtr XGetSelectionOwner (IntPtr display, int selection);
4606 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
4607 internal extern static int XSetSelectionOwner (IntPtr display, int selection, IntPtr owner, IntPtr time);
4609 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
4610 internal extern static int XSetPlaneMask (IntPtr display, IntPtr gc, uint mask);
4612 [DllImport ("libX11", EntryPoint="XSetForeground")]
4613 internal extern static int XSetForeground (IntPtr display, IntPtr gc, uint foreground);
4615 [DllImport ("libX11", EntryPoint="XSetBackground")]
4616 internal extern static int XSetBackground (IntPtr display, IntPtr gc, uint background);
4618 #endregion
4620 #region gdk imports
4621 [DllImport("libgdk-x11-2.0.so")]
4622 static extern bool gdk_init_check (IntPtr argc, IntPtr argv);
4624 [DllImport("libgdk-x11-2.0.so")]
4625 internal static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
4627 [DllImport("libgdk-x11-2.0.so")]
4628 internal static extern IntPtr gdk_display_get_default ();
4630 [DllImport("libgdk-x11-2.0.so")]
4631 static extern IntPtr gdk_pixmap_new (IntPtr drawable, int width, int height, int depth);
4633 [DllImport("libgdk-x11-2.0.so")]
4634 static extern IntPtr gdk_x11_drawable_get_xid (IntPtr gdkdrawable);
4636 [DllImport("libgdk-x11-2.0.so")]
4637 static extern void gdk_draw_drawable (IntPtr drawable_dest, IntPtr gdk_gc, IntPtr drawable_src, int xsrc, int ysrc, int xdest, int ydest, int width, int height);
4639 [DllImport("libgdk-x11-2.0.so")]
4640 static extern IntPtr gdk_gc_new (IntPtr drawable);
4642 [DllImport("libgdk-x11-2.0.so")]
4643 static extern IntPtr gdk_window_foreign_new (IntPtr anid);
4645 [DllImport("libgdk-x11-2.0.so")]
4646 static extern IntPtr gdk_x11_lookup_xdisplay (IntPtr xdisplay);
4648 [DllImport("libgdk-x11-2.0.so")]
4649 static extern void gdk_display_close (IntPtr display);
4651 [DllImport("libgdk-x11-2.0.so")]
4652 static extern void gdk_display_beep (IntPtr display);
4654 [DllImport("libgdk-x11-2.0.so")]
4655 static extern void gdk_display_sync (IntPtr display);
4657 [DllImport("libgdk-x11-2.0.so")]
4658 static extern IntPtr gdk_get_default_root_window ();
4660 [DllImport("libgdk-x11-2.0.so")]
4661 static extern IntPtr gdk_colormap_get_system ();
4663 [DllImport("libgdk-x11-2.0.so")]
4664 static extern IntPtr gdk_x11_colormap_get_xcolormap (IntPtr gdk_colormap);
4666 [DllImport("libgdk-x11-2.0.so")]
4667 static extern void gdk_window_destroy (IntPtr gdk_window);
4669 [DllImport("libgdk-x11-2.0.so")]
4670 static extern void gdk_x11_grab_server ();
4672 [DllImport("libgdk-x11-2.0.so")]
4673 static extern void gdk_x11_ungrab_server ();
4675 [DllImport("libgdk-x11-2.0.so")]
4676 static extern void gdk_display_flush (IntPtr gdk_display);
4678 [DllImport("libgdk-x11-2.0.so")]
4679 static extern void gdk_window_iconify (IntPtr gdk_window);
4681 [DllImport("libgdk-x11-2.0.so")]
4682 static extern void gdk_window_deiconify (IntPtr gdk_window);
4684 [DllImport("libgdk-x11-2.0.so")]
4685 static extern void gdk_window_set_decorations (IntPtr gdk_window, int decorations);
4687 [DllImport("libgdk-x11-2.0.so")]
4688 static extern IntPtr gdk_screen_get_default ();
4690 [DllImport("libgdk-x11-2.0.so")]
4691 static extern int gdk_screen_get_number (IntPtr gdk_screen);
4693 [DllImport("libgdk-x11-2.0.so")]
4694 static extern IntPtr gdk_window_lookup (IntPtr anid);
4696 [DllImport("libgdk-x11-2.0.so")]
4697 static extern IntPtr gdk_window_new (IntPtr gdk_parent, ref GdkWindowAttr gdk_window_attributes, int attributes_mask);
4699 [DllImport("libgdk-x11-2.0.so")]
4700 static extern void gdk_window_set_events (IntPtr gdk_window, int event_mask);
4702 [DllImport("libgdk-x11-2.0.so")]
4703 static extern void gdk_window_show (IntPtr window);
4705 [DllImport("libgdk-x11-2.0.so")]
4706 static extern void gdk_window_set_title (IntPtr gdk_window, string title);
4708 [DllImport("libgdk-x11-2.0.so")]
4709 static extern int gdk_window_get_origin (IntPtr gdk_window, out int x, out int y);
4711 [DllImport("libgdk-x11-2.0.so")]
4712 static extern void gdk_window_get_geometry (IntPtr gdk_window, out int x, out int y, out int width, out int height, out int depth);
4714 [DllImport("libgdk-x11-2.0.so")]
4715 static extern void gdk_property_change (IntPtr gdk_window, /*GdkAtom*/IntPtr property, /*GdkAtom*/IntPtr type, int format, int gdk_prop_mode, /*const guchar **/ IntPtr data, int nelements);
4717 [DllImport("libgdk-x11-2.0.so")]
4718 static extern IntPtr gdk_window_get_parent (IntPtr gdk_window);
4720 [DllImport("libgdk-x11-2.0.so")]
4721 static extern void gdk_display_get_maximal_cursor_size (IntPtr gdk_display, out uint width, out uint height);
4723 [DllImport("libgdk-x11-2.0.so")]
4724 static extern int gdk_visual_get_best_depth ();
4725 #endregion
4727 #region gobject imports
4728 [DllImport("libglib-2.0.so")]
4729 static extern void g_free (IntPtr mem);
4731 [DllImport("libgobject-2.0.so")]
4732 static extern void g_object_unref (IntPtr nativeObject);
4733 #endregion