-
Notifications
You must be signed in to change notification settings - Fork 867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add remote notifications app delegates #3649
Closed
extrawurst
wants to merge
273
commits into
rust-windowing:master
from
extrawurst:add-remote-notifications-app-delegates
Closed
Add remote notifications app delegates #3649
extrawurst
wants to merge
273
commits into
rust-windowing:master
from
extrawurst:add-remote-notifications-app-delegates
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The utils in this module should help the users to activate the windows they create, as well as manage activation tokens environment variables. The API is essential for Wayland in the first place, since some compositors may decide initial focus of the window based on whether the activation token was during the window creation. Fixes rust-windowing#2279. Co-authored-by: John Nunley <jtnunley01@gmail.com>
Unfortunately this isn't a total removal, for two reasons: - We still need "libc" for the Xlib XIM implementation, for locales. - BSD requires libc to check for main-threadedness. First one we can likely resolve in the near future, not so sure about the second one without using some weird pthreads trick.
This adds two new extensions for running a Winit event loop which will replace `EventLoopExtRunReturn` The `run_return` API is trying to solve multiple problems and address multiple, unrelated, use cases but in doing so it is not succeeding at addressing any of them fully. The notable use cases we have are: 1. Applications want to be able to implement their own external event loop and call some Winit API to poll / pump events, once per iteration of their own loop, without blocking the outer, external loop. Addressing rust-windowing#2706 2. Applications want to be able to re-run separate instantiations of some Winit-based GUI and want to allow the event loop to exit with a status, and then later be able to run the loop again for a new instantiation of their GUI. Addressing rust-windowing#2431 It's very notable that these use cases can't be supported across all platforms and so they are extensions, similar to `EventLoopExtRunReturn` The intention is to support these extensions on: - Windows - Linux (X11 + Wayland) - macOS - Android These extensions aren't compatible with Web or iOS though. Each method of running the loop will behave consistently in terms of how `NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched (so portable application code wouldn't necessarily need to have any awareness of which method of running the loop was being used) Once all backends have support for these extensions then we can remove `EventLoopExtRunReturn` For simplicity, the extensions are documented with the assumption that the above platforms will be supported. This patch makes no functional change, it only introduces these new extensions so we can then handle adding platform-specific backends in separate pull requests, so the work can be landed in stages.
A surprising amount of work was required to enable these extensions on Windows. I had originally assumed that pump_events was going to be very similar to run except would use PeekMessageW instead of GetMessageW to avoid blocking the external loop but I found the Windows backend broke several assumptions I had. Overall I think these changes can hopefully be considered a quite a significant simplification (I think it's a net deletion of a fair amount of code) and I think it also helps bring it into slightly closer alignment with other backends too Key changes: - I have removed the `wait_thread` that was a fairly fiddly way of handling `ControlFlow::WaitUntil` timeouts in favor of using `SetTimer` which works with the same messages picked up by `GetMessage` and `PeekMessage`. - I have removed the ordering guarantees between `MainEventsCleared`, `RedrawRequested` and `RedrawEventsCleared` events due to the complexity in maintaining this artificial ordering, which is already not supported consistently across backends anyway (in particular this ordering already isn't compatible with how MacOS / iOS work). - `RedrawRequested` events are now directly dispatched via `WM_PAINT` messages - comparable to how `RedrawRequested` is dispatched via `drawRect` in the MacOS backend. - I have re-worked how `NewEvents`, `MainEventsCleared`, and `RedrawEventsCleared` get dispatched to be more in line with the MacOS backend and also more in line with how we have recently discussed defining them for all platforms. `NewEvents` is conceptually delivered when the event loop "wakes up" and `MainEventsCleared` gets dispatched when the event loop is about to ask the OS to wait for new events. This is a more portable model, and is already how these events work in the MacOS backend. `RedrawEventsCleared` are just delivered after `MainEventsCleared` but this event no longer has a useful meaning. Probably the most controversial thing here is that this "breaks" the ordering rules for redraw event handling, but since my changes interacted with how the order is maintained I was very reluctant to figure out how to continue maintaining something that we have recently been discussing changing: rust-windowing#2640. Additionally, since the MacOS backend already doesn't strictly maintain this order it's somewhat academic to see this as a breakage if Winit applications can't really rely on it already. This updates the documentation for `request_redraw()` to reflect that we no longer guarantee that `RedrawRequested` events must be dispatched after `MainEventsCleared`.
The implementation of `pump_events` essentially works by hooking into the `RunLoopObserver` and requesting that the app should be stopped the next time that the `RunLoop` prepares to wait for new events. Originally I had thought I would poke the `CFRunLoop` for the app directly and I was originally going to implement `pump_events` based on a timeout which I'd seen SDL doing. I found that `[NSApp run]` wasn't actually being stopped by asking the RunLoop to stop directly and inferred that `NSApp run` will actually catch this and re-start the loop. Hooking into the observer and calling `[NSApp stop]` actually seems like a better solution that doesn't need a hacky constant timeout. The end result is quite similar to what happens with existing apps that call `run_return` inside an external loop and cause the loop to exit for each iteration (that also results in the `NSApp` stopping each iteration).
Wayland: I found the calloop abstraction a little awkward to work with while I was trying to understand why there was surprising workaround code in the wayland backend for manually dispatching pending events. Investigating this further it looks like there may currently be several issues with the calloop WaylandSource (with how prepare_read is used and with (not) flushing writes before polling) Considering the current minimal needs for polling in all winit backends I do personally tend to think it would be simpler to just own the responsibility for polling more directly, so the logic for wayland-client `prepare_read` wouldn't be in a separate crate (and in this current situation would also be easier to fix) I've tried to maintain the status quo with calloop + workarounds. X11: I found that the recent changes (4ac2006) to port the X11 backend from mio to calloop lost the ability to check for pending events before needing to poll/dispatch. (The `has_pending` state being queried before dispatching() was based on state that was filled in during dispatching) As part of the rebase this re-introduces the PeekableReceiver and WakeSender which are small utilities on top of `std::sync::mpsc::channel()`. This adds a calloop `PingSource` so we can use a `Ping` as a generic event loop waker. For taking into account false positive wake ups the X11 source now tracks when the file descriptor is readable so after we poll via calloop we can then specifically check if there are new X11 events or pending redraw/user events when deciding whether to skip the event loop iteration.
This re-works the portable `run()` API that consumes the `EventLoop` and runs the loop on the calling thread until the app exits. This can be supported across _all_ platforms and compared to the previous `run() -> !` API is now able to return a `Result` status on all platforms except iOS and Web. Fixes: rust-windowing#2709 By moving away from `run() -> !` we stop calling `std::process::exit()` internally as a means to kill the process without returning which means it's possible to return an exit status and applications can return from their `main()` function normally. This also fixes Android support where an Activity runs in a thread but we can't assume to have full ownership of the process (other services could be running in separate threads). Additionally all examples have generally been updated so that `main()` returns a `Result` from `run()` Fixes: rust-windowing#2709
A minimal example of an application based on an external event loop that calls `pump_events` for each iteration of the external loop.
A minimal example that shows an application running the event loop more than once via `run_ondemand` There is a 5 second delay between each run to help highlight problems with destroying the window from the first loop.
Although we document that applications can't keep windows between separate run_ondemand calls it's possible that the application has only just dropped their windows and we need to flush these requests to the server/compositor. This fixes the window_ondemand example - by ensuring the window from the first loop really is destroyed before waiting for 5 seconds and starting the second loop.
Considering the strict requirement that applications can't keep windows across run_ondemand calls, this tries to make the window_ondemand example explicitly wait for its Window to be destroyed before exiting each run_ondemand iteration. This updates the example to only `.set_exit()` after it gets a `Destroyed` event after the Window has been dropped. On Windows this works to ensure the Window is destroyed before the example waits for 5 seconds. Unfortunately though: 1. The Wayland backend doesn't emit `Destroyed` events for windows 2. The macOS backend emits `Destroyed` events before the window is really destroyed. and so the example isn't currently portable.
This layers pump_events on a pump_events_with_timeout API, like we have for Linux and Android. This is just an internal implementation detail for now but we could consider making pump_events_with_timeout public, or just making it so that pump_events() takes the timeout argument.
This renames all internal implementations of pump_events_with_timeout to pump_events and makes them public. Since all platforms that support pump_events support timeouts there's no need to have a separate API.
…ng#2979) * Always set timer when polling to avoid slow waking * add comment and changelog --------- Co-authored-by: Dusty DeWeese <dustin.deweese@gmail.com> Co-authored-by: Mads Marquart <mads@marquart.dk>
Considering the possibility of re-running an event loop via run_ondemand then it's more correct to say that the loop is about to exit without assuming it's going to be destroyed.
The idea that redraw events are dispatched with a specific ordering that makes it possible to specifically report when we have finished dispatching redraw events isn't portable and the way in which we dispatched RedrawEventsCleared was inconsistent across backends. More generally speaking, there is no inherent relationship between redrawing and event loop iterations. An event loop may wake up at any frequency depending on what sources of input events are being listened to but redrawing is generally throttled and in some way synchronized with the display frequency. Similarly there's no inherent relationship between a single event loop iteration and the dispatching of any specific kind of "main" event. An event loop wakes up when there are events to read (e.g. input events or responses from a display server / compositor) and goes back to waiting when there's nothing else to read. There isn't really a special kind of "main" event that is dispatched in order with respect to other events. What we can do more portably is emit an event when the event loop is about to block and wait for new events. In practice this is very similar to how MainEventsCleared was implemented except it wasn't the very last event previously since redraw events could be dispatched afterwards. The main backend where we don't strictly know when we're going to wait for events is Web (since the real event loop is internal to the browser). For now we emulate AboutToWait on Web similar to how MainEventsCleared was dispatched. In practice most applications almost certainly shouldn't care about AboutToWait because the frequency of event loop iterations is essentially arbitrary and usually irrelevant.
Lifetimes don't work nicely when dealing with multithreaded environments in the current design of the existing winit's event handling model, so remove it in favor of `InnerSizeWriter` fences passed to client, so they could try to update the size. Fixes rust-windowing#1387.
rust-windowing#2662 renamed `VirtualKeyCode` to `Key` yet references to the former type still exist in `src/platform_impl/linux/x11/events.rs`. As it turns out the `mod events;` in `x11/mod.rs` was removed in the same PR, but the file accidentally stuck around without being referenced anywhere else.
Make code more clear wrt explicit returns during event handling, which may lead to skipped IME event handling.
Implement the following methods on the `Window`: - `Window::set_cursor_grab`. - `Window::set_cursor_visible`. - `Window::drag_window`. - `Window::drag_resize_window`. - `Window::set_transparent`. - `Window::set_visible`. - `Window::is_visible`. - `Window::set_resizable`. - `Window::is_resizable`. - `Window::set_maximized`. - `Window::is_maximized`. - `Window::set_decorations`. - `Window::is_decorated`. - `Window::set_window_level`. To make locked pointer useful, the `DeviceEvent::MouseMotion` event was also implemented.
In general, we may want to use xinput v2 for keyboard input in such cases, so we have compose going, but for now just don't crash if there's no XIM.
While there's a separate event to deliver modifiers for keyboard, unfortunately, it's not even remotely reflects the modifiers state. Thus use events along side regular modifier updates to correctly detect the state. Also, apply the modifiers from the regular key event by converting their state to xkb modifiers state. Links: alacritty/alacritty#7549 Closes: rust-windowing#3388
Given that `ModifiersChanged` is a window event, it means that clients may track it for each window individually, thus not sending it between focus changes may result in modifiers getting desynced on the consumer side.
Usually, if mouse events are equal to (0, 0) we filter them out. However, if the event is very close to zero it will still be given to the user. In some cases this can be caused by bad float math on the X11 server side. Fix it by filtering absolute values smaller than floating point epsilon. Signed-off-by: John Nunley <dev@notgull.net> Closes: rust-windowing#3500
Invert the mouse delta filter, so it aligns with the intention of filtering values lower than epsilon. Signed-off-by: John Nunley <dev@notgull.net> Closes: rust-windowing#3558
Some compositors break when re-taking the same grab. Closes: rust-windowing#3566
When composing the text was not reset to `None` leading to input in some applications e.g. alacritty. Links: alacritty/alacritty#7806
Don't crash when xsettings query fails with _present_ xsettings. Closes: rust-windowing#3573
see #3650 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I need some input here :)
I am not sure about the way to bubble up the events. For now i added a new one entirely but that feels wrong. do you think it should rather be a DeviceEvent cause it is for sure not a window event, right?
Wtf, something went wrong with building this on top of
0.29.x
changelog
module if knowledge of this change could be valuable to users