From 0fcc658d4f81d6915eb3da4300e0fee1a7bcc733 Mon Sep 17 00:00:00 2001 From: mgth Date: Thu, 4 Jan 2018 18:22:13 +0100 Subject: [PATCH] engine start stop fix --- HLab/Windows.Monitors/DisplayDevice.cs | 19 +- HLab/Windows.Monitors/Monitor.cs | 10 +- HLab/Windows.Monitors/MonitorsService.cs | 16 +- HLab/Windows.Monitors/PhysicalAdapter.cs | 14 +- LittleBigMouse/Control.Core/MainService.cs | 5 +- .../Control.Core/ScreenFrameViewModel.cs | 1 + .../Control.Loader/setup/LittleBigMouse.iss | 2 +- LittleBigMouse/Daemon/Geo.cs | 7 +- .../Daemon/LittleBigMouse.Daemon.csproj | 1 + LittleBigMouse/Daemon/MouseEngine.cs | 411 ++++++++++++------ LittleBigMouse/Daemon/Zone.cs | 110 +++++ .../Plugins/Location/LocationControlView.xaml | 7 +- .../Location/LocationControlView.xaml.cs | 80 +--- .../Location/LocationControlViewModel.cs | 14 +- .../ScreenConfig/ILittleBigMouseService.cs | 4 +- LittleBigMouse/ScreenConfig/ScreenConfig.cs | 48 +- 16 files changed, 488 insertions(+), 261 deletions(-) create mode 100644 LittleBigMouse/Daemon/Zone.cs diff --git a/HLab/Windows.Monitors/DisplayDevice.cs b/HLab/Windows.Monitors/DisplayDevice.cs index 6591cd55..097276fe 100644 --- a/HLab/Windows.Monitors/DisplayDevice.cs +++ b/HLab/Windows.Monitors/DisplayDevice.cs @@ -34,12 +34,17 @@ namespace HLab.Windows.Monitors { public class DisplayDevice : NotifierObject { - public DisplayDevice() + public DisplayDevice(MonitorsService service) { + Service = service; this.SubscribeNotifier(); } - public MonitorsService Service => this.Get(()=>MonitorsService.D); + public MonitorsService Service + { + get => this.Get(); + private set => this.Set(value); + } public void Init(DisplayDevice parent, NativeMethods.DISPLAY_DEVICE dev, IList oldDevices) { @@ -57,13 +62,13 @@ public void Init(DisplayDevice parent, NativeMethods.DISPLAY_DEVICE dev, IList new Monitor {DeviceId = DeviceId}); + var mon = Service.GetOrAddMonitor(DeviceId, () => new Monitor(Service) {DeviceId = DeviceId}); mon.DeviceKey = DeviceKey; mon.DeviceString = DeviceString; mon.AttachedToDesktop = AttachedToDesktop; break; case "PCI": - Service.GetOrAddAdapter(DeviceId, () => new PhysicalAdapter + Service.GetOrAddAdapter(DeviceId, () => new PhysicalAdapter(Service) { DeviceId = DeviceId, DeviceString = DeviceString @@ -81,7 +86,7 @@ public void Init(DisplayDevice parent, NativeMethods.DISPLAY_DEVICE dev, IList m.DeviceName == child.DeviceName); + var device = Service.Devices.FirstOrDefault(m => m.DeviceName == child.DeviceName); if (device != null) { oldDevices.Remove(device); @@ -89,9 +94,9 @@ public void Init(DisplayDevice parent, NativeMethods.DISPLAY_DEVICE dev, IList 0) NativeMethods.DestroyPhysicalMonitors((uint)_pPhysicalMonitorArray.Length, ref _pPhysicalMonitorArray); } - public MonitorsService Service => this.Get(() => MonitorsService.D); + public MonitorsService Service + { + get => this.Get(); + private set => this.Set(value); + } + public string DeviceKey { get => this.Get(); @@ -168,8 +173,9 @@ internal set private NativeMethods.PHYSICAL_MONITOR[] _pPhysicalMonitorArray; - public Monitor() + public Monitor(MonitorsService service) { + Service = service; this.SubscribeNotifier(); } diff --git a/HLab/Windows.Monitors/MonitorsService.cs b/HLab/Windows.Monitors/MonitorsService.cs index 7c28cfe9..58a75eae 100644 --- a/HLab/Windows.Monitors/MonitorsService.cs +++ b/HLab/Windows.Monitors/MonitorsService.cs @@ -38,7 +38,14 @@ You should have received a copy of the GNU General Public License namespace HLab.Windows.Monitors { - public class MonitorsService : Singleton, INotifyPropertyChanged + public interface IMonitorsService + { + ObservableCollection Monitors { get; } + ObservableFilter AttachedMonitors { get; } + } + + + public class MonitorsService : Singleton, INotifyPropertyChanged, IMonitorsService { public event EventHandler DevicesUpdated; @@ -48,6 +55,8 @@ private MonitorsService() _displayChanges.Show(); _displayChanges.Hide(); + UpdateDevices(); + this.SubscribeNotifier(); } @@ -57,9 +66,6 @@ private MonitorsService() public ObservableCollection Devices => this.Get(() => new ObservableCollection()); public ObservableCollection Monitors => this.Get(() => new ObservableCollection()); - [TriggedOn(nameof(Monitors), "Item", "AttachedToDesktop")] - public void test() - { } [TriggedOn(nameof(Monitors),"Item","AttachedToDesktop")] public ObservableFilter AttachedMonitors => this.Get(()=> new ObservableFilter() @@ -101,7 +107,7 @@ public void UpdateDevices() List oldDevices = Devices.ToList(); - var device = new DisplayDevice(); + var device = new DisplayDevice(this); device.Init(null,new NativeMethods.DISPLAY_DEVICE(true){DeviceID = "ROOT",DeviceName = null}, oldDevices ); foreach (var d in oldDevices) diff --git a/HLab/Windows.Monitors/PhysicalAdapter.cs b/HLab/Windows.Monitors/PhysicalAdapter.cs index 84ffffed..b1424515 100644 --- a/HLab/Windows.Monitors/PhysicalAdapter.cs +++ b/HLab/Windows.Monitors/PhysicalAdapter.cs @@ -10,7 +10,17 @@ namespace HLab.Windows.Monitors { public class PhysicalAdapter : NotifierObject { - public MonitorsService Service => this.Get(()=>MonitorsService.D); + public PhysicalAdapter(MonitorsService service) + { + Service = service; + this.SubscribeNotifier(); + } + + public MonitorsService Service + { + get => this.Get(); + private set => this.Set(value); + } public string DeviceString { @@ -24,7 +34,7 @@ public string DeviceId } [TriggedOn(nameof(DeviceId))] - [TriggedOn(nameof(Service),"Displays","Item","DeviceId")] + [TriggedOn(nameof(Service), "Devices", "Item","DeviceId")] public ObservableFilter Displays => this.Get(() => new ObservableFilter() .AddFilter(a => a.DeviceId == DeviceId) .Link(Service.Devices) diff --git a/LittleBigMouse/Control.Core/MainService.cs b/LittleBigMouse/Control.Core/MainService.cs index 76cac3ea..9de1787d 100644 --- a/LittleBigMouse/Control.Core/MainService.cs +++ b/LittleBigMouse/Control.Core/MainService.cs @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License using System.Windows; using HLab.Mvvm; using HLab.Plugin; +using HLab.Windows.Monitors; using LittleBigMouse.ScreenConfigs; namespace LittleBigMouse.Control.Core @@ -34,7 +35,9 @@ public override void Register() { var viewModel = D.MainViewModel; - var config = new ScreenConfig(); + var m = MonitorsService.D; + + var config = new ScreenConfig(m); viewModel.Config = config; viewModel.Presenter = new MultiScreensViewModel { Config = config }; diff --git a/LittleBigMouse/Control.Core/ScreenFrameViewModel.cs b/LittleBigMouse/Control.Core/ScreenFrameViewModel.cs index f4221141..8b66e195 100644 --- a/LittleBigMouse/Control.Core/ScreenFrameViewModel.cs +++ b/LittleBigMouse/Control.Core/ScreenFrameViewModel.cs @@ -201,6 +201,7 @@ public void UpdateLogo() Logo = (Viewbox)Application.Current.FindResource("LogoHp"); return; case "lg": case "lgs": + case "gsm"://GoldStar Logo = (Viewbox)Application.Current.FindResource("LogoLg"); return; case "apl": case "app": diff --git a/LittleBigMouse/Control.Loader/setup/LittleBigMouse.iss b/LittleBigMouse/Control.Loader/setup/LittleBigMouse.iss index 301ff494..7d30b9d6 100644 --- a/LittleBigMouse/Control.Loader/setup/LittleBigMouse.iss +++ b/LittleBigMouse/Control.Loader/setup/LittleBigMouse.iss @@ -1,6 +1,6 @@ ; -- LittleBigMouse.iss -- ;#define AppVer GetFileVersion('..\bin\x64\Release\LittleBigMouse_Control.exe') -#define AppVer '4.0-beta5' +#define AppVer '4.0-beta6' [Setup] AppName=Little Big Mouse diff --git a/LittleBigMouse/Daemon/Geo.cs b/LittleBigMouse/Daemon/Geo.cs index fc09d230..4eaeff8c 100644 --- a/LittleBigMouse/Daemon/Geo.cs +++ b/LittleBigMouse/Daemon/Geo.cs @@ -163,17 +163,18 @@ public Segment(Point a, Point b) public Line Line => _line ?? (_line = Line.fromSegment(this)); public Rect Rect => new Rect(A, B); - - public double Size + public double SizeSquared { get { Rect r = Rect; - return Math.Sqrt(r.Width * r.Width + r.Height * r.Height); + return r.Width * r.Width + r.Height * r.Height; } } + public double Size => Math.Sqrt(SizeSquared); + public Point? Intersect(Line l) { if (l == null) throw new ArgumentNullException(nameof(l)); diff --git a/LittleBigMouse/Daemon/LittleBigMouse.Daemon.csproj b/LittleBigMouse/Daemon/LittleBigMouse.Daemon.csproj index 9ddeb5cb..1107ee57 100644 --- a/LittleBigMouse/Daemon/LittleBigMouse.Daemon.csproj +++ b/LittleBigMouse/Daemon/LittleBigMouse.Daemon.csproj @@ -147,6 +147,7 @@ True Resources.resx + diff --git a/LittleBigMouse/Daemon/MouseEngine.cs b/LittleBigMouse/Daemon/MouseEngine.cs index 35c04213..3f73a5c0 100644 --- a/LittleBigMouse/Daemon/MouseEngine.cs +++ b/LittleBigMouse/Daemon/MouseEngine.cs @@ -21,12 +21,15 @@ You should have received a copy of the GNU General Public License http://www.mgth.fr */ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.ServiceModel; using System.ServiceModel.Description; +using System.Threading; using System.Windows; +using HLab.Windows.API; using HLab.Windows.MonitorVcp; using HLab.Windows.Monitors; using LittleBigMouse.ScreenConfigs; @@ -37,14 +40,17 @@ You should have received a copy of the GNU General Public License namespace LittleBigMouse_Daemon { [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] - public class MouseEngine + public class MouseEngine { public ScreenConfig Config { get; private set; } + + private Zones _zones; + private double _initMouseSpeed; public readonly MouseHookListener Hook = new MouseHookListener(new GlobalHooker()); - private Point? _oldPoint = null; private ServiceHost _host; + public void StartServer(ILittleBigMouseService service) { if (_host == null) @@ -58,8 +64,9 @@ public void StartServer(ILittleBigMouseService service) _host.Description.Behaviors.Add(smb); } - _host.Open(); + _host.Open(); } + public void StopServer() { _host.Close(); @@ -72,15 +79,12 @@ public void Quit() public void Start() { - if (Hook.Enabled) return; + Stop(); - if (Config == null) - LoadConfig(); + LoadConfig(); if (Config == null || !Config.Enabled) return; - SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged; - using (RegistryKey key = ScreenConfig.OpenRootRegKey(true)) { string ms = key.GetValue("InitialMouseSpeed", string.Empty).ToString(); @@ -88,9 +92,10 @@ public void Start() if (string.IsNullOrEmpty(ms)) { _initMouseSpeed = LbmMouse.MouseSpeed; - key.SetValue("InitialMouseSpeed", _initMouseSpeed.ToString(CultureInfo.InvariantCulture), RegistryValueKind.String); + key.SetValue("InitialMouseSpeed", _initMouseSpeed.ToString(CultureInfo.InvariantCulture), + RegistryValueKind.String); } - else + else double.TryParse(ms, out _initMouseSpeed); using (RegistryKey savekey = key.CreateSubKey("InitialCursor")) @@ -104,20 +109,40 @@ public void Start() Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; - Hook.MouseMoveExt += OnMouseMoveExt; + + _handler = OnMouseMoveExtFirst; + Hook.MouseMoveExt += _handler; + + if (Config.AdjustPointer) + ZoneChanged += AdjustPointer; + + if (Config.AdjustSpeed) + ZoneChanged += AdjustSpeed; + + if(Config.HomeCinema) + ZoneChanged += HomeCinema; + + Hook.Enabled = true; - // LittleBigMouseDaemon.Callback?.OnStateChange(); } public void Stop() { - SystemEvents.DisplaySettingsChanged -= OnDisplaySettingsChanged; - if (!Hook.Enabled) return; - Hook.MouseMoveExt -= OnMouseMoveExt; + Hook.MouseMoveExt -= _handler; + + if (Config.AdjustPointer) + ZoneChanged -= AdjustPointer; + + if (Config.AdjustSpeed) + ZoneChanged -= AdjustSpeed; + + if (Config.HomeCinema) + ZoneChanged -= HomeCinema; + + Hook.Enabled = false; - // LittleBigMouseDaemon.Callback?.OnStateChange(); if (Config == null) return; @@ -152,182 +177,296 @@ public void Stop() public void LoadConfig(ScreenConfig config) { Config = config; - ConfigLoaded?.Invoke(config,null); + ConfigLoaded?.Invoke(config, null); } public event EventHandler ConfigLoaded; + public void LoadConfig() { - if(Config!=null) Config.Load(); - else - LoadConfig(new ScreenConfig()); + LoadConfig(new ScreenConfig(MonitorsService.D)); + + _zones = new Zones(); + foreach (var screen in Config.AllScreens) + { + _zones.Add(new Zone(screen)); + } + + + if (Config.LoopX) + { + foreach (var screen in Config.AllScreens) + { + var main = _zones.Main.FirstOrDefault(e => ReferenceEquals(e.Screen, screen)); + _zones.Add(new Zone(screen,main,-Config.PhysicalOutsideBounds.Width,0)); + _zones.Add(new Zone(screen,main,Config.PhysicalOutsideBounds.Width,0)); + } + } + + if (Config.LoopY) + { + foreach (var screen in Config.AllScreens) + { + var main = _zones.Main.FirstOrDefault(e => ReferenceEquals(e.Screen,screen)); + _zones.Add(new Zone(screen,main, 0,-Config.PhysicalOutsideBounds.Height)); + _zones.Add(new Zone(screen,main, 0,Config.PhysicalOutsideBounds.Height)); + } + } } - private void OnDisplaySettingsChanged(object sender, EventArgs e) + + private readonly Stopwatch _timer = new Stopwatch(); + private int _count = -10; + + //private void OnMouseMoveExt(object sender, MouseEventExtArgs e) + //{ + // //_timer.Start(); + // //try + // //{ + // if (e.Clicked) return; + // var pIn = new Point(e.X, e.Y); + + // if (_oldZone.ContainsPx(pIn)) + // { + // _oldPoint = pIn; + // e.Handled = false; + // return; + // } + + // e.Handled = _handler(pIn); + + // //} + // //finally + // //{ + // // _timer.Stop(); + // // _count++; + // //} + //} + + private void PrintResult() { - LoadConfig(); + Console.WriteLine("AVG :" + _timer.ElapsedTicks / _count); + Console.WriteLine("AVG :" + _timer.Elapsed.TotalMilliseconds / _count); } - private void OnMouseMoveExt(object sender, MouseEventExtArgs e) + + private EventHandler _handler; + private Point _oldPoint; + private Zone _oldZone; + + private void OnMouseMoveExtFirst(object sender, MouseEventExtArgs e) { - // If first time called just save that point - if (_oldPoint == null) - { - _oldPoint = new Point(e.X, e.Y); - return; - } + _oldPoint = new Point(e.X,e.Y); + //_oldScreenRect = Config.ScreenFromPixel(_oldPoint).InPixel.Bounds; + _oldZone = _zones.FromPx(_oldPoint); + Hook.MouseMoveExt -= _handler; - if (e.Clicked) return; + if (Config.AllowCornerCrossing) + _handler = MouseMoveCross; + else + { + _handler = MouseMovestraight; + } - Screen oldScreen = Config.ScreenFromPixel(_oldPoint.Value); + Hook.MouseMoveExt += _handler; - Point pIn = new Point(e.X, e.Y); + e.Handled = false; + } - // No move - if (pIn.Equals(_oldPoint)) return; + public event EventHandler ZoneChanged; - //Debug.Print(pIn.X + " , " + pIn.Y + " -> " + pIn.TargetScreen?.Monitor.Adapter.DeviceName); + private void MouseMovestraight(object sender, MouseEventExtArgs e) + { + if (e.Clicked) return; + var pIn = new Point(e.X, e.Y); - // no screen change - if (oldScreen == null || Equals(Config.ScreenFromPixel(pIn), oldScreen)) + if (_oldZone.ContainsPx(pIn)) { _oldPoint = pIn; + e.Handled = false; return; } - Point oldpInMm = oldScreen.InMm.GetPoint(oldScreen.InPixel, _oldPoint.Value); - Point pInMm = oldScreen.InMm.GetPoint(oldScreen.InPixel, pIn); - Screen screenOut = null; //Config.ScreenFromMmPosition(pInMm);// pIn.Mm.TargetScreen; - - Debug.Print(oldScreen?.Monitor.AttachedDisplay.DeviceName + "P:" + _oldPoint + " --> P:" + pIn + " " + screenOut?.Monitor.AttachedDisplay.DeviceName); - - Point pOut = pIn; + //Point oldpInMm = _oldZone.Px2Mm(_oldPoint); + Point pInMm = _oldZone.Px2Mm(pIn); + Zone zoneOut = null; + var minDx = 0.0; + var minDy = 0.0; - // - // Allow Corner Jump - // - if (screenOut == null) + if (pIn.Y > _oldZone.Px.Bottom) + { + foreach (var zone in _zones.All/*.Where(z => z.Mm.Top > _oldZone.Mm.Bottom)*/) + { + if (zone.Mm.Left > pInMm.X || zone.Mm.Right < pInMm.X) continue; + var dy = zone.Mm.Top - _oldZone.Mm.Bottom; + + if (dy < 0) continue; + if (dy > minDy && minDy > 0) continue; + + + // = pInMm + new Vector(0, dy); + minDy = dy; + zoneOut = zone; + } + } + else if (pIn.Y < _oldZone.Px.Top) { - double dist = double.PositiveInfinity;// (100.0); - Segment seg = new Segment(oldpInMm, pInMm); + foreach (var zone in _zones.All/*.Where(z => !ReferenceEquals(z, _oldZone))*/) + { + if (zone.Mm.Left > pInMm.X || zone.Mm.Right < pInMm.X) continue; + var dy = zone.Mm.Bottom - _oldZone.Mm.Top; - // Calculate side to enter screen when corner crossing not allowed. - Side side = seg.IntersectSide(oldScreen.InMm.Bounds); + if (dy > 0) continue; + if (dy < minDy && minDy < 0) continue; + minDy= dy; + zoneOut = zone; + } + } - if (Config.AllowCornerCrossing) + if (pIn.X > _oldZone.Px.Right) + { + foreach (var zone in _zones.All) { - foreach (var screen in Config.AllBut(oldScreen)) - { - foreach (Point p in seg.Line.Intersect(screen.InMm.Bounds)) - { - var travel = new Segment(oldpInMm, p); - if (!travel.Rect.Contains(pInMm)) continue; - if (travel.Size > dist) continue; + if (zone.Mm.Top > pInMm.Y || zone.Mm.Bottom < pInMm.Y) continue; + var dx = zone.Mm.Left - _oldZone.Mm.Right; - dist = travel.Size; - pOut = screen.InPixel.GetPoint(screen.InMm, - p); // (new PhysicalPoint(Config, screen, p.X, p.Y)).Pixel.Inside; - pOut = screen.InPixel.Inside(pOut); - screenOut = screen; - } - } + if (dx < 0) continue; + if (dx > minDx && minDx > 0) continue; + + minDx = dx; + zoneOut = zone; } - else + } + else if (pIn.X < _oldZone.Px.Left) + { + foreach (var zone in _zones.All) { - foreach (var screen in Config.AllBut(oldScreen)) - { - Vector offset = new Vector(0, 0); - - switch (side) - { - case Side.None: - break; - case Side.Bottom: - offset.Y = seg.Rect.Height + screen.InMm.Y - (oldScreen.InMm.Y + oldScreen.InMm.Height); - if (offset.Y < 0) offset.Y = 0; - break; - case Side.Top: - offset.Y = -seg.Rect.Height + (screen.InMm.Y + screen.InMm.Height) - oldScreen.InMm.Y; - if (offset.Y > 0) offset.Y = 0; - break; - case Side.Right: - offset.X = seg.Rect.Width + screen.InMm.X - (oldScreen.InMm.X + oldScreen.InMm.Width); - if (offset.X < 0) offset.X = 0; - break; - case Side.Left: - offset.X = -seg.Rect.Width + (screen.InMm.X + screen.InMm.Width) - oldScreen.InMm.X; - if (offset.X > 0) offset.X = 0; - break; - default: - throw new ArgumentOutOfRangeException(); - } + if (zone.Mm.Top > pInMm.Y || zone.Mm.Bottom < pInMm.Y) continue; + var dx = zone.Mm.Right - _oldZone.Mm.Left; - Debug.Print(screen.Monitor.AttachedDisplay.DeviceName + " = " + offset.Length); + if (dx < minDx && minDx < 0) continue; + if (dx > 0) continue; - if (offset.Length > 0 && offset.Length < dist) - { - Point shiftedPoint = pInMm + offset; - - if (Equals(Config.ScreenFromMmPosition(shiftedPoint), screen)) - { - dist = offset.Length; - pOut = screen.InPixel.GetPoint(screen.InMm, shiftedPoint); - pOut = screen.InPixel.Inside(pOut); - screenOut = screen; - } - else - { - - } - } - } + minDx = dx; + zoneOut = zone; } } - // if new position is not within another screen - if (screenOut == null) + if (zoneOut == null) { - Debug.Print("Out"); - LbmMouse.CursorPos = oldScreen.InPixel.Inside(pIn); // _oldPoint.Value; fix #40 + LbmMouse.CursorPos = _oldZone.InsidePx(pIn); e.Handled = true; return; } + var pOut = zoneOut.Mm2Px(new Point(pInMm.X+minDx,pInMm.Y+minDy)); + pOut = zoneOut.InsidePx(pOut); + _oldZone = zoneOut.Main; + _oldPoint = pOut; + LbmMouse.CursorPos = pOut; + ZoneChanged?.Invoke(this, new ZoneChangeEventArgs(_oldZone, zoneOut)); + e.Handled = true; + } - // Actual mouving mouse to new location - LbmMouse.CursorPos = pOut;//.Mm.ToScreen(screenOut).Pixel.Inside.Point; - Debug.Print(">" + pOut.X + "," + pOut.Y); - Debug.Print(">" + LbmMouse.CursorPos.X + "," + LbmMouse.CursorPos.Y); + private void MouseMoveCross(object sender, MouseEventExtArgs e) + { + if (e.Clicked) return; + var pIn = new Point(e.X, e.Y); - // Adjust pointer size to dpi ratio : should not be usefull if windows screen ratio is used - if (Config.AdjustPointer) + if (_oldZone.ContainsPx(pIn)) { - if (screenOut.RealDpiAvg > 110) - { - LbmMouse.SetCursorAero(screenOut.RealDpiAvg > 138 ? 3 : 2); - } - else LbmMouse.SetCursorAero(1); + _oldPoint = pIn; + e.Handled = false; + return; } + //if (_count >= 0) _timer.Start(); + //try + //{ + Point oldpInMm = _oldZone.Px2Mm(_oldPoint); + Point pInMm = _oldZone.Px2Mm(pIn); + Zone zoneOut = null; + var seg = new Segment(oldpInMm, pInMm); + var minDist = double.PositiveInfinity; - // Adjust pointer speed to dpi ratio : should not be usefull if windows screen ratio is used - if (Config.AdjustSpeed) + var pOutInMm = pInMm; + + foreach (var zone in _zones.All.Where(z => !ReferenceEquals(z, _oldZone))) + { + foreach (var p in seg.Line.Intersect(zone.Mm)) + { + var travel = new Segment(oldpInMm, p); + if (!travel.Rect.Contains(pInMm)) continue; + var dist = travel.SizeSquared; + if (dist > minDist) continue; + + minDist = dist; + zoneOut = zone; + pOutInMm = p; + } + } + + if (zoneOut == null) + { + LbmMouse.CursorPos = _oldZone.InsidePx(pIn); + e.Handled = true; + return; + } + + var pOut = zoneOut.Mm2Px(pOutInMm); + pOut = zoneOut.InsidePx(pOut); + _oldZone = zoneOut.Main; + _oldPoint = pOut; + LbmMouse.CursorPos = pOut; + ZoneChanged?.Invoke(this, new ZoneChangeEventArgs(_oldZone, zoneOut)); + e.Handled = true; + return; + + //} + + //finally + //{ + // if (_count >= 0) _timer.Stop(); + // _count++; + //} + } + + public class ZoneChangeEventArgs : EventArgs + { + public ZoneChangeEventArgs(Zone oldZone, Zone newZone) { - LbmMouse.MouseSpeed = Math.Round((5.0/96.0)*screenOut.RealDpiAvg, 0); + OldZone = oldZone; + NewZone = newZone; } - if (Config.HomeCinema) + public Zone OldZone { get; } + public Zone NewZone { get; } + } + + private void AdjustPointer(object sender, ZoneChangeEventArgs args) + { + if (args.NewZone.Dpi - args.OldZone.Dpi < 1) return; + if (args.NewZone.Dpi > 110) { - oldScreen.Monitor.Vcp().Power = false; + LbmMouse.SetCursorAero(args.NewZone.Dpi > 138 ? 3 : 2); } - screenOut.Monitor.Vcp().Power = true; + else LbmMouse.SetCursorAero(1); + } - _oldPoint = pOut; - e.Handled = true; + private void AdjustSpeed(object sender, ZoneChangeEventArgs args) + { + LbmMouse.MouseSpeed = Math.Round((5.0/96.0)* args.NewZone.Dpi, 0); + } + + private void HomeCinema(object sender, ZoneChangeEventArgs args) + { + args.OldZone.Screen.Monitor.Vcp().Power = false; + args.NewZone.Screen.Monitor.Vcp().Power = true; } + public void MatchConfig(string configId) { Config.MatchConfig(configId); diff --git a/LittleBigMouse/Daemon/Zone.cs b/LittleBigMouse/Daemon/Zone.cs new file mode 100644 index 00000000..9bed44d3 --- /dev/null +++ b/LittleBigMouse/Daemon/Zone.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Remoting.Messaging; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; +using LittleBigMouse.ScreenConfigs; + +namespace LittleBigMouse_Daemon +{ + public class Zones + { + public void Add(Zone zone) + { + All.Add(zone); + if(ReferenceEquals(zone.Main,zone)) Main.Add(zone); + } + + public Zone FromPx(Point px) => Main.FirstOrDefault(zone => zone.ContainsPx(px)); + public Zone FromMm(Point mm) => All.FirstOrDefault(zone => zone.ContainsMm(mm)); + + public List All { get; } = new List(); + public List Main { get; } = new List(); + + } + + public class Zone + { + public readonly Rect Px; + public readonly Rect Mm; + public readonly Zone Main; + public Rect Capture; + + public readonly double Dpi; + + private readonly Matrix _px2Mm; + private readonly Matrix _mm2Px; + + public Screen Screen { get; } + + public Zone(Screen screen,Zone main = null,double translateX=0, double translateY = 0) + { + Screen = screen; + + if (main == null) main = this; + + Main = main; + + Px = screen.InPixel.Bounds; + Px.Width = Px.Width - 1; + Px.Height = Px.Height - 1; + + var mm = screen.InMm.Bounds; + var matrix = new Matrix(); + matrix.Translate(translateX,translateY); + mm.Transform(matrix); + Mm = mm; + + + var px2Mm = new Matrix(); + px2Mm.Translate(-Px.X,-Px.Y); + px2Mm.Scale(1/ Px.Width, 1/ Px.Height); + px2Mm.Scale(Mm.Width, Mm.Height); + px2Mm.Translate(Mm.X, Mm.Y); + _px2Mm = px2Mm; + + var mm2Px = new Matrix(); + mm2Px.Translate(-Mm.X, -Mm.Y); + mm2Px.Scale(1 / Mm.Width, 1 / Mm.Height); + mm2Px.Scale(Px.Width, Px.Height); + mm2Px.Translate(Px.X, Px.Y); + _mm2Px = mm2Px; + + var dpiX = Px.Width / (Mm.Width / 25.4); + var dpiY = Px.Height / (Mm.Height / 25.4); + + Dpi = Math.Sqrt(dpiX * dpiX + dpiY * dpiY) / Math.Sqrt(2); + } + + public Point Px2Mm(Point px) => px * _px2Mm; + + public Point Mm2Px(Point mm) => mm * _mm2Px; + + public bool ContainsPx(Point px) => Px.Contains(px); + public bool ContainsMm(Point mm) => Mm.Contains(mm); + + public Point InsidePx(Point px) + { + if (px.X < Px.X) px.X = Px.X; + else if (px.X > Px.Right) px.X = Px.Right; + + if (px.Y < Px.Y) px.Y = Px.Y; + else if (px.Y > Px.Bottom) px.Y = Px.Bottom; + + return px; + } + public Point InsideMm(Point mm) + { + if (mm.X < Mm.X) mm.X = Mm.X; + else if (mm.X > Mm.Right) mm.X = Mm.Right; + + if (mm.Y < Mm.Y) mm.Y = Mm.Y; + else if (mm.Y > Mm.Bottom) mm.Y = Mm.Bottom; + + return mm; + } + } +} diff --git a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml index 4592d565..cd1e3ab4 100644 --- a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml +++ b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml @@ -1,4 +1,4 @@ - --> + + + + + diff --git a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml.cs b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml.cs index 13cbcc71..26d9d45a 100644 --- a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml.cs +++ b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlView.xaml.cs @@ -20,17 +20,12 @@ You should have received a copy of the GNU General Public License mailto:mathieu@mgth.fr http://www.mgth.fr */ -using System.Collections.Generic; -using System.ComponentModel; -using System.Windows; + using System.Windows.Controls; -using System.Windows.Input; using HLab.Mvvm; using LittleBigMouse.Control.Core; -using LittleBigMouse.LocationPlugin.Plugins.Location.Rulers; -using LittleBigMouse.ScreenConfigs; -namespace LittleBigMouse.LocationPlugin.Plugins.Location +namespace LittleBigMouse.Plugin.Location.Plugins.Location { /// /// Logique d'interaction pour ControlGuiSizer.xaml @@ -44,77 +39,6 @@ public LocationControlView() InitializeComponent(); } - private ICommand Save = new RoutedCommand(); - - private void cmdOk_Click(object sender, RoutedEventArgs e) - { - cmdApply_Click(sender, e); - // MainGui.Close(); - } - - private void cmdApply_Click(object sender, RoutedEventArgs e) - { - //Save(); - //LittleBigMouseClient.Client.LoadAtStartup(Config.LoadAtStartup); - LittleBigMouseClient.Client.LoadConfig(); - LittleBigMouseClient.Client.Start(); - } - - private void cmdCancel_Click(object sender, RoutedEventArgs e) - { - // MainGui.Close(); - } - - private void cmdUnload_Click(object sender, RoutedEventArgs e) - { - LittleBigMouseClient.Client.Quit(); - } - - - - private readonly List _rulers = new List(); - private bool _liveUpdate = false; - private void AddRuler(RulerViewModel.RulerSide side) - { - //if (Config.Selected == null) return; - - //foreach (var sz in Config.AllScreens.Select(s => new Ruler(Config.Selected, s, side))) - //{ - // _rulers.Add(sz); - //} - } - - public bool LiveUpdate - { - get => _liveUpdate; set - { - //if (Change.Set(ref _liveUpdate, value) && value) - // ActivateConfig(); - //else - //{ - // LittleBigMouseClient.Client.LoadConfig(); - //} - } - } - - public void ActivateConfig() - { - if (LiveUpdate) - { - //Save(); - LittleBigMouseClient.Client.LoadConfig(); - } - - } - private void Config_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - ActivateConfig(); - } - - private void cmdColors_Click(object sender, RoutedEventArgs e) - { - new ColorsWindow().Show(); - } } } \ No newline at end of file diff --git a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlViewModel.cs b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlViewModel.cs index bb281f7f..942f60cf 100644 --- a/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlViewModel.cs +++ b/LittleBigMouse/Plugin/Location/Plugins/Location/LocationControlViewModel.cs @@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License mailto:mathieu@mgth.fr http://www.mgth.fr */ + using System; using System.ComponentModel; using HLab.Mvvm; @@ -29,7 +30,7 @@ You should have received a copy of the GNU General Public License using LittleBigMouse.ScreenConfigs; using Tester = LittleBigMouse.LocationPlugin.Plugins.Location.Rulers.Tester; -namespace LittleBigMouse.LocationPlugin.Plugins.Location +namespace LittleBigMouse.Plugin.Location.Plugins.Location { class LocationControlViewModel : IViewModel { @@ -66,15 +67,14 @@ private void Client_StateChanged() { Config.Enabled = true; - if (!Config.Saved) Config.Save(); + if (!Config.Saved) + Config.Save(); + + LittleBigMouseClient.Client.LoadConfig(); if (!Running) LittleBigMouseClient.Client.Start(); - else - { - Config.Save(); - LittleBigMouseClient.Client.LoadConfig(); - } + Client_StateChanged(); }, () => !(Running && Config.Saved)); diff --git a/LittleBigMouse/ScreenConfig/ILittleBigMouseService.cs b/LittleBigMouse/ScreenConfig/ILittleBigMouseService.cs index fd9bcd86..0c6222bf 100644 --- a/LittleBigMouse/ScreenConfig/ILittleBigMouseService.cs +++ b/LittleBigMouse/ScreenConfig/ILittleBigMouseService.cs @@ -76,6 +76,7 @@ public void LoadConfig() try { Channel.LoadConfig(); } catch (EndpointNotFoundException) { LauchServer("--loadconfig"); } catch (CommunicationException) { } + catch (TimeoutException) { } //catch (FaultException) { } } @@ -139,7 +140,8 @@ public void LauchServer(string args="") { var p = Process.GetCurrentProcess(); string filename = p.MainModule.FileName.Replace("_Control", "_Daemon").Replace(".vshost", ""); - Process.Start(filename,args); + var process = Process.Start(filename,args); + //Thread.Sleep(1000); //Init(); } diff --git a/LittleBigMouse/ScreenConfig/ScreenConfig.cs b/LittleBigMouse/ScreenConfig/ScreenConfig.cs index 3d539ffb..bec07ac5 100644 --- a/LittleBigMouse/ScreenConfig/ScreenConfig.cs +++ b/LittleBigMouse/ScreenConfig/ScreenConfig.cs @@ -85,18 +85,16 @@ public Screen ScreenFromMmPosition(Point mm) return null; } - public ScreenConfig() - { - MonitorsOnCollectionChanged(MonitorsService.D.AttachedMonitors, - new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, MonitorsService.D.AttachedMonitors)); - MonitorsService.D.AttachedMonitors.CollectionChanged += MonitorsOnCollectionChanged; - this.SubscribeNotifier(); - MonitorsService.D.UpdateDevices(); + public ScreenConfig(IMonitorsService monitorsService) + { + this.SubscribeNotifier(); - SetPhysicalAuto(false); + MonitorsOnCollectionChanged(monitorsService.AttachedMonitors, + new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, MonitorsService.D.AttachedMonitors)); + monitorsService.AttachedMonitors.CollectionChanged += MonitorsOnCollectionChanged; } private void MonitorsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) @@ -119,6 +117,7 @@ private void MonitorsOnCollectionChanged(object sender, NotifyCollectionChangedE } Load(); + SetPhysicalAuto(false); } public ObservableCollection AllScreens => this.Get(()=>new ObservableCollection()); @@ -164,15 +163,8 @@ internal static string ConfigPath(string configId, bool create) [TriggedOn(nameof(AllScreens),"Item","Id")] - public string Id - { - get => this.Get(IdDefault); - private set => this.Set(value); - } - - public string IdDefault() => AllScreens.OrderBy(s => s.Id) - .Aggregate("", (current, screen) => current + (((current != "") ? "." : "") + screen.Id)); - + public string Id => this.Get(() => AllScreens.OrderBy(s => s.Id) + .Aggregate("", (current, screen) => current + (current != "" ? "." : "") + screen.Id)); public void MatchConfig(string id) { @@ -293,6 +285,8 @@ public void Load() AllowDiscontinuity = k.GetValue("AllowDiscontinuity", 0).ToString() == "1"; LoadAtStartup = k.GetValue("LoadAtStartup", 0).ToString() == "1"; HomeCinema = k.GetValue("HomeCinema", 0).ToString() == "1"; + LoopX = k.GetValue("LoopX", 0).ToString() == "1"; + LoopY = k.GetValue("LoopY", 0).ToString() == "1"; } } @@ -321,6 +315,8 @@ public bool Save() k.SetValue("AllowDiscontinuity", AllowDiscontinuity ? "1" : "0"); k.SetValue("LoadAtStartup", LoadAtStartup ? "1" : "0"); k.SetValue("HomeCinema", HomeCinema ? "1" : "0"); + k.SetValue("LoopX", LoopX ? "1" : "0"); + k.SetValue("LoopY", LoopY ? "1" : "0"); foreach (Screen s in AllScreens) s.Save(k); @@ -438,6 +434,23 @@ public bool LoadAtStartup set { if (this.Set(value)) { Saved = false; } } } + //[TriggedOn(nameof(AllowCornerCrossing))] + public bool LoopAllowed => true; + + [TriggedOn(nameof(LoopAllowed))] + public bool LoopX + { + get => LoopAllowed && this.Get(); + set { if (this.Set(value)) { Saved = false; } } + } + [TriggedOn(nameof(LoopAllowed))] + public bool LoopY + { + get => LoopAllowed && this.Get(); + set { if (this.Set(value)) { Saved = false; } } + } + + [TriggedOn(nameof(AllScreens),"Item","PixelToDipRatio")] public bool IsRatio100 { get @@ -451,6 +464,7 @@ public bool IsRatio100 } } + [TriggedOn(nameof(IsRatio100))] public bool AdjustPointerAllowed => IsRatio100; public bool AdjustPointer