PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/danipen/mono
C# | 2418 lines | 1871 code | 427 blank | 120 comment | 389 complexity | 6e0edcc1f8837db7d4c77905bc9192da 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-2007 Novell, Inc.
  21. //
  22. // Authors:
  23. // Geoff Norton <gnorton@novell.com>
  24. //
  25. //
  26. using System;
  27. using System.Threading;
  28. using System.Drawing;
  29. using System.ComponentModel;
  30. using System.Collections;
  31. using System.Diagnostics;
  32. using System.Runtime.InteropServices;
  33. using Carbon = System.Windows.Forms.CarbonInternal;
  34. /// Carbon Version
  35. namespace System.Windows.Forms {
  36. internal delegate Rectangle [] HwndDelegate (IntPtr handle);
  37. internal class XplatUICarbon : XplatUIDriver {
  38. #region Local Variables
  39. // General driver variables
  40. private static XplatUICarbon Instance;
  41. private static int RefCount;
  42. private static bool themes_enabled;
  43. // Internal members available to the event handler sub-system
  44. internal static IntPtr FocusWindow;
  45. internal static IntPtr ActiveWindow;
  46. internal static IntPtr UnactiveWindow;
  47. internal static IntPtr ReverseWindow;
  48. internal static IntPtr CaretWindow;
  49. internal static Hwnd MouseHwnd;
  50. internal static MouseButtons MouseState;
  51. internal static Carbon.Hover Hover;
  52. internal static HwndDelegate HwndDelegate = new HwndDelegate (GetClippingRectangles);
  53. // Instance members
  54. internal Point mouse_position;
  55. // Event handlers
  56. internal Carbon.ApplicationHandler ApplicationHandler;
  57. internal Carbon.ControlHandler ControlHandler;
  58. internal Carbon.HIObjectHandler HIObjectHandler;
  59. internal Carbon.KeyboardHandler KeyboardHandler;
  60. internal Carbon.MouseHandler MouseHandler;
  61. internal Carbon.WindowHandler WindowHandler;
  62. // Carbon Specific
  63. internal static GrabStruct Grab;
  64. internal static Carbon.Caret Caret;
  65. private static Carbon.Dnd Dnd;
  66. private static Hashtable WindowMapping;
  67. private static Hashtable HandleMapping;
  68. private static IntPtr FosterParent;
  69. private static IntPtr Subclass;
  70. private static int MenuBarHeight;
  71. internal static ArrayList UtilityWindows;
  72. // Message loop
  73. private static Queue MessageQueue;
  74. private static bool GetMessageResult;
  75. private static bool ReverseWindowMapped;
  76. // Timers
  77. private ArrayList TimerList;
  78. private static bool in_doevents;
  79. static readonly object instancelock = new object ();
  80. static readonly object queuelock = new object ();
  81. // Event Handlers
  82. internal override event EventHandler Idle;
  83. #endregion
  84. #region Constructors
  85. private XplatUICarbon() {
  86. RefCount = 0;
  87. TimerList = new ArrayList ();
  88. in_doevents = false;
  89. MessageQueue = new Queue ();
  90. Initialize ();
  91. }
  92. ~XplatUICarbon() {
  93. // FIXME: Clean up the FosterParent here.
  94. }
  95. #endregion
  96. #region Singleton specific code
  97. public static XplatUICarbon GetInstance() {
  98. lock (instancelock) {
  99. if (Instance == null) {
  100. Instance = new XplatUICarbon ();
  101. }
  102. RefCount++;
  103. }
  104. return Instance;
  105. }
  106. public int Reference {
  107. get {
  108. return RefCount;
  109. }
  110. }
  111. #endregion
  112. #region Internal methods
  113. internal void AddExpose (Hwnd hwnd, bool client, Carbon.HIRect rect) {
  114. AddExpose (hwnd, client, (int) rect.origin.x, (int) rect.origin.y, (int) rect.size.width, (int) rect.size.height);
  115. }
  116. internal void AddExpose (Hwnd hwnd, bool client, Rectangle rect) {
  117. AddExpose (hwnd, client, (int) rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height);
  118. }
  119. internal void FlushQueue () {
  120. CheckTimers (DateTime.UtcNow);
  121. lock (queuelock) {
  122. while (MessageQueue.Count > 0) {
  123. object queueobj = MessageQueue.Dequeue ();
  124. if (queueobj is GCHandle) {
  125. XplatUIDriverSupport.ExecuteClientMessage((GCHandle)queueobj);
  126. } else {
  127. MSG msg = (MSG)queueobj;
  128. NativeWindow.WndProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
  129. }
  130. }
  131. }
  132. }
  133. internal static Rectangle [] GetClippingRectangles (IntPtr handle) {
  134. Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
  135. if (hwnd == null)
  136. return null;
  137. if (hwnd.Handle != handle)
  138. return new Rectangle [] {hwnd.ClientRect};
  139. return (Rectangle []) hwnd.GetClippingRectangles ().ToArray (typeof (Rectangle));
  140. }
  141. internal IntPtr GetMousewParam(int Delta) {
  142. int result = 0;
  143. if ((MouseState & MouseButtons.Left) != 0) {
  144. result |= (int)MsgButtons.MK_LBUTTON;
  145. }
  146. if ((MouseState & MouseButtons.Middle) != 0) {
  147. result |= (int)MsgButtons.MK_MBUTTON;
  148. }
  149. if ((MouseState & MouseButtons.Right) != 0) {
  150. result |= (int)MsgButtons.MK_RBUTTON;
  151. }
  152. Keys mods = ModifierKeys;
  153. if ((mods & Keys.Control) != 0) {
  154. result |= (int)MsgButtons.MK_CONTROL;
  155. }
  156. if ((mods & Keys.Shift) != 0) {
  157. result |= (int)MsgButtons.MK_SHIFT;
  158. }
  159. result |= Delta << 16;
  160. return (IntPtr)result;
  161. }
  162. internal IntPtr HandleToWindow (IntPtr handle) {
  163. if (HandleMapping [handle] != null)
  164. return (IntPtr) HandleMapping [handle];
  165. return IntPtr.Zero;
  166. }
  167. internal void Initialize () {
  168. // Initialize the event handlers
  169. Carbon.EventHandler.Driver = this;
  170. ApplicationHandler = new Carbon.ApplicationHandler (this);
  171. ControlHandler = new Carbon.ControlHandler (this);
  172. HIObjectHandler = new Carbon.HIObjectHandler (this);
  173. KeyboardHandler = new Carbon.KeyboardHandler (this);
  174. MouseHandler = new Carbon.MouseHandler (this);
  175. WindowHandler = new Carbon.WindowHandler (this);
  176. // Initilize the mouse controls
  177. Hover.Interval = 500;
  178. Hover.Timer = new Timer ();
  179. Hover.Timer.Enabled = false;
  180. Hover.Timer.Interval = Hover.Interval;
  181. Hover.Timer.Tick += new EventHandler (HoverCallback);
  182. Hover.X = -1;
  183. Hover.Y = -1;
  184. MouseState = MouseButtons.None;
  185. mouse_position = Point.Empty;
  186. // Initialize the Caret
  187. Caret.Timer = new Timer ();
  188. Caret.Timer.Interval = 500;
  189. Caret.Timer.Tick += new EventHandler (CaretCallback);
  190. // Initialize the D&D
  191. Dnd = new Carbon.Dnd ();
  192. // Initialize the Carbon Specific stuff
  193. WindowMapping = new Hashtable ();
  194. HandleMapping = new Hashtable ();
  195. UtilityWindows = new ArrayList ();
  196. // Initialize the FosterParent
  197. Carbon.Rect rect = new Carbon.Rect ();
  198. SetRect (ref rect, (short)0, (short)0, (short)0, (short)0);
  199. Carbon.ProcessSerialNumber psn = new Carbon.ProcessSerialNumber();
  200. GetCurrentProcess( ref psn );
  201. TransformProcessType (ref psn, 1);
  202. SetFrontProcess (ref psn);
  203. HIObjectRegisterSubclass (__CFStringMakeConstantString ("com.novell.mwfview"), __CFStringMakeConstantString ("com.apple.hiview"), 0, Carbon.EventHandler.EventHandlerDelegate, (uint)Carbon.EventHandler.HIObjectEvents.Length, Carbon.EventHandler.HIObjectEvents, IntPtr.Zero, ref Subclass);
  204. Carbon.EventHandler.InstallApplicationHandler ();
  205. CreateNewWindow (Carbon.WindowClass.kDocumentWindowClass, Carbon.WindowAttributes.kWindowStandardHandlerAttribute | Carbon.WindowAttributes.kWindowCloseBoxAttribute | Carbon.WindowAttributes.kWindowFullZoomAttribute | Carbon.WindowAttributes.kWindowCollapseBoxAttribute | Carbon.WindowAttributes.kWindowResizableAttribute | Carbon.WindowAttributes.kWindowCompositingAttribute, ref rect, ref FosterParent);
  206. CreateNewWindow (Carbon.WindowClass.kOverlayWindowClass, Carbon.WindowAttributes.kWindowNoUpdatesAttribute | Carbon.WindowAttributes.kWindowNoActivatesAttribute, ref rect, ref ReverseWindow);
  207. CreateNewWindow (Carbon.WindowClass.kOverlayWindowClass, Carbon.WindowAttributes.kWindowNoUpdatesAttribute | Carbon.WindowAttributes.kWindowNoActivatesAttribute, ref rect, ref CaretWindow);
  208. // Get some values about bar heights
  209. Carbon.Rect structRect = new Carbon.Rect ();
  210. Carbon.Rect contentRect = new Carbon.Rect ();
  211. GetWindowBounds (FosterParent, 32, ref structRect);
  212. GetWindowBounds (FosterParent, 33, ref contentRect);
  213. MenuBarHeight = GetMBarHeight ();
  214. // Focus
  215. FocusWindow = IntPtr.Zero;
  216. // Message loop
  217. GetMessageResult = true;
  218. ReverseWindowMapped = false;
  219. }
  220. internal void PerformNCCalc(Hwnd hwnd) {
  221. XplatUIWin32.NCCALCSIZE_PARAMS ncp;
  222. IntPtr ptr;
  223. Rectangle rect;
  224. rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
  225. ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
  226. ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
  227. ncp.rgrc1.left = rect.Left;
  228. ncp.rgrc1.top = rect.Top;
  229. ncp.rgrc1.right = rect.Right;
  230. ncp.rgrc1.bottom = rect.Bottom;
  231. Marshal.StructureToPtr(ncp, ptr, true);
  232. NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
  233. ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
  234. Marshal.FreeHGlobal(ptr);
  235. rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
  236. hwnd.ClientRect = rect;
  237. rect = TranslateClientRectangleToQuartzClientRectangle (hwnd);
  238. if (hwnd.visible) {
  239. Carbon.HIRect r = new Carbon.HIRect (rect.X, rect.Y, rect.Width, rect.Height);
  240. HIViewSetFrame (hwnd.client_window, ref r);
  241. }
  242. AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
  243. }
  244. internal void ScreenToClient(IntPtr handle, ref Carbon.QDPoint point) {
  245. int x = (int) point.x;
  246. int y = (int) point.y;
  247. ScreenToClient (handle, ref x, ref y);
  248. point.x = (short) x;
  249. point.y = (short) y;
  250. }
  251. internal static Rectangle TranslateClientRectangleToQuartzClientRectangle (Hwnd hwnd) {
  252. return TranslateClientRectangleToQuartzClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
  253. }
  254. internal static Rectangle TranslateClientRectangleToQuartzClientRectangle (Hwnd hwnd, Control ctrl) {
  255. /* From XplatUIX11
  256. * If this is a form with no window manager, X is handling all the border and caption painting
  257. * so remove that from the area (since the area we set of the window here is the part of the window
  258. * we're painting in only)
  259. */
  260. Rectangle rect = hwnd.ClientRect;
  261. Form form = ctrl as Form;
  262. CreateParams cp = null;
  263. if (form != null)
  264. cp = form.GetCreateParams ();
  265. if (form != null && (form.window_manager == null || cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  266. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  267. Rectangle qrect = rect;
  268. qrect.Y -= borders.top;
  269. qrect.X -= borders.left;
  270. qrect.Width += borders.left + borders.right;
  271. qrect.Height += borders.top + borders.bottom;
  272. rect = qrect;
  273. }
  274. if (rect.Width < 1 || rect.Height < 1) {
  275. rect.Width = 1;
  276. rect.Height = 1;
  277. rect.X = -5;
  278. rect.Y = -5;
  279. }
  280. return rect;
  281. }
  282. internal static Size TranslateWindowSizeToQuartzWindowSize (CreateParams cp) {
  283. return TranslateWindowSizeToQuartzWindowSize (cp, new Size (cp.Width, cp.Height));
  284. }
  285. internal static Size TranslateWindowSizeToQuartzWindowSize (CreateParams cp, Size size) {
  286. /* From XplatUIX11
  287. * If this is a form with no window manager, X is handling all the border and caption painting
  288. * so remove that from the area (since the area we set of the window here is the part of the window
  289. * we're painting in only)
  290. */
  291. Form form = cp.control as Form;
  292. if (form != null && (form.window_manager == null || cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  293. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  294. Size qsize = size;
  295. qsize.Width -= borders.left + borders.right;
  296. qsize.Height -= borders.top + borders.bottom;
  297. size = qsize;
  298. }
  299. if (size.Height == 0)
  300. size.Height = 1;
  301. if (size.Width == 0)
  302. size.Width = 1;
  303. return size;
  304. }
  305. internal static Size TranslateQuartzWindowSizeToWindowSize (CreateParams cp, int width, int height) {
  306. /* From XplatUIX11
  307. * If this is a form with no window manager, X is handling all the border and caption painting
  308. * so remove that from the area (since the area we set of the window here is the part of the window
  309. * we're painting in only)
  310. */
  311. Size size = new Size (width, height);
  312. Form form = cp.control as Form;
  313. if (form != null && (form.window_manager == null || cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
  314. Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
  315. Size qsize = size;
  316. qsize.Width += borders.left + borders.right;
  317. qsize.Height += borders.top + borders.bottom;
  318. size = qsize;
  319. }
  320. return size;
  321. }
  322. #endregion
  323. #region Callbacks
  324. private void CaretCallback (object sender, EventArgs e) {
  325. if (Caret.Paused) {
  326. return;
  327. }
  328. if (!Caret.On) {
  329. ShowCaret ();
  330. } else {
  331. HideCaret ();
  332. }
  333. }
  334. private void HoverCallback (object sender, EventArgs e) {
  335. if ((Hover.X == mouse_position.X) && (Hover.Y == mouse_position.Y)) {
  336. MSG msg = new MSG ();
  337. msg.hwnd = Hover.Hwnd;
  338. msg.message = Msg.WM_MOUSEHOVER;
  339. msg.wParam = GetMousewParam (0);
  340. msg.lParam = (IntPtr)((ushort)Hover.X << 16 | (ushort)Hover.X);
  341. EnqueueMessage (msg);
  342. }
  343. }
  344. #endregion
  345. #region Private Methods
  346. private Point ConvertScreenPointToClient (IntPtr handle, Point point) {
  347. Point converted_point = new Point ();
  348. Carbon.Rect window_bounds = new Carbon.Rect ();
  349. Carbon.CGPoint native_point = new Carbon.CGPoint ();
  350. GetWindowBounds (HIViewGetWindow (handle), 32, ref window_bounds);
  351. native_point.x = (point.X - window_bounds.left);
  352. native_point.y = (point.Y - window_bounds.top);
  353. HIViewConvertPoint (ref native_point, IntPtr.Zero, handle);
  354. converted_point.X = (int)native_point.x;
  355. converted_point.Y = (int)native_point.y;
  356. return converted_point;
  357. }
  358. private Point ConvertClientPointToScreen (IntPtr handle, Point point) {
  359. Point converted_point = new Point ();
  360. Carbon.Rect window_bounds = new Carbon.Rect ();
  361. Carbon.CGPoint native_point = new Carbon.CGPoint ();
  362. GetWindowBounds (HIViewGetWindow (handle), 32, ref window_bounds);
  363. native_point.x = point.X;
  364. native_point.y = point.Y;
  365. HIViewConvertPoint (ref native_point, handle, IntPtr.Zero);
  366. converted_point.X = (int)(native_point.x + window_bounds.left);
  367. converted_point.Y = (int)(native_point.y + window_bounds.top);
  368. return converted_point;
  369. }
  370. private double NextTimeout () {
  371. DateTime now = DateTime.UtcNow;
  372. int timeout = 0x7FFFFFF;
  373. lock (TimerList) {
  374. foreach (Timer timer in TimerList) {
  375. int next = (int) (timer.Expires - now).TotalMilliseconds;
  376. if (next < 0)
  377. return 0;
  378. if (next < timeout)
  379. timeout = next;
  380. }
  381. }
  382. if (timeout < Timer.Minimum)
  383. timeout = Timer.Minimum;
  384. return (double)((double)timeout/1000);
  385. }
  386. private void CheckTimers (DateTime now) {
  387. lock (TimerList) {
  388. int count = TimerList.Count;
  389. if (count == 0)
  390. return;
  391. for (int i = 0; i < TimerList.Count; i++) {
  392. Timer timer = (Timer) TimerList [i];
  393. if (timer.Enabled && timer.Expires <= now) {
  394. // Timer ticks:
  395. // - Before MainForm.OnLoad if DoEvents () is called.
  396. // - After MainForm.OnLoad if not.
  397. //
  398. if (in_doevents ||
  399. (Application.MWFThread.Current.Context != null &&
  400. Application.MWFThread.Current.Context.MainForm != null &&
  401. Application.MWFThread.Current.Context.MainForm.IsLoaded)) {
  402. timer.FireTick ();
  403. timer.Update (now);
  404. }
  405. }
  406. }
  407. }
  408. }
  409. private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
  410. MSG msg = new MSG ();
  411. bool done = false;
  412. do {
  413. if (GetMessage(null, ref msg, IntPtr.Zero, 0, 0)) {
  414. if ((Msg)msg.message == Msg.WM_QUIT) {
  415. PostQuitMessage (0);
  416. done = true;
  417. }
  418. else {
  419. if (msg.hwnd == hwnd.Handle) {
  420. if ((Msg)msg.message == message)
  421. break;
  422. else if ((Msg)msg.message == Msg.WM_DESTROY)
  423. done = true;
  424. }
  425. TranslateMessage (ref msg);
  426. DispatchMessage (ref msg);
  427. }
  428. }
  429. } while (!done);
  430. }
  431. private void SendParentNotify(IntPtr child, Msg cause, int x, int y) {
  432. Hwnd hwnd;
  433. if (child == IntPtr.Zero) {
  434. return;
  435. }
  436. hwnd = Hwnd.GetObjectFromWindow (child);
  437. if (hwnd == null) {
  438. return;
  439. }
  440. if (hwnd.Handle == IntPtr.Zero) {
  441. return;
  442. }
  443. if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
  444. return;
  445. }
  446. if (hwnd.Parent == null) {
  447. return;
  448. }
  449. if (hwnd.Parent.Handle == IntPtr.Zero) {
  450. return;
  451. }
  452. if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
  453. SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
  454. } else {
  455. SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
  456. }
  457. SendParentNotify (hwnd.Parent.Handle, cause, x, y);
  458. }
  459. private bool StyleSet (int s, WindowStyles ws) {
  460. return (s & (int)ws) == (int)ws;
  461. }
  462. private bool ExStyleSet (int ex, WindowExStyles exws) {
  463. return (ex & (int)exws) == (int)exws;
  464. }
  465. private 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) {
  466. caption_height = 0;
  467. tool_caption_height = 0;
  468. border_static = false;
  469. if (StyleSet (Style, WindowStyles.WS_CHILD)) {
  470. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
  471. border_style = FormBorderStyle.Fixed3D;
  472. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
  473. border_style = FormBorderStyle.Fixed3D;
  474. border_static = true;
  475. } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
  476. border_style = FormBorderStyle.None;
  477. } else {
  478. border_style = FormBorderStyle.FixedSingle;
  479. }
  480. title_style = TitleStyle.None;
  481. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  482. caption_height = 0;
  483. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  484. title_style = TitleStyle.Tool;
  485. } else {
  486. title_style = TitleStyle.Normal;
  487. }
  488. }
  489. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
  490. caption_height = 0;
  491. if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
  492. ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  493. border_style = (FormBorderStyle) 0xFFFF;
  494. } else {
  495. border_style = FormBorderStyle.None;
  496. }
  497. }
  498. } else {
  499. title_style = TitleStyle.None;
  500. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  501. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  502. title_style = TitleStyle.Tool;
  503. } else {
  504. title_style = TitleStyle.Normal;
  505. }
  506. }
  507. border_style = FormBorderStyle.None;
  508. if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
  509. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  510. border_style = FormBorderStyle.SizableToolWindow;
  511. } else {
  512. border_style = FormBorderStyle.Sizable;
  513. }
  514. } else {
  515. if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
  516. if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
  517. border_style = FormBorderStyle.Fixed3D;
  518. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
  519. border_style = FormBorderStyle.Fixed3D;
  520. border_static = true;
  521. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
  522. border_style = FormBorderStyle.FixedDialog;
  523. } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
  524. border_style = FormBorderStyle.FixedToolWindow;
  525. } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
  526. border_style = FormBorderStyle.FixedSingle;
  527. }
  528. } else {
  529. if (StyleSet (Style, WindowStyles.WS_BORDER)) {
  530. border_style = FormBorderStyle.FixedSingle;
  531. }
  532. }
  533. }
  534. }
  535. }
  536. private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
  537. 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);
  538. }
  539. private void ShowCaret () {
  540. if (Caret.On)
  541. return;
  542. Caret.On = true;
  543. ShowWindow (CaretWindow);
  544. Graphics g = Graphics.FromHwnd (HIViewGetRoot (CaretWindow));
  545. g.FillRectangle (new SolidBrush (Color.Black), new Rectangle (0, 0, Caret.Width, Caret.Height));
  546. g.Dispose ();
  547. }
  548. private void HideCaret () {
  549. if (!Caret.On)
  550. return;
  551. Caret.On = false;
  552. HideWindow (CaretWindow);
  553. }
  554. private void AccumulateDestroyedHandles (Control c, ArrayList list) {
  555. if (c != null) {
  556. Control[] controls = c.Controls.GetAllControls ();
  557. if (c.IsHandleCreated && !c.IsDisposed) {
  558. Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
  559. list.Add (hwnd);
  560. CleanupCachedWindows (hwnd);
  561. }
  562. for (int i = 0; i < controls.Length; i ++) {
  563. AccumulateDestroyedHandles (controls[i], list);
  564. }
  565. }
  566. }
  567. private void CleanupCachedWindows (Hwnd hwnd) {
  568. if (ActiveWindow == hwnd.Handle) {
  569. SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
  570. ActiveWindow = IntPtr.Zero;
  571. }
  572. if (FocusWindow == hwnd.Handle) {
  573. SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
  574. FocusWindow = IntPtr.Zero;
  575. }
  576. if (Grab.Hwnd == hwnd.Handle) {
  577. Grab.Hwnd = IntPtr.Zero;
  578. Grab.Confined = false;
  579. }
  580. DestroyCaret (hwnd.Handle);
  581. }
  582. private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
  583. // Don't waste time
  584. if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
  585. return;
  586. }
  587. // Keep the invalid area as small as needed
  588. if ((x + width) > hwnd.width) {
  589. width = hwnd.width - x;
  590. }
  591. if ((y + height) > hwnd.height) {
  592. height = hwnd.height - y;
  593. }
  594. if (client) {
  595. hwnd.AddInvalidArea(x, y, width, height);
  596. if (!hwnd.expose_pending && hwnd.visible) {
  597. MSG msg = new MSG ();
  598. msg.message = Msg.WM_PAINT;
  599. msg.hwnd = hwnd.Handle;
  600. EnqueueMessage (msg);
  601. hwnd.expose_pending = true;
  602. }
  603. } else {
  604. hwnd.AddNcInvalidArea (x, y, width, height);
  605. if (!hwnd.nc_expose_pending && hwnd.visible) {
  606. MSG msg = new MSG ();
  607. Region rgn = new Region (hwnd.Invalid);
  608. IntPtr hrgn = rgn.GetHrgn (null); // Graphics object isn't needed
  609. msg.message = Msg.WM_NCPAINT;
  610. msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
  611. msg.refobject = rgn;
  612. msg.hwnd = hwnd.Handle;
  613. EnqueueMessage (msg);
  614. hwnd.nc_expose_pending = true;
  615. }
  616. }
  617. }
  618. #endregion
  619. #region Public Methods
  620. internal void EnqueueMessage (MSG msg) {
  621. lock (queuelock) {
  622. MessageQueue.Enqueue (msg);
  623. }
  624. }
  625. internal override void RaiseIdle (EventArgs e)
  626. {
  627. if (Idle != null)
  628. Idle (this, e);
  629. }
  630. internal override IntPtr InitializeDriver() {
  631. return IntPtr.Zero;
  632. }
  633. internal override void ShutdownDriver(IntPtr token) {
  634. }
  635. internal override void EnableThemes() {
  636. themes_enabled = true;
  637. }
  638. internal override void Activate(IntPtr handle) {
  639. if (ActiveWindow != IntPtr.Zero) {
  640. UnactiveWindow = ActiveWindow;
  641. ActivateWindow (HIViewGetWindow (ActiveWindow), false);
  642. }
  643. ActivateWindow (HIViewGetWindow (handle), true);
  644. ActiveWindow = handle;
  645. }
  646. internal override void AudibleAlert(AlertType alert) {
  647. AlertSoundPlay ();
  648. }
  649. internal override void BeginMoveResize (IntPtr handle) {
  650. }
  651. internal override void CaretVisible (IntPtr hwnd, bool visible) {
  652. if (Caret.Hwnd == hwnd) {
  653. if (visible) {
  654. if (Caret.Visible < 1) {
  655. Caret.Visible++;
  656. Caret.On = false;
  657. if (Caret.Visible == 1) {
  658. ShowCaret ();
  659. Caret.Timer.Start ();
  660. }
  661. }
  662. } else {
  663. Caret.Visible--;
  664. if (Caret.Visible == 0) {
  665. Caret.Timer.Stop ();
  666. HideCaret ();
  667. }
  668. }
  669. }
  670. }
  671. internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
  672. WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
  673. return true;
  674. }
  675. internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
  676. Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
  677. Point point = ConvertClientPointToScreen (hwnd.ClientWindow, new Point (x, y));
  678. x = point.X;
  679. y = point.Y;
  680. }
  681. internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
  682. Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
  683. Point point = ConvertClientPointToScreen (hwnd.ClientWindow, new Point (x, y));
  684. x = point.X;
  685. y = point.Y;
  686. }
  687. internal override int[] ClipboardAvailableFormats(IntPtr handle) {
  688. ArrayList list = new ArrayList ();
  689. DataFormats.Format f = DataFormats.Format.List;
  690. while (f != null) {
  691. list.Add (f.Id);
  692. f = f.Next;
  693. }
  694. return (int [])list.ToArray (typeof (int));
  695. }
  696. internal override void ClipboardClose(IntPtr handle) {
  697. }
  698. //TODO: Map our internal formats to the right os code where we can
  699. internal override int ClipboardGetID(IntPtr handle, string format) {
  700. return (int)__CFStringMakeConstantString (format);
  701. }
  702. internal override IntPtr ClipboardOpen(bool primary_selection) {
  703. if (primary_selection)
  704. return Carbon.Pasteboard.Primary;
  705. return Carbon.Pasteboard.Application;
  706. }
  707. internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
  708. return Carbon.Pasteboard.Retrieve (handle, type);
  709. }
  710. internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy) {
  711. Carbon.Pasteboard.Store (handle, obj, type);
  712. }
  713. internal override void CreateCaret (IntPtr hwnd, int width, int height) {
  714. if (Caret.Hwnd != IntPtr.Zero)
  715. DestroyCaret (Caret.Hwnd);
  716. Caret.Hwnd = hwnd;
  717. Caret.Width = width;
  718. Caret.Height = height;
  719. Caret.Visible = 0;
  720. Caret.On = false;
  721. }
  722. internal override IntPtr CreateWindow(CreateParams cp) {
  723. Hwnd hwnd;
  724. Hwnd parent_hwnd = null;
  725. int X;
  726. int Y;
  727. int Width;
  728. int Height;
  729. IntPtr ParentHandle;
  730. IntPtr WindowHandle;
  731. IntPtr WholeWindow;
  732. IntPtr ClientWindow;
  733. IntPtr WholeWindowTracking;
  734. IntPtr ClientWindowTracking;
  735. hwnd = new Hwnd ();
  736. X = cp.X;
  737. Y = cp.Y;
  738. Width = cp.Width;
  739. Height = cp.Height;
  740. ParentHandle = IntPtr.Zero;
  741. WindowHandle = IntPtr.Zero;
  742. WholeWindow = IntPtr.Zero;
  743. ClientWindow = IntPtr.Zero;
  744. WholeWindowTracking = IntPtr.Zero;
  745. ClientWindowTracking = IntPtr.Zero;
  746. if (Width < 1) Width = 1;
  747. if (Height < 1) Height = 1;
  748. if (cp.Parent != IntPtr.Zero) {
  749. parent_hwnd = Hwnd.ObjectFromHandle (cp.Parent);
  750. ParentHandle = parent_hwnd.client_window;
  751. } else {
  752. if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
  753. HIViewFindByID (HIViewGetRoot (FosterParent), new Carbon.HIViewID (Carbon.EventHandler.kEventClassWindow, 1), ref ParentHandle);
  754. }
  755. }
  756. Point next;
  757. if (cp.control is Form) {
  758. next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
  759. X = next.X;
  760. Y = next.Y;
  761. }
  762. hwnd.x = X;
  763. hwnd.y = Y;
  764. hwnd.width = Width;
  765. hwnd.height = Height;
  766. hwnd.Parent = Hwnd.ObjectFromHandle (cp.Parent);
  767. hwnd.initial_style = cp.WindowStyle;
  768. hwnd.initial_ex_style = cp.WindowExStyle;
  769. hwnd.visible = false;
  770. if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
  771. hwnd.enabled = false;
  772. }
  773. ClientWindow = IntPtr.Zero;
  774. Size QWindowSize = TranslateWindowSizeToQuartzWindowSize (cp);
  775. Rectangle QClientRect = TranslateClientRectangleToQuartzClientRectangle (hwnd, cp.control);
  776. SetHwndStyles(hwnd, cp);
  777. /* FIXME */
  778. if (ParentHandle == IntPtr.Zero) {
  779. IntPtr WindowView = IntPtr.Zero;
  780. IntPtr GrowBox = IntPtr.Zero;
  781. Carbon.WindowClass windowklass = Carbon.WindowClass.kOverlayWindowClass;
  782. Carbon.WindowAttributes attributes = Carbon.WindowAttributes.kWindowCompositingAttribute | Carbon.WindowAttributes.kWindowStandardHandlerAttribute;
  783. if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
  784. attributes |= Carbon.WindowAttributes.kWindowCollapseBoxAttribute;
  785. }
  786. if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
  787. attributes |= Carbon.WindowAttributes.kWindowResizableAttribute | Carbon.WindowAttributes.kWindowHorizontalZoomAttribute | Carbon.WindowAttributes.kWindowVerticalZoomAttribute;
  788. }
  789. if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
  790. attributes |= Carbon.WindowAttributes.kWindowCloseBoxAttribute;
  791. }
  792. if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
  793. windowklass = Carbon.WindowClass.kDocumentWindowClass;
  794. }
  795. if (hwnd.border_style == FormBorderStyle.FixedToolWindow) {
  796. windowklass = Carbon.WindowClass.kUtilityWindowClass;
  797. } else if (hwnd.border_style == FormBorderStyle.SizableToolWindow) {
  798. attributes |= Carbon.WindowAttributes.kWindowResizableAttribute;
  799. windowklass = Carbon.WindowClass.kUtilityWindowClass;
  800. }
  801. if (windowklass == Carbon.WindowClass.kOverlayWindowClass) {
  802. attributes = Carbon.WindowAttributes.kWindowCompositingAttribute | Carbon.WindowAttributes.kWindowStandardHandlerAttribute;
  803. }
  804. attributes |= Carbon.WindowAttributes.kWindowLiveResizeAttribute;
  805. Carbon.Rect rect = new Carbon.Rect ();
  806. if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
  807. SetRect (ref rect, (short)X, (short)(Y), (short)(X + QWindowSize.Width), (short)(Y + QWindowSize.Height));
  808. } else {
  809. SetRect (ref rect, (short)X, (short)(Y + MenuBarHeight), (short)(X + QWindowSize.Width), (short)(Y + MenuBarHeight + QWindowSize.Height));
  810. }
  811. CreateNewWindow (windowklass, attributes, ref rect, ref WindowHandle);
  812. Carbon.EventHandler.InstallWindowHandler (WindowHandle);
  813. HIViewFindByID (HIViewGetRoot (WindowHandle), new Carbon.HIViewID (Carbon.EventHandler.kEventClassWindow, 1), ref WindowView);
  814. HIViewFindByID (HIViewGetRoot (WindowHandle), new Carbon.HIViewID (Carbon.EventHandler.kEventClassWindow, 7), ref GrowBox);
  815. HIGrowBoxViewSetTransparent (GrowBox, true);
  816. SetAutomaticControlDragTrackingEnabledForWindow (WindowHandle, true);
  817. ParentHandle = WindowView;
  818. }
  819. HIObjectCreate (__CFStringMakeConstantString ("com.novell.mwfview"), 0, ref WholeWindow);
  820. HIObjectCreate (__CFStringMakeConstantString ("com.novell.mwfview"), 0, ref ClientWindow);
  821. Carbon.EventHandler.InstallControlHandler (WholeWindow);
  822. Carbon.EventHandler.InstallControlHandler (ClientWindow);
  823. // Enable embedding on controls
  824. HIViewChangeFeatures (WholeWindow, 1<<1, 0);
  825. HIViewChangeFeatures (ClientWindow, 1<<1, 0);
  826. HIViewNewTrackingArea (WholeWindow, IntPtr.Zero, (UInt64)WholeWindow, ref WholeWindowTracking);
  827. HIViewNewTrackingArea (ClientWindow, IntPtr.Zero, (UInt64)ClientWindow, ref ClientWindowTracking);
  828. Carbon.HIRect WholeRect;
  829. if (WindowHandle != IntPtr.Zero) {
  830. WholeRect = new Carbon.HIRect (0, 0, QWindowSize.Width, QWindowSize.Height);
  831. } else {
  832. WholeRect = new Carbon.HIRect (X, Y, QWindowSize.Width, QWindowSize.Height);
  833. }
  834. Carbon.HIRect ClientRect = new Carbon.HIRect (QClientRect.X, QClientRect.Y, QClientRect.Width, QClientRect.Height);
  835. HIViewSetFrame (WholeWindow, ref WholeRect);
  836. HIViewSetFrame (ClientWindow, ref ClientRect);
  837. HIViewAddSubview (ParentHandle, WholeWindow);
  838. HIViewAddSubview (WholeWindow, ClientWindow);
  839. hwnd.WholeWindow = WholeWindow;
  840. hwnd.ClientWindow = ClientWindow;
  841. if (WindowHandle != IntPtr.Zero) {
  842. WindowMapping [hwnd.Handle] = WindowHandle;
  843. HandleMapping [WindowHandle] = hwnd.Handle;
  844. if (hwnd.border_style == FormBorderStyle.FixedToolWindow || hwnd.border_style == FormBorderStyle.SizableToolWindow) {
  845. UtilityWindows.Add (WindowHandle);
  846. }
  847. }
  848. // Allow dnd on controls
  849. Dnd.SetAllowDrop (hwnd, true);
  850. Text (hwnd.Handle, cp.Caption);
  851. SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
  852. SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
  853. if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
  854. if (WindowHandle != IntPtr.Zero) {
  855. if (Control.FromHandle(hwnd.Handle) is Form) {
  856. Form f = Control.FromHandle(hwnd.Handle) as Form;
  857. if (f.WindowState == FormWindowState.Normal) {
  858. SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
  859. }
  860. }
  861. ShowWindow (WindowHandle);
  862. WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
  863. }
  864. HIViewSetVisible (WholeWindow, true);
  865. HIViewSetVisible (ClientWindow, true);
  866. hwnd.visible = true;
  867. if (!(Control.FromHandle(hwnd.Handle) is Form)) {
  868. SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
  869. }
  870. }
  871. if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
  872. SetWindowState(hwnd.Handle, FormWindowState.Minimized);
  873. } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
  874. SetWindowState(hwnd.Handle, FormWindowState.Maximized);
  875. }
  876. return hwnd.Handle;
  877. }
  878. internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
  879. CreateParams create_params = new CreateParams();
  880. create_params.Caption = "";
  881. create_params.X = X;
  882. create_params.Y = Y;
  883. create_params.Width = Width;
  884. create_params.Height = Height;
  885. create_params.ClassName=XplatUI.GetDefaultClassName (GetType ());
  886. create_params.ClassStyle = 0;
  887. create_params.ExStyle=0;
  888. create_params.Parent=IntPtr.Zero;
  889. create_params.Param=0;
  890. return CreateWindow(create_params);
  891. }
  892. internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
  893. return Carbon.Cursor.DefineStdCursorBitmap (id);
  894. }
  895. internal override IntPtr DefineCursor (Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
  896. return Carbon.Cursor.DefineCursor (bitmap, mask, cursor_pixel, mask_pixel, xHotSpot, yHotSpot);
  897. }
  898. internal override IntPtr DefineStdCursor (StdCursor id) {
  899. return Carbon.Cursor.DefineStdCursor (id);
  900. }
  901. internal override IntPtr DefWndProc(ref Message msg) {
  902. Hwnd hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
  903. switch ((Msg)msg.Msg) {
  904. case Msg.WM_IME_COMPOSITION:
  905. string s = KeyboardHandler.ComposedString;
  906. foreach (char c in s)
  907. SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
  908. break;
  909. case Msg.WM_IME_CHAR:
  910. // On Windows API it sends two WM_CHAR messages for each byte, but
  911. // I wonder if it is worthy to emulate it (also no idea how to
  912. // reconstruct those bytes into chars).
  913. SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
  914. return IntPtr.Zero;
  915. case Msg.WM_QUIT: {
  916. if (WindowMapping [hwnd.Handle] != null)
  917. Exit ();
  918. break;
  919. }
  920. case Msg.WM_PAINT: {
  921. hwnd.expose_pending = false;
  922. break;
  923. }
  924. case Msg.WM_NCPAINT: {
  925. hwnd.nc_expose_pending = false;
  926. break;
  927. }
  928. case Msg.WM_NCCALCSIZE: {
  929. if (msg.WParam == (IntPtr)1) {
  930. XplatUIWin32.NCCALCSIZE_PARAMS ncp;
  931. ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
  932. // Add all the stuff X is supposed to draw.
  933. Control ctrl = Control.FromHandle (hwnd.Handle);
  934. if (ctrl != null) {
  935. Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
  936. ncp.rgrc1.top += rect.top;
  937. ncp.rgrc1.bottom -= rect.bottom;
  938. ncp.rgrc1.left += rect.left;
  939. ncp.rgrc1.right -= rect.right;
  940. Marshal.StructureToPtr (ncp, msg.LParam, true);
  941. }
  942. }
  943. break;
  944. }
  945. case Msg.WM_SETCURSOR: {
  946. // Pass to parent window first
  947. while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
  948. hwnd = hwnd.parent;
  949. msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
  950. }
  951. if (msg.Result == IntPtr.Zero) {
  952. IntPtr handle;
  953. switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
  954. case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
  955. case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
  956. case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
  957. case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
  958. case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
  959. //FIXME: AudibleAlert();
  960. }
  961. handle = Cursors.Default.handle;
  962. break;
  963. case HitTest.HTHELP: handle = Cursors.Help.handle; break;
  964. case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
  965. case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
  966. case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
  967. case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
  968. case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
  969. #if SameAsDefault
  970. case HitTest.HTGROWBOX:
  971. case HitTest.HTSIZE:
  972. case HitTest.HTZOOM:
  973. case HitTest.HTVSCROLL:
  974. case HitTest.HTSYSMENU:
  975. case HitTest.HTREDUCE:
  976. case HitTest.HTNOWHERE:
  977. case HitTest.HTMAXBUTTON:
  978. case HitTest.HTMINBUTTON:
  979. case HitTest.HTMENU:
  980. case HitTest.HSCROLL:
  981. case HitTest.HTBOTTOM:
  982. case HitTest.HTCAPTION:
  983. case HitTest.HTCLIENT:
  984. case HitTest.HTCLOSE:
  985. #endif
  986. default: handle = Cursors.Default.handle; break;
  987. }
  988. SetCursor(msg.HWnd, handle);
  989. }
  990. return (IntPtr)1;
  991. }
  992. }
  993. return IntPtr.Zero;
  994. }
  995. internal override void DestroyCaret (IntPtr hwnd) {
  996. if (Caret.Hwnd == hwnd) {
  997. if (Caret.Visible == 1) {
  998. Caret.Timer.Stop ();
  999. HideCaret ();
  1000. }
  1001. Caret.Hwnd = IntPtr.Zero;
  1002. Caret.Visible = 0;
  1003. Caret.On = false;
  1004. }
  1005. }
  1006. [MonoTODO]
  1007. internal override void DestroyCursor(IntPtr cursor) {
  1008. throw new NotImplementedException ();
  1009. }
  1010. internal override void DestroyWindow(IntPtr handle) {
  1011. Hwnd hwnd;
  1012. hwnd = Hwnd.ObjectFromHandle(handle);
  1013. if (hwnd == null) {
  1014. return;
  1015. }
  1016. SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
  1017. CleanupCachedWindows (hwnd);
  1018. ArrayList windows = new ArrayList ();
  1019. AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
  1020. foreach (Hwnd h in windows) {
  1021. SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
  1022. h.zombie = true;
  1023. }
  1024. // TODO: This is crashing swf-messageboxes
  1025. /*
  1026. if (false && hwnd.whole_window != IntPtr.Zero)
  1027. CFRelease (hwnd.whole_window);
  1028. if (false && hwnd.client_window != IntPtr.Zero)
  1029. CFRelease (hwnd.client_window);
  1030. */
  1031. if (WindowMapping [hwnd.Handle] != null) {
  1032. DisposeWindow ((IntPtr)(WindowMapping [hwnd.Handle]));
  1033. WindowMapping.Remove (hwnd.Handle);
  1034. }
  1035. }
  1036. internal override IntPtr DispatchMessage(ref MSG msg) {
  1037. return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  1038. }
  1039. internal override void DoEvents() {
  1040. MSG msg = new MSG ();
  1041. in_doevents = true;
  1042. while (PeekMessage (null, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
  1043. TranslateMessage (ref msg);
  1044. DispatchMessage (ref msg);
  1045. }
  1046. in_doevents = false;
  1047. }
  1048. internal override void EnableWindow(IntPtr handle, bool Enable) {
  1049. //Like X11 we need not do anything here
  1050. }
  1051. internal override void EndLoop(Thread thread) {
  1052. }
  1053. internal void Exit () {
  1054. GetMessageResult = false;
  1055. }
  1056. internal override IntPtr GetActive() {
  1057. return ActiveWindow;
  1058. }
  1059. internal override Region GetClipRegion(IntPtr hwnd) {
  1060. return null;
  1061. }
  1062. [MonoTODO]
  1063. internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
  1064. width = 12;
  1065. height = 12;
  1066. hotspot_x = 0;
  1067. hotspot_y = 0;
  1068. }
  1069. internal override void GetDisplaySize(out Size size) {
  1070. Carbon.HIRect bounds = CGDisplayBounds (CGMainDisplayID ());
  1071. size = new Size ((int)bounds.size.width, (int)bounds.size.height);
  1072. }
  1073. internal override IntPtr GetParent(IntPtr handle) {
  1074. Hwnd hwnd;
  1075. hwnd = Hwnd.ObjectFromHandle(handle);
  1076. if (hwnd != null && hwnd.Parent != null) {
  1077. return hwnd.Parent.Handle;
  1078. }
  1079. return IntPtr.Zero;
  1080. }
  1081. internal override IntPtr GetPreviousWindow(IntPtr handle) {
  1082. return HIViewGetPreviousView(handle);
  1083. }
  1084. internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
  1085. Carbon.QDPoint pt = new Carbon.QDPoint ();
  1086. GetGlobalMouse (ref pt);
  1087. x = pt.x;
  1088. y = pt.y;
  1089. }
  1090. internal override IntPtr GetFocus() {
  1091. return FocusWindow;
  1092. }
  1093. internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
  1094. FontFamily ff = font.FontFamily;
  1095. ascent = ff.GetCellAscent (font.Style);
  1096. descent = ff.GetCellDescent (font.Style);
  1097. return true;
  1098. }
  1099. internal override Point GetMenuOrigin(IntPtr handle) {
  1100. Hwnd hwnd;
  1101. hwnd = Hwnd.ObjectFromHandle(handle);
  1102. if (hwnd != null) {
  1103. return hwnd.MenuOrigin;
  1104. }
  1105. return Point.Empty;
  1106. }
  1107. internal override bool GetMessage(object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
  1108. IntPtr evtRef = IntPtr.Zero;
  1109. IntPtr target = GetEventDispatcherTarget();
  1110. CheckTimers (DateTime.UtcNow);
  1111. ReceiveNextEvent (0, IntPtr.Zero, 0, true, ref evtRef);
  1112. if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
  1113. SendEventToEventTarget (evtRef, target);
  1114. ReleaseEvent (evtRef);
  1115. }
  1116. object queueobj;
  1117. loop:
  1118. lock (queuelock) {
  1119. if (MessageQueue.Count <= 0) {
  1120. if (Idle != null)
  1121. Idle (this, EventArgs.Empty);
  1122. else if (TimerList.Count == 0) {
  1123. ReceiveNextEvent (0, IntPtr.Zero, 0.15, true, ref evtRef);
  1124. if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
  1125. SendEventToEventTarget (evtRef, target);
  1126. ReleaseEvent (evtRef);
  1127. }
  1128. } else {
  1129. ReceiveNextEvent (0, IntPtr.Zero, NextTimeout (), true, ref evtRef);
  1130. if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
  1131. SendEventToEventTarget (evtRef, target);
  1132. ReleaseEvent (evtRef);
  1133. }
  1134. }
  1135. msg.hwnd = IntPtr.Zero;
  1136. msg.message = Msg.WM_ENTERIDLE;
  1137. return GetMessageResult;
  1138. }
  1139. queueobj = MessageQueue.Dequeue ();
  1140. }
  1141. if (queueobj is GCHandle) {
  1142. XplatUIDriverSupport.ExecuteClientMessage((GCHandle)queueobj);
  1143. goto loop;
  1144. } else {
  1145. msg = (MSG)queueobj;
  1146. }
  1147. return GetMessageResult;
  1148. }
  1149. [MonoTODO]
  1150. internal override bool GetText(IntPtr handle, out string text) {
  1151. throw new NotImplementedException ();
  1152. }
  1153. internal override void GetWindowPos(IntPtr handle, bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
  1154. Hwnd hwnd;
  1155. hwnd = Hwnd.ObjectFromHandle(handle);
  1156. if (hwnd != null) {
  1157. x = hwnd.x;
  1158. y = hwnd.y;
  1159. width = hwnd.width;
  1160. height = hwnd.height;
  1161. PerformNCCalc(hwnd);
  1162. client_width = hwnd.ClientRect.Width;
  1163. client_height = hwnd.ClientRect.Height;
  1164. return;
  1165. }
  1166. // Should we throw an exception or fail silently?
  1167. // throw new ArgumentException("Called with an invalid window handle", "handle");
  1168. x = 0;
  1169. y = 0;
  1170. width = 0;
  1171. height = 0;
  1172. client_width = 0;
  1173. client_height = 0;
  1174. }
  1175. internal override FormWindowState GetWindowState(IntPtr hwnd) {
  1176. IntPtr window = HIViewGetWindow (hwnd);
  1177. if (IsWindowCollapsed (window))
  1178. return FormWindowState.Minimized;
  1179. if (IsWindowInStandardState (window, IntPtr.Zero, IntPtr.Zero))
  1180. return FormWindowState.Maximized;
  1181. return FormWindowState.Normal;
  1182. }
  1183. internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
  1184. handle = Grab.Hwnd;
  1185. GrabConfined = Grab.Confined;
  1186. GrabArea = Grab.Area;
  1187. }
  1188. internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
  1189. Grab.Hwnd = handle;
  1190. Grab.Confined = confine_to_handle != IntPtr.Zero;
  1191. /* FIXME: Set the Grab.Area */
  1192. }
  1193. internal override void UngrabWindow(IntPtr hwnd) {
  1194. bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
  1195. Grab.Hwnd = IntPtr.Zero;
  1196. Grab.Confined = false;
  1197. if (was_grabbed) {
  1198. // lparam should be the handle to the window gaining the mouse capture,
  1199. // but we dont have that information like X11.
  1200. // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
  1201. SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
  1202. }
  1203. }
  1204. internal override void HandleException(Exception e) {
  1205. StackTrace st = new StackTrace(e);
  1206. Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
  1207. Console.WriteLine("{0}{1}", e.Message, st.ToString());
  1208. }
  1209. internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear) {
  1210. Hwnd hwnd;
  1211. hwnd = Hwnd.ObjectFromHandle(handle);
  1212. if (clear) {
  1213. AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
  1214. } else {
  1215. AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
  1216. }
  1217. }
  1218. internal override void InvalidateNC (IntPtr handle)
  1219. {
  1220. Hwnd hwnd;
  1221. hwnd = Hwnd.ObjectFromHandle(handle);
  1222. AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
  1223. }
  1224. internal override bool IsEnabled(IntPtr handle) {
  1225. return Hwnd.ObjectFromHandle(handle).Enabled;
  1226. }
  1227. internal override bool IsVisible(IntPtr handle) {
  1228. return Hwnd.ObjectFromHandle(handle).visible;
  1229. }
  1230. internal override void KillTimer(Timer timer) {
  1231. lock (TimerList) {
  1232. TimerList.Remove(timer);
  1233. }
  1234. }
  1235. internal override void OverrideCursor(IntPtr cursor) {
  1236. }
  1237. internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
  1238. PaintEventArgs paint_event;
  1239. Hwnd hwnd;
  1240. Hwnd paint_hwnd;
  1241. hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
  1242. if (msg.HWnd == handle) {
  1243. paint_hwnd = hwnd;
  1244. } else {
  1245. paint_hwnd = Hwnd.ObjectFromHandle (handle);
  1246. }
  1247. if (Caret.Visible == 1) {
  1248. Caret.Paused = true;
  1249. HideCaret();
  1250. }
  1251. Graphics dc;
  1252. if (client) {
  1253. dc = Graphics.FromHwnd (paint_hwnd.client_window);
  1254. Region clip_region = new Region ();
  1255. clip_region.MakeEmpty();
  1256. foreach (Rectangle r in hwnd.ClipRectangles) {
  1257. /* Expand the region slightly.
  1258. * See bug 464464.
  1259. */
  1260. Rectangle r2 = Rectangle.FromLTRB (r.Left, r.Top, r.Right, r.Bottom + 1);
  1261. clip_region.Union (r2);
  1262. }
  1263. if (hwnd.UserClip != null) {
  1264. clip_region.Intersect(hwnd.UserClip);
  1265. }
  1266. // FIXME: Clip region is hosed
  1267. dc.Clip = clip_region;
  1268. paint_event = new PaintEventArgs(dc, hwnd.Invalid);
  1269. hwnd.expose_pending = false;
  1270. hwnd.ClearInvalidArea();
  1271. hwnd.drawing_stack.Push (paint_event);
  1272. hwnd.drawing_stack.Push (dc);
  1273. } else {
  1274. dc = Graphics.FromHwnd (paint_hwnd.whole_window);
  1275. if (!hwnd.nc_invalid.IsEmpty) {
  1276. // FIXME: Clip region is hosed
  1277. dc.SetClip (hwnd.nc_invalid);
  1278. paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
  1279. } else {
  1280. paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
  1281. }
  1282. hwnd.nc_expose_pending = false;
  1283. hwnd.ClearNcInvalidArea ();
  1284. hwnd.drawing_stack.Push (paint_event);
  1285. hwnd.drawing_stack.Push (dc);
  1286. }
  1287. return paint_event;
  1288. }
  1289. internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
  1290. Hwnd hwnd;
  1291. hwnd = Hwnd.ObjectFromHandle(handle);
  1292. // FIXME: Pop is causing invalid stack ops sometimes; race condition?
  1293. try {
  1294. Graphics dc = (Graphics)hwnd.drawing_stack.Pop();
  1295. dc.Flush ();
  1296. dc.Dispose ();
  1297. PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
  1298. pe.SetGraphics (null);
  1299. pe.Dispose ();
  1300. } catch {}
  1301. if (Caret.Visible == 1) {
  1302. ShowCaret();
  1303. Caret.Paused = false;
  1304. }
  1305. }
  1306. internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
  1307. IntPtr evtRef = IntPtr.Zero;
  1308. IntPtr target = GetEventDispatcherTarget();
  1309. CheckTimers (DateTime.UtcNow);
  1310. ReceiveNextEvent (0, IntPtr.Zero, 0, true, ref evtRef);
  1311. if (evtRef != IntPtr.Zero && target != IntPtr.Zero) {
  1312. SendEventToEventTarget (evtRef, target);
  1313. ReleaseEvent (evtRef);
  1314. }
  1315. lock (queuelock) {
  1316. if (MessageQueue.Count <= 0) {
  1317. return false;
  1318. } else {
  1319. object queueobj;
  1320. if (flags == (uint)PeekMessageFlags.PM_REMOVE)
  1321. queueobj = MessageQueue.Dequeue ();
  1322. else
  1323. queueobj = MessageQueue.Peek ();
  1324. if (queueobj is GCHandle) {
  1325. XplatUIDriverSupport.ExecuteClientMessage((GCHandle)queueobj);
  1326. return false;
  1327. }
  1328. msg = (MSG)queueobj;
  1329. return true;
  1330. }
  1331. }
  1332. }
  1333. internal override bool PostMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam) {
  1334. MSG msg = new MSG();
  1335. msg.hwnd = hwnd;
  1336. msg.message = message;
  1337. msg.wParam = wParam;
  1338. msg.lParam = lParam;
  1339. EnqueueMessage (msg);
  1340. return true;
  1341. }
  1342. internal override void PostQuitMessage(

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