diff --git a/Perspex.Windows/Input/MouseDevice.cs b/Perspex.Windows/Input/MouseDevice.cs
new file mode 100644
index 0000000000..08d0253570
--- /dev/null
+++ b/Perspex.Windows/Input/MouseDevice.cs
@@ -0,0 +1,14 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Windows.Input
+{
+ using Perspex.Input;
+
+ public class MouseDevice : IInputDevice
+ {
+ }
+}
diff --git a/Perspex.Windows/Perspex.Windows.csproj b/Perspex.Windows/Perspex.Windows.csproj
index e8950efe2c..ba75d8f5d9 100644
--- a/Perspex.Windows/Perspex.Windows.csproj
+++ b/Perspex.Windows/Perspex.Windows.csproj
@@ -66,6 +66,7 @@
+
diff --git a/Perspex.Windows/Window.cs b/Perspex.Windows/Window.cs
index dac820691a..6ddbd227d0 100644
--- a/Perspex.Windows/Window.cs
+++ b/Perspex.Windows/Window.cs
@@ -13,21 +13,28 @@ namespace Perspex.Windows
using System.Runtime.InteropServices;
using Perspex.Controls;
using Perspex.Input;
+ using Perspex.Input.Raw;
using Perspex.Layout;
+ using Perspex.Windows.Input;
using Perspex.Windows.Interop;
using Perspex.Windows.Threading;
+ using Splat;
public class Window : ContentControl, ILayoutRoot
{
public static readonly PerspexProperty FontSizeProperty =
TextBlock.FontSizeProperty.AddOwner();
+ private static readonly IInputDevice MouseDevice = new MouseDevice();
+
private UnmanagedMethods.WndProc wndProcDelegate;
private string className;
private Renderer renderer;
+ private IInputManager inputManager;
+
static Window()
{
FontSizeProperty.OverrideDefaultValue(typeof(Window), 18.0);
@@ -39,6 +46,7 @@ namespace Perspex.Windows
Size clientSize = this.ClientSize;
this.LayoutManager = new LayoutManager();
this.renderer = new Renderer(this.Handle, (int)clientSize.Width, (int)clientSize.Height);
+ this.inputManager = Locator.Current.GetService();
this.Template = ControlTemplate.Create(this.DefaultTemplate);
this.LayoutManager.LayoutNeeded.Subscribe(x =>
@@ -138,64 +146,11 @@ namespace Perspex.Windows
}
}
- private void MouseDown(Visual visual, Point p)
- {
- IVisual hit = visual.GetVisualAt(p);
-
- if (hit != null)
- {
- Interactive source = (hit as Interactive) ?? hit.GetVisualAncestor();
-
- if (source != null)
- {
- source.RaiseEvent(new PointerEventArgs
- {
- RoutedEvent = Control.PointerPressedEvent,
- OriginalSource = source,
- Source = source,
- });
- }
- }
- }
-
- private void MouseMove(Visual visual, Point p)
- {
- Control control = visual as Control;
-
- if (control != null)
- {
- control.IsPointerOver = visual.Bounds.Contains(p);
- }
-
- foreach (Visual child in ((IVisual)visual).VisualChildren)
- {
- this.MouseMove(child, p - visual.Bounds.Position);
- }
- }
-
- private void MouseUp(Visual visual, Point p)
- {
- IVisual hit = visual.GetVisualAt(p);
-
- if (hit != null)
- {
- Interactive source = (hit as Interactive) ?? hit.GetVisualAncestor();
-
- if (source != null)
- {
- source.RaiseEvent(new PointerEventArgs
- {
- RoutedEvent = Control.PointerReleasedEvent,
- OriginalSource = source,
- Source = source,
- });
- }
- }
- }
-
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
+ RawInputEventArgs e = null;
+
switch ((UnmanagedMethods.WindowsMessage)msg)
{
////case UnmanagedMethods.WindowsMessage.WM_DESTROY:
@@ -211,15 +166,27 @@ namespace Perspex.Windows
//// break;
case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN:
- this.MouseDown(this, new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ e = new RawMouseEventArgs(
+ MouseDevice,
+ this,
+ RawMouseEventType.LeftButtonDown,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
break;
case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP:
- this.MouseUp(this, new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ e = new RawMouseEventArgs(
+ MouseDevice,
+ this,
+ RawMouseEventType.LeftButtonUp,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
break;
case UnmanagedMethods.WindowsMessage.WM_MOUSEMOVE:
- this.MouseMove(this, new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ e = new RawMouseEventArgs(
+ MouseDevice,
+ this,
+ RawMouseEventType.Move,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
break;
case UnmanagedMethods.WindowsMessage.WM_SIZE:
@@ -228,6 +195,11 @@ namespace Perspex.Windows
return IntPtr.Zero;
}
+ if (e != null)
+ {
+ this.inputManager.Process(e);
+ }
+
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
}
}
diff --git a/Perspex/Input/IInputDevice.cs b/Perspex/Input/IInputDevice.cs
new file mode 100644
index 0000000000..f69f13e837
--- /dev/null
+++ b/Perspex/Input/IInputDevice.cs
@@ -0,0 +1,18 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ public interface IInputDevice
+ {
+ }
+}
diff --git a/Perspex/Input/IInputManager.cs b/Perspex/Input/IInputManager.cs
new file mode 100644
index 0000000000..9c5fee1095
--- /dev/null
+++ b/Perspex/Input/IInputManager.cs
@@ -0,0 +1,15 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input
+{
+ using Perspex.Input.Raw;
+
+ public interface IInputManager
+ {
+ void Process(RawInputEventArgs e);
+ }
+}
diff --git a/Perspex/Input/InputManager.cs b/Perspex/Input/InputManager.cs
new file mode 100644
index 0000000000..d2341bd3f2
--- /dev/null
+++ b/Perspex/Input/InputManager.cs
@@ -0,0 +1,95 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input
+{
+ using Perspex.Controls;
+ using Perspex.Input.Raw;
+
+ public class InputManager : IInputManager
+ {
+ public void Process(RawInputEventArgs e)
+ {
+ RawMouseEventArgs mouse = e as RawMouseEventArgs;
+
+ if (mouse != null)
+ {
+ this.ProcessMouse(mouse);
+ }
+ }
+
+ private void ProcessMouse(RawMouseEventArgs e)
+ {
+ switch (e.Type)
+ {
+ case RawMouseEventType.Move:
+ this.MouseMove((IVisual)e.Root, e.Position);
+ break;
+ case RawMouseEventType.LeftButtonDown:
+ this.MouseDown((IVisual)e.Root, e.Position);
+ break;
+ case RawMouseEventType.LeftButtonUp:
+ this.MouseUp((IVisual)e.Root, e.Position);
+ break;
+ }
+ }
+
+ private void MouseMove(IVisual visual, Point p)
+ {
+ Control control = visual as Control;
+
+ if (control != null)
+ {
+ control.IsPointerOver = visual.Bounds.Contains(p);
+ }
+
+ foreach (IVisual child in visual.VisualChildren)
+ {
+ this.MouseMove(child, p - visual.Bounds.Position);
+ }
+ }
+
+ private void MouseDown(IVisual visual, Point p)
+ {
+ IVisual hit = visual.GetVisualAt(p);
+
+ if (hit != null)
+ {
+ Interactive source = (hit as Interactive) ?? hit.GetVisualAncestor();
+
+ if (source != null)
+ {
+ source.RaiseEvent(new PointerEventArgs
+ {
+ RoutedEvent = Control.PointerPressedEvent,
+ OriginalSource = source,
+ Source = source,
+ });
+ }
+ }
+ }
+
+ private void MouseUp(IVisual visual, Point p)
+ {
+ IVisual hit = visual.GetVisualAt(p);
+
+ if (hit != null)
+ {
+ Interactive source = (hit as Interactive) ?? hit.GetVisualAncestor();
+
+ if (source != null)
+ {
+ source.RaiseEvent(new PointerEventArgs
+ {
+ RoutedEvent = Control.PointerReleasedEvent,
+ OriginalSource = source,
+ Source = source,
+ });
+ }
+ }
+ }
+ }
+}
diff --git a/Perspex/Input/Raw/RawInputEventArgs.cs b/Perspex/Input/Raw/RawInputEventArgs.cs
new file mode 100644
index 0000000000..0e9a08c6fe
--- /dev/null
+++ b/Perspex/Input/Raw/RawInputEventArgs.cs
@@ -0,0 +1,27 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input.Raw
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+ using Perspex.Layout;
+
+ public class RawInputEventArgs : EventArgs
+ {
+ public RawInputEventArgs(IInputDevice device)
+ {
+ Contract.Requires(device != null);
+
+ this.Device = device;
+ }
+
+ public IInputDevice Device { get; private set; }
+ }
+}
diff --git a/Perspex/Input/Raw/RawMouseEventArgs.cs b/Perspex/Input/Raw/RawMouseEventArgs.cs
new file mode 100644
index 0000000000..41da9ec88a
--- /dev/null
+++ b/Perspex/Input/Raw/RawMouseEventArgs.cs
@@ -0,0 +1,42 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input.Raw
+{
+ using System;
+ using Perspex.Layout;
+
+ public enum RawMouseEventType
+ {
+ Move,
+ LeftButtonDown,
+ LeftButtonUp,
+ }
+
+ public class RawMouseEventArgs : RawInputEventArgs
+ {
+ public RawMouseEventArgs(
+ IInputDevice device,
+ ILayoutRoot root,
+ RawMouseEventType type,
+ Point position)
+ : base(device)
+ {
+ Contract.Requires(device != null);
+ Contract.Requires(root != null);
+
+ this.Root = root;
+ this.Position = position;
+ this.Type = type;
+ }
+
+ public ILayoutRoot Root { get; private set; }
+
+ public Point Position { get; private set; }
+
+ public RawMouseEventType Type { get; private set; }
+ }
+}
diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj
index 75228446c7..a85e1de6c6 100644
--- a/Perspex/Perspex.csproj
+++ b/Perspex/Perspex.csproj
@@ -73,6 +73,11 @@
+
+
+
+
+
diff --git a/TestApplication/Program.cs b/TestApplication/Program.cs
index 6655d8d818..1b45b30206 100644
--- a/TestApplication/Program.cs
+++ b/TestApplication/Program.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using Perspex;
using Perspex.Controls;
+using Perspex.Input;
using Perspex.Media;
using Perspex.Styling;
using Perspex.Themes.Default;
@@ -37,7 +38,9 @@ namespace TestApplication
static void Main(string[] args)
{
TextService textService = new TextService(new SharpDX.DirectWrite.Factory());
+ InputManager inputManager = new InputManager();
+ Locator.CurrentMutable.Register(() => inputManager, typeof(IInputManager));
Locator.CurrentMutable.Register(() => textService, typeof(ITextService));
Locator.CurrentMutable.Register(() => new Styler(), typeof(IStyler));
Locator.CurrentMutable.Register(() => new TestLogger(), typeof(ILogger));