From 3d0a3dfb4ef5a36607aaa8f16ede13271080079a Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Tue, 27 Oct 2009 23:57:44 +0000 Subject: [PATCH] Implemented INativeWindow.MouseEnter/MouseLeave events on Win32 and X11. --- Source/OpenTK/INativeWindow.cs | 13 ++++- Source/OpenTK/NativeWindow.cs | 52 ++++++++++++++++++ .../OpenTK/Platform/MacOS/CarbonGLNative.cs | 4 ++ Source/OpenTK/Platform/Windows/API.cs | 40 ++++++++++++++ Source/OpenTK/Platform/Windows/WinGLNative.cs | 53 ++++++++++++------- Source/OpenTK/Platform/X11/X11GLNative.cs | 17 +++++- 6 files changed, 158 insertions(+), 21 deletions(-) diff --git a/Source/OpenTK/INativeWindow.cs b/Source/OpenTK/INativeWindow.cs index b5f0915e..6bb3b33b 100644 --- a/Source/OpenTK/INativeWindow.cs +++ b/Source/OpenTK/INativeWindow.cs @@ -223,8 +223,17 @@ namespace OpenTK /// Occurs whenever a character is typed. /// event EventHandler KeyPress; - - //event EventHandler MouseEnter; + + /// + /// Occurs whenever the mouse cursor leaves the window . + /// + event EventHandler MouseLeave; + + /// + /// Occurs whenever the mouse cursor enters the window . + /// + event EventHandler MouseEnter; + //event EventHandler MouseMove; //event EventHandler MouseWheel; //event EventHandler MouseDown; diff --git a/Source/OpenTK/NativeWindow.cs b/Source/OpenTK/NativeWindow.cs index edbce7ab..4f075c47 100644 --- a/Source/OpenTK/NativeWindow.cs +++ b/Source/OpenTK/NativeWindow.cs @@ -565,6 +565,16 @@ namespace OpenTK /// public event EventHandler Move; + /// + /// Occurs whenever the mouse cursor enters the window . + /// + public event EventHandler MouseEnter; + + /// + /// Occurs whenever the mouse cursor leaves the window . + /// + public event EventHandler MouseLeave; + /// /// Occurs whenever the window is resized. /// @@ -747,6 +757,32 @@ namespace OpenTK #endregion + #region OnMouseEnter + + /// + /// Called whenever the mouse cursor reenters the window . + /// + /// Not used. + protected virtual void OnMouseEnter(EventArgs e) + { + if (MouseEnter != null) MouseEnter(this, e); + } + + #endregion + + #region OnMouseLeave + + /// + /// Called whenever the mouse cursor leaves the window . + /// + /// Not used. + protected virtual void OnMouseLeave(EventArgs e) + { + if (MouseLeave != null) MouseLeave(this, e); + } + + #endregion + #region OnResize /// @@ -875,6 +911,18 @@ namespace OpenTK #endregion + #region OnMouseEnterInternal + + private void OnMouseEnterInternal(object sender, EventArgs e) { OnMouseEnter(e); } + + #endregion + + #region OnMouseLeaveInternal + + private void OnMouseLeaveInternal(object sender, EventArgs e) { OnMouseLeave(e); } + + #endregion + #region OnMoveInternal private void OnMoveInternal(object sender, EventArgs e) { OnMove(e); } @@ -933,6 +981,8 @@ namespace OpenTK implementation.FocusedChanged += OnFocusedChangedInternal; implementation.IconChanged += OnIconChangedInternal; implementation.KeyPress += OnKeyPressInternal; + implementation.MouseEnter += OnMouseEnterInternal; + implementation.MouseLeave += OnMouseLeaveInternal; implementation.Move += OnMoveInternal; implementation.Resize += OnResizeInternal; implementation.TitleChanged += OnTitleChangedInternal; @@ -949,6 +999,8 @@ namespace OpenTK implementation.FocusedChanged -= OnFocusedChangedInternal; implementation.IconChanged -= OnIconChangedInternal; implementation.KeyPress -= OnKeyPressInternal; + implementation.MouseEnter -= OnMouseEnterInternal; + implementation.MouseLeave -= OnMouseLeaveInternal; implementation.Move -= OnMoveInternal; implementation.Resize -= OnResizeInternal; implementation.TitleChanged -= OnTitleChangedInternal; diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs index b32e130d..4f7a8088 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs @@ -954,6 +954,10 @@ namespace OpenTK.Platform.MacOS public event EventHandler KeyPress; + public event EventHandler MouseEnter; + + public event EventHandler MouseLeave; + #endregion } } diff --git a/Source/OpenTK/Platform/Windows/API.cs b/Source/OpenTK/Platform/Windows/API.cs index 19db5f99..02e61dca 100644 --- a/Source/OpenTK/Platform/Windows/API.cs +++ b/Source/OpenTK/Platform/Windows/API.cs @@ -928,6 +928,18 @@ namespace OpenTK.Platform.Windows #region Input functions + [DllImport("user32.dll", SetLastError=true)] + public static extern BOOL TrackMouseEvent(ref TrackMouseEventStructure lpEventTrack); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] + public static extern bool ReleaseCapture(); + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern IntPtr SetCapture(IntPtr hwnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern IntPtr GetCapture(); + #region Async input #region GetCursorPos @@ -2755,6 +2767,20 @@ namespace OpenTK.Platform.Windows #endregion + #region TrackMouseEventStructure + + struct TrackMouseEventStructure + { + public DWORD Size; + public TrackMouseEventFlags Flags; + public HWND TrackWindowHandle; + public DWORD HoverTime; + + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(TrackMouseEventStructure)); + } + + #endregion + #endregion #region --- Enums --- @@ -4063,6 +4089,20 @@ namespace OpenTK.Platform.Windows #endregion + #region TrackMouseEventFlags + + [Flags] + enum TrackMouseEventFlags : uint + { + HOVER = 0x00000001, + LEAVE = 0x00000002, + NONCLIENT = 0x00000010, + QUERY = 0x40000000, + CANCEL = 0x80000000, + } + + #endregion + #endregion #region --- Callbacks --- diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index fe87ad60..9b3f9b2c 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -131,6 +131,8 @@ namespace OpenTK.Platform.Windows keyboards.Add(keyboard); mice.Add(mouse); + + EnableMouseLeaveNotifications(); } #endregion @@ -141,7 +143,7 @@ namespace OpenTK.Platform.Windows IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) { - bool mouse_about_to_enter = false; + bool mouse_left = false; switch (message) { @@ -289,27 +291,26 @@ namespace OpenTK.Platform.Windows KeyPress(this, key_press); break; - //case WindowMessage.MOUSELEAVE: - // Cursor.Current = Cursors.Default; - // break; - - //case WindowMessage.MOUSE_ENTER: - // Cursor.Current = Cursors.Default; - // break; - - // Mouse events: - case WindowMessage.NCMOUSEMOVE: - mouse_about_to_enter = true; // Used to simulate a mouse enter event. - break; - case WindowMessage.MOUSEMOVE: - mouse.Position = new System.Drawing.Point( + System.Drawing.Point point = new System.Drawing.Point( (int)(lParam.ToInt32() & 0x0000FFFF), (int)(lParam.ToInt32() & 0xFFFF0000) >> 16); - if (mouse_about_to_enter) + mouse.Position = point; { - //Cursor.Current = Cursors.Default; - mouse_about_to_enter = false; + Rectangle rect; + Functions.GetClientRect(window.WindowHandle, out rect); + if (!rect.ToRectangle().Contains(point)) + { + Functions.ReleaseCapture(); + if (MouseLeave != null) + MouseLeave(this, EventArgs.Empty); + } + else if (Functions.GetCapture() != window.WindowHandle) + { + Functions.SetCapture(window.WindowHandle); + if (MouseEnter != null) + MouseEnter(this, EventArgs.Empty); + } } break; @@ -619,6 +620,18 @@ namespace OpenTK.Platform.Windows #endregion + void EnableMouseLeaveNotifications() + { + TrackMouseEventStructure tme = new TrackMouseEventStructure(); + tme.Size = TrackMouseEventStructure.SizeInBytes; + tme.Flags |= TrackMouseEventFlags.LEAVE; + tme.TrackWindowHandle = child_window.WindowHandle; + tme.HoverTime = -1; // HOVER_DEFAULT + if (!Functions.TrackMouseEvent(ref tme)) + Debug.Print("[Error] Failed to enable mouse event tracking. Error: {0}", + Marshal.GetLastWin32Error()); + } + #endregion #region INativeWindow Members @@ -1052,6 +1065,10 @@ namespace OpenTK.Platform.Windows public event EventHandler WindowStateChanged; public event EventHandler KeyPress; + + public event EventHandler MouseEnter; + + public event EventHandler MouseLeave; #endregion diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 8cbf1a47..0a55165a 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -142,7 +142,8 @@ namespace OpenTK.Platform.X11 window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | EventMask.KeyReleaseMask | EventMask.KeyPressMask | EventMask.PointerMotionMask | EventMask.FocusChangeMask | - EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; + EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | + EventMask.EnterWindowMask | EventMask.LeaveWindowMask; attributes.event_mask = (IntPtr)window.EventMask; uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | @@ -678,6 +679,16 @@ namespace OpenTK.Platform.X11 FocusedChanged(this, EventArgs.Empty); } break; + + case XEventName.LeaveNotify: + if (MouseLeave != null) + MouseLeave(this, EventArgs.Empty); + break; + + case XEventName.EnterNotify: + if (MouseEnter != null) + MouseEnter(this, EventArgs.Empty); + break; default: //Debug.WriteLine(String.Format("{0} event was not handled", e.type)); @@ -1092,6 +1103,10 @@ namespace OpenTK.Platform.X11 public event EventHandler WindowStateChanged; public event EventHandler KeyPress; + + public event EventHandler MouseEnter; + + public event EventHandler MouseLeave; #endregion