1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2007 Novell, Inc.
23 // Geoff Norton <gnorton@novell.com>
28 using System.Runtime.InteropServices;
30 namespace System.Windows.Forms.CarbonInternal {
31 internal class MouseHandler : EventHandlerBase, IEventHandler {
32 internal const uint kEventMouseDown = 1;
33 internal const uint kEventMouseUp = 2;
34 internal const uint kEventMouseMoved = 5;
35 internal const uint kEventMouseDragged = 6;
36 internal const uint kEventMouseEntered = 8;
37 internal const uint kEventMouseExited = 9;
38 internal const uint kEventMouseWheelMoved = 10;
40 internal const uint kEventParamMouseLocation = 1835822947;
41 internal const uint kEventParamMouseButton = 1835168878;
42 internal const uint typeMouseButton = 1835168878;
43 internal const uint typeQDPoint = 1363439732;
45 internal const uint DoubleClickInterval = 7500000;
46 internal static ClickStruct ClickPending;
48 internal MouseHandler (XplatUICarbon driver) : base (driver) {}
50 public bool ProcessEvent (IntPtr callref, IntPtr eventref, IntPtr handle, uint kind, ref MSG msg) {
51 QDPoint qdpoint = new QDPoint ();
52 CGPoint point = new CGPoint ();
53 Rect window_bounds = new Rect ();
54 IntPtr view_handle = IntPtr.Zero;
55 IntPtr window_handle = IntPtr.Zero;
60 GetEventParameter (eventref, kEventParamMouseLocation, typeQDPoint, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (QDPoint)), IntPtr.Zero, ref qdpoint);
61 GetEventParameter (eventref, kEventParamMouseButton, typeMouseButton, IntPtr.Zero, (uint)Marshal.SizeOf (typeof (ushort)), IntPtr.Zero, ref button);
63 if (button == 1 && ((Driver.ModifierKeys & Keys.Control) != 0))
70 GetWindowBounds (handle, 33, ref window_bounds);
71 HIViewFindByID (HIViewGetRoot (handle), new HIViewID (EventHandler.kEventClassWindow, 1), ref window_handle);
73 point.x -= window_bounds.left;
74 point.y -= window_bounds.top;
76 HIViewGetSubviewHit (window_handle, ref point, true, ref view_handle);
77 HIViewConvertPoint (ref point, window_handle, view_handle);
79 hwnd = Hwnd.ObjectFromHandle (view_handle);
82 client = (hwnd.ClientWindow == view_handle ? true : false);
84 if (XplatUICarbon.Grab.Hwnd != IntPtr.Zero) {
85 hwnd = Hwnd.ObjectFromHandle (XplatUICarbon.Grab.Hwnd);
92 qdpoint.x = (short) point.x;
93 qdpoint.y = (short) point.y;
95 Driver.ScreenToClient (hwnd.Handle, ref qdpoint);
101 msg.hwnd = hwnd.Handle;
102 msg.lParam = (IntPtr) ((ushort) point.y << 16 | (ushort) point.x);
105 case kEventMouseDown:
106 msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE) + ((button - 1) * 3) + 1;
107 msg.wParam = ButtonTowParam (button);
108 if (ClickPending.Pending && (((DateTime.Now.Ticks - ClickPending.Time) < DoubleClickInterval) && (msg.hwnd == ClickPending.Hwnd) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
109 msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE) + ((button - 1) * 3) + 3;
110 ClickPending.Pending = false;
112 ClickPending.Pending = true;
113 ClickPending.Hwnd = msg.hwnd;
114 ClickPending.Message = msg.message;
115 ClickPending.wParam = msg.wParam;
116 ClickPending.lParam = msg.lParam;
117 ClickPending.Time = DateTime.Now.Ticks;
121 msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE) + ((StateToButton (XplatUICarbon.MouseState) - 1) * 3) + 2;
122 msg.wParam = StateTowParam (XplatUICarbon.MouseState);
124 case kEventMouseDragged:
125 case kEventMouseMoved:
126 msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE);
127 msg.wParam = Driver.GetMousewParam (0);
132 Driver.mouse_position.X = (int) point.x;
133 Driver.mouse_position.Y = (int) point.y;
137 internal bool TranslateMessage (ref MSG msg) {
138 if (msg.message == Msg.WM_MOUSEMOVE || msg.message == Msg.WM_NCMOUSEMOVE) {
139 Hwnd hwnd = Hwnd.ObjectFromHandle (msg.hwnd);
140 if (XplatUICarbon.MouseHwnd == null)
141 Driver.PostMessage (hwnd.Handle, Msg.WM_MOUSE_ENTER, IntPtr.Zero, IntPtr.Zero);
142 else if (XplatUICarbon.MouseHwnd.Handle != hwnd.Handle) {
143 Driver.PostMessage (XplatUICarbon.MouseHwnd.Handle, Msg.WM_MOUSELEAVE, IntPtr.Zero, IntPtr.Zero);
144 Driver.PostMessage (hwnd.Handle, Msg.WM_MOUSE_ENTER, IntPtr.Zero, IntPtr.Zero);
146 XplatUICarbon.MouseHwnd = hwnd;
152 private int StateToButton (MouseButtons state) {
156 case MouseButtons.Left:
159 case MouseButtons.Right:
162 case MouseButtons.Middle:
170 private IntPtr StateTowParam (MouseButtons state) {
171 int wparam = (int) Driver.GetMousewParam (0);
174 case MouseButtons.Left:
175 XplatUICarbon.MouseState &= ~MouseButtons.Left;
176 wparam &= (int)MsgButtons.MK_LBUTTON;
178 case MouseButtons.Right:
179 XplatUICarbon.MouseState &= ~MouseButtons.Right;
180 wparam &= (int)MsgButtons.MK_RBUTTON;
182 case MouseButtons.Middle:
183 XplatUICarbon.MouseState &= ~MouseButtons.Middle;
184 wparam &= (int)MsgButtons.MK_MBUTTON;
188 return (IntPtr) wparam;
191 private IntPtr ButtonTowParam (ushort button) {
192 int wparam = (int) Driver.GetMousewParam (0);
196 XplatUICarbon.MouseState |= MouseButtons.Left;
197 wparam |= (int)MsgButtons.MK_LBUTTON;
200 XplatUICarbon.MouseState |= MouseButtons.Right;
201 wparam |= (int)MsgButtons.MK_RBUTTON;
204 XplatUICarbon.MouseState |= MouseButtons.Middle;
205 wparam |= (int)MsgButtons.MK_MBUTTON;
209 return (IntPtr) wparam;
213 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
214 static extern int GetEventParameter (IntPtr eventref, uint name, uint type, IntPtr outtype, uint size, IntPtr outsize, ref QDPoint data);
215 [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
216 static extern int GetEventParameter (IntPtr eventref, uint name, uint type, IntPtr outtype, uint size, IntPtr outsize, ref ushort data);
218 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
219 internal static extern int GetWindowBounds (IntPtr handle, uint region, ref Rect bounds);
220 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
221 internal static extern int HIViewConvertPoint (ref CGPoint point, IntPtr source_view, IntPtr target_view);
222 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
223 internal static extern IntPtr HIViewGetRoot (IntPtr handle);
224 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
225 internal static extern int HIViewGetSubviewHit (IntPtr content_view, ref CGPoint point, bool tval, ref IntPtr hit_view);
226 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
227 internal static extern int HIViewFindByID (IntPtr root_window, HIViewID id, ref IntPtr view_handle);
229 [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
230 internal static extern int GetCurrentEventButtonState ();