PageRenderTime 82ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 1ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11GTK.cs

https://bitbucket.org/danipen/mono
C# | 4732 lines | 3616 code | 894 blank | 222 comment | 662 complexity | e0883dca3567277fc2ace0937d6d8fd2 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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.
  19. //
  20. // Copyright (c) 2004-2006 Novell, Inc.
  21. //
  22. // Authors:
  23. // Peter Bartok pbartok@novell.com
  24. // Alexander Olk alex.olk@googlemail.com
  25. //
  26. //
  27. // NOTE:
  28. // This driver understands the following environment variables: (Set the var to enable feature)
  29. //
  30. // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
  31. // by default a message is displayed but execution continues
  32. //
  33. // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
  34. // helps in debugging errors
  35. //
  36. // NOT COMPLETE - WORK IN PROGRESS
  37. // One feature of the driver is, that PaintEventstart returns a graphics context created from a offscreen drawable (pixmap)
  38. // define to log Window handles and relationships to stdout
  39. #undef DriverDebug
  40. // Extra detailed debug
  41. #undef DriverDebugExtra
  42. using System;
  43. using System.ComponentModel;
  44. using System.Collections;
  45. using System.Diagnostics;
  46. using System.Drawing;
  47. using System.Drawing.Drawing2D;
  48. using System.Drawing.Imaging;
  49. using System.IO;
  50. using System.Net;
  51. using System.Net.Sockets;
  52. using System.Reflection;
  53. using System.Runtime.InteropServices;
  54. using System.Text;
  55. using System.Threading;
  56. // Only do the poll when building with mono for now
  57. #if __MonoCS__
  58. using Mono.Unix.Native;
  59. #endif
  60. /// X11 Version
  61. namespace System.Windows.Forms {
  62. internal class XplatUIX11GTK : XplatUIDriver {
  63. internal enum GdkWindowClass {
  64. GDK_INPUT_OUTPUT,
  65. GDK_INPUT_ONLY
  66. }
  67. internal enum GdkWindowType {
  68. GDK_WINDOW_ROOT,
  69. GDK_WINDOW_TOPLEVEL,
  70. GDK_WINDOW_CHILD,
  71. GDK_WINDOW_DIALOG,
  72. GDK_WINDOW_TEMP,
  73. GDK_WINDOW_FOREIGN
  74. }
  75. internal enum GdkWindowHints {
  76. GDK_HINT_POS = 1 << 0,
  77. GDK_HINT_MIN_SIZE = 1 << 1,
  78. GDK_HINT_MAX_SIZE = 1 << 2,
  79. GDK_HINT_BASE_SIZE = 1 << 3,
  80. GDK_HINT_ASPECT = 1 << 4,
  81. GDK_HINT_RESIZE_INC = 1 << 5,
  82. GDK_HINT_WIN_GRAVITY = 1 << 6,
  83. GDK_HINT_USER_POS = 1 << 7,
  84. GDK_HINT_USER_SIZE = 1 << 8
  85. }
  86. internal enum GdkGravity {
  87. GDK_GRAVITY_NORTH_WEST = 1,
  88. GDK_GRAVITY_NORTH,
  89. GDK_GRAVITY_NORTH_EAST,
  90. GDK_GRAVITY_WEST,
  91. GDK_GRAVITY_CENTER,
  92. GDK_GRAVITY_EAST,
  93. GDK_GRAVITY_SOUTH_WEST,
  94. GDK_GRAVITY_SOUTH,
  95. GDK_GRAVITY_SOUTH_EAST,
  96. GDK_GRAVITY_STATIC
  97. }
  98. internal enum GdkWindowEdge {
  99. GDK_WINDOW_EDGE_NORTH_WEST,
  100. GDK_WINDOW_EDGE_NORTH,
  101. GDK_WINDOW_EDGE_NORTH_EAST,
  102. GDK_WINDOW_EDGE_WEST,
  103. GDK_WINDOW_EDGE_EAST,
  104. GDK_WINDOW_EDGE_SOUTH_WEST,
  105. GDK_WINDOW_EDGE_SOUTH,
  106. GDK_WINDOW_EDGE_SOUTH_EAST
  107. }
  108. internal enum GdkWindowTypeHint {
  109. GDK_WINDOW_TYPE_HINT_NORMAL,
  110. GDK_WINDOW_TYPE_HINT_DIALOG,
  111. GDK_WINDOW_TYPE_HINT_MENU,
  112. GDK_WINDOW_TYPE_HINT_TOOLBAR,
  113. GDK_WINDOW_TYPE_HINT_SPLASHSCREEN,
  114. GDK_WINDOW_TYPE_HINT_UTILITY,
  115. GDK_WINDOW_TYPE_HINT_DOCK,
  116. GDK_WINDOW_TYPE_HINT_DESKTOP
  117. }
  118. internal enum GdkWindowAttributesType {
  119. GDK_WA_TITLE = 1 << 1,
  120. GDK_WA_X = 1 << 2,
  121. GDK_WA_Y = 1 << 3,
  122. GDK_WA_CURSOR = 1 << 4,
  123. GDK_WA_COLORMAP = 1 << 5,
  124. GDK_WA_VISUAL = 1 << 6,
  125. GDK_WA_WMCLASS = 1 << 7,
  126. GDK_WA_NOREDIR = 1 << 8
  127. }
  128. internal enum GdkEventMask {
  129. GDK_EXPOSURE_MASK = 1 << 1,
  130. GDK_POINTER_MOTION_MASK = 1 << 2,
  131. GDK_POINTER_MOTION_HINT_MASK = 1 << 3,
  132. GDK_BUTTON_MOTION_MASK = 1 << 4,
  133. GDK_BUTTON1_MOTION_MASK = 1 << 5,
  134. GDK_BUTTON2_MOTION_MASK = 1 << 6,
  135. GDK_BUTTON3_MOTION_MASK = 1 << 7,
  136. GDK_BUTTON_PRESS_MASK = 1 << 8,
  137. GDK_BUTTON_RELEASE_MASK = 1 << 9,
  138. GDK_KEY_PRESS_MASK = 1 << 10,
  139. GDK_KEY_RELEASE_MASK = 1 << 11,
  140. GDK_ENTER_NOTIFY_MASK = 1 << 12,
  141. GDK_LEAVE_NOTIFY_MASK = 1 << 13,
  142. GDK_FOCUS_CHANGE_MASK = 1 << 14,
  143. GDK_STRUCTURE_MASK = 1 << 15,
  144. GDK_PROPERTY_CHANGE_MASK = 1 << 16,
  145. GDK_VISIBILITY_NOTIFY_MASK = 1 << 17,
  146. GDK_PROXIMITY_IN_MASK = 1 << 18,
  147. GDK_PROXIMITY_OUT_MASK = 1 << 19,
  148. GDK_SUBSTRUCTURE_MASK = 1 << 20,
  149. GDK_SCROLL_MASK = 1 << 21,
  150. GDK_ALL_EVENTS_MASK = 0x3FFFFE
  151. }
  152. internal enum GdkEventType {
  153. GDK_NOTHING = -1,
  154. GDK_DELETE = 0,
  155. GDK_DESTROY = 1,
  156. GDK_EXPOSE = 2,
  157. GDK_MOTION_NOTIFY = 3,
  158. GDK_BUTTON_PRESS = 4,
  159. GDK_2BUTTON_PRESS = 5,
  160. GDK_3BUTTON_PRESS = 6,
  161. GDK_BUTTON_RELEASE = 7,
  162. GDK_KEY_PRESS = 8,
  163. GDK_KEY_RELEASE = 9,
  164. GDK_ENTER_NOTIFY = 10,
  165. GDK_LEAVE_NOTIFY = 11,
  166. GDK_FOCUS_CHANGE = 12,
  167. GDK_CONFIGURE = 13,
  168. GDK_MAP = 14,
  169. GDK_UNMAP = 15,
  170. GDK_PROPERTY_NOTIFY = 16,
  171. GDK_SELECTION_CLEAR = 17,
  172. GDK_SELECTION_REQUEST = 18,
  173. GDK_SELECTION_NOTIFY = 19,
  174. GDK_PROXIMITY_IN = 20,
  175. GDK_PROXIMITY_OUT = 21,
  176. GDK_DRAG_ENTER = 22,
  177. GDK_DRAG_LEAVE = 23,
  178. GDK_DRAG_MOTION = 24,
  179. GDK_DRAG_STATUS = 25,
  180. GDK_DROP_START = 26,
  181. GDK_DROP_FINISHED = 27,
  182. GDK_CLIENT_EVENT = 28,
  183. GDK_VISIBILITY_NOTIFY = 29,
  184. GDK_NO_EXPOSE = 30,
  185. GDK_SCROLL = 31,
  186. GDK_WINDOW_STATE = 32,
  187. GDK_SETTING = 33,
  188. GDK_OWNER_CHANGE = 34,
  189. GDK_GRAB_BROKEN = 35
  190. }
  191. internal enum GdkWMDecoration {
  192. GDK_DECOR_ALL = 1 << 0,
  193. GDK_DECOR_BORDER = 1 << 1,
  194. GDK_DECOR_RESIZEH = 1 << 2,
  195. GDK_DECOR_TITLE = 1 << 3,
  196. GDK_DECOR_MENU = 1 << 4,
  197. GDK_DECOR_MINIMIZE = 1 << 5,
  198. GDK_DECOR_MAXIMIZE = 1 << 6
  199. }
  200. internal enum GdkWMFunction {
  201. GDK_FUNC_ALL = 1 << 0,
  202. GDK_FUNC_RESIZE = 1 << 1,
  203. GDK_FUNC_MOVE = 1 << 2,
  204. GDK_FUNC_MINIMIZE = 1 << 3,
  205. GDK_FUNC_MAXIMIZE = 1 << 4,
  206. GDK_FUNC_CLOSE = 1 << 5
  207. }
  208. internal enum GdkCursorType {
  209. GDK_X_CURSOR = 0,
  210. GDK_ARROW = 2,
  211. GDK_BASED_ARROW_DOWN = 4,
  212. GDK_BASED_ARROW_UP = 6,
  213. GDK_BOAT = 8,
  214. GDK_BOGOSITY = 10,
  215. GDK_BOTTOM_LEFT_CORNER = 12,
  216. GDK_BOTTOM_RIGHT_CORNER = 14,
  217. GDK_BOTTOM_SIDE = 16,
  218. GDK_BOTTOM_TEE = 18,
  219. GDK_BOX_SPIRAL = 20,
  220. GDK_CENTER_PTR = 22,
  221. GDK_CIRCLE = 24,
  222. GDK_CLOCK = 26,
  223. GDK_COFFEE_MUG = 28,
  224. GDK_CROSS = 30,
  225. GDK_CROSS_REVERSE = 32,
  226. GDK_CROSSHAIR = 34,
  227. GDK_DIAMOND_CROSS = 36,
  228. GDK_DOT = 38,
  229. GDK_DOTBOX = 40,
  230. GDK_DOUBLE_ARROW = 42,
  231. GDK_DRAFT_LARGE = 44,
  232. GDK_DRAFT_SMALL = 46,
  233. GDK_DRAPED_BOX = 48,
  234. GDK_EXCHANGE = 50,
  235. GDK_FLEUR = 52,
  236. GDK_GOBBLER = 54,
  237. GDK_GUMBY = 56,
  238. GDK_HAND1 = 58,
  239. GDK_HAND2 = 60,
  240. GDK_HEART = 62,
  241. GDK_ICON = 64,
  242. GDK_IRON_CROSS = 66,
  243. GDK_LEFT_PTR = 68,
  244. GDK_LEFT_SIDE = 70,
  245. GDK_LEFT_TEE = 72,
  246. GDK_LEFTBUTTON = 74,
  247. GDK_LL_ANGLE = 76,
  248. GDK_LR_ANGLE = 78,
  249. GDK_MAN = 80,
  250. GDK_MIDDLEBUTTON = 82,
  251. GDK_MOUSE = 84,
  252. GDK_PENCIL = 86,
  253. GDK_PIRATE = 88,
  254. GDK_PLUS = 90,
  255. GDK_QUESTION_ARROW = 92,
  256. GDK_RIGHT_PTR = 94,
  257. GDK_RIGHT_SIDE = 96,
  258. GDK_RIGHT_TEE = 98,
  259. GDK_RIGHTBUTTON = 100,
  260. GDK_RTL_LOGO = 102,
  261. GDK_SAILBOAT = 104,
  262. GDK_SB_DOWN_ARROW = 106,
  263. GDK_SB_H_DOUBLE_ARROW = 108,
  264. GDK_SB_LEFT_ARROW = 110,
  265. GDK_SB_RIGHT_ARROW = 112,
  266. GDK_SB_UP_ARROW = 114,
  267. GDK_SB_V_DOUBLE_ARROW = 116,
  268. GDK_SHUTTLE = 118,
  269. GDK_SIZING = 120,
  270. GDK_SPIDER = 122,
  271. GDK_SPRAYCAN = 124,
  272. GDK_STAR = 126,
  273. GDK_TARGET = 128,
  274. GDK_TCROSS = 130,
  275. GDK_TOP_LEFT_ARROW = 132,
  276. GDK_TOP_LEFT_CORNER = 134,
  277. GDK_TOP_RIGHT_CORNER = 136,
  278. GDK_TOP_SIDE = 138,
  279. GDK_TOP_TEE = 140,
  280. GDK_TREK = 142,
  281. GDK_UL_ANGLE = 144,
  282. GDK_UMBRELLA = 146,
  283. GDK_UR_ANGLE = 148,
  284. GDK_WATCH = 150,
  285. GDK_XTERM = 152,
  286. GDK_LAST_CURSOR,
  287. GDK_CURSOR_IS_PIXMAP = -1
  288. }
  289. internal enum GdkPropMode {
  290. GDK_PROP_MODE_REPLACE,
  291. GDK_PROP_MODE_PREPEND,
  292. GDK_PROP_MODE_APPEND
  293. }
  294. [StructLayout (LayoutKind.Sequential)]
  295. internal struct GdkGeometry {
  296. internal int min_width;
  297. internal int min_height;
  298. internal int max_width;
  299. internal int max_height;
  300. internal int base_width;
  301. internal int base_height;
  302. internal int width_inc;
  303. internal int height_inc;
  304. internal double min_aspect;
  305. internal double max_aspect;
  306. internal GdkGravity win_gravity;
  307. }
  308. [StructLayout (LayoutKind.Sequential)]
  309. internal struct GdkWindowAttr {
  310. internal string title;
  311. internal int event_mask;
  312. internal int x, y;
  313. internal int width;
  314. internal int height;
  315. internal GdkWindowClass wclass;
  316. internal IntPtr visual;
  317. internal IntPtr colormap;
  318. internal GdkWindowType window_type;
  319. internal IntPtr cursor;
  320. internal string wmclass_name;
  321. internal string wmclass_class;
  322. internal bool override_redirect;
  323. }
  324. #region Local Variables
  325. // General
  326. static volatile XplatUIX11GTK Instance;
  327. private static int RefCount;
  328. private static object XlibLock; // Our locking object
  329. private static bool ThemesEnabled;
  330. // General X11
  331. private static IntPtr DisplayHandle; // X11 handle to display
  332. private static IntPtr GdkDisplayHandle; // gdk handle to display
  333. private static int ScreenNo; // Screen number used
  334. private static IntPtr GdkScreen;
  335. private static IntPtr DefaultColormap; // Colormap for screen
  336. private static IntPtr GdkDefaultColormap; // Gdk Colormap for screen
  337. private static IntPtr CustomVisual; // Visual for window creation
  338. private static IntPtr GdkCustomVisual;
  339. private static IntPtr CustomColormap; // Colormap for window creation
  340. private static IntPtr GdkCustomColormap;
  341. private static int VisualBestDepth;
  342. private static IntPtr RootWindow; // Handle of the root window for the screen/display
  343. private static IntPtr GdkRootWindow; // Gdk handle of the root window for the screen/display
  344. private static IntPtr FosterParent; // Container to hold child windows until their parent exists
  345. private static IntPtr GdkFosterParent; // Container to hold child windows until their parent exists
  346. private static XErrorHandler ErrorHandler; // Error handler delegate
  347. private static bool ErrorExceptions; // Throw exceptions on X errors
  348. private static bool PostQuitState; // True if we've got an pending exit
  349. // Clipboard
  350. private static IntPtr ClipMagic = new IntPtr(27051977);
  351. private static ClipboardStruct Clipboard; // Our clipboard
  352. // Communication
  353. private static int PostAtom; // PostMessage atom
  354. private static int AsyncAtom; // Support for async messages
  355. // Message Loop
  356. private static XEventQueue MessageQueue; // Holds our queued up events
  357. #if __MonoCS__ //
  358. private static Pollfd[] pollfds; // For watching the X11 socket
  359. #endif //
  360. private static X11Keyboard Keyboard; //
  361. private static X11Dnd Dnd;
  362. private static Socket listen; //
  363. private static Socket wake; //
  364. private static Socket wake_receive; //
  365. private static byte[] network_buffer; //
  366. // Focus tracking
  367. private static IntPtr ActiveWindow; // Handle of the active window
  368. private static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
  369. // Modality support
  370. private static Stack ModalWindows; // Stack of our modal windows
  371. // Systray
  372. private static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
  373. // Cursors
  374. private static IntPtr LastCursorWindow; // The last window we set the cursor on
  375. private static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
  376. private static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
  377. // Caret
  378. private static CaretStruct Caret; //
  379. // Support for Window Styles
  380. private static int[] NetAtoms; // All atoms we know
  381. // mouse hover message generation
  382. private static HoverStruct HoverState; //
  383. // double click message generation
  384. private static ClickStruct ClickPending; //
  385. // Support for mouse grab
  386. private static GrabStruct Grab; //
  387. // State
  388. private static Point MousePosition; // Last position of mouse, in screen coords
  389. internal static MouseButtons MouseState; // Last state of mouse buttons
  390. // Timers
  391. private static ArrayList TimerList; // Holds SWF.Timers
  392. // 'Constants'
  393. private static int DoubleClickInterval; // msec; max interval between clicks to count as double click
  394. const GdkEventMask GdkSelectInputMask = GdkEventMask.GDK_BUTTON_PRESS_MASK |
  395. GdkEventMask.GDK_BUTTON_RELEASE_MASK |
  396. GdkEventMask.GDK_KEY_PRESS_MASK |
  397. GdkEventMask.GDK_KEY_RELEASE_MASK |
  398. GdkEventMask.GDK_ENTER_NOTIFY_MASK |
  399. GdkEventMask.GDK_LEAVE_NOTIFY_MASK |
  400. GdkEventMask.GDK_EXPOSURE_MASK |
  401. GdkEventMask.GDK_FOCUS_CHANGE_MASK |
  402. GdkEventMask.GDK_POINTER_MOTION_MASK |
  403. GdkEventMask.GDK_VISIBILITY_NOTIFY_MASK |
  404. GdkEventMask.GDK_SUBSTRUCTURE_MASK |
  405. GdkEventMask.GDK_STRUCTURE_MASK;
  406. static readonly object lockobj = new object ();
  407. static Hashtable backing_store = new Hashtable (5);
  408. #endregion // Local Variables
  409. #region Constructors
  410. private XplatUIX11GTK ()
  411. {
  412. Console.WriteLine ("XplatUIX11GTK ctor...");
  413. // Handle singleton stuff first
  414. RefCount = 0;
  415. // init gdk
  416. gdk_init_check (IntPtr.Zero, IntPtr.Zero);
  417. // Now regular initialization
  418. XlibLock = new object ();
  419. MessageQueue = new XEventQueue ();
  420. TimerList = new ArrayList ();
  421. XInitThreads ();
  422. ErrorExceptions = false;
  423. // X11 Initialization
  424. SetDisplay (gdk_x11_display_get_xdisplay (gdk_display_get_default ()));
  425. X11DesktopColors.Initialize ();
  426. // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
  427. ErrorHandler = new XErrorHandler (HandleError);
  428. XSetErrorHandler (ErrorHandler);
  429. }
  430. #endregion // Constructors
  431. #region Singleton Specific Code
  432. public static XplatUIX11GTK GetInstance ()
  433. {
  434. lock (lockobj) {
  435. if (Instance == null) {
  436. Instance = new XplatUIX11GTK ();
  437. }
  438. RefCount++;
  439. }
  440. return Instance;
  441. }
  442. public int Reference {
  443. get {
  444. return RefCount;
  445. }
  446. }
  447. #endregion
  448. #region Internal Properties
  449. internal static IntPtr Display {
  450. get {
  451. return DisplayHandle;
  452. }
  453. set {
  454. XplatUIX11GTK.GetInstance ().SetDisplay (value);
  455. }
  456. }
  457. internal static int Screen {
  458. get {
  459. return ScreenNo;
  460. }
  461. set {
  462. ScreenNo = value;
  463. }
  464. }
  465. internal static IntPtr RootWindowHandle {
  466. get {
  467. return RootWindow;
  468. }
  469. set {
  470. RootWindow = value;
  471. }
  472. }
  473. internal static IntPtr Visual {
  474. get {
  475. return CustomVisual;
  476. }
  477. set {
  478. CustomVisual = value;
  479. }
  480. }
  481. internal static IntPtr ColorMap {
  482. get {
  483. return CustomColormap;
  484. }
  485. set {
  486. CustomColormap = value;
  487. }
  488. }
  489. #endregion
  490. #region XExceptionClass
  491. internal class XException : ApplicationException {
  492. IntPtr Display;
  493. IntPtr ResourceID;
  494. IntPtr Serial;
  495. XRequest RequestCode;
  496. byte ErrorCode;
  497. byte MinorCode;
  498. public XException (IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode)
  499. {
  500. this.Display = Display;
  501. this.ResourceID = ResourceID;
  502. this.Serial = Serial;
  503. this.RequestCode = RequestCode;
  504. this.ErrorCode = ErrorCode;
  505. this.MinorCode = MinorCode;
  506. }
  507. public override string Message {
  508. get {
  509. return GetMessage (Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
  510. }
  511. }
  512. public static string GetMessage (IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode)
  513. {
  514. StringBuilder sb;
  515. string x_error_text;
  516. string error;
  517. sb = new StringBuilder (160);
  518. XGetErrorText (Display, ErrorCode, sb, sb.Capacity);
  519. x_error_text = sb.ToString ();
  520. 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);
  521. return error;
  522. }
  523. }
  524. #endregion // XExceptionClass
  525. #region Internal Methods
  526. // native X display handle
  527. internal void SetDisplay (IntPtr display_handle)
  528. {
  529. if (display_handle != IntPtr.Zero) {
  530. Hwnd hwnd;
  531. if ((GdkDisplayHandle != IntPtr.Zero) && (GdkFosterParent != IntPtr.Zero)) {
  532. hwnd = Hwnd.ObjectFromHandle (gdk_x11_drawable_get_xid (GdkFosterParent));
  533. gdk_window_destroy (GdkFosterParent);
  534. hwnd.Dispose ();
  535. }
  536. if (GdkDisplayHandle != IntPtr.Zero) {
  537. gdk_display_close (GdkDisplayHandle);
  538. }
  539. DisplayHandle = display_handle;
  540. GdkDisplayHandle = gdk_x11_lookup_xdisplay (display_handle);
  541. // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
  542. // been hacked to do this for us.
  543. Graphics.FromHdcInternal (DisplayHandle);
  544. // Debugging support
  545. if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
  546. XSynchronize (DisplayHandle, true);
  547. }
  548. if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
  549. ErrorExceptions = true;
  550. }
  551. // Generic X11 setup
  552. GdkScreen = gdk_screen_get_default ();
  553. // or gdk_x11_get_default_screen
  554. ScreenNo = gdk_screen_get_number (GdkScreen);
  555. GdkRootWindow = gdk_get_default_root_window ();
  556. RootWindow = gdk_x11_drawable_get_xid (GdkRootWindow);
  557. GdkDefaultColormap = gdk_colormap_get_system ();
  558. DefaultColormap = gdk_x11_colormap_get_xcolormap (GdkDefaultColormap);
  559. VisualBestDepth = gdk_visual_get_best_depth ();
  560. //Console.WriteLine (VisualBestDepth);
  561. // Create the foster parent
  562. FosterParent = XCreateSimpleWindow (DisplayHandle, RootWindow, 0, 0, 1, 1, 4, 0, 0);
  563. GdkFosterParent = gdk_window_foreign_new (FosterParent);
  564. if (GdkFosterParent == IntPtr.Zero) {
  565. Console.WriteLine ("XplatUIX11GTK Constructor failed to create FosterParent");
  566. }
  567. hwnd = new Hwnd ();
  568. hwnd.WholeWindow = FosterParent;
  569. hwnd.ClientWindow = FosterParent;
  570. // For sleeping on the X11 socket
  571. listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
  572. IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
  573. listen.Bind (ep);
  574. listen.Listen (1);
  575. // To wake up when a timer is ready
  576. network_buffer = new byte [10];
  577. wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
  578. wake.Connect (listen.LocalEndPoint);
  579. wake_receive = listen.Accept ();
  580. #if __MonoCS__
  581. pollfds = new Pollfd [2];
  582. pollfds [0] = new Pollfd ();
  583. pollfds [0].fd = XConnectionNumber (DisplayHandle);
  584. pollfds [0].events = PollEvents.POLLIN;
  585. pollfds [1] = new Pollfd ();
  586. pollfds [1].fd = wake_receive.Handle.ToInt32 ();
  587. pollfds [1].events = PollEvents.POLLIN;
  588. #endif
  589. Keyboard = new X11Keyboard (DisplayHandle);
  590. Dnd = new X11Dnd (DisplayHandle);
  591. PostQuitState = false;
  592. DoubleClickInterval = 500;
  593. HoverState.Interval = 500;
  594. HoverState.Timer = new Timer ();
  595. HoverState.Timer.Enabled = false;
  596. HoverState.Timer.Interval = HoverState.Interval;
  597. HoverState.Timer.Tick += new EventHandler (MouseHover);
  598. HoverState.X = -1;
  599. HoverState.Y = -1;
  600. ActiveWindow = IntPtr.Zero;
  601. FocusWindow = IntPtr.Zero;
  602. ModalWindows = new Stack (3);
  603. MouseState = MouseButtons.None;
  604. MousePosition = new Point (0, 0);
  605. Caret.Timer = new Timer ();
  606. Caret.Timer.Interval = 500; // FIXME - where should this number come from?
  607. Caret.Timer.Tick += new EventHandler (CaretCallback);
  608. SetupAtoms ();
  609. // Grab atom changes off the root window to catch certain WM events
  610. gdk_window_set_events (GdkRootWindow, (int)GdkEventMask.GDK_PROPERTY_CHANGE_MASK);
  611. // Handle any upcoming errors
  612. ErrorHandler = new XErrorHandler (HandleError);
  613. XSetErrorHandler (ErrorHandler);
  614. } else {
  615. throw new ArgumentNullException ("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
  616. }
  617. }
  618. #endregion // Internal Methods
  619. #region Private Methods
  620. private static void SetupAtoms ()
  621. {
  622. NetAtoms = new int [(int)NA.LAST_NET_ATOM];
  623. NetAtoms [(int)NA.WM_PROTOCOLS] = XInternAtom (DisplayHandle, "WM_PROTOCOLS", false);
  624. NetAtoms [(int)NA.WM_DELETE_WINDOW] = XInternAtom (DisplayHandle, "WM_DELETE_WINDOW", false);
  625. NetAtoms [(int)NA.WM_TAKE_FOCUS] = XInternAtom (DisplayHandle, "WM_TAKE_FOCUS", false);
  626. NetAtoms [(int)NA._NET_SUPPORTED] = XInternAtom (DisplayHandle, "_NET_SUPPORTED", false);
  627. NetAtoms [(int)NA._NET_CLIENT_LIST] = XInternAtom (DisplayHandle, "_NET_CLIENT_LIST", false);
  628. NetAtoms [(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom (DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
  629. NetAtoms [(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom (DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
  630. NetAtoms [(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom (DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
  631. NetAtoms [(int)NA._NET_CURRENT_DESKTOP] = XInternAtom (DisplayHandle, "_NET_CURRENT_DESKTOP", false);
  632. NetAtoms [(int)NA._NET_DESKTOP_NAMES] = XInternAtom (DisplayHandle, "_NET_DESKTOP_NAMES", false);
  633. NetAtoms [(int)NA._NET_ACTIVE_WINDOW] = XInternAtom (DisplayHandle, "_NET_ACTIVE_WINDOW", false);
  634. NetAtoms [(int)NA._NET_WORKAREA] = XInternAtom (DisplayHandle, "_NET_WORKAREA", false);
  635. NetAtoms [(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom (DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
  636. NetAtoms [(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom (DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
  637. NetAtoms [(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom (DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
  638. NetAtoms [(int)NA._NET_SHOWING_DESKTOP] = XInternAtom (DisplayHandle, "_NET_SHOWING_DESKTOP", false);
  639. NetAtoms [(int)NA._NET_CLOSE_WINDOW] = XInternAtom (DisplayHandle, "_NET_CLOSE_WINDOW", false);
  640. NetAtoms [(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom (DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
  641. NetAtoms [(int)NA._NET_WM_MOVERESIZE] = XInternAtom (DisplayHandle, "_NET_WM_MOVERESIZE", false);
  642. NetAtoms [(int)NA._NET_RESTACK_WINDOW] = XInternAtom (DisplayHandle, "_NET_RESTACK_WINDOW", false);
  643. NetAtoms [(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom (DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
  644. NetAtoms [(int)NA._NET_WM_NAME] = XInternAtom (DisplayHandle, "_NET_WM_NAME", false);
  645. NetAtoms [(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom (DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
  646. NetAtoms [(int)NA._NET_WM_ICON_NAME] = XInternAtom (DisplayHandle, "_NET_WM_ICON_NAME", false);
  647. NetAtoms [(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom (DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
  648. NetAtoms [(int)NA._NET_WM_DESKTOP] = XInternAtom (DisplayHandle, "_NET_WM_DESKTOP", false);
  649. NetAtoms [(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom (DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
  650. NetAtoms [(int)NA._NET_WM_STATE] = XInternAtom (DisplayHandle, "_NET_WM_STATE", false);
  651. NetAtoms [(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom (DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
  652. NetAtoms [(int)NA._NET_WM_STRUT] = XInternAtom (DisplayHandle, "_NET_WM_STRUT", false);
  653. NetAtoms [(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom (DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
  654. NetAtoms [(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom (DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
  655. NetAtoms [(int)NA._NET_WM_ICON] = XInternAtom (DisplayHandle, "_NET_WM_ICON", false);
  656. NetAtoms [(int)NA._NET_WM_PID] = XInternAtom (DisplayHandle, "_NET_WM_PID", false);
  657. NetAtoms [(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom (DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
  658. NetAtoms [(int)NA._NET_WM_USER_TIME] = XInternAtom (DisplayHandle, "_NET_WM_USER_TIME", false);
  659. NetAtoms [(int)NA._NET_FRAME_EXTENTS] = XInternAtom (DisplayHandle, "_NET_FRAME_EXTENTS", false);
  660. NetAtoms [(int)NA._NET_WM_PING] = XInternAtom (DisplayHandle, "_NET_WM_PING", false);
  661. NetAtoms [(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom (DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
  662. NetAtoms [(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString (), false);
  663. NetAtoms [(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
  664. NetAtoms [(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
  665. NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
  666. NetAtoms [(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
  667. NetAtoms [(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom (DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
  668. NetAtoms [(int)NA._XEMBED] = XInternAtom (DisplayHandle, "_XEMBED", false);
  669. NetAtoms [(int)NA._XEMBED_INFO] = XInternAtom (DisplayHandle, "_XEMBED_INFO", false);
  670. NetAtoms [(int)NA._MOTIF_WM_HINTS] = XInternAtom (DisplayHandle, "_MOTIF_WM_HINTS", false);
  671. NetAtoms [(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom (DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
  672. NetAtoms [(int)NA._NET_WM_STATE_ABOVE] = XInternAtom (DisplayHandle, "_NET_WM_STATE_ABOVE", false);
  673. NetAtoms [(int)NA._NET_WM_STATE_MODAL] = XInternAtom (DisplayHandle, "_NET_WM_STATE_MODAL", false);
  674. NetAtoms [(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom (DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
  675. NetAtoms [(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom (DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
  676. // Clipboard support
  677. NetAtoms [(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
  678. NetAtoms [(int)NA.DIB] = (int)Atom.XA_PIXMAP;
  679. NetAtoms [(int)NA.OEMTEXT] = XInternAtom (DisplayHandle, "COMPOUND_TEXT", false);
  680. NetAtoms [(int)NA.UNICODETEXT] = XInternAtom (DisplayHandle, "UTF8_STRING", false);
  681. NetAtoms [(int)NA.TARGETS] = XInternAtom (DisplayHandle, "TARGETS", false);
  682. // Special Atoms
  683. AsyncAtom = XInternAtom (DisplayHandle, "_SWF_AsyncAtom", false);
  684. PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
  685. HoverState.Atom = XInternAtom (DisplayHandle, "_SWF_HoverAtom", false);
  686. }
  687. private void GetSystrayManagerWindow ()
  688. {
  689. gdk_x11_grab_server ();
  690. SystrayMgrWindow = XGetSelectionOwner (DisplayHandle, NetAtoms [(int)NA._NET_SYSTEM_TRAY_S]);
  691. gdk_x11_ungrab_server ();
  692. gdk_display_flush (GdkDisplayHandle);
  693. }
  694. private void SendNetWMMessage (IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
  695. {
  696. XEvent xev;
  697. xev = new XEvent ();
  698. xev.ClientMessageEvent.type = XEventName.ClientMessage;
  699. xev.ClientMessageEvent.send_event = true;
  700. xev.ClientMessageEvent.window = window;
  701. xev.ClientMessageEvent.message_type = message_type;
  702. xev.ClientMessageEvent.format = 32;
  703. xev.ClientMessageEvent.ptr1 = l0;
  704. xev.ClientMessageEvent.ptr2 = l1;
  705. xev.ClientMessageEvent.ptr3 = l2;
  706. XSendEvent (DisplayHandle, RootWindow, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
  707. }
  708. private void SendNetClientMessage (IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
  709. {
  710. XEvent xev;
  711. xev = new XEvent ();
  712. xev.ClientMessageEvent.type = XEventName.ClientMessage;
  713. xev.ClientMessageEvent.send_event = true;
  714. xev.ClientMessageEvent.window = window;
  715. xev.ClientMessageEvent.message_type = message_type;
  716. xev.ClientMessageEvent.format = 32;
  717. xev.ClientMessageEvent.ptr1 = l0;
  718. xev.ClientMessageEvent.ptr2 = l1;
  719. xev.ClientMessageEvent.ptr3 = l2;
  720. XSendEvent (DisplayHandle, window, false, EventMask.NoEventMask, ref xev);
  721. }
  722. 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)
  723. {
  724. // Only MDI windows get caption_heights
  725. caption_height = 0;
  726. tool_caption_height = 19;
  727. if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
  728. if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
  729. border_style = FormBorderStyle.None;
  730. } else if ((ExStyle & (int) WindowStyles.WS_EX_CLIENTEDGE) != 0) {
  731. border_style = FormBorderStyle.Fixed3D;
  732. } else {
  733. border_style = FormBorderStyle.FixedSingle;
  734. }
  735. title_style = TitleStyle.None;
  736. } else {
  737. bool is_mdi = false;
  738. if ((ExStyle & (int) WindowStyles.WS_EX_MDICHILD) != 0) {
  739. caption_height = 26;
  740. is_mdi = true;
  741. }
  742. title_style = TitleStyle.None;
  743. if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
  744. if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
  745. title_style = TitleStyle.Tool;
  746. } else {
  747. title_style = TitleStyle.Normal;
  748. }
  749. }
  750. if (!is_mdi) {
  751. border_style = FormBorderStyle.None;
  752. if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
  753. if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
  754. border_style = FormBorderStyle.SizableToolWindow;
  755. } else {
  756. border_style = FormBorderStyle.Sizable;
  757. }
  758. } else {
  759. if ((ExStyle & (int)WindowStyles.WS_EX_CLIENTEDGE) != 0) {
  760. border_style = FormBorderStyle.Fixed3D;
  761. } else if ((ExStyle & (int)WindowStyles.WS_EX_DLGMODALFRAME) != 0) {
  762. border_style = FormBorderStyle.FixedDialog;
  763. } else if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
  764. border_style = FormBorderStyle.FixedToolWindow;
  765. } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
  766. border_style = FormBorderStyle.Sizable;
  767. } else {
  768. border_style = FormBorderStyle.None;
  769. }
  770. }
  771. } else {
  772. if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
  773. (ExStyle & (int) WindowStyles.WS_EX_TOOLWINDOW) != 0) {
  774. border_style = (FormBorderStyle) 0xFFFF;
  775. } else {
  776. border_style = FormBorderStyle.None;
  777. }
  778. }
  779. }
  780. }
  781. private void SetHwndStyles (Hwnd hwnd, CreateParams cp)
  782. {
  783. DeriveStyles (hwnd.Handle, cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
  784. }
  785. private void SetWMStyles (Hwnd hwnd, CreateParams cp)
  786. {
  787. GdkWMDecoration decorations = GdkWMDecoration.GDK_DECOR_ALL;
  788. if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
  789. decorations |= GdkWMDecoration.GDK_DECOR_TITLE | GdkWMDecoration.GDK_DECOR_MENU;
  790. }
  791. if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
  792. decorations |= GdkWMDecoration.GDK_DECOR_BORDER | GdkWMDecoration.GDK_DECOR_RESIZEH;
  793. }
  794. if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
  795. decorations |= GdkWMDecoration.GDK_DECOR_MINIMIZE;
  796. }
  797. if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
  798. decorations |= GdkWMDecoration.GDK_DECOR_MAXIMIZE;
  799. }
  800. // is this needed ? most window managers do not even honour any MotifFunctions...
  801. // if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
  802. // functions |= MotifFunctions.Close;
  803. // }
  804. if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
  805. decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
  806. }
  807. if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
  808. decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
  809. }
  810. if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
  811. decorations |= GdkWMDecoration.GDK_DECOR_BORDER;
  812. }
  813. if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
  814. decorations = 0;
  815. }
  816. gdk_window_set_decorations (gdk_window_foreign_new (hwnd.whole_window), (int)decorations);
  817. }
  818. private void SetIcon (Hwnd hwnd, Icon icon)
  819. {
  820. Bitmap bitmap;
  821. int size;
  822. uint[] data;
  823. int index;
  824. bitmap = icon.ToBitmap ();
  825. index = 0;
  826. size = bitmap.Width * bitmap.Height + 2;
  827. data = new uint [size];
  828. data [index++] = (uint)bitmap.Width;
  829. data [index++] = (uint)bitmap.Height;
  830. for (int y = 0; y < bitmap.Height; y++) {
  831. for (int x = 0; x < bitmap.Width; x++) {
  832. data [index++] = (uint)bitmap.GetPixel (x, y).ToArgb ();
  833. }
  834. }
  835. XChangeProperty (DisplayHandle, hwnd.whole_window, NetAtoms [(int)NA._NET_WM_ICON], Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
  836. }
  837. private IntPtr ImageToPixmap (Image image)
  838. {
  839. return IntPtr.Zero;
  840. }
  841. private void WakeupMain ()
  842. {
  843. wake.Send (new byte [] { 0xFF });
  844. }
  845. private void TranslatePropertyToClipboard (int property)
  846. {
  847. Atom actual_atom;
  848. int actual_format;
  849. int nitems;
  850. int bytes_after;
  851. IntPtr prop = IntPtr.Zero;
  852. Clipboard.Item = null;
  853. XGetWindowProperty (DisplayHandle, FosterParent, property, 0, 0x7fffffff, true, Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
  854. if (nitems > 0) {
  855. if (property == (int)Atom.XA_STRING) {
  856. Clipboard.Item = Marshal.PtrToStringAnsi (prop);
  857. } else if (property == (int)Atom.XA_BITMAP) {
  858. // FIXME - convert bitmap to image
  859. } else if (property == (int)Atom.XA_PIXMAP) {
  860. // FIXME - convert pixmap to image
  861. } else if (property == NetAtoms [(int)NA.OEMTEXT]) {
  862. Clipboard.Item = Marshal.PtrToStringAnsi (prop);
  863. } else if (property == NetAtoms [(int)NA.UNICODETEXT]) {
  864. Clipboard.Item = Marshal.PtrToStringAnsi (prop);
  865. }
  866. XFree (prop);
  867. }
  868. }
  869. private void AddExpose (XEvent xevent)
  870. {
  871. Hwnd hwnd;
  872. hwnd = Hwnd.GetObjectFromWindow (xevent.AnyEvent.window);
  873. // Don't waste time
  874. if (hwnd == null) {
  875. return;
  876. }
  877. if (xevent.AnyEvent.window == hwnd.client_window) {
  878. hwnd.AddInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
  879. if (!hwnd.expose_pending) {
  880. MessageQueue.Enqueue (xevent);
  881. hwnd.expose_pending = true;
  882. }
  883. } else {
  884. if (!hwnd.nc_expose_pending) {
  885. MessageQueue.Enqueue (xevent);
  886. hwnd.nc_expose_pending = true;
  887. }
  888. }
  889. }
  890. private void InvalidateWholeWindow (IntPtr handle)
  891. {
  892. Hwnd hwnd;
  893. hwnd = Hwnd.ObjectFromHandle (handle);
  894. InvalidateWholeWindow (handle, new Rectangle (0, 0, hwnd.Width, hwnd.Height));
  895. }
  896. private void InvalidateWholeWindow (IntPtr handle, Rectangle rectangle)
  897. {
  898. Hwnd hwnd;
  899. XEvent xevent;
  900. hwnd = Hwnd.ObjectFromHandle (handle);
  901. xevent = new XEvent ();
  902. xevent.type = XEventName.Expose;
  903. xevent.ExposeEvent.display = DisplayHandle;
  904. xevent.ExposeEvent.window = hwnd.whole_window;
  905. xevent.ExposeEvent.x = rectangle.X;
  906. xevent.ExposeEvent.y = rectangle.Y;
  907. xevent.ExposeEvent.width = rectangle.Width;
  908. xevent.ExposeEvent.height = rectangle.Height;
  909. AddExpose (xevent);
  910. }
  911. private void WholeToScreen (IntPtr handle, ref int x, ref int y)
  912. {
  913. int dest_x_return;
  914. int dest_y_return;
  915. Hwnd hwnd;
  916. hwnd = Hwnd.ObjectFromHandle (handle);
  917. lock (XlibLock) {
  918. gdk_window_get_origin (gdk_window_lookup (hwnd.whole_window), out dest_x_return, out dest_y_return);
  919. }
  920. x = dest_x_return;
  921. y = dest_y_return;
  922. }
  923. private void AddConfigureNotify (XEvent xevent)
  924. {
  925. Hwnd hwnd;
  926. hwnd = Hwnd.GetObjectFromWindow (xevent.ConfigureEvent.window);
  927. // Don't waste time
  928. if (hwnd == null) {
  929. return;
  930. }
  931. if (xevent.ConfigureEvent.window == hwnd.whole_window) {
  932. if (!hwnd.reparented) {
  933. hwnd.x = xevent.ConfigureEvent.x;
  934. hwnd.y = xevent.ConfigureEvent.y;
  935. } else {
  936. int dummy_int;
  937. 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);
  938. }
  939. hwnd.width = xevent.ConfigureEvent.width;
  940. hwnd.height = xevent.ConfigureEvent.height;
  941. if (!hwnd.configure_pending) {
  942. MessageQueue.Enqueue (xevent);
  943. hwnd.configure_pending = true;
  944. }
  945. }
  946. // We drop configure events for Client windows
  947. }
  948. private void ShowCaret ()
  949. {
  950. if ((Caret.gc == IntPtr.Zero) || Caret.On) {
  951. return;
  952. }
  953. Caret.On = true;
  954. // gdk_gc_set_foreground
  955. // gdk_draw_line
  956. lock (XlibLock) {
  957. XDrawLine (DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
  958. }
  959. }
  960. private void HideCaret ()
  961. {
  962. if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
  963. return;
  964. }
  965. Caret.On = false;
  966. // gdk_gc_set_foreground
  967. // gdk_draw_text_wc
  968. lock (XlibLock) {
  969. XDrawLine (DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
  970. }
  971. }
  972. private int NextTimeout (DateTime now)
  973. {
  974. int timeout = Int32.MaxValue;
  975. lock (TimerList) {
  976. foreach (Timer timer in TimerList) {
  977. int next = (int) (timer.Expires - now).TotalMilliseconds;
  978. if (next < 0) {
  979. return 0; // Have a timer that has already expired
  980. }
  981. if (next < timeout) {
  982. timeout = next;
  983. }
  984. }
  985. }
  986. if (timeout < Timer.Minimum) {
  987. timeout = Timer.Minimum;
  988. }
  989. return timeout;
  990. }
  991. private void CheckTimers (DateTime now)
  992. {
  993. lock (TimerList) {
  994. int count;
  995. count = TimerList.Count;
  996. if (count == 0) {
  997. return;
  998. }
  999. for (int i = 0; i < TimerList.Count; i++) {
  1000. Timer timer;
  1001. timer = (Timer) TimerList [i];
  1002. if (timer.Enabled && timer.Expires <= now) {
  1003. timer.Update (now);
  1004. timer.FireTick ();
  1005. }
  1006. }
  1007. }
  1008. }
  1009. private void UpdateMessageQueue ()
  1010. {
  1011. DateTime now;
  1012. int pending;
  1013. now = DateTime.Now;
  1014. lock (XlibLock) {
  1015. pending = XPending (DisplayHandle);
  1016. }
  1017. if (pending == 0) {
  1018. if (Idle != null) {
  1019. Idle (this, EventArgs.Empty);
  1020. }
  1021. lock (XlibLock) {
  1022. pending = XPending (DisplayHandle);
  1023. }
  1024. }
  1025. if (pending == 0) {
  1026. int timeout;
  1027. timeout = NextTimeout (now);
  1028. if (timeout > 0) {
  1029. #if __MonoCS__
  1030. Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
  1031. // Clean out buffer, so we're not busy-looping on the same data
  1032. if (pollfds[1].revents != 0) {
  1033. wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
  1034. }
  1035. #endif
  1036. lock (XlibLock) {
  1037. pending = XPending (DisplayHandle);
  1038. }
  1039. }
  1040. }
  1041. CheckTimers (now);
  1042. if (pending == 0) {
  1043. lock (XlibLock) {
  1044. pending = XPending (DisplayHandle);
  1045. }
  1046. }
  1047. while (pending > 0) {
  1048. XEvent xevent = new XEvent ();
  1049. lock (XlibLock) {
  1050. XNextEvent (DisplayHandle, ref xevent);
  1051. }
  1052. //Console.WriteLine("Got x event {0}", xevent);
  1053. switch (xevent.type) {
  1054. case XEventName.Expose:
  1055. AddExpose (xevent);
  1056. break;
  1057. case XEventName.SelectionClear: {
  1058. // Should we do something?
  1059. break;
  1060. }
  1061. case XEventName.SelectionRequest: {
  1062. if (Dnd.HandleSelectionRequestEvent (ref xevent))
  1063. break;
  1064. XEvent sel_event;
  1065. sel_event = new XEvent ();
  1066. sel_event.SelectionEvent.type = XEventName.SelectionNotify;
  1067. sel_event.SelectionEvent.send_event = true;
  1068. sel_event.SelectionEvent.display = DisplayHandle;
  1069. sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
  1070. sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
  1071. sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
  1072. sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
  1073. sel_event.SelectionEvent.property = 0;
  1074. // Seems that some apps support asking for supported types
  1075. if (xevent.SelectionEvent.target == NetAtoms [(int)NA.TARGETS]) {
  1076. uint[] atoms;
  1077. int atom_count;
  1078. atoms = new uint [5];
  1079. atom_count = 0;
  1080. if (Clipboard.Item is String) {
  1081. atoms [atom_count++] = (uint)Atom.XA_STRING;
  1082. atoms [atom_count++] = (uint)NetAtoms [(int)NA.OEMTEXT];
  1083. atoms [atom_count++] = (uint)NetAtoms [(int)NA.UNICODETEXT];
  1084. } else if (Clipboard.Item is Image) {
  1085. atoms [atom_count++] = (uint)Atom.XA_PIXMAP;
  1086. atoms [atom_count++] = (uint)Atom.XA_BITMAP;
  1087. } else {
  1088. // FIXME - handle other types
  1089. }
  1090. XChangeProperty (DisplayHandle, xevent.SelectionEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
  1091. } else if (Clipboard.Item is string) {
  1092. IntPtr buffer;
  1093. int buflen;
  1094. buflen = 0;
  1095. if (xevent.SelectionRequestEvent.target == (int)Atom.XA_STRING) {
  1096. Byte[] bytes;
  1097. bytes = new ASCIIEncoding ().GetBytes ((string)Clipboard.Item);
  1098. buffer = Marshal.AllocHGlobal (bytes.Length);
  1099. buflen = bytes.Length;
  1100. for (int i = 0; i < buflen; i++) {
  1101. Marshal.WriteByte (buffer, i, bytes [i]);
  1102. }
  1103. } else if (xevent.SelectionRequestEvent.target == NetAtoms [(int)NA.OEMTEXT]) {
  1104. // FIXME - this should encode into ISO2022
  1105. buffer = Marshal.StringToHGlobalAnsi ((string)Clipboard.Item);
  1106. while (Marshal.ReadByte (buffer, buflen) != 0) {
  1107. buflen++;
  1108. }
  1109. } else if (xevent.SelectionRequestEvent.target == NetAtoms [(int)NA.UNICODETEXT]) {
  1110. buffer = Marshal.StringToHGlobalAnsi ((string)Clipboard.Item);
  1111. while (Marshal.ReadByte (buffer, buflen) != 0) {
  1112. buflen++;
  1113. }
  1114. } else {
  1115. buffer = IntPtr.Zero;
  1116. }
  1117. if (buffer != IntPtr.Zero) {
  1118. XChangeProperty (DisplayHandle, xevent.SelectionRequestEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
  1119. sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
  1120. Marshal.FreeHGlobal (buffer);
  1121. }
  1122. } else if (Clipboard.Item is Image) {
  1123. if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
  1124. // FIXME - convert image and store as property
  1125. } else if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
  1126. // FIXME - convert image and store as property
  1127. }
  1128. }
  1129. XSendEvent (DisplayHandle, xevent.SelectionRequestEvent.requestor, false, EventMask.NoEventMask, ref sel_event);
  1130. break;
  1131. }
  1132. case XEventName.SelectionNotify: {
  1133. if (Clipboard.Enumerating) {
  1134. Clipboard.Enumerating = false;
  1135. if (xevent.SelectionEvent.property != 0) {
  1136. XDeleteProperty (DisplayHandle, FosterParent, xevent.SelectionEvent.property);
  1137. if (!Clipboard.Formats.Contains (xevent.SelectionEvent.property)) {
  1138. Clipboard.Formats.Add (xevent.SelectionEvent.property);
  1139. #if DriverDebugExtra
  1140. Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
  1141. #endif
  1142. }
  1143. }
  1144. } else if (Clipboard.Retrieving) {
  1145. Clipboard.Retrieving = false;
  1146. if (xevent.SelectionEvent.property != 0) {
  1147. TranslatePropertyToClipboard (xevent.SelectionEvent.property);
  1148. } else {
  1149. Clipboard.Item = null;
  1150. }
  1151. } else {
  1152. Dnd.HandleSelectionNotifyEvent (ref xevent);
  1153. }
  1154. break;
  1155. }
  1156. case XEventName.KeyPress:
  1157. case XEventName.KeyRelease:
  1158. case XEventName.ButtonPress:
  1159. case XEventName.ButtonRelease:
  1160. case XEventName.MotionNotify:
  1161. case XEventName.EnterNotify:
  1162. case XEventName.LeaveNotify:
  1163. case XEventName.CreateNotify:
  1164. case XEventName.DestroyNotify:
  1165. case XEventName.FocusIn:
  1166. case XEventName.FocusOut:
  1167. case XEventName.ClientMessage:
  1168. case XEventName.ReparentNotify:
  1169. MessageQueue.Enqueue (xevent);
  1170. break;
  1171. case XEventName.ConfigureNotify:
  1172. AddConfigureNotify (xevent);
  1173. break;
  1174. case XEventName.PropertyNotify:
  1175. if (xevent.PropertyEvent.atom == NetAtoms [(int)NA._NET_ACTIVE_WINDOW]) {
  1176. Atom actual_atom;
  1177. int actual_format;
  1178. int nitems;
  1179. int bytes_after;
  1180. IntPtr prop = IntPtr.Zero;
  1181. IntPtr prev_active;;
  1182. prev_active = ActiveWindow;
  1183. 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);
  1184. if ((nitems > 0) && (prop != IntPtr.Zero)) {
  1185. ActiveWindow = Hwnd.GetHandleFromWindow ((IntPtr)Marshal.ReadInt32 (prop));
  1186. XFree (prop);
  1187. if (prev_active != ActiveWindow) {
  1188. if (prev_active != IntPtr.Zero) {
  1189. PostMessage (prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
  1190. }
  1191. if (ActiveWindow != IntPtr.Zero) {
  1192. PostMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
  1193. }
  1194. }
  1195. if (ModalWindows.Count == 0) {
  1196. break;
  1197. } else {
  1198. // Modality handling, if we are modal and the new active window is one
  1199. // of ours but not the modal one, switch back to the modal window
  1200. if (NativeWindow.FromHandle (ActiveWindow) != null) {
  1201. if (ActiveWindow != (IntPtr)ModalWindows.Peek ()) {
  1202. Activate ((IntPtr)ModalWindows.Peek ());
  1203. }
  1204. }
  1205. break;
  1206. }
  1207. }
  1208. }
  1209. break;
  1210. }
  1211. lock (XlibLock) {
  1212. pending = XPending (DisplayHandle);
  1213. }
  1214. }
  1215. }
  1216. private IntPtr GetMousewParam (int Delta)
  1217. {
  1218. int result = 0;
  1219. if ((MouseState & MouseButtons.Left) != 0) {
  1220. result |= (int)MsgButtons.MK_LBUTTON;
  1221. }
  1222. if ((MouseState & MouseButtons.Middle) != 0) {
  1223. result |= (int)MsgButtons.MK_MBUTTON;
  1224. }
  1225. if ((MouseState & MouseButtons.Right) != 0) {
  1226. result |= (int)MsgButtons.MK_RBUTTON;
  1227. }
  1228. Keys mods = ModifierKeys;
  1229. if ((mods & Keys.Control) != 0) {
  1230. result |= (int)MsgButtons.MK_CONTROL;
  1231. }
  1232. if ((mods & Keys.Shift) != 0) {
  1233. result |= (int)MsgButtons.MK_SHIFT;
  1234. }
  1235. result |= Delta << 16;
  1236. return (IntPtr)result;
  1237. }
  1238. private IntPtr XGetParent (IntPtr handle)
  1239. {
  1240. return gdk_x11_drawable_get_xid (gdk_window_get_parent (gdk_window_lookup (handle)));
  1241. }
  1242. private int HandleError (IntPtr display, ref XErrorEvent error_event)
  1243. {
  1244. if (ErrorExceptions) {
  1245. throw new XException (error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
  1246. } else {
  1247. 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);
  1248. }
  1249. return 0;
  1250. }
  1251. private void DestroyChildWindow (Control c)
  1252. {
  1253. Hwnd hwnd;
  1254. int i;
  1255. Control[] controls;
  1256. if (c != null) {
  1257. controls = c.Controls.GetAllControls ();
  1258. for (i = 0; i < controls.Length; i++) {
  1259. if (controls [i].IsHandleCreated) {
  1260. hwnd = Hwnd.ObjectFromHandle (controls [i].Handle);
  1261. SendMessage (controls [i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
  1262. hwnd.Dispose ();
  1263. }
  1264. DestroyChildWindow (controls [i]);
  1265. }
  1266. }
  1267. }
  1268. #endregion // Private Methods
  1269. #region Callbacks
  1270. private void MouseHover (object sender, EventArgs e)
  1271. {
  1272. if ((HoverState.X == MousePosition.X) && (HoverState.Y == MousePosition.Y)) {
  1273. XEvent xevent;
  1274. HoverState.Timer.Enabled = false;
  1275. if (HoverState.Window != IntPtr.Zero) {
  1276. xevent = new XEvent ();
  1277. xevent.type = XEventName.ClientMessage;
  1278. xevent.ClientMessageEvent.display = DisplayHandle;
  1279. xevent.ClientMessageEvent.window = (IntPtr)HoverState.Window;
  1280. xevent.ClientMessageEvent.message_type = (IntPtr)HoverState.Atom;
  1281. xevent.ClientMessageEvent.format = 32;
  1282. xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
  1283. MessageQueue.EnqueueLocked (xevent);
  1284. WakeupMain ();
  1285. }
  1286. }
  1287. }
  1288. private void CaretCallback (object sender, EventArgs e)
  1289. {
  1290. if (Caret.Paused) {
  1291. return;
  1292. }
  1293. Caret.On = !Caret.On;
  1294. XDrawLine (DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
  1295. }
  1296. #endregion // Callbacks
  1297. #region Public Properties
  1298. internal override int Caption {
  1299. get {
  1300. return 25;
  1301. }
  1302. }
  1303. internal override Size CursorSize {
  1304. get {
  1305. uint x;
  1306. uint y;
  1307. gdk_display_get_maximal_cursor_size (GdkDisplayHandle, out x, out y);
  1308. return new Size ((int)x, (int)y);
  1309. }
  1310. }
  1311. internal override bool DragFullWindows {
  1312. get {
  1313. return true;
  1314. }
  1315. }
  1316. internal override Size DragSize {
  1317. get {
  1318. return new Size (4, 4);
  1319. }
  1320. }
  1321. internal override Size FrameBorderSize {
  1322. get {
  1323. throw new NotImplementedException ();
  1324. }
  1325. }
  1326. internal override Size IconSize {
  1327. get {
  1328. IntPtr

Large files files are truncated, but you can click here to view the full file