They are safe, since they use the rust `std::env` stuff. Making them
safe lets downstream to determine that `std::env` is used and not the
`libc` env manipulation routines, which are unsafe.
* macOS & iOS: Refactor EventWrapper
* macOS & iOS: Make EventLoopWindowTarget independent of the user event
* iOS: Use MainThreadMarker instead of marking functions unsafe
* Make iOS thread safe
Inner panics could make it hard to trouble shoot the issues and for some
users it's not desirable.
The inner panics were left only when they are used to `assert!` during
development.
This reverts commit 9f91bc413fe20618bd7090829832bb074aab15c3 which
reverted the original patch which was merged without a proper review.
Fixes: #500.
Inner panics could make it hard to trouble shoot the issues and for some
users ints not desirable.
The inner panics were left only when they are used to `assert!` during
development.
At the moment, the with_x11_visual function takes a pointer and
immediately dereferences it to get the visual info inside. As it is safe
to pass a null pointer to this function, it is unsound. This commit
replaces the pointer parameter with a visual ID, and then uses that ID
to look up the actual visual under
the X11 setup. As this is what was already practically happening before,
this change shouldn't cause any performance downgrades.
This is a breaking change, but it's done in the name of soundness so it
should be okay. It should be trivial for end users to accommodate it,
as it's just a matter of getting the visual ID from the pointer to the
visual before passing it in.
Signed-off-by: John Nunley <dev@notgull.net>
Nothing changed from the user point of view, other than they should
use the `raw-window-handle`, which is objectively better, given that
it reduces the amount of `cfg` guards in downstream code.
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#1387.
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.
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.
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 (4ac2006cbc) 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.
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).
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:
https://github.com/rust-windowing/winit/issues/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`.
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 #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 #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.
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#2279.
Co-authored-by: John Nunley <jtnunley01@gmail.com>
This should provide a way to iterate all the tabs and select the last
tab. The tab indicies are now zero based as any other sane index.
Follow-up-to: c5941d105f (add tabbing API)
The correct handling of this setting requires to change the events
we're getting from the macOS on the fly and call `interpretKeyEvents`,
which could affect handling of the next events, meaning that we can't
provide them on `KeyEvent`.
Overhaul the keyboard API in winit to mimic the W3C specification
to achieve better crossplatform parity. The `KeyboardInput` event
is now uses `KeyEvent` which consists of:
- `physical_key` - a cross platform way to refer to scancodes;
- `logical_key` - keysym value, which shows your key respecting the
layout;
- `text` - the text produced by this keypress;
- `location` - the location of the key on the keyboard;
- `repeat` - whether the key was produced by the repeat.
And also a `platform_specific` field which encapsulates extra
information on desktop platforms, like key without modifiers
and text with all modifiers.
The `Modifiers` were also slightly reworked as in, the information
whether the left or right modifier is pressed is now also exposed
on platforms where it could be queried reliably. The support was
also added for the web and orbital platforms finishing the API
change.
This change made the `OptionAsAlt` API on macOS redundant thus it
was removed all together.
Co-authored-by: Artúr Kovács <kovacs.artur.barnabas@gmail.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: daxpedda <daxpedda@gmail.com>
Fixes: #2631.
Fixes: #2055.
Fixes: #2032.
Fixes: #1904.
Fixes: #1810.
Fixes: #1700.
Fixes: #1443.
Fixes: #1343.
Fixes: #1208.
Fixes: #1151.
Fixes: #812.
Fixes: #600.
Fixes: #361.
Fixes: #343.
This update rewrites the winit's Wayland backend using new wayland-rs
0.30 API. This fixes long standing issue with the forward compatibility
of the wayland backend, meaning that future updates to the wayland
protocol won't break rust code anymore. like it was before when adding
new shm/enum variants into the protocol.
Fixes#2560.
Fixes#2164.
Fixes#2128.
Fixes#1760.
Fixes#725.
This adds an ability to control left and right `Option` keys to be
treated as `Alt`, thus not producing diacritical marks.
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
* Use a bit less `unsafe` on iOS
I did test this in XCode 11.3's "Debug View Heirarchy", the NSStringRust problem is no longer applicable (likely because Rust got better at emitting correct debug info).
* Avoid using `id` on iOS
This commit fixes it, by not updating the `latest_error` when
any of the hooks handled the error, otherwise it'd interfere
with the winit's error checking.
* Add Redox OS support
* Simplify control flow usage
* Apply more recommendations
* Update naming to indicate that Orbital is a platform
* Adjust import order