winit: DeviceEvent should be optional, causes unneccessary CPU usage

I use winit for background application for Windows 10.

Even though not a single window is visible or activated it eats CPU if I move the mouse: Process Explorer shows 0.33% of CPU usage when moving a mouse, but when I stop the mouse it goes to 0%.

This indicates that it just keeps on listening the device events, even though I don’t even need them. It’s not ideal for a background application to eat CPU when mouse is moved outside the application’s own window.

I don’t know is background applications (that occasionally show a Window) even a target for winit, but I surely would want it to be.

Thanks.


There is multiple ways to fix this, easiest but not so great is to make an emit_device_events(bool) for the EventLoop builder. Another way would be to make them toggleable at runtime, so one could toggle DeviceEvents on when necessary (e.g. when the window is activated).

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 17 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Yeah, I don’t quite understand why one would by default want to receive mouse movements and keyboard events when not in foreground.

Is this behaviour present on other platforms?

I’m expirimenting with this kind of signature:

pub struct EventLoop<T: 'static> {
    pub(crate) event_loop: platform_impl::EventLoop<T>,
    pub(crate) device_events: bool,
    pub(crate) _marker: ::std::marker::PhantomData<*mut ()>, // Not Send nor Sync
}

impl<T> EventLoop<T> {
    /// Enable or disable device events
    pub fn with_device_events(mut self, enabled: bool) -> Self {
        self.device_events = enabled;
        self
    }
    ...
}

Since the with implies chainability, and this pattern is used e.g. in WindowBuilder. I think it’s more idiomatic for winit than &mut self. I try to implement this for Windows side, maybe someone can help with the other OS’s.

IMO starting with an EventLoop::with_device_events(&mut self, bool) would be fine, which de/registers all raw input devices. For game applications it’s ok to receive all events and for pure UI device events are less important. If the gamepad related parts get more traction I would see that we end up with more fine-grained control in this direction (adding devices to the eventloop similar to a window).

In Windows, DeviceEvents are abstraction of Raw Input. And the document said:

By default, no application receives raw input. To receive raw input from a device, an application must register the device.

So, technically, we can make them as optional.

In X11, DevicEvents are abstraction of XI_Raw.* events. To receive them, an application need to set the mask by calling XISelectEvents. So we can make them as optional as well.

As we discuss in #1775, I agree that the functionality to disable DeviceEvents based on window status will be useful for many application, but I think providing an option to disabling DeviceEvents at all is also useful because there are applications receiving device events through WindowEvent and ignoring all DeviceEvent (e.g. Alacritty).

I can help implementing this feature for X11 once we decide what API we want to implement