diff --git a/Perspex.Windows/Input/MouseDevice.cs b/Perspex.Windows/Input/MouseDevice.cs deleted file mode 100644 index 75ba5846d5..0000000000 --- a/Perspex.Windows/Input/MouseDevice.cs +++ /dev/null @@ -1,59 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright 2014 MIT Licence. See licence.md for more information. -// -// ----------------------------------------------------------------------- - -namespace Perspex.Windows.Input -{ - using System; - using System.Reactive.Disposables; - using Perspex.Input; - using Perspex.Input.Raw; - using Splat; - - public class MouseDevice : IMouseDevice - { - private static MouseDevice instance = new MouseDevice(); - - public static MouseDevice Instance - { - get { return instance; } - } - - public Interactive Captured - { - get; - private set; - } - - public Window CurrentWindow - { - get; - set; - } - - public Point Position - { - get; - set; - } - - public void Capture(Interactive visual) - { - this.Captured = visual; - - if (visual == null) - { - RawMouseEventArgs e = new RawMouseEventArgs( - this, - this.CurrentWindow, - RawMouseEventType.Move, - this.Position); - - IInputManager inputManager = Locator.Current.GetService(); - inputManager.Process(e); - } - } - } -} diff --git a/Perspex.Windows/Input/WindowsMouseDevice.cs b/Perspex.Windows/Input/WindowsMouseDevice.cs new file mode 100644 index 0000000000..c14dbc0742 --- /dev/null +++ b/Perspex.Windows/Input/WindowsMouseDevice.cs @@ -0,0 +1,34 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Windows.Input +{ + using Perspex.Input; + using Perspex.Input.Raw; + using Splat; + + public class WindowsMouseDevice : MouseDevice + { + private static WindowsMouseDevice instance = new WindowsMouseDevice(); + + public static WindowsMouseDevice Instance + { + get { return instance; } + } + + public Window CurrentWindow + { + get; + set; + } + + public new Point Position + { + get { return base.Position; } + internal set { base.Position = value; } + } + } +} diff --git a/Perspex.Windows/Perspex.Windows.csproj b/Perspex.Windows/Perspex.Windows.csproj index 7eacbfc990..243df648e7 100644 --- a/Perspex.Windows/Perspex.Windows.csproj +++ b/Perspex.Windows/Perspex.Windows.csproj @@ -56,7 +56,7 @@ - + diff --git a/Perspex.Windows/Window.cs b/Perspex.Windows/Window.cs index efd5c5cfa6..089382e2b8 100644 --- a/Perspex.Windows/Window.cs +++ b/Perspex.Windows/Window.cs @@ -167,7 +167,7 @@ namespace Perspex.Windows { RawMouseEventArgs e = null; - MouseDevice.Instance.CurrentWindow = this; + WindowsMouseDevice.Instance.CurrentWindow = this; switch ((UnmanagedMethods.WindowsMessage)msg) { @@ -185,7 +185,7 @@ namespace Perspex.Windows case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN: e = new RawMouseEventArgs( - MouseDevice.Instance, + WindowsMouseDevice.Instance, this, RawMouseEventType.LeftButtonDown, new Point((uint)lParam & 0xffff, (uint)lParam >> 16)); @@ -193,7 +193,7 @@ namespace Perspex.Windows case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP: e = new RawMouseEventArgs( - MouseDevice.Instance, + WindowsMouseDevice.Instance, this, RawMouseEventType.LeftButtonUp, new Point((uint)lParam & 0xffff, (uint)lParam >> 16)); @@ -201,7 +201,7 @@ namespace Perspex.Windows case UnmanagedMethods.WindowsMessage.WM_MOUSEMOVE: e = new RawMouseEventArgs( - MouseDevice.Instance, + WindowsMouseDevice.Instance, this, RawMouseEventType.Move, new Point((uint)lParam & 0xffff, (uint)lParam >> 16)); @@ -215,7 +215,7 @@ namespace Perspex.Windows if (e != null) { - MouseDevice.Instance.Position = e.Position; + WindowsMouseDevice.Instance.Position = e.Position; this.inputManager.Process(e); } diff --git a/Perspex/Input/IInputManager.cs b/Perspex/Input/IInputManager.cs index d7df6a0bf8..0cddac4e33 100644 --- a/Perspex/Input/IInputManager.cs +++ b/Perspex/Input/IInputManager.cs @@ -6,11 +6,16 @@ namespace Perspex.Input { + using System; using Perspex.Input.Raw; using Perspex.Layout; public interface IInputManager { + IObservable RawEventReceived { get; } + void Process(RawInputEventArgs e); + + void SetPointerOver(IPointerDevice device, IVisual visual, Point p); } } diff --git a/Perspex/Input/IMouseDevice.cs b/Perspex/Input/IMouseDevice.cs index 6a51c65eb0..b4b30ee65b 100644 --- a/Perspex/Input/IMouseDevice.cs +++ b/Perspex/Input/IMouseDevice.cs @@ -6,9 +6,8 @@ namespace Perspex.Input { - using System; - public interface IMouseDevice : IPointerDevice { + Point Position { get; } } } diff --git a/Perspex/Input/InputManager.cs b/Perspex/Input/InputManager.cs index 1d203c1002..7f967e7cea 100644 --- a/Perspex/Input/InputManager.cs +++ b/Perspex/Input/InputManager.cs @@ -6,8 +6,10 @@ namespace Perspex.Input { + using System; using System.Collections.Generic; using System.Linq; + using System.Reactive.Subjects; using Perspex.Controls; using Perspex.Input.Raw; @@ -15,104 +17,19 @@ namespace Perspex.Input { private List pointerOvers = new List(); - 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((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); - break; - case RawMouseEventType.LeftButtonDown: - this.MouseDown((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); - break; - case RawMouseEventType.LeftButtonUp: - this.MouseUp((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); - break; - } - } - - private void MouseMove(IMouseDevice device, IVisual visual, Point p) - { - if (device.Captured == null) - { - this.UpdatePointerOver(device, visual, p); - } - else - { - Point offset = new Point(); - - foreach (IVisual ancestor in device.Captured.GetVisualAncestors()) - { - offset += ancestor.Bounds.Position; - } + private Subject rawEventReceived = new Subject(); - this.UpdatePointerOver(device, device.Captured, p - offset); - } - } - - private void MouseDown(IMouseDevice device, IVisual visual, Point p) + public IObservable RawEventReceived { - IVisual hit = visual.GetVisualAt(p); - - if (hit != null) - { - Interactive interactive = device.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor(); - IFocusable focusable = - device.Captured as IFocusable ?? - hit.GetVisualAncestorsAndSelf() - .OfType() - .FirstOrDefault(x => x.Focusable); - - if (interactive != null) - { - interactive.RaiseEvent(new PointerEventArgs - { - Device = device, - RoutedEvent = Control.PointerPressedEvent, - OriginalSource = interactive, - Source = interactive, - }); - } - - if (focusable != null && focusable.Focusable) - { - focusable.Focus(); - } - } + get { return this.rawEventReceived; } } - private void MouseUp(IMouseDevice device, IVisual visual, Point p) + public void Process(RawInputEventArgs e) { - IVisual hit = visual.GetVisualAt(p); - - if (hit != null) - { - Interactive source = device.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor(); - - if (source != null) - { - source.RaiseEvent(new PointerEventArgs - { - Device = device, - RoutedEvent = Control.PointerReleasedEvent, - OriginalSource = source, - Source = source, - }); - } - } + this.rawEventReceived.OnNext(e); } - private void UpdatePointerOver(IPointerDevice device, IVisual visual, Point p) + public void SetPointerOver(IPointerDevice device, IVisual visual, Point p) { IEnumerable hits = visual.GetVisualsAt(p); diff --git a/Perspex/Input/MouseDevice.cs b/Perspex/Input/MouseDevice.cs new file mode 100644 index 0000000000..502a392f7a --- /dev/null +++ b/Perspex/Input/MouseDevice.cs @@ -0,0 +1,135 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 Tricycle. All rights reserved. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Input +{ + using System; + using System.Linq; + using System.Reactive.Linq; + using Perspex.Controls; + using Perspex.Input.Raw; + using Splat; + + public abstract class MouseDevice : IMouseDevice + { + public MouseDevice() + { + this.InputManager.RawEventReceived + .OfType() + .Where(x => x.Device == this) + .Subscribe(this.ProcessMouse); + } + + public Interactive Captured + { + get; + protected set; + } + + public IInputManager InputManager + { + get { return Locator.Current.GetService(); } + } + + public Point Position + { + get; + protected set; + } + + public virtual void Capture(Interactive visual) + { + this.Captured = visual; + } + + private void ProcessMouse(RawMouseEventArgs e) + { + switch (e.Type) + { + case RawMouseEventType.Move: + this.MouseMove((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); + break; + case RawMouseEventType.LeftButtonDown: + this.MouseDown((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); + break; + case RawMouseEventType.LeftButtonUp: + this.MouseUp((IMouseDevice)e.Device, (IVisual)e.Root, e.Position); + break; + } + } + + private void MouseMove(IMouseDevice device, IVisual visual, Point p) + { + if (this.Captured == null) + { + this.InputManager.SetPointerOver(this, visual, p); + } + else + { + Point offset = new Point(); + + foreach (IVisual ancestor in this.Captured.GetVisualAncestors()) + { + offset += ancestor.Bounds.Position; + } + + this.InputManager.SetPointerOver(this, this.Captured, p - offset); + } + } + + private void MouseDown(IMouseDevice device, IVisual visual, Point p) + { + IVisual hit = visual.GetVisualAt(p); + + if (hit != null) + { + Interactive interactive = this.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor(); + IFocusable focusable = + this.Captured as IFocusable ?? + hit.GetVisualAncestorsAndSelf() + .OfType() + .FirstOrDefault(x => x.Focusable); + + if (interactive != null) + { + interactive.RaiseEvent(new PointerEventArgs + { + Device = this, + RoutedEvent = Control.PointerPressedEvent, + OriginalSource = interactive, + Source = interactive, + }); + } + + if (focusable != null && focusable.Focusable) + { + focusable.Focus(); + } + } + } + + private void MouseUp(IMouseDevice device, IVisual visual, Point p) + { + IVisual hit = visual.GetVisualAt(p); + + if (hit != null) + { + Interactive source = this.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor(); + + if (source != null) + { + source.RaiseEvent(new PointerEventArgs + { + Device = this, + RoutedEvent = Control.PointerReleasedEvent, + OriginalSource = source, + Source = source, + }); + } + } + } + } +} diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index beee983b6c..0fdefe0219 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -93,6 +93,7 @@ +