• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dapplo / Dapplo.Windows / 22325004088

23 Feb 2026 09:11PM UTC coverage: 32.847% (-0.2%) from 33.028%
22325004088

push

github

Lakritzator
Merge branch 'master' of https://github.com/dapplo/Dapplo.Windows

619 of 2002 branches covered (30.92%)

Branch coverage included in aggregate %.

1702 of 5064 relevant lines covered (33.61%)

29.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Dapplo.Windows.Input/RawInputMonitor.cs
1
// Copyright (c) Dapplo and contributors. All rights reserved.
2
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3

4

5
#if !NETSTANDARD2_0
6
using Dapplo.Windows.Input.Enums;
7
using Dapplo.Windows.Input.Structs;
8
using Dapplo.Windows.Messages;
9
using Dapplo.Windows.Messages.Enumerations;
10
using System;
11
using System.Reactive.Disposables;
12
using System.Reactive.Linq;
13
using System.Runtime.InteropServices;
14

15
namespace Dapplo.Windows.Input;
16

17
/// <summary>
18
/// Reactive access to RawInput
19
/// </summary>
20
public static class RawInputMonitor
21
{
22
    private static IObservable<RawInputEventArgs> _rawInputObservable;
23

24
    /// <summary>
25
    /// Gets the shared observable for Raw Input.
26
    /// Multiple subscribers will share the same underlying hook, and the hook 
27
    /// is automatically disposed when the subscriber count reaches zero.
28
    /// </summary>
29
    public static IObservable<RawInputEventArgs> Listen(params RawInputDevices[] devices)
30
    {
31
        if (_rawInputObservable != null)
×
32
        {
33
            RawInputApi.RegisterRawInput(SharedMessageWindow.Handle, RawInputDeviceFlags.InputSink | RawInputDeviceFlags.DeviceNotify, devices);
×
34
            return _rawInputObservable;
×
35
        }
36

37
        _rawInputObservable = Observable.Create<RawInputEventArgs>(observer =>
×
38
        {
×
39
            // Subscribe to the SharedMessageWindow for handling the WM_INPUT
×
40
            var messageSubscription = SharedMessageWindow.Messages
×
41
                .Where(windowsMessage => windowsMessage.Msg == WindowsMessages.WM_INPUT) // filter for raw input
×
42
                .Subscribe(windowsMessage =>
×
43
                {
×
44
                    windowsMessage.Handled = true;
×
45
                    int outSize;
×
46
                    int size = Marshal.SizeOf<RawInput>();
×
47

×
48
                    outSize = RawInputApi.GetRawInputData(windowsMessage.LParam, RawInputDataCommands.Input, out var rawInput, ref size, Marshal.SizeOf<RawInputHeader>());
×
49
                    if (outSize != -1)
×
50
                    {
×
51
                        observer.OnNext(new RawInputEventArgs
×
52
                        {
×
53
                            IsForeground = (int)windowsMessage.WParam == 0,
×
54
                            RawInput = rawInput
×
55
                        });
×
56
                    }
×
57
                });
×
58

×
59
            RawInputApi.RegisterRawInput(SharedMessageWindow.Handle, RawInputDeviceFlags.InputSink | RawInputDeviceFlags.DeviceNotify, devices);
×
60

×
61
            // Return the disposal logic
×
62
            return Disposable.Create(() =>
×
63
            {
×
64
                // Unregister raw input devices from the OS here if necessary
×
65
                // UnregisterRawInputDevices(...);
×
66
                _rawInputObservable = null; // Clear the cached observable so it can be recreated if Listen() is called again.
×
67
                // Dispose the SharedMessageWindow subscription
×
68
                messageSubscription.Dispose();
×
69
            });
×
70
        })
×
71
        // This is the magic part:
×
72
        // .Publish() multicasts the observable to all subscribers.
×
73
        // .RefCount() keeps track of subscribers and automatically disposes 
×
74
        // the inner subscription when the count reaches 0.
×
75
        .Publish()
×
76
        .RefCount();
×
77
        return _rawInputObservable;
×
78
    }
79
}
80
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc