Closed ostwilkens closed 2 years ago
For an immersive game, you could argue that preventing these hotkeys is correct. The scope of winit however, is both apps and games. For a web app, you expect these keys to work as normal.
Making it an option makes more sense than reverting the behaviour completely.
I'm curious though: How would a webapp make use of winit
? Implementing a web UI using winit
in its current state will result in significant accessibility and usability issues that it doesn't seem to make much sense outside of games.
Yes, an option would be fine :-)
The reason I mentioned web apps is this quote from features.md:
Winit Scope
Winit aims to expose an interface that abstracts over window creation and input handling, and can be used to create both games and applications.
There are kinds of apps that are best implemented in a game engine. Visualization apps often require good rendering performance. While the current tools may not be production ready for this usecase, I do believe the web will be moving more and more to compiled wasm apps, allowing the developer full control over the experience. I can absolutely see a future filled with flashy, interactive web applications using winit.
My personal usecase is a full-viewport game using bevy_webgl2. (think agar.io).
What should the API look like? Can this be solved without major API changes?
I'm curious though: How would a webapp make use of
winit
? Implementing a web UI usingwinit
in its current state will result in significant accessibility and usability issues that it doesn't seem to make much sense outside of games.
In my case I'm developing a cross-platform GIS library (drawing maps), and web is one of the targets. The consumers of the library are mainly JS applications creating web interface, and using rust-driven map just a black box component. For these applications I definitely don't want F5
or Ctrl+Shift+I
to be prevented. I actually have an issue for that in my repo: https://github.com/Everpoint/yoda/issues/3
But even for games, disabling F5
, F11
or F12
in browsers is very dubious decision.
It would be nice if this were fixed.
You could have the canvas from platform_impl::web::web_sys
pass in the event to the handler (as a generic Event
instead of the specific type), and then have the runner dispatch immediately, allowing the user to call a platform-specific extension method on the EventLoopWindowTarget
to get a reference to the underlying web_sys::Event
so that they can prevent default or stop propagation or whatever. This would only really work if they're not polling, so if they're not in a mode where the event can be handled immediately (i.e. this variable is false ) then we perform the default behavior of calling event.prevent_default()
, but if not then the user can decide what to do. You could even have the getter for the platform specific behavior check whether it was accessed and automatically call prevent_default
if the getter isn't called, so that previous behavior is preserved.
Alternatively, you could add a platform-specific field to KeyboardInput
instead of adding a method to EventLoopWindowTarget
. I guess that could mess up the organization of the codebase though.
I'm having the same problem, and I'm developing an app where rendering does not need to be real-time: redraws are manually triggered from JS. In my case, the simplest API would be something like WindowBuilderExtWebSys::with_prevent_default(false)
or WindowBuilderExtWebSys::with_focusable(false)
(I don't even need the canvas
to be focusable, it's purely visual).
I like nasso's idea of having a global with_prevent_default
builder option. Even if this doesn't solve the issue of dynamically preventing default, I think it's an acceptable and welcome solution for now and probably covers most people's requirements. A more robust system can be added on top later if really necessary.
For people interested - here is my functioning temporary workaround. Could probably use some work.
It puts an invisible, focusable div on top of the canvas which reads keyboard and mouse input, and then forwards it to both the canvas and the window itself. The canvas eats the event, but the window gets another copy.
You will need to add CSS to position #event-receiver
on top of the canvas
.
<div id="event-receiver" tabindex="0"></div>
<canvas id="game-canvas"></canvas>
<script>
const gc = document.getElementById("game-canvas");
const er = document.getElementById("event-receiver");
function keyboard(e) {
gc.dispatchEvent(new KeyboardEvent(e.type, e));
window.dispatchEvent(new KeyboardEvent(e.type, e));
}
function mouse(e) {
gc.dispatchEvent(new MouseEvent(e.type, e));
window.dispatchEvent(new MouseEvent(e.type, e));
}
er.addEventListener("keydown", keyboard);
er.addEventListener("keyup", keyboard);
er.addEventListener("keypress", keyboard);
er.addEventListener("mousemove", mouse);
er.addEventListener("mousedown", mouse);
er.addEventListener("mouseup", mouse);
</script>
Created PR #2365 for with_prevent_default
and with_focusable
proposed by @nasso above – hopefully this helps!
When I'm on the web, I expect to be able to use Ctrl+R, F5, F12 etc. I can understand a developer might want to hijack some keys, but that can easily be done using javascript in the host document. The way it is now, it is not possible to get the default behaviour (working F5) using winit.
1576 should be reverted.