PageRenderTime 59ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 2ms

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

https://bitbucket.org/danipen/mono
C# | 7588 lines | 5716 code | 1347 blank | 525 comment | 1173 complexity | a5b31050b832856e57a30cc5ca58b9dc 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. //
  25. //
  26. // NOTE:
  27. // This driver understands the following environment variables: (Set the var to enable feature)
  28. //
  29. // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
  30. // by default a message is displayed but execution continues
  31. //
  32. // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
  33. // helps in debugging errors
  34. //
  35. // NOT COMPLETE
  36. // define to log Window handles and relationships to stdout
  37. #undef DriverDebug
  38. // Extra detailed debug
  39. #undef DriverDebugExtra
  40. #undef DriverDebugParent
  41. #undef DriverDebugCreate
  42. #undef DriverDebugDestroy
  43. #undef DriverDebugThreads
  44. #undef DriverDebugXEmbed
  45. //#define TRACE
  46. //#define DEBUG
  47. using System;
  48. using System.ComponentModel;
  49. using System.Collections;
  50. using System.Diagnostics;
  51. using System.Drawing;
  52. using System.Drawing.Drawing2D;
  53. using System.Drawing.Imaging;
  54. using System.IO;
  55. using System.Net;
  56. using System.Net.Sockets;
  57. using System.Reflection;
  58. using System.Runtime.InteropServices;
  59. using System.Runtime.Serialization;
  60. using System.Runtime.Serialization.Formatters.Binary;
  61. using System.Text;
  62. using System.Threading;
  63. // Only do the poll when building with mono for now
  64. #if __MonoCS__
  65. using Mono.Unix.Native;
  66. #endif
  67. /// X11 Version
  68. namespace System.Windows.Forms {
  69. internal class XplatUIX11 : XplatUIDriver {
  70. #region Local Variables
  71. // General
  72. static volatile XplatUIX11 Instance;
  73. static int RefCount;
  74. static object XlibLock; // Our locking object
  75. static bool themes_enabled;
  76. // General X11
  77. static IntPtr DisplayHandle; // X11 handle to display
  78. static int ScreenNo; // Screen number used
  79. static IntPtr DefaultColormap; // Colormap for screen
  80. static IntPtr CustomVisual; // Visual for window creation
  81. static IntPtr CustomColormap; // Colormap for window creation
  82. static IntPtr RootWindow; // Handle of the root window for the screen/display
  83. static IntPtr FosterParent; // Container to hold child windows until their parent exists
  84. static XErrorHandler ErrorHandler; // Error handler delegate
  85. static bool ErrorExceptions; // Throw exceptions on X errors
  86. int render_major_opcode;
  87. int render_first_event;
  88. int render_first_error;
  89. // Clipboard
  90. static IntPtr ClipMagic;
  91. static ClipboardData Clipboard; // Our clipboard
  92. // Communication
  93. static IntPtr PostAtom; // PostMessage atom
  94. static IntPtr AsyncAtom; // Support for async messages
  95. // Message Loop
  96. static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
  97. static ArrayList unattached_timer_list; // holds timers that are enabled but not attached to a window.
  98. #if __MonoCS__ //
  99. static Pollfd[] pollfds; // For watching the X11 socket
  100. static bool wake_waiting;
  101. static object wake_waiting_lock = new object ();
  102. #endif //
  103. static X11Keyboard Keyboard; //
  104. static X11Dnd Dnd;
  105. static Socket listen; //
  106. static Socket wake; //
  107. static Socket wake_receive; //
  108. static byte[] network_buffer; //
  109. static bool detectable_key_auto_repeat;
  110. // Focus tracking
  111. static IntPtr ActiveWindow; // Handle of the active window
  112. static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
  113. // Modality support
  114. static Stack ModalWindows; // Stack of our modal windows
  115. // Systray
  116. static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
  117. // Cursors
  118. static IntPtr LastCursorWindow; // The last window we set the cursor on
  119. static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
  120. static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
  121. // Caret
  122. static CaretStruct Caret; //
  123. // Last window containing the pointer
  124. static IntPtr LastPointerWindow; // The last window containing the pointer
  125. // Our atoms
  126. static IntPtr WM_PROTOCOLS;
  127. static IntPtr WM_DELETE_WINDOW;
  128. static IntPtr WM_TAKE_FOCUS;
  129. //static IntPtr _NET_SUPPORTED;
  130. //static IntPtr _NET_CLIENT_LIST;
  131. //static IntPtr _NET_NUMBER_OF_DESKTOPS;
  132. static IntPtr _NET_DESKTOP_GEOMETRY;
  133. //static IntPtr _NET_DESKTOP_VIEWPORT;
  134. static IntPtr _NET_CURRENT_DESKTOP;
  135. //static IntPtr _NET_DESKTOP_NAMES;
  136. static IntPtr _NET_ACTIVE_WINDOW;
  137. static IntPtr _NET_WORKAREA;
  138. //static IntPtr _NET_SUPPORTING_WM_CHECK;
  139. //static IntPtr _NET_VIRTUAL_ROOTS;
  140. //static IntPtr _NET_DESKTOP_LAYOUT;
  141. //static IntPtr _NET_SHOWING_DESKTOP;
  142. //static IntPtr _NET_CLOSE_WINDOW;
  143. //static IntPtr _NET_MOVERESIZE_WINDOW;
  144. static IntPtr _NET_WM_MOVERESIZE;
  145. //static IntPtr _NET_RESTACK_WINDOW;
  146. //static IntPtr _NET_REQUEST_FRAME_EXTENTS;
  147. static IntPtr _NET_WM_NAME;
  148. //static IntPtr _NET_WM_VISIBLE_NAME;
  149. //static IntPtr _NET_WM_ICON_NAME;
  150. //static IntPtr _NET_WM_VISIBLE_ICON_NAME;
  151. //static IntPtr _NET_WM_DESKTOP;
  152. static IntPtr _NET_WM_WINDOW_TYPE;
  153. static IntPtr _NET_WM_STATE;
  154. //static IntPtr _NET_WM_ALLOWED_ACTIONS;
  155. //static IntPtr _NET_WM_STRUT;
  156. //static IntPtr _NET_WM_STRUT_PARTIAL;
  157. //static IntPtr _NET_WM_ICON_GEOMETRY;
  158. static IntPtr _NET_WM_ICON;
  159. //static IntPtr _NET_WM_PID;
  160. //static IntPtr _NET_WM_HANDLED_ICONS;
  161. static IntPtr _NET_WM_USER_TIME;
  162. static IntPtr _NET_FRAME_EXTENTS;
  163. //static IntPtr _NET_WM_PING;
  164. //static IntPtr _NET_WM_SYNC_REQUEST;
  165. static IntPtr _NET_SYSTEM_TRAY_S;
  166. //static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
  167. static IntPtr _NET_SYSTEM_TRAY_OPCODE;
  168. static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
  169. static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
  170. static IntPtr _XEMBED;
  171. static IntPtr _XEMBED_INFO;
  172. static IntPtr _MOTIF_WM_HINTS;
  173. static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
  174. static IntPtr _NET_WM_STATE_ABOVE;
  175. static IntPtr _NET_WM_STATE_MODAL;
  176. static IntPtr _NET_WM_STATE_HIDDEN;
  177. static IntPtr _NET_WM_CONTEXT_HELP;
  178. static IntPtr _NET_WM_WINDOW_OPACITY;
  179. //static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
  180. //static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
  181. //static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
  182. //static IntPtr _NET_WM_WINDOW_TYPE_MENU;
  183. static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
  184. //static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
  185. // static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
  186. static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
  187. static IntPtr CLIPBOARD;
  188. static IntPtr PRIMARY;
  189. //static IntPtr DIB;
  190. static IntPtr OEMTEXT;
  191. static IntPtr UTF8_STRING;
  192. static IntPtr UTF16_STRING;
  193. static IntPtr RICHTEXTFORMAT;
  194. static IntPtr TARGETS;
  195. // mouse hover message generation
  196. static HoverStruct HoverState; //
  197. // double click message generation
  198. static ClickStruct ClickPending; //
  199. // Support for mouse grab
  200. static GrabStruct Grab; //
  201. // State
  202. Point mouse_position; // Last position of mouse, in screen coords
  203. internal static MouseButtons MouseState; // Last state of mouse buttons
  204. internal static bool in_doevents;
  205. // 'Constants'
  206. static int DoubleClickInterval; // msec; max interval between clicks to count as double click
  207. const EventMask SelectInputMask = (EventMask.ButtonPressMask |
  208. EventMask.ButtonReleaseMask |
  209. EventMask.KeyPressMask |
  210. EventMask.KeyReleaseMask |
  211. EventMask.EnterWindowMask |
  212. EventMask.LeaveWindowMask |
  213. EventMask.ExposureMask |
  214. EventMask.FocusChangeMask |
  215. EventMask.PointerMotionMask |
  216. EventMask.PointerMotionHintMask |
  217. EventMask.SubstructureNotifyMask);
  218. static readonly object lockobj = new object ();
  219. // messages WaitForHwndMwssage is waiting on
  220. static Hashtable messageHold;
  221. #endregion // Local Variables
  222. #region Constructors
  223. XplatUIX11()
  224. {
  225. // Handle singleton stuff first
  226. RefCount = 0;
  227. in_doevents = false;
  228. // Now regular initialization
  229. XlibLock = new object ();
  230. X11Keyboard.XlibLock = XlibLock;
  231. MessageQueues = Hashtable.Synchronized (new Hashtable(7));
  232. unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
  233. messageHold = Hashtable.Synchronized (new Hashtable(3));
  234. Clipboard = new ClipboardData ();
  235. XInitThreads();
  236. ErrorExceptions = false;
  237. // X11 Initialization
  238. SetDisplay(XOpenDisplay(IntPtr.Zero));
  239. X11DesktopColors.Initialize();
  240. // Disable keyboard autorepeat
  241. try {
  242. XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
  243. detectable_key_auto_repeat = true;
  244. } catch {
  245. Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
  246. detectable_key_auto_repeat = false;
  247. }
  248. // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
  249. ErrorHandler = new XErrorHandler(HandleError);
  250. XSetErrorHandler(ErrorHandler);
  251. }
  252. ~XplatUIX11() {
  253. // Remove our display handle from S.D
  254. Graphics.FromHdcInternal (IntPtr.Zero);
  255. }
  256. #endregion // Constructors
  257. #region Singleton Specific Code
  258. public static XplatUIX11 GetInstance() {
  259. lock (lockobj) {
  260. if (Instance == null) {
  261. Instance=new XplatUIX11();
  262. }
  263. RefCount++;
  264. }
  265. return Instance;
  266. }
  267. public int Reference {
  268. get {
  269. return RefCount;
  270. }
  271. }
  272. #endregion
  273. #region Internal Properties
  274. internal static IntPtr Display {
  275. get {
  276. return DisplayHandle;
  277. }
  278. set {
  279. XplatUIX11.GetInstance().SetDisplay(value);
  280. }
  281. }
  282. internal static int Screen {
  283. get {
  284. return ScreenNo;
  285. }
  286. set {
  287. ScreenNo = value;
  288. }
  289. }
  290. internal static IntPtr RootWindowHandle {
  291. get {
  292. return RootWindow;
  293. }
  294. set {
  295. RootWindow = value;
  296. }
  297. }
  298. internal static IntPtr Visual {
  299. get {
  300. return CustomVisual;
  301. }
  302. set {
  303. CustomVisual = value;
  304. }
  305. }
  306. internal static IntPtr ColorMap {
  307. get {
  308. return CustomColormap;
  309. }
  310. set {
  311. CustomColormap = value;
  312. }
  313. }
  314. #if DEBUG_shana
  315. internal static IntPtr DefaultColorMap {
  316. get {
  317. return DefaultColormap;
  318. }
  319. }
  320. #endif
  321. #endregion
  322. #region XExceptionClass
  323. internal class XException : ApplicationException {
  324. IntPtr Display;
  325. IntPtr ResourceID;
  326. IntPtr Serial;
  327. XRequest RequestCode;
  328. byte ErrorCode;
  329. byte MinorCode;
  330. public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
  331. this.Display = Display;
  332. this.ResourceID = ResourceID;
  333. this.Serial = Serial;
  334. this.RequestCode = RequestCode;
  335. this.ErrorCode = ErrorCode;
  336. this.MinorCode = MinorCode;
  337. }
  338. public override string Message {
  339. get {
  340. return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
  341. }
  342. }
  343. public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
  344. StringBuilder sb;
  345. string x_error_text;
  346. string error;
  347. string hwnd_text;
  348. string control_text;
  349. Hwnd hwnd;
  350. Control c;
  351. sb = new StringBuilder(160);
  352. XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
  353. x_error_text = sb.ToString();
  354. hwnd = Hwnd.ObjectFromHandle(ResourceID);
  355. if (hwnd != null) {
  356. hwnd_text = hwnd.ToString();
  357. c = Control.FromHandle(hwnd.Handle);
  358. if (c != null) {
  359. control_text = c.ToString();
  360. } else {
  361. control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle.ToInt32());
  362. }
  363. } else {
  364. hwnd_text = "<null>";
  365. control_text = "<null>";
  366. }
  367. error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
  368. return error;
  369. }
  370. }
  371. #endregion // XExceptionClass
  372. #region Internal Methods
  373. internal void SetDisplay(IntPtr display_handle)
  374. {
  375. if (display_handle != IntPtr.Zero) {
  376. Hwnd hwnd;
  377. if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
  378. hwnd = Hwnd.ObjectFromHandle(FosterParent);
  379. XDestroyWindow(DisplayHandle, FosterParent);
  380. hwnd.Dispose();
  381. }
  382. if (DisplayHandle != IntPtr.Zero) {
  383. XCloseDisplay(DisplayHandle);
  384. }
  385. DisplayHandle=display_handle;
  386. // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
  387. // been hacked to do this for us.
  388. Graphics.FromHdcInternal (DisplayHandle);
  389. // query for the render extension so
  390. // we can ignore the spurious
  391. // BadPicture errors that are
  392. // generated by cairo/render.
  393. XQueryExtension (DisplayHandle, "RENDER",
  394. ref render_major_opcode, ref render_first_event, ref render_first_error);
  395. // Debugging support
  396. if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
  397. XSynchronize(DisplayHandle, true);
  398. }
  399. if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
  400. ErrorExceptions = true;
  401. }
  402. // Generic X11 setup
  403. ScreenNo = XDefaultScreen(DisplayHandle);
  404. RootWindow = XRootWindow(DisplayHandle, ScreenNo);
  405. DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
  406. // Create the foster parent
  407. // it is important that border_width is kept in synch with the other XCreateWindow calls
  408. FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
  409. if (FosterParent==IntPtr.Zero) {
  410. Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
  411. }
  412. DebugHelper.WriteLine ("FosterParent created 0x{0:x}", FosterParent.ToInt32());
  413. hwnd = new Hwnd();
  414. hwnd.Queue = ThreadQueue(Thread.CurrentThread);
  415. hwnd.WholeWindow = FosterParent;
  416. hwnd.ClientWindow = FosterParent;
  417. // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
  418. hwnd = new Hwnd();
  419. hwnd.Queue = ThreadQueue(Thread.CurrentThread);
  420. hwnd.whole_window = RootWindow;
  421. hwnd.ClientWindow = RootWindow;
  422. // For sleeping on the X11 socket
  423. listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
  424. IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
  425. listen.Bind(ep);
  426. listen.Listen(1);
  427. // To wake up when a timer is ready
  428. network_buffer = new byte[10];
  429. wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
  430. wake.Connect(listen.LocalEndPoint);
  431. // Make this non-blocking, so it doesn't
  432. // deadlock if too many wakes are sent
  433. // before the wake_receive end is polled
  434. wake.Blocking = false;
  435. wake_receive = listen.Accept();
  436. #if __MonoCS__
  437. pollfds = new Pollfd [2];
  438. pollfds [0] = new Pollfd ();
  439. pollfds [0].fd = XConnectionNumber (DisplayHandle);
  440. pollfds [0].events = PollEvents.POLLIN;
  441. pollfds [1] = new Pollfd ();
  442. pollfds [1].fd = wake_receive.Handle.ToInt32 ();
  443. pollfds [1].events = PollEvents.POLLIN;
  444. #endif
  445. Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
  446. Dnd = new X11Dnd (DisplayHandle, Keyboard);
  447. DoubleClickInterval = 500;
  448. HoverState.Interval = 500;
  449. HoverState.Timer = new Timer();
  450. HoverState.Timer.Enabled = false;
  451. HoverState.Timer.Interval = HoverState.Interval;
  452. HoverState.Timer.Tick += new EventHandler(MouseHover);
  453. HoverState.Size = new Size(4, 4);
  454. HoverState.X = -1;
  455. HoverState.Y = -1;
  456. ActiveWindow = IntPtr.Zero;
  457. FocusWindow = IntPtr.Zero;
  458. ModalWindows = new Stack(3);
  459. MouseState = MouseButtons.None;
  460. mouse_position = new Point(0, 0);
  461. Caret.Timer = new Timer();
  462. Caret.Timer.Interval = 500; // FIXME - where should this number come from?
  463. Caret.Timer.Tick += new EventHandler(CaretCallback);
  464. SetupAtoms();
  465. // Grab atom changes off the root window to catch certain WM events
  466. XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
  467. // Handle any upcoming errors
  468. ErrorHandler = new XErrorHandler(HandleError);
  469. XSetErrorHandler(ErrorHandler);
  470. } else {
  471. throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
  472. }
  473. }
  474. #endregion // Internal Methods
  475. #region Methods
  476. [Conditional ("DriverDebug")]
  477. static void DriverDebug (string format, params object [] args)
  478. {
  479. Console.WriteLine (String.Format (format, args));
  480. }
  481. int unixtime() {
  482. TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
  483. return (int) t.TotalSeconds;
  484. }
  485. static void SetupAtoms() {
  486. // make sure this array stays in sync with the statements below
  487. string [] atom_names = new string[] {
  488. "WM_PROTOCOLS",
  489. "WM_DELETE_WINDOW",
  490. "WM_TAKE_FOCUS",
  491. //"_NET_SUPPORTED",
  492. //"_NET_CLIENT_LIST",
  493. //"_NET_NUMBER_OF_DESKTOPS",
  494. "_NET_DESKTOP_GEOMETRY",
  495. //"_NET_DESKTOP_VIEWPORT",
  496. "_NET_CURRENT_DESKTOP",
  497. //"_NET_DESKTOP_NAMES",
  498. "_NET_ACTIVE_WINDOW",
  499. "_NET_WORKAREA",
  500. //"_NET_SUPPORTING_WM_CHECK",
  501. //"_NET_VIRTUAL_ROOTS",
  502. //"_NET_DESKTOP_LAYOUT",
  503. //"_NET_SHOWING_DESKTOP",
  504. //"_NET_CLOSE_WINDOW",
  505. //"_NET_MOVERESIZE_WINDOW",
  506. "_NET_WM_MOVERESIZE",
  507. //"_NET_RESTACK_WINDOW",
  508. //"_NET_REQUEST_FRAME_EXTENTS",
  509. "_NET_WM_NAME",
  510. //"_NET_WM_VISIBLE_NAME",
  511. //"_NET_WM_ICON_NAME",
  512. //"_NET_WM_VISIBLE_ICON_NAME",
  513. //"_NET_WM_DESKTOP",
  514. "_NET_WM_WINDOW_TYPE",
  515. "_NET_WM_STATE",
  516. //"_NET_WM_ALLOWED_ACTIONS",
  517. //"_NET_WM_STRUT",
  518. //"_NET_WM_STRUT_PARTIAL",
  519. //"_NET_WM_ICON_GEOMETRY",
  520. "_NET_WM_ICON",
  521. //"_NET_WM_PID",
  522. //"_NET_WM_HANDLED_ICONS",
  523. "_NET_WM_USER_TIME",
  524. "_NET_FRAME_EXTENTS",
  525. //"_NET_WM_PING",
  526. //"_NET_WM_SYNC_REQUEST",
  527. "_NET_SYSTEM_TRAY_OPCODE",
  528. //"_NET_SYSTEM_TRAY_ORIENTATION",
  529. "_NET_WM_STATE_MAXIMIZED_HORZ",
  530. "_NET_WM_STATE_MAXIMIZED_VERT",
  531. "_NET_WM_STATE_HIDDEN",
  532. "_XEMBED",
  533. "_XEMBED_INFO",
  534. "_MOTIF_WM_HINTS",
  535. "_NET_WM_STATE_SKIP_TASKBAR",
  536. "_NET_WM_STATE_ABOVE",
  537. "_NET_WM_STATE_MODAL",
  538. "_NET_WM_CONTEXT_HELP",
  539. "_NET_WM_WINDOW_OPACITY",
  540. //"_NET_WM_WINDOW_TYPE_DESKTOP",
  541. //"_NET_WM_WINDOW_TYPE_DOCK",
  542. //"_NET_WM_WINDOW_TYPE_TOOLBAR",
  543. //"_NET_WM_WINDOW_TYPE_MENU",
  544. "_NET_WM_WINDOW_TYPE_UTILITY",
  545. // "_NET_WM_WINDOW_TYPE_DIALOG",
  546. //"_NET_WM_WINDOW_TYPE_SPLASH",
  547. "_NET_WM_WINDOW_TYPE_NORMAL",
  548. "CLIPBOARD",
  549. "PRIMARY",
  550. "COMPOUND_TEXT",
  551. "UTF8_STRING",
  552. "UTF16_STRING",
  553. "RICHTEXTFORMAT",
  554. "TARGETS",
  555. "_SWF_AsyncAtom",
  556. "_SWF_PostMessageAtom",
  557. "_SWF_HoverAtom" };
  558. IntPtr[] atoms = new IntPtr [atom_names.Length];;
  559. XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
  560. int off = 0;
  561. WM_PROTOCOLS = atoms [off++];
  562. WM_DELETE_WINDOW = atoms [off++];
  563. WM_TAKE_FOCUS = atoms [off++];
  564. //_NET_SUPPORTED = atoms [off++];
  565. //_NET_CLIENT_LIST = atoms [off++];
  566. //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
  567. _NET_DESKTOP_GEOMETRY = atoms [off++];
  568. //_NET_DESKTOP_VIEWPORT = atoms [off++];
  569. _NET_CURRENT_DESKTOP = atoms [off++];
  570. //_NET_DESKTOP_NAMES = atoms [off++];
  571. _NET_ACTIVE_WINDOW = atoms [off++];
  572. _NET_WORKAREA = atoms [off++];
  573. //_NET_SUPPORTING_WM_CHECK = atoms [off++];
  574. //_NET_VIRTUAL_ROOTS = atoms [off++];
  575. //_NET_DESKTOP_LAYOUT = atoms [off++];
  576. //_NET_SHOWING_DESKTOP = atoms [off++];
  577. //_NET_CLOSE_WINDOW = atoms [off++];
  578. //_NET_MOVERESIZE_WINDOW = atoms [off++];
  579. _NET_WM_MOVERESIZE = atoms [off++];
  580. //_NET_RESTACK_WINDOW = atoms [off++];
  581. //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
  582. _NET_WM_NAME = atoms [off++];
  583. //_NET_WM_VISIBLE_NAME = atoms [off++];
  584. //_NET_WM_ICON_NAME = atoms [off++];
  585. //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
  586. //_NET_WM_DESKTOP = atoms [off++];
  587. _NET_WM_WINDOW_TYPE = atoms [off++];
  588. _NET_WM_STATE = atoms [off++];
  589. //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
  590. //_NET_WM_STRUT = atoms [off++];
  591. //_NET_WM_STRUT_PARTIAL = atoms [off++];
  592. //_NET_WM_ICON_GEOMETRY = atoms [off++];
  593. _NET_WM_ICON = atoms [off++];
  594. //_NET_WM_PID = atoms [off++];
  595. //_NET_WM_HANDLED_ICONS = atoms [off++];
  596. _NET_WM_USER_TIME = atoms [off++];
  597. _NET_FRAME_EXTENTS = atoms [off++];
  598. //_NET_WM_PING = atoms [off++];
  599. //_NET_WM_SYNC_REQUEST = atoms [off++];
  600. _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
  601. //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
  602. _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
  603. _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
  604. _NET_WM_STATE_HIDDEN = atoms [off++];
  605. _XEMBED = atoms [off++];
  606. _XEMBED_INFO = atoms [off++];
  607. _MOTIF_WM_HINTS = atoms [off++];
  608. _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
  609. _NET_WM_STATE_ABOVE = atoms [off++];
  610. _NET_WM_STATE_MODAL = atoms [off++];
  611. _NET_WM_CONTEXT_HELP = atoms [off++];
  612. _NET_WM_WINDOW_OPACITY = atoms [off++];
  613. //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
  614. //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
  615. //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
  616. //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
  617. _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
  618. // _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
  619. //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
  620. _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
  621. CLIPBOARD = atoms [off++];
  622. PRIMARY = atoms [off++];
  623. OEMTEXT = atoms [off++];
  624. UTF8_STRING = atoms [off++];
  625. UTF16_STRING = atoms [off++];
  626. RICHTEXTFORMAT = atoms [off++];
  627. TARGETS = atoms [off++];
  628. AsyncAtom = atoms [off++];
  629. PostAtom = atoms [off++];
  630. HoverState.Atom = atoms [off++];
  631. //DIB = (IntPtr)Atom.XA_PIXMAP;
  632. _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
  633. }
  634. void GetSystrayManagerWindow() {
  635. XGrabServer(DisplayHandle);
  636. SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
  637. XUngrabServer(DisplayHandle);
  638. XFlush(DisplayHandle);
  639. }
  640. void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
  641. SendNetWMMessage (window, message_type, l0, l1, l2, IntPtr.Zero);
  642. }
  643. void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2, IntPtr l3) {
  644. XEvent xev;
  645. xev = new XEvent();
  646. xev.ClientMessageEvent.type = XEventName.ClientMessage;
  647. xev.ClientMessageEvent.send_event = true;
  648. xev.ClientMessageEvent.window = window;
  649. xev.ClientMessageEvent.message_type = message_type;
  650. xev.ClientMessageEvent.format = 32;
  651. xev.ClientMessageEvent.ptr1 = l0;
  652. xev.ClientMessageEvent.ptr2 = l1;
  653. xev.ClientMessageEvent.ptr3 = l2;
  654. xev.ClientMessageEvent.ptr4 = l3;
  655. XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
  656. }
  657. void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
  658. XEvent xev;
  659. xev = new XEvent();
  660. xev.ClientMessageEvent.type = XEventName.ClientMessage;
  661. xev.ClientMessageEvent.send_event = true;
  662. xev.ClientMessageEvent.window = window;
  663. xev.ClientMessageEvent.message_type = message_type;
  664. xev.ClientMessageEvent.format = 32;
  665. xev.ClientMessageEvent.ptr1 = l0;
  666. xev.ClientMessageEvent.ptr2 = l1;
  667. xev.ClientMessageEvent.ptr3 = l2;
  668. XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
  669. }
  670. // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
  671. // WM_CREATE and WM_DESTROY causes
  672. void SendParentNotify(IntPtr child, Msg cause, int x, int y)
  673. {
  674. Hwnd hwnd;
  675. if (child == IntPtr.Zero) {
  676. return;
  677. }
  678. hwnd = Hwnd.GetObjectFromWindow (child);
  679. if (hwnd == null) {
  680. return;
  681. }
  682. if (hwnd.Handle == IntPtr.Zero) {
  683. return;
  684. }
  685. if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
  686. return;
  687. }
  688. if (hwnd.Parent == null) {
  689. return;
  690. }
  691. if (hwnd.Parent.Handle == IntPtr.Zero) {
  692. return;
  693. }
  694. if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
  695. SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
  696. } else {
  697. SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
  698. }
  699. SendParentNotify (hwnd.Parent.Handle, cause, x, y);
  700. }
  701. bool StyleSet (int s, WindowStyles ws)
  702. {
  703. return (s & (int)ws) == (int)ws;
  704. }
  705. bool ExStyleSet (int ex, WindowExStyles exws)
  706. {
  707. return (ex & (int)exws) == (int)exws;
  708. }
  709. internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
  710. {
  711. return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
  712. }
  713. internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
  714. {
  715. /*
  716. * If this is a form with no window manager, X is handling all the border and caption painting
  717. * so remove that from the area (since the area we set of the window here is the part of the window
  718. * we're painting in only)
  719. */
  720. Rectangle rect = hwnd.ClientRect;
  721. Form form = ctrl as Form;
  722. CreateParams cp = null;
  723. if (form != null)
  724. cp = form.GetCreateParams ();
  725. if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  726. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  727. Rectangle xrect = rect;
  728. xrect.Y -= borders.top;
  729. xrect.X -= borders.left;
  730. xrect.Width += borders.left + borders.right;
  731. xrect.Height += borders.top + borders.bottom;
  732. rect = xrect;
  733. }
  734. if (rect.Width < 1 || rect.Height < 1) {
  735. rect.Width = 1;
  736. rect.Height = 1;
  737. rect.X = -5;
  738. rect.Y = -5;
  739. }
  740. return rect;
  741. }
  742. internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
  743. {
  744. return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
  745. }
  746. internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
  747. {
  748. /*
  749. * If this is a form with no window manager, X is handling all the border and caption painting
  750. * so remove that from the area (since the area we set of the window here is the part of the window
  751. * we're painting in only)
  752. */
  753. Form form = cp.control as Form;
  754. if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  755. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  756. Size xrect = size;
  757. xrect.Width -= borders.left + borders.right;
  758. xrect.Height -= borders.top + borders.bottom;
  759. size = xrect;
  760. }
  761. if (size.Height == 0)
  762. size.Height = 1;
  763. if (size.Width == 0)
  764. size.Width = 1;
  765. return size;
  766. }
  767. internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
  768. {
  769. /*
  770. * If this is a form with no window manager, X is handling all the border and caption painting
  771. * so remove that from the area (since the area we set of the window here is the part of the window
  772. * we're painting in only)
  773. */
  774. Size rect = new Size (xWidth, xHeight);
  775. Form form = cp.control as Form;
  776. if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  777. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  778. Size xrect = rect;
  779. xrect.Width += borders.left + borders.right;
  780. xrect.Height += borders.top + borders.bottom;
  781. rect = xrect;
  782. }
  783. return rect;
  784. }
  785. internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
  786. {
  787. IntPtr dummy;
  788. int x, y;
  789. Hwnd.Borders frame;
  790. XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
  791. frame = FrameExtents (hwnd.whole_window);
  792. x -= frame.left;
  793. y -= frame.top;
  794. return new Point (x, y);
  795. }
  796. void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
  797. caption_height = 0;
  798. tool_caption_height = 19;
  799. border_static = false;
  800. if (StyleSet (Style, WindowStyles.WS_CHILD)) {
  801. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
  802. border_style = FormBorderStyle.Fixed3D;
  803. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
  804. border_style = FormBorderStyle.Fixed3D;
  805. border_static = true;
  806. } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
  807. border_style = FormBorderStyle.None;
  808. } else {
  809. border_style = FormBorderStyle.FixedSingle;
  810. }
  811. title_style = TitleStyle.None;
  812. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  813. caption_height = 19;
  814. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  815. title_style = TitleStyle.Tool;
  816. } else {
  817. title_style = TitleStyle.Normal;
  818. }
  819. }
  820. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
  821. caption_height = 19;
  822. if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
  823. ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  824. border_style = (FormBorderStyle) 0xFFFF;
  825. } else {
  826. border_style = FormBorderStyle.None;
  827. }
  828. }
  829. } else {
  830. title_style = TitleStyle.None;
  831. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  832. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  833. title_style = TitleStyle.Tool;
  834. } else {
  835. title_style = TitleStyle.Normal;
  836. }
  837. }
  838. border_style = FormBorderStyle.None;
  839. if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
  840. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  841. border_style = FormBorderStyle.SizableToolWindow;
  842. } else {
  843. border_style = FormBorderStyle.Sizable;
  844. }
  845. } else {
  846. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  847. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
  848. border_style = FormBorderStyle.Fixed3D;
  849. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
  850. border_style = FormBorderStyle.Fixed3D;
  851. border_static = true;
  852. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
  853. border_style = FormBorderStyle.FixedDialog;
  854. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  855. border_style = FormBorderStyle.FixedToolWindow;
  856. } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
  857. border_style = FormBorderStyle.FixedSingle;
  858. }
  859. } else {
  860. if (StyleSet (Style, WindowStyles.WS_BORDER)) {
  861. border_style = FormBorderStyle.FixedSingle;
  862. }
  863. }
  864. }
  865. }
  866. }
  867. void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
  868. DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.border_static, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
  869. }
  870. void SetWMStyles(Hwnd hwnd, CreateParams cp) {
  871. MotifWmHints mwmHints;
  872. MotifFunctions functions;
  873. MotifDecorations decorations;
  874. int[] atoms;
  875. int atom_count;
  876. Rectangle client_rect;
  877. Form form;
  878. IntPtr window_type;
  879. bool hide_from_taskbar;
  880. IntPtr transient_for_parent;
  881. // Windows we manage ourselves don't need WM window styles.
  882. if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
  883. return;
  884. }
  885. atoms = new int[8];
  886. mwmHints = new MotifWmHints();
  887. functions = 0;
  888. decorations = 0;
  889. window_type = _NET_WM_WINDOW_TYPE_NORMAL;
  890. transient_for_parent = IntPtr.Zero;
  891. mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
  892. mwmHints.functions = (IntPtr)0;
  893. mwmHints.decorations = (IntPtr)0;
  894. form = cp.control as Form;
  895. if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  896. /* tool windows get no window manager
  897. decorations.
  898. */
  899. /* just because the window doesn't get any decorations doesn't
  900. mean we should disable the functions. for instance, without
  901. MotifFunctions.Maximize, changing the windowstate to Maximized
  902. is ignored by metacity. */
  903. functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
  904. } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
  905. /* allow borderless window to be maximized */
  906. functions |= MotifFunctions.All | MotifFunctions.Resize;
  907. } else {
  908. if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
  909. functions |= MotifFunctions.Move;
  910. decorations |= MotifDecorations.Title | MotifDecorations.Menu;
  911. }
  912. if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
  913. functions |= MotifFunctions.Move | MotifFunctions.Resize;
  914. decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
  915. }
  916. if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
  917. functions |= MotifFunctions.Minimize;
  918. decorations |= MotifDecorations.Minimize;
  919. }
  920. if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
  921. functions |= MotifFunctions.Maximize;
  922. decorations |= MotifDecorations.Maximize;
  923. }
  924. if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
  925. functions |= MotifFunctions.Resize;
  926. decorations |= MotifDecorations.ResizeH;
  927. }
  928. if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
  929. decorations |= MotifDecorations.Border;
  930. }
  931. if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
  932. decorations |= MotifDecorations.Border;
  933. }
  934. if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
  935. decorations |= MotifDecorations.Border;
  936. }
  937. if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
  938. functions |= MotifFunctions.Close;
  939. }
  940. else {
  941. functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
  942. decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
  943. if (cp.Caption == "") {
  944. functions &= ~MotifFunctions.Move;
  945. decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
  946. }
  947. }
  948. }
  949. if ((functions & MotifFunctions.Resize) == 0) {
  950. hwnd.fixed_size = true;
  951. Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
  952. SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
  953. } else {
  954. hwnd.fixed_size = false;
  955. }
  956. mwmHints.functions = (IntPtr)functions;
  957. mwmHints.decorations = (IntPtr)decorations;
  958. DriverDebug ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
  959. if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
  960. // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
  961. // and get those windows in front of their parents
  962. window_type = _NET_WM_WINDOW_TYPE_UTILITY;
  963. } else {
  964. window_type = _NET_WM_WINDOW_TYPE_NORMAL;
  965. }
  966. if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
  967. hide_from_taskbar = true;
  968. } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
  969. hide_from_taskbar = true;
  970. } else {
  971. hide_from_taskbar = false;
  972. }
  973. if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  974. if (form != null && !hwnd.reparented) {
  975. if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
  976. Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
  977. if (owner_hwnd != null)
  978. transient_for_parent = owner_hwnd.whole_window;
  979. }
  980. }
  981. }
  982. if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
  983. transient_for_parent = hwnd.parent.whole_window;
  984. }
  985. FormWindowState current_state = GetWindowState (hwnd.Handle);
  986. if (current_state == (FormWindowState)(-1))
  987. current_state = FormWindowState.Normal;
  988. client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
  989. lock (XlibLock) {
  990. atom_count = 0;
  991. atoms [0] = window_type.ToInt32 ();
  992. XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
  993. XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
  994. if (transient_for_parent != IntPtr.Zero) {
  995. XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
  996. }
  997. MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
  998. if (hide_from_taskbar) {
  999. /* this line keeps the window from showing up in gnome's taskbar */
  1000. atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
  1001. }
  1002. /* we need to add these atoms in the
  1003. * event we're maximized, since we're
  1004. * replacing the existing
  1005. * _NET_WM_STATE here. If we don't
  1006. * add them, future calls to
  1007. * GetWindowState will return Normal
  1008. * for a window which is maximized. */
  1009. if (current_state == FormWindowState.Maximized) {
  1010. atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
  1011. atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
  1012. }
  1013. if (form != null && form.Modal) {
  1014. atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
  1015. }
  1016. XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
  1017. atom_count = 0;
  1018. IntPtr[] atom_ptrs = new IntPtr[2];
  1019. atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
  1020. if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
  1021. atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
  1022. }
  1023. XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
  1024. }
  1025. }
  1026. void SetIcon(Hwnd hwnd, Icon icon)
  1027. {
  1028. if (icon == null) {
  1029. // XXX
  1030. // This really needs to do whatever it
  1031. // takes to remove the window manager
  1032. // menu, not just delete the ICON
  1033. // property. This will cause metacity
  1034. // to use the "no icon set" icon, and
  1035. // we'll still have an icon.
  1036. XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
  1037. }
  1038. else {
  1039. Bitmap bitmap;
  1040. int size;
  1041. IntPtr[] data;
  1042. int index;
  1043. bitmap = icon.ToBitmap();
  1044. index = 0;
  1045. size = bitmap.Width * bitmap.Height + 2;
  1046. data = new IntPtr[size];
  1047. data[index++] = (IntPtr)bitmap.Width;
  1048. data[index++] = (IntPtr)bitmap.Height;
  1049. for (int y = 0; y < bitmap.Height; y++) {
  1050. for (int x = 0; x < bitmap.Width; x++) {
  1051. data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
  1052. }
  1053. }
  1054. XChangeProperty (DisplayHandle, hwnd.whole_window,
  1055. _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
  1056. PropertyMode.Replace, data, size);
  1057. }
  1058. }
  1059. void WakeupMain () {
  1060. try {
  1061. wake.Send (new byte [] { 0xFF });
  1062. } catch (SocketException ex) {
  1063. if (ex.SocketErrorCode != SocketError.WouldBlock) {
  1064. throw;
  1065. }
  1066. }
  1067. }
  1068. XEventQueue ThreadQueue(Thread thread) {
  1069. XEventQueue queue;
  1070. queue = (XEventQueue)MessageQueues[thread];
  1071. if (queue == null) {
  1072. queue = new XEventQueue(thread);
  1073. MessageQueues[thread] = queue;
  1074. }
  1075. return queue;
  1076. }
  1077. void TranslatePropertyToClipboard(IntPtr property) {
  1078. IntPtr actual_atom;
  1079. int actual_format;
  1080. IntPtr nitems;
  1081. IntPtr bytes_after;
  1082. IntPtr prop = IntPtr.Zero;
  1083. Clipboard.Item = null;
  1084. XGetWindowProperty(DisplayHandle, FosterParent, property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
  1085. if ((long)nitems > 0) {
  1086. if (property == (IntPtr)Atom.XA_STRING) {
  1087. // Xamarin-5116: PtrToStringAnsi expects to get UTF-8, but we might have
  1088. // Latin-1 instead.
  1089. var s = Marshal.PtrToStringAnsi (prop);
  1090. if (string.IsNullOrEmpty (s)) {
  1091. var sb = new StringBuilder ();
  1092. for (int i = 0; i < (int)nitems; i++) {
  1093. var b = Marshal.ReadByte (prop, i);
  1094. sb.Append ((char)b);
  1095. }
  1096. s = sb.ToString ();
  1097. }
  1098. // Some X managers/apps pass unicode chars as escaped strings, so
  1099. // we may need to unescape them.
  1100. Clipboard.Item = UnescapeUnicodeFromAnsi (s);
  1101. } else if (property == (IntPtr)Atom.XA_BITMAP) {
  1102. // FIXME - convert bitmap to image
  1103. } else if (property == (IntPtr)Atom.XA_PIXMAP) {
  1104. // FIXME - convert pixmap to image
  1105. } else if (property == OEMTEXT) {
  1106. Clipboard.Item = UnescapeUnicodeFromAnsi (Marshal.PtrToStringAnsi(prop));
  1107. } else if (property == UTF8_STRING) {
  1108. byte [] buffer = new byte [(int)nitems];
  1109. for (int i = 0; i < (int)nitems; i++)
  1110. buffer [i] = Marshal.ReadByte (prop, i);
  1111. Clipboard.Item = Encoding.UTF8.GetString (buffer);
  1112. } else if (property == UTF16_STRING) {
  1113. Clipboard.Item = Marshal.PtrToStringUni (prop, Encoding.Unicode.GetMaxCharCount ((int)nitems));
  1114. } else if (property == RICHTEXTFORMAT)
  1115. Clipboard.Item = Marshal.PtrToStringAnsi(prop);
  1116. else if (DataFormats.ContainsFormat (property.ToInt32 ())) {
  1117. if (DataFormats.GetFormat (property.ToInt32 ()).is_serializable) {
  1118. MemoryStream memory_stream = new MemoryStream ((int)nitems);
  1119. for (int i = 0; i < (int)nitems; i++)
  1120. memory_stream.WriteByte (Marshal.ReadByte (prop, i));
  1121. memory_stream.Position = 0;
  1122. BinaryFormatter formatter = new BinaryFormatter ();
  1123. Clipboard.Item = formatter.Deserialize (memory_stream);
  1124. memory_stream.Close ();
  1125. }
  1126. }
  1127. XFree(prop);
  1128. }
  1129. }
  1130. string UnescapeUnicodeFromAnsi (string value)
  1131. {
  1132. if (value == null || value.IndexOf ("\\u") == -1)
  1133. return value;
  1134. StringBuilder sb = new StringBuilder (value.Length);
  1135. int start, pos;
  1136. start = pos = 0;
  1137. while (start < value.Length) {
  1138. pos = value.IndexOf ("\\u", start);
  1139. if (pos == -1)
  1140. break;
  1141. sb.Append (value, start, pos - start);
  1142. pos += 2;
  1143. start = pos;
  1144. int length = 0;
  1145. while (pos < value.Length) {
  1146. if (!ValidHexDigit (value [pos]))
  1147. break;
  1148. length++;
  1149. pos++;
  1150. }
  1151. int res;
  1152. if (!Int32.TryParse (value.Substring (start, length), System.Globalization.NumberStyles.HexNumber,
  1153. null, out res))
  1154. return value; // Error, return the unescaped original value.
  1155. sb.Append ((char)res);
  1156. start = pos;
  1157. }
  1158. // Append any remaining data.
  1159. if (start < value.Length)
  1160. sb.Append (value, start, value.Length - start);
  1161. return sb.ToString ();
  1162. }
  1163. private static bool ValidHexDigit (char e)
  1164. {
  1165. return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
  1166. }
  1167. void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
  1168. // Don't waste time
  1169. if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
  1170. return;
  1171. }
  1172. // Keep the invalid area as small as needed
  1173. if ((x + width) > hwnd.width) {
  1174. width = hwnd.width - x;
  1175. }
  1176. if ((y + height) > hwnd.height) {
  1177. height = hwnd.height - y;
  1178. }
  1179. if (client) {
  1180. hwnd.AddInvalidArea(x, y, width, height);
  1181. if (!hwnd.expose_pending) {
  1182. if (!hwnd.nc_expose_pending) {
  1183. hwnd.Queue.Paint.Enqueue(hwnd);
  1184. }
  1185. hwnd.expose_pending = true;
  1186. }
  1187. } else {
  1188. hwnd.AddNcInvalidArea (x, y, width, height);
  1189. if (!hwnd.nc_expose_pending) {
  1190. if (!hwnd.expose_pending) {
  1191. hwnd.Queue.Paint.Enqueue(hwnd);
  1192. }
  1193. hwnd.nc_expose_pending = true;
  1194. }
  1195. }
  1196. }
  1197. static Hwnd.Borders FrameExtents (IntPtr window)
  1198. {
  1199. IntPtr actual_atom;
  1200. int actual_format;
  1201. IntPtr nitems;
  1202. IntPtr bytes_after;
  1203. IntPtr prop = IntPtr.Zero;
  1204. Hwnd.Borders rect = new Hwnd.Borders ();
  1205. XGetWindowProperty (DisplayHandle, window, _NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
  1206. if (prop != IntPtr.Zero) {
  1207. if (nitems.ToInt32 () == 4) {
  1208. rect.left = Marshal.ReadInt32 (prop, 0);
  1209. rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
  1210. rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
  1211. rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
  1212. }
  1213. XFree (prop);
  1214. }
  1215. return rect;
  1216. }
  1217. void AddConfigureNotify (XEvent xevent) {
  1218. Hwnd hwnd;
  1219. hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
  1220. // Don't waste time
  1221. if (hwnd == null || hwnd.zombie) {
  1222. return;
  1223. }
  1224. if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
  1225. if (hwnd.parent == null) {
  1226. // The location given by the event is not reliable between different wm's,
  1227. // so use an alternative way of getting it.
  1228. Point location = GetTopLevelWindowLocation (hwnd);
  1229. hwnd.x = location.X;
  1230. hwnd.y = location.Y;
  1231. }
  1232. // XXX this sucks. this isn't thread safe
  1233. Control ctrl = Control.FromHandle (hwnd.Handle);
  1234. Size TranslatedSize;
  1235. if (ctrl != null) {
  1236. TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
  1237. } else {
  1238. TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
  1239. }
  1240. hwnd.width = TranslatedSize.Width;
  1241. hwnd.height = TranslatedSize.Height;
  1242. hwnd.ClientRect = Rectangle.Empty;
  1243. DriverDebug ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})",
  1244. new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle,
  1245. new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
  1246. lock (hwnd.configure_lock) {
  1247. if (!hwnd.configure_pending) {
  1248. hwnd.Queue.EnqueueLocked (xevent);
  1249. hwnd.configure_pending = true;
  1250. }
  1251. }
  1252. }
  1253. // We drop configure events for Client windows
  1254. }
  1255. void ShowCaret() {
  1256. if ((Caret.gc == IntPtr.Zero) || Caret.On) {
  1257. return;
  1258. }
  1259. Caret.On = true;
  1260. lock (XlibLock) {
  1261. XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
  1262. }
  1263. }
  1264. void HideCaret() {
  1265. if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
  1266. return;
  1267. }
  1268. Caret.On = false;
  1269. lock (XlibLock) {
  1270. XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
  1271. }
  1272. }
  1273. int NextTimeout (ArrayList timers, DateTime now) {
  1274. int timeout = 0;
  1275. foreach (Timer timer in timers) {
  1276. int next = (int) (timer.Expires - now).TotalMilliseconds;
  1277. if (next < 0) {
  1278. return 0; // Have a timer that has already expired
  1279. }
  1280. if (next < timeout) {
  1281. timeout = next;
  1282. }
  1283. }
  1284. if (timeout < Timer.Minimum) {
  1285. timeout = Timer.Minimum;
  1286. }
  1287. if (timeout > 1000)
  1288. timeout = 1000;
  1289. return timeout;
  1290. }
  1291. void CheckTimers (ArrayList timers, DateTime now) {
  1292. int count;
  1293. count = timers.Count;
  1294. if (count == 0)
  1295. return;
  1296. for (int i = 0; i < timers.Count; i++) {
  1297. Timer timer;
  1298. timer = (Timer) timers [i];
  1299. if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
  1300. // Timer ticks:
  1301. // - Before MainForm.OnLoad if DoEvents () is called.
  1302. // - After MainForm.OnLoad if not.
  1303. //
  1304. if (in_doevents ||
  1305. (Application.MWFThread.Current.Context != null &&
  1306. (Application.MWFThread.Current.Context.MainForm == null ||
  1307. Application.MWFThread.Current.Context.MainForm.IsLoaded))) {
  1308. timer.Busy = true;
  1309. timer.Update (now);
  1310. timer.FireTick ();
  1311. timer.Busy = false;
  1312. }
  1313. }
  1314. }
  1315. }
  1316. void WaitForHwndMessage (Hwnd hwnd, Msg message) {
  1317. WaitForHwndMessage (hwnd, message, false);
  1318. }
  1319. void WaitForHwndMessage (Hwnd hwnd, Msg message, bool process) {
  1320. MSG msg = new MSG ();
  1321. XEventQueue queue;
  1322. queue = ThreadQueue(Thread.CurrentThread);
  1323. queue.DispatchIdle = false;
  1324. bool done = false;
  1325. string key = hwnd.Handle + ":" + message;
  1326. if (!messageHold.ContainsKey (key))
  1327. messageHold.Add (key, 1);
  1328. else
  1329. messageHold[key] = ((int)messageHold[key]) + 1;
  1330. do {
  1331. DebugHelper.WriteLine ("Waiting for message " + message + " on hwnd " + String.Format("0x{0:x}", hwnd.Handle.ToInt32 ()));
  1332. DebugHelper.Indent ();
  1333. if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
  1334. if ((Msg)msg.message == Msg.WM_QUIT) {
  1335. PostQuitMessage (0);
  1336. done = true;
  1337. }
  1338. else {
  1339. DebugHelper.WriteLine ("PeekMessage got " + msg);
  1340. if (msg.hwnd == hwnd.Handle) {
  1341. if ((Msg)msg.message == message) {
  1342. if (process) {
  1343. TranslateMessage (ref msg);
  1344. DispatchMessage (ref msg);
  1345. }
  1346. break;
  1347. }
  1348. else if ((Msg)msg.message == Msg.WM_DESTROY)
  1349. done = true;
  1350. }
  1351. TranslateMessage (ref msg);
  1352. DispatchMessage (ref msg);
  1353. }
  1354. }
  1355. done = !messageHold.ContainsKey (key) || ((int)messageHold[key] < 1) || done;
  1356. } while (!done);
  1357. messageHold.Remove (k

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