public HotkeyIsActiveTrigger( [NotNull] IHotkeyConverter hotkeyConverter, [NotNull] IKeyboardEventsSource eventSource, [NotNull][Dependency(WellKnownWindows.MainWindow)] IWindowTracker mainWindowTracker, [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler) { this.hotkeyConverter = hotkeyConverter; Disposable .Create(() => Log.Debug($"Disposing HotkeyTrigger, gesture: {Hotkey} (mode: {HotkeyMode})")) .AddTo(Anchors); IsActive = true; this.RaiseWhenSourceValue(x => x.Properties, this, x => x.IsActive).AddTo(Anchors); this.WhenAnyValue(x => x.Hotkey) .Select(hotkey => hotkey == null ? Observable.Empty <HotkeyData>() : BuildHotkeySubscription(eventSource)) .Switch() .DistinctUntilChanged(x => new { x.Hotkey, x.KeyDown }) .Where( hotkeyData => { /* * This method MUST be executed on the same thread which emitted Key/Mouse event * otherwise .Handled value will be ignored due to obvious concurrency reasons */ if (mainWindowTracker.ActiveProcessId != CurrentProcessId) { Log.Debug($"Application is NOT active, processing hotkey {hotkeyData.Hotkey} (isDown: {hotkeyData.KeyDown}, suppressKey: {suppressKey}, configuredKey: {Hotkey}, mode: {HotkeyMode})"); if (suppressKey) { hotkeyData.MarkAsHandled(); } return(true); } Log.Debug($"Application is active, skipping hotkey {hotkeyData.Hotkey} (isDown: {hotkeyData.KeyDown}, suppressKey: {suppressKey}, configuredKey: {Hotkey}, mode: {HotkeyMode})"); return(false); }) .Subscribe( hotkeyData => { Log.Debug($"Hotkey {hotkeyData.Hotkey} pressed, state: {(hotkeyData.KeyDown ? "down" : "up")}, suppressed: {suppressKey}"); if (HotkeyMode == HotkeyMode.Click) { if (hotkeyData.KeyDown) { IsActive = !IsActive; } } else { IsActive = !IsActive; } }, Log.HandleUiException) .AddTo(Anchors); }
public SelectionAdornerViewModel( [NotNull] IKeyboardEventsSource keyboardEventsSource, [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler, [NotNull][Dependency(WellKnownSchedulers.Background)] IScheduler bgScheduler) { this.keyboardEventsSource = keyboardEventsSource; this.uiScheduler = uiScheduler; this.RaiseWhenSourceValue(x => x.ScreenMousePosition, this, x => x.MousePosition).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.ScreenSelection, this, x => x.Selection).AddTo(Anchors); this.WhenAnyProperty(x => x.Selection, x => x.MousePosition, x => x.Owner) .Where(x => Owner != null) .Sample(DesiredRedrawRate, bgScheduler) // MouseMove generates thousands of events .ObserveOn(uiScheduler) .Subscribe(Redraw) .AddTo(Anchors); }