Compare commits

...

1019 Commits

Author SHA1 Message Date
Kirill Chibisov
340202f842 Winit version 0.28.5 2023-05-06 20:42:05 +03:00
Kirill Chibisov
870e6d1cb2 On macOS, fix key_up being ignored without IME
Fixes: d15feb5cfa (On macOS, fix empty marked text)
2023-05-06 20:42:05 +03:00
Kirill Chibisov
b455f88f40 Winit version 0.28.4 2023-05-04 17:00:41 +03:00
Kirill Chibisov
30678cbcef On Wayland, fix nightly warnings
The new analysis suggests that we can remove mut.
2023-05-04 17:00:41 +03:00
Kirill Chibisov
bb26b0355c On macOS, fix empty marked text blocking input
Fixes #2775.
2023-05-04 17:00:41 +03:00
Kirill Chibisov
6f97ff174b On X11, fix nightly warnings
The new analysis suggests that we can remove mut.
2023-05-04 17:00:41 +03:00
Amandus Søve Thorsrud
0881a28302 Run Window::set_ime_position on main thread on macOS
Fixes #2756.
2023-05-04 17:00:41 +03:00
Xiaopeng Li
d37dac8f39 Fix potential panic (#2755)
* Fix potential panic

* Update CHANGELOG.md

* Use checked_div

---------

Co-authored-by: Xiaopeng Li <lixiaopeng.jetspark@bytedance.com>
2023-05-04 17:00:41 +03:00
Kirill Chibisov
64a97c16c7 Winit version 0.28.3 2023-03-16 22:03:19 +03:00
Mads Marquart
dec45bb09f Fix macos memory leaks (#2739)
* Use a weak reference from WinitView to WinitWindow

* Allow patched objc2 version

* Add changelog entry
2023-03-16 22:03:19 +03:00
Kirill Chibisov
d102c21792 Winit version 0.28.2 2023-03-02 14:35:02 +03:00
Dylan Scott
68ed564def On macOS, resize simple fullscreen on window move
Fixes #1118.
2023-03-02 14:35:02 +03:00
Nicolas Mazzon
339d57b646 On Windows, check whether CoCreateInstance succeeds 2023-03-02 14:35:02 +03:00
Kirill Chibisov
2e4dafc9fe On macOS, fix initial focused state
The synthetic focused event was queued after the real event was send
leading to focused issues on startup.

Fixes #2695.
2023-03-02 14:35:02 +03:00
John Nunley
0fbba02318 Update FEATURES.md 2023-03-02 14:35:02 +03:00
Kirill Chibisov
41e524f12c On Wayland, fix rounding issue in resizes 2023-03-02 14:35:02 +03:00
Simon Hausmann
644c47a6f8 Add support for Window::theme on the web (#2687) 2023-03-02 14:35:02 +03:00
Kirill Chibisov
0be08e574d On Wayland, fix rare crash on DPI change
While I don't understand the root cause for this issue, we can
dirty fix like that for now.
2023-03-02 14:35:02 +03:00
Kirill Chibisov
811cc5cdb7 On macOS, set resize increments only for live resize
Closes #2684 for macOS.
2023-03-02 14:35:02 +03:00
Sludge
230b37df56 Implement HasRawDisplayHandle for EventLoop (#2677)
* Implement `HasRawDisplayHandle` for `EventLoop`

* Add changelog entry
2023-03-02 14:35:02 +03:00
John Nunley
09bca59cf3 On Windows, name the waiter thread (#2672) 2023-03-02 14:35:02 +03:00
John Nunley
9fb8aaa6f4 Replace lazy window message ids with a slimmer version (#2598) 2023-03-02 14:35:02 +03:00
Kirill Chibisov
546ab7575e Winit version 0.28.1 2023-02-02 14:49:31 +03:00
Kirill Chibisov
3e258a377f Fix window drop on Wayland
In some scenarious of window dropping the callback for keyboard
may run after the window was dropped.
2023-02-02 14:45:38 +03:00
Kirill Chibisov
e5260da95b Winit version 0.28.0 2023-02-02 06:52:53 +03:00
Kirill Chibisov
3fd73848dd On macOS, fix Ime::Commit persisting
This commit clears the currently marked text on `Ime::Commit`, so
normal `ReceivedCharacter` input can continue.
2023-02-01 18:08:25 +03:00
Samuel
4e1c46fe9e Windows: Fix Alt key press entering menu loop (#2665) 2023-02-01 12:03:58 +01:00
Jack Wright
180a4c7a16 Add WindowExtMacOS::{set_,}option_as_alt
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>
2023-01-31 12:35:49 +03:00
Kirill Chibisov
13613931cf Implement serde ser/deser for Theme 2023-01-31 12:14:15 +03:00
Diggory Hardy
483c1d40ae Properly print outputs in monitor_list example 2023-01-30 14:17:41 +03:00
Lukas Lihotzki
1b4045dcb2 Add Window::set_ime_purpose
This adds a way to set the purpose for the IME input, implemented
only on Wayland for now.
2023-01-29 18:46:46 +03:00
Kirill Chibisov
8f8da0f8bb Fix rerun-if-changed emmiting from build.rs
The docs state that it accepts `PATH`, but not like the env variable.
So to make it work each `PATH` should be emmited from each `println!`.

Fixes #2657.
2023-01-29 14:23:45 +03:00
Markus Siglreithmaier
23b821285c On Windows, fix window size for maximized, undecorated windows (#2584)
Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
2023-01-28 14:04:47 +01:00
Diggory Hardy
c984476687 Clarify Window::set_decorations/is_decorated behaviour 2023-01-28 10:50:34 +03:00
Andrea Pessino
42c395e49d Fixed visibility/activation issues on Windows. (#2656) 2023-01-27 23:01:41 +01:00
Shane Pearman
422c6b1987 Allow introspection of WindowBuilder attributes
Makes WindowAttributes public and adds window_attributes() getter to
WindowBuilder.

In version 0.27, the WindowAttributes struct was made private, but this
removed the ability to introspect the default WindowBuilder values.
2023-01-27 08:38:56 +03:00
Amr Bashir
b457329003 Add WindowBuilder::with_active
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2023-01-27 08:08:29 +03:00
Kirill Chibisov
930df0ec45 Fix clippy issues on stable 2023-01-27 07:18:58 +03:00
Markus Siglreithmaier
e1b7fda409 Bump windows-sys version to 0.45 (#2639)
Bump windows-sys version to fix regression
2023-01-23 22:10:28 +01:00
Francesca Lovebloom
e423802ed3 Remove francesca64 from CODEOWNERS (#2644) 2023-01-23 09:56:09 +01:00
Mads Marquart
a82f66826b Use a bit less unsafe on iOS (#2643)
* 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
2023-01-23 00:01:45 +01:00
Mads Marquart
0f2fbe373b Simplify event queuing on macOS (#2642) 2023-01-22 23:29:38 +01:00
Mads Marquart
7341ee80ea Note the status quo on RedrawRequested (#2641)
And link to https://github.com/rust-windowing/winit/issues/2640
2023-01-21 18:56:58 +01:00
Jim Eckerlein
d448d3e14f Add smart magnify gesture support for macOS (#2554)
* Add smart magnification gesture

* Deliver position of smart magnification event

* Document smart magnification event

* Revert "Deliver position of smart magnification event"

This reverts commit ac0e61a9a4.

* Remove mention of touchpad from smart magnification event

* Update change log

* Mention minimum macOS version supporting smart magnification

* Improve doc
2023-01-21 17:35:07 +01:00
Andreas Reich
a867032e1e [MacOS] Fix deadlock on maximizing window from event callback (#2636) 2023-01-21 17:29:29 +01:00
Douglas Dwyer
b711a11549 Properly remove window mouse event listeners (#2632)
* Properly remove window mouse event listeners

* Update CHANGELOG.md

* Fix formatting

Co-authored-by: Mads Marquart <mads@marquart.dk>
2023-01-21 16:58:05 +01:00
Amr Bashir
809162fbd0 Add Window::is_minimized
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
2023-01-20 00:39:04 +03:00
Kirill Chibisov
de782504ab On Wayland, add support for fractional scaling
This adds support for the fractional scaling on Wayland via the
wp-fractional-scale protocol.

Co-authored-by: Julian Orth <ju.orth@gmail.com>
2023-01-20 00:02:16 +03:00
Roman Akberov
1886949efe On macOS, fix middle/other mouse buttons reporting
All buttons except for the left/right/middle was always reported
as middle.
2023-01-18 06:32:34 +03:00
Kirill Chibisov
b1a5fae1f5 On X11, fix errors bleeding from hooks handling them
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.
2023-01-18 05:58:09 +03:00
Amr Bashir
a88d2e079d On Windows and MacOS, add Window::has_focus 2023-01-17 04:30:14 +03:00
Amr Bashir
067535eb38 Fix Window::set_minimized(false) on Windows
When other application minimized the winit window the
minimize state was going out of sync. This commit fixes
it by polling the state in `set_minimized`.
2023-01-17 03:22:52 +03:00
John Nunley
7d626d9dfd Add a function for waiting on a Duration 2023-01-16 04:14:09 +03:00
Kirill Chibisov
62ce14a013 Add Window::set_transparent
Provide a hint to system compositor whether the window is transparent or
not. Only implemented on macOS and Wayland for now.
2023-01-15 23:39:36 +03:00
Mads Marquart
6f60c7a6cc Note the macOS and Windows versions that winit supports 2023-01-15 23:18:23 +03:00
Turki Jamaan
6cf0bf76da iOS: fix accidentally flipped assertion (#2629)
* iOS: fix accidentally flipped assertion

* No need to update the changelog
2023-01-13 23:40:24 +01:00
Michael Murphy
9225b2812e feat(x11): Add Window::drag_resize_window (#2515) 2023-01-11 10:07:09 -07:00
John Nunley
08ce3af3e1 Ensure all free unixes can build
This fixes the `cfg` guards inside the `Cargo.toml`.
2023-01-10 12:00:28 +03:00
John Nunley
490abcad14 Remove xlib_xconnection from public interface 2023-01-10 11:46:48 +03:00
John Nunley
4b22ca8daf chore: Alphabetize dependencies (#2619) 2023-01-06 11:26:57 +01:00
Jeremy Soller
66ca445caa Redox OS support (#2588)
* Add Redox OS support

* Simplify control flow usage

* Apply more recommendations

* Update naming to indicate that Orbital is a platform

* Adjust import order
2023-01-05 06:58:08 -07:00
Kirill Chibisov
2f52c23fa9 Fix RedrawRequested not emitted on Wayland in resize
Fixes #2609.
2022-12-29 21:06:46 +03:00
Mads Marquart
ee88e38f13 Reduce amount of unsafe on iOS (#2579)
* Use objc2::foundation CG types

* Add safe abstraction over UIApplication

* Add safe abstraction over UIDevice

* Add safe abstraction over UIScreen

* Add safe abstraction over UIWindow

* Add safe abstraction over UIViewController

* Add safe abstraction over UIView

* Appease clippy
2022-12-28 18:36:32 +01:00
Amr Bashir
5e77d70245 Use cfg aliases throught the code base
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-12-25 10:57:27 +03:00
Alphyr
58ec458877 Remove compatibility shim for raw-window-handle 0.4 2022-12-24 15:53:46 +03:00
Miguel Medina Ballesteros
94e4c394e7 Swap assert by debug_assert for recovereable issue. Fixes #2597 (#2599)
* Swap assert by debug_assert for recovereable issue

* Remove debug assert completely
2022-12-23 14:19:25 +01:00
Ryo Hirayama
f43ce2a131 Web touch event (#2188)
* feat: add pointer events to web

* feat: remove PointerType for touch events

* Remove duplicate

* Changelog and features

* Remove PointerType

* feat: renamed events, added touch type guard

* Rename

* Flip the y axis

* Fix physical position and add force

* Update comment

* Update features

* Use normalized force

* Remove unnecessary todos

* Update comment

* Refactor add touch_handler

* Rephrase by Liamolucko

* Update CHANGELOG.md

* Fix duplicate mouse and touch events

* Removed workaround for scale factor

* Flip the y axis

* Fix

* Fmt

* Replace `match` with a single pattern with `if let`

* Update documentation

* Have one callback per event

* Remove a comment

* Fix

* Remove y-axis flip

* Update src/event.rs

Co-authored-by: Mads Marquart <mads@marquart.dk>

* Fix platform specific comment

* Fix extra argument to `touch_position` function

Co-authored-by: Dany Sluijk <me@dany.dev>
Co-authored-by: Johan Klokkhammer Helsing <johanhelsing@gmail.com>
Co-authored-by: oscrim <oscar@widefind.se>
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-12-23 06:55:22 +01:00
Amr Bashir
402cbd55f9 fix unnecessary cast lint (#2596)
* fix clippy lints on Windows

* fix lints on other platforms

* a couple more

* again

* don't know what's goging on anymore

* fix examples

* comon

* how about now?

* this is getting annoying

* hmmm

* explicitly set a type

* 😢

* don't cast on x64 targets

* apply code review requests

* fix attributes on expressions

* fix ios
2022-12-22 20:35:33 +01:00
Ngo Iok Ui (Wu Yu Wei)
da7422c6e1 Add WindowBuilder::with_parent_window (#2548)
* On macOS, add `WindowBuilderExtMacOS::with_parent_window`

* Replace Parent with Option<Id<NSWindow, Shared>>

* Add addChildWindow method on NSWindow instead

* Update with_parent_window to be unsafe fn

* Add unified `with_parent_window`

* Remove `WindowBuilderExtUnix::with_parent`

* Remove `WindowBuilderExtWindows::with_parent_window`

* Clean up CI warnings

* Update CHANGELOG.md

It's `WindowBuilderExtX11` rather than `WindowBuilderExtUnix`

* Rename parent to owner

* Make with_parent_window unsafe and update its doc

* Add another way to get window on mac

* Add more documentations

* Add match arm and panic on invalid varients

* Add Xcb arm

* Update child_window example to make it safer and work in i686

* Remove duplicate entry in CHANGELOG.md

* Propogate error instead of expect

* Replace unreachable to panic

* Add platform note to X11

Co-authored-by: Wu Yu Wei <wusyong9104@gmail.com>
2022-12-22 01:07:13 +01:00
Amr Bashir
8934d2765d Add missing closing parentheses (#2587) 2022-12-11 03:29:19 +01:00
Amr Bashir
89eea64a4a Retain WS_MAXIMZE when unminmizing a maximized window (#2581)
Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
2022-12-09 19:33:11 +01:00
feelingnothing
9f781bc422 On Windows, fix left mouse button release event not being sent after Window::drag_window (#2564) 2022-12-06 23:18:50 +01:00
Mads Marquart
4ed4e918f3 Clean up UIView override declaration (#2578) 2022-12-01 09:32:44 +01:00
Mads Marquart
2e4d79f57a Do fullscreen logic synchronously on main thread (#2575) 2022-11-30 14:49:18 +01:00
Mads Marquart
bf92f3e97b macOS: Run tasks synchronously on main thread instead of asynchronously (#2574)
* Close windows synchronously on main thread

* Set style mask synchronously on main thread

* Set title synchronously on main thread

* Set visibility and focus synchronously on main thread

* Set window level synchronously on main thread

* Set position and size synchronously on main thread

* Set cursor hittest synchronously on main thread

* Add changelog entry
2022-11-30 14:30:32 +01:00
Mads Marquart
2a58b785fe Refactor SharedState so that it is no longer behind an Arc (#2573)
* Refactor SharedState so that it is no longer behind an Arc

* Always use `Window::lock_shared_state`
2022-11-29 12:58:35 +01:00
Xiaopeng Li
32784af3c4 Don't panic when getting refresh rate failed (#2533)
This fixes a crash on macOS when trying to get the monitor
refresh rate from the disabled monitor.

Co-authored-by: Jet Spark <lixiaopeng.jetspark@bytedance.com>
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-11-29 11:28:46 +01:00
Amr Bashir
94688a62f0 On Windows and macOS, add API to enable/disable window controls (#2537)
* On Windows and macOS, add API to enable/disable window controls

* fix build

* missing import

* use `WindowButtons` flags

* rename to `[set_]enabled_buttons`

* add example, fix windows impl for minimize

* macOS: Fix button enabling close/minimize while disabling maximized

* Update src/platform_impl/windows/window.rs

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>

* compose the flags on a sep line, use `bool::then`

Co-authored-by: Mads Marquart <mads@marquart.dk>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2022-11-29 11:03:51 +01:00
Amr Bashir
28e34c2e1b Add Window::set_theme (#2553)
* Add `Window::set_theme`

* typo

* fix linux build

* fix wayland

* review changes

* update docs

* update changelog

* pin `image` dep

* suppport falling back to system default

* fix linux

* default to dark on macOS and x11

* fix `setAppearance` definition

* add macOS notes

* update docs

* Update CHANGELOG.md

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>

* update doc

* Revert "pin `image` dep"

This reverts commit 7517f7c506.

* Update theme example with Window::set_theme

* Fix Window::theme getter on macOS

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-11-29 10:05:51 +01:00
Fotis Gimian
9ae7498a8a On Windows, revert window background to an empty brush to avoid white flashes when changing scaling (#2571) 2022-11-27 22:28:14 +01:00
Robert Bragg
1786c877ec android: depend on android-activity 0.4.0 (#2557) 2022-11-26 11:54:08 +01:00
Amr Bashir
101ac8908c Add Window::set_window_level API
This adds `Window::set_window_level` to control the preferred
z level of the window.

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-11-26 04:50:58 +03:00
Marijn Suijten
ba4bf03675 ci: Specify to build winit package when invoking cargo-apk (#2561)
* ci: Don't use `$CMD` for Android doc building

Since migrating `cargo-apk` to `clap` [it is now annoying] to pass
unknown arguments to an underlying `cargo` command (like `cargo doc`):
fortunately generating docs doesn't need to go through `cargo apk` to
set up cross-compiler/linker environment variables at all.

[it is now annoying]: https://github.com/rust-windowing/android-ndk-rs/pull/363

* ci: Simplify

* ci: Explicitly build just the `winit` package on Android

Since https://github.com/dvc94ch/cargo-subcommand/pull/23 `cargo-apk`
now strictly searches for workspaces first before committing to finding
the right package _within said workspace_, and bails when no package was
selected since we don't support selecting (building, packaging, running)
>1 target currently.

Perhaps it's a bit hash to enforce this on free-form `cargo apk --`
invocations, but it is what it is.
2022-11-24 21:49:47 +01:00
Mads Marquart
a63b066ed5 Fix MouseButton::Other value on Windows (#2565)
This was a mistake in the transition to windows-sys: https://github.com/rust-windowing/winit/pull/2057

We used winapi's GET_XBUTTON_WPARAM before which is using HIWORD instead of LOWORD: https://docs.rs/winapi/0.3.9/src/winapi/um/winuser.rs.html#1297-1299
2022-11-23 16:43:56 +01:00
Amr Bashir
f77f858e9b On macOS, add documentEdited APIs (#2550)
* On macOS, add documentEdited APIs

Port of 33fdeab629

* Update src/platform/macos.rs

Co-authored-by: Mads Marquart <mads@marquart.dk>

* typo

Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-11-23 16:07:41 +01:00
Mads Marquart
6d0cf6a275 Remove WindowBuilderExtIOS::with_root_view_class (#2459) 2022-11-23 15:53:06 +01:00
Mads Marquart
12df8b6c0c macOS: Fix ApplicationDelegate::init (#2566) 2022-11-23 15:23:06 +01:00
Amr Bashir
65baae75c4 Add Window::set_content_protected on macOS and Windows (#2525)
* Add `Window::set_content_protect` on macOS and Windows

* Update window.rs

* Add builder variant

* fix import

* fix argument type

* fix import

* fix always visible window on Windows

* update docs
2022-11-23 14:51:34 +01:00
Amr Bashir
418cc44e93 On macOS, add EventLoopBuilderExtMacOS::with_activate_ignoring_other_apps (#2551)
* On macOS,  add `EventLoopBuilderExtMacOS::with_activate_ignoring_other_apps`

* Update src/platform/macos.rs

Co-authored-by: Mads Marquart <mads@marquart.dk>

* remove todo

Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-11-23 13:42:46 +01:00
Mads Marquart
ce6c6e8c95 Only build, but don't run tests in MSRV CI (#2558)
* Only build, but don't run tests in MSRV CI

Since the MSRV of development dependencies can easily be bumped without it affecting the MSRV of the published version of `winit`

* Run clippy on stable Rust instead of MSRV Rust

clippy inspects the `rust-version` field, and only suggests changes that conform to that.
2022-11-23 13:07:58 +01:00
Mads Marquart
bdcbd7d1f9 macOS: Fix NSWindowLevel values (#2545)
* Fix NSWindowLevel values

* Fix formatting
2022-11-22 11:08:56 +01:00
Robert Bragg
05484c5888 Android: rework backend to use android-activity crate (#2444)
This updates the Android backend to use the android-activity crate instead
of ndk-glue. This solves a few issues:
1. The backend is agnostic of the application's choice of Activity base
   class
2. Winit is no longer responsible for handling any Java synchronization
   details, since these are encapsulated by the design of
   android_activity
3. The backend no longer depends on global / static getters for state
   such as the native_window() which puts it in a better position to
   support running multiple activities within a single Android process.
4. Redraw requests are flagged, not queued, in a way that avoids taking
   priority over user events (resolves #2299)

To make it possible for application crates to avoid explicitly
depending on the `android-activity` crate (and avoid version conflicts)
this re-exports the android-activity crate under:

  `winit::platform::android::activity::*`

This also adds `android-native-activity` and `android-game-activity`
features that set the corresponding android-activity features.

Addresses: PR https://github.com/rust-windowing/winit/pull/1892
Addresses: PR https://github.com/rust-windowing/winit/pull/2307
Addresses: PR https://github.com/rust-windowing/winit/pull/2343

Addresses: #2293
Resolves: #2299

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
2022-11-10 17:55:19 +01:00
Amr Bashir
50bbc85dc3 On Windows, fix icons specified on WindowBuilder not taking effect for windows created after the first one (#2530) 2022-11-06 21:30:55 +01:00
Xiaopeng Li
8669c2e8df On macOS, fix panic in current_monitor_inner 2022-11-05 05:30:39 +03:00
Mads Marquart
97d4c7b303 macOS: Fix overridden fullscreen selectors (#2546) 2022-11-03 22:33:38 +01:00
Amr Bashir
08f9e374e0 Add Window::title getter on Windows and macOS 2022-11-03 20:11:37 +03:00
Ihor Ranchynskyi
a7a7cc64cd Bump windows-sys to 0.42 (#2540) 2022-10-31 23:19:45 +01:00
Kirill Chibisov
04d9e081b8 Bump version on master
This commit does not represent a release and only
synchronizes CHANGELOG from the latest release.
2022-10-26 18:20:58 +03:00
i509VCB
8fc24c959a Generate docs.rs documentation with doc_auto_cfg (#2358) 2022-10-25 00:02:52 +02:00
Amr Bashir
2fb15dbe8a Fix menubar focus using Alt on Windows (#2521) 2022-10-20 17:59:12 +02:00
keiya sasaki
92fdf5ba85 Rework theme API
This commit adds support for theming on macOS and
also unifies the system theme handling across platforms.
2022-10-18 21:34:36 +03:00
Kirill Chibisov
4f06cfcf5b On Wayland, fix invalid offsets being sent in Preedit
Even when the protocol explicitly tells to send proper UTF-8
boundaries for cursor, some IMEs don't do that, so sanity check
them before sending downstream.
2022-10-18 17:13:31 +03:00
Kirill Chibisov
462bb4d324 Bump version on master
This commit does not represent a release and only
synchronizes CHANGELOG from the latest release.
2022-10-15 09:30:25 +03:00
Kirill Chibisov
f6ca8515ab On X11, fix IME crashing during reload
During reload we were picking old styles, but the styles could
change during reload leading to errors during IME building.

Fixes #2510.
2022-10-10 00:13:37 +03:00
Shinichi Tanaka
71094e5703 On X11, allow building window with parent 2022-10-09 23:12:23 +03:00
Lucas Kent
bb0f965c57 Update cargo-run-wasm (#2509) 2022-10-09 04:49:19 +02:00
Markus Siglreithmaier
4d48c76da9 Windows, emit ReceivedCharacter on system keybinds
Currently needed for downstream users relaying on `ReceivedCharacter` for implementing
keybindings.
2022-10-08 06:32:40 +03:00
Mads Marquart
fafdedfb7d Simplify internal type construction 2022-09-21 11:04:28 +03:00
killian
25b129362f On Windows, fixed focus event emission on minimize. 2022-09-20 20:26:37 +02:00
Mads Marquart
48b843e42d Accepts first mouse (#2457)
* MacOS: set value for `accepts_first_mouse`

* Update CHANGELOG and FEATURES

* Field doesn't need to be public

* Convert `bool` to `BOOL`

* Fix formatting

* Move flag from window state to view instance

* Feedback from PR

* Fix changelog location
2022-09-13 21:11:18 +02:00
Kirill Chibisov
58f2455aa9 Bump version on master
This commit does not represent a release and only
synchronizes CHANGELOG from the latest release.
2022-09-12 18:15:30 +03:00
Kirill Chibisov
155f1f9720 On X11 query for XIM styles before creating IME
Fixes #2448.
2022-09-11 19:36:56 +03:00
Kirill Chibisov
3b56b0e76f Add release process
This should maintainers to handle releases and
establish a non-blocking workflow.

Fixes #2454.
2022-09-11 16:20:09 +03:00
Kirill Chibisov
5d2aca90bd Send empty Ime::Preedit before the Ime::Commit
This should help downstream to automatically clear it.
2022-09-11 00:48:24 +03:00
Kirill Chibisov
ba49db2cb9 Remove automatic publish script
This script is confusing and provides no value especially
with release branches and patch fixes.
2022-09-09 19:01:05 +03:00
Kirill Chibisov
a4695c5397 Specify minimum supported version for RWH 0.4
Winit uses raw-window-handle of version 0.4.3,
but only 0.4.0 was specified.
2022-09-09 12:11:55 +03:00
Weng Xuetian
92ddb3483e Clear preedit if there is no pending preedit on Wayland
Fixes #2478.
2022-09-09 10:53:58 +03:00
Mads Marquart
fec52b028e Fix runloop entry (#2480)
Introduced in https://github.com/rust-windowing/winit/pull/2479; turns out the definitions were not entirely equal, the `kCFRunLoopEntry` that we were using previously was defined as `0` while the correct value is `1` (which meant the `unimplemented!()` branch suddenly started triggering)
2022-09-08 21:56:53 +02:00
Mads Marquart
d8c0ee733b Remove custom definition of Core Foundation runloop functionality (#2479)
Use the definitions that `core_foundation` exposes (almost the same, except `CFRunLoopSourceContext::perform` is not nullable, so we account for that as well).
2022-09-08 21:03:25 +02:00
Mads Marquart
fb248eaadc Clean up iOS class declaration (#2462)
* Begin abstraction over UIKit

* Clean up UIWindow override declaration

* Clean up UIApplication delegate declaration

* Clean up UIViewController override declaration

* Finalize objc -> objc2 rename
2022-09-08 20:30:34 +02:00
Mads Marquart
da7bf8e29b macOS: Fix WindowBuilder::with_resize_increments (#2477)
Introduced in https://github.com/rust-windowing/winit/pull/2411
2022-09-08 18:54:22 +02:00
shuo
a6a8b12537 Update Readme for iOS platform specific info (#2473)
* Update Readme for iOS platform specific info

* Update README.md

Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-09-08 16:52:57 +02:00
Mads Marquart
340f951d10 Refactor macOS to use new objc2 features (#2465)
* Remove UnownedWindow::inner_rect

* Refactor custom view to use much less `unsafe`

The compiler fence is safe to get rid of now since `interpretKeyEvents` takes `&mut self`

* Refactor Window to use much less unsafe

* Refactor NSApplication usage to have much less unsafe

* Remove cocoa dependency

* Enable `deny(unsafe_op_in_unsafe_fn)` on macOS

Also re-enable clippy `let_unit_value` lint

* Remove #[macro_use] on macOS

* Refactor window delegate to use much less unsafe
2022-09-08 16:45:29 +02:00
Marijn Suijten
05dd31b8ea Revert "ci: manually point ANDROID_NDK_ROOT to latest supplied version"
This reverts commit 4895a29e92.

GitHub Actions' runner-images readded this environment variable on my
request [1] as it wasn't strictly related to the deprecated and removed
`ndk-bundle` NDK release.  Back out of the workaround to keep CI scripts
tidy.

[1]: https://github.com/actions/runner-images/issues/5879#issuecomment-1197811704
2022-09-06 16:48:28 +03:00
Lucas Kent
0fca8b088d WindowBuilderExtWebSys::with_prevent_default disables scrolling on both mobile and desktop (previously just desktop) (#2216)
* Disable scrolling on web by default but provide method in builder to enable it

* rename enable_web_scroll -> enable_web_page_scroll

* move enable_web_page_scroll into prevent_default option

* final approach

* Mark prevent_default change as breaking

Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-09-04 05:45:30 +02:00
Anton Bulakh
ab56e9f57d Allow changing resize increments after window creation 2022-09-03 21:50:22 +03:00
Lucas Kent
97d2aaa953 Add web_aspect_ratio example (#2209)
* Add web_aspect_ratio example

* Review feedback
2022-09-03 18:26:24 +02:00
Mads Marquart
29419d6c38 Refactor macOS cursor code (#2463) 2022-09-02 21:02:40 +02:00
Mads Marquart
e517e468f8 Fix declare_class! indentation (#2461)
* Fix NSWindow delegate indentation

* Fix NSView delegate indentation
2022-09-02 19:38:32 +02:00
Mads Marquart
d67c928120 Clean up macOS class declaration (#2458)
* Begin abstraction over AppKit

* Clean up NSApplication delegate declaration

* Clean up NSApplication override declaration

* Clean up NSWindow delegate declaration

* Clean up NSWindow override declaration

* Clean up NSView delegate declaration
2022-09-02 18:46:18 +02:00
Mads Marquart
112965b4ff Initial transition to objc2 (#2452)
* Use objc2

* Use objc2's NSInteger/NSUInteger/NSRange
2022-09-02 15:48:02 +02:00
Mads Marquart
e0018d0710 Bump MSRV to 1.60 (#2453) 2022-09-02 10:59:05 +02:00
Mads Marquart
1ca8b65e85 Split platform::unix into platform::x11 and platform::wayland
This also removes deprecated `WindowExtUnix::is_ready`.
2022-09-01 08:05:32 +03:00
Mads Marquart
a43a15b4a0 iOS: Fix a few instances of UB (#2428)
* Fix iOS 32-bit

* Fix a few invalid message sends on iOS
2022-09-01 03:10:00 +02:00
Mads Marquart
66aa6c945d Add myself as iOS co-maintainer (#2451) 2022-09-01 01:45:11 +02:00
ajtribick
dfecdc5762 Windows: Update handling of system keypresses (#2445)
- Pass WM_SYSKEYDOWN to DefWindowProc
- Avoid intercepting WM_SYSCHAR to allow ALT+Space to work: removes ReceivedCharacter events for alt+keypress
- Intercept WM_MENUCHAR to disable bell sound
2022-09-01 00:03:48 +02:00
Mads Marquart
8729119536 Remove parking_lot dependency (#2423) 2022-08-31 18:32:19 +02:00
daxpedda
ec7e935248 Document WindowEvent::Moved OS support (#2442) 2022-08-31 06:57:37 +02:00
ajtribick
fd72000a9a Disable default features in simple_logger
This fix CI building due to implicit rust version
bump in examples.
2022-08-29 00:26:51 +03:00
Alex Butler
e91ee811cb Use sctk-adwaita 0.5.1 auto theme selection
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2022-08-24 23:43:36 +03:00
Kirill Chibisov
b3b80166ce Mark new events as breaking change
Adding a new enum variant is a breaking change in winit.
2022-08-24 16:33:58 +03:00
daxpedda
f9b41fd819 Update sctk-adwaita to use ab_glyph
The crossfont will still be available under the option.
2022-08-24 15:24:29 +03:00
Sludge
0d9c39029c Document WindowEvent::Moved as unsupported on Wayland 2022-08-20 00:32:40 +03:00
Joonas Satka
da2cef97a3 Add touchpad magnify and rotate gestures support for macOS (#2157)
* Add touchpad magnify support for macOS

* Add touchpad rotate support for macOS

* Add macOS rotate and magnify gesture cancelled phases

* Correct docs for TouchpadRotate event

* Fix tracing macros
2022-08-16 17:20:06 +02:00
Markus Siglreithmaier
76f158d310 On Windows, improve support for undecorated windows (#2419) 2022-08-15 02:36:37 +02:00
Kirill Chibisov
2e4338bb8d Release 0.27.2 version 2022-08-12 14:39:44 +04:00
Kirill Chibisov
ec2888b8b7 On Wayland, fix Window::request_redraw being delayed
On Waylnad when asking for redraw before `MainEventsCleared`
would result for redraw being send on the next event loop tick,
which is not expectable given that it must be delivered on the same
event loop tick.
2022-08-12 11:54:02 +04:00
Kirill Chibisov
fa83bace12 Remove redundant steps from CI
Tests are already building the entire crate, so no need for a
separate builds slowing down the CI.
2022-08-11 19:31:11 +04:00
Kirill Chibisov
ee7dc48e3b Fix missleading breaking change on Windows
The applications should not rely on not-implemented behavior and
should use the right functions for that.
2022-08-11 19:07:40 +04:00
Robert Bragg
11d4a301e4 Implement version 0.4 of the HasRawWindowHandle trait
This makes Winit 0.27 compatible with crates like Wgpu 0.13 that are
using the raw_window_handle v0.4 crate and aren't able to upgrade to 0.5
until they do a new release (since it requires a semver change).

The change is intended to be self-contained (instead of pushing
the details into all the platform_impl backends) since this is only
intended to be a temporary trait implementation for backwards
compatibility that will likely be removed before the next Winit release.

Fixes #2415.
2022-08-11 18:33:02 +04:00
Mads Marquart
ad41eaf151 Add CODEOWNERS file (#2420)
* Add CODEOWNERS file

This makes it very clear when you're stepping down from the post as a maintainer, and makes it clear for users who is expected to review their PR

* Fix grammar

* Make @kchibisov receive pings for the X11 platform

* Fix typo

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2022-08-11 16:13:56 +02:00
ajtribick
9b71df9f97 On Windows, add opt-in function for device events (#2409) 2022-08-11 15:17:46 +02:00
Mads Marquart
b1c9e4a6fa Fix tracking of phase changes for mousewheel on trackpad (#2158) 2022-08-10 18:28:19 +02:00
Anton Bulakh
cdbaf4816a On X11, fix window hints not persisting
This commit fixes the issue with min, max, and resize increments
not persisting across the dpi changes.
2022-08-08 18:27:11 +04:00
Amr Bashir
6b7ceedc91 Windows: respect min/max sizes when creating the window (#2393) 2022-08-04 23:03:55 +02:00
Kirill Chibisov
c53a574bff Release 0.27.1 version 2022-07-30 19:33:23 +03:00
Kirill Chibisov
95246d81c1 On X11, fix crash when can't disable IME
Fixes #2402.
2022-07-30 17:15:57 +03:00
Kirill Chibisov
bf537009d9 Explicitly specify minimum supported rust version
This should help with distributing apps using winit.

Fixes #1075.
2022-07-29 14:39:41 +03:00
Kirill Chibisov
50035643f7 Release 0.27.0 version 2022-07-26 23:54:12 +03:00
Mads Marquart
64c22f9075 Fix changelog entry wrt scrolling
The breaking change was put into the wrong release section.
2022-07-26 22:25:00 +03:00
Marijn Suijten
4895a29e92 ci: manually point ANDROID_NDK_ROOT to latest supplied version
It seems the symlink to `ndk-bundle` and this environment variable
pointing to it have been removed to prevent the sdkmanager from failing,
when finding the SDK setup to be in an "indeterminate" state.  It is now
up to the users themselves to install an NDK through that tool or point
the right variables to a preinstalled "latest" NDK.

https://github.com/actions/virtual-environments/issues/2689
https://github.com/actions/virtual-environments/pull/5926
2022-07-26 19:55:06 +03:00
Robert Bragg
6cdb3179c8 Consistently deliver a Resumed event on all platforms
To be more consistent with mobile platforms this updates the Windows,
macOS, Wayland, X11 and Web backends to all emit a Resumed event
immediately after the initial `NewEvents(StartCause::Init)` event.

The documentation for Suspended and Resumed has also been updated
to provide general recommendations for how to handle Suspended and
Resumed events in portable applications as well as providing
Android and iOS specific details.

This consistency makes it possible to write applications that lazily
initialize their graphics state when the application resumes without
any platform-specific knowledge. Previously, applications that wanted
to run on Android and other systems would have to maintain two,
mutually-exclusive, initialization paths.

Note: This patch does nothing to guarantee that Suspended events will
be delivered. It's still reasonable to say that most OSs without a
formal lifecycle for applications will simply never "suspend" your
application. There are currently no known portability issues caused
by not delivering `Suspended` events consistently and technically
it's not possible to guarantee the delivery of `Suspended` events if
the OS doesn't define an application lifecycle. (app can always be
terminated without any kind of clean up notification on most
non-mobile OSs)

Fixes #2185.

Co-authored-by: Marijn Suijten <marijns95@gmail.com>
Co-authored-by: Markus Røyset <maroider@protonmail.com>
2022-07-26 16:03:12 +03:00
Kirill Chibisov
4fd52af682 Fix type hint reference for xlib hook 2022-07-26 16:02:09 +03:00
Marijn Suijten
5a0bad130d Bump ndk and ndk-glue dependencies to stable 0.7.0 release (#2392) 2022-07-25 15:20:31 +02:00
Amr Bashir
08d025968e Fix hiding a maximized window On Windows (#2336) 2022-07-23 14:23:58 +02:00
Amr Bashir
1cd0e94c26 Windows: apply skip taskbar state when taskbar is restarted (#2380) 2022-07-22 19:33:22 +02:00
Kirill Chibisov
1ec976f95e Add method to hook xlib error handler
This should help glutin to handle errors coming from GLX
and offer multithreading support in a safe way.

Fixes #2378.
2022-07-22 20:21:28 +03:00
Kirill Chibisov
f10ef5f331 On macOS, fix confirmed character inserted
When confirming input in e.g. Korean IME or using characters like
`+` winit was sending those twice, once via `Ime::Commit` and the
other one via `ReceivedCharacter`, since those events weren't generating
any `Ime::Preedit` and were forwarded due to `do_command_by_selector`.
2022-07-21 22:23:22 +03:00
Kirill Chibisov
653bc59813 Update raw-window-handle to v0.5.0
This updates raw-window-handle to v0.5.0.
2022-07-21 22:22:36 +03:00
Rodrigo Batista de Moraes
3e991e13dc Android: avoid deadlocks while handling UserEvent (#2343)
Replace `Arc<Mutex<VecDeque<T>>` by `mpsc`
2022-07-20 19:52:36 +02:00
Markus Røyset
5397b53e04 Tidy up "platform-specifc" doc sections (#2356)
* Tidy up "platform-specific" doc sections

* Unrelated grammatical fix

* Subjective improvements
2022-07-20 13:45:12 +02:00
Kirill Chibisov
f09259f6de Bump sctk-adwaita to 0.4.1
This should force the use of system libraries for Fontconfig
and freetype instead of building them with cmake if missing.

This also fixes compilation failures on nightly.

Fixes #2373.
2022-07-20 11:50:49 +03:00
Josh Groves
430a49ebc2 Fix typos (#2375) 2022-07-15 18:32:12 +02:00
Steve Wooster
1091a8ba1a Make winit focus take activity into account on Windows (#2159)
winit's notion of "focus" is very simple; you're either focused or not.
However, Windows has both notions of focused window and active window
and paying attention only to WM_SETFOCUS/WM_KILLFOCUS can cause a window
to believe the user is interacting with it when they're not. (this
manifests when a user switches to another application between when a
winit application starts and it creates its first window)
2022-07-15 10:27:27 +02:00
Josh Groves
9116b6c8cd windows: Use correct value for mouse wheel delta (#2374) 2022-07-14 22:00:22 +02:00
Josh Groves
990e34a129 web: add with_prevent_default, with_focusable (#2365)
* web: add `with_prevent_default`, `with_focusable`

`with_prevent_default` controls whether `event.preventDefault` is called

`with_focusable` controls whether `tabindex` is added

Fixes #1768

* Remove extra space from CHANGELOG
2022-07-14 17:52:31 +02:00
Marijn Suijten
472d7b9376 android: Hold NativeWindow lock until after notifying the user with Event::Suspended (#2307)
This applies https://github.com/rust-windowing/android-ndk-rs/issues/117
on the `winit` side: Android destroys its window/surface as soon as the
user returns from [`onNativeWindowDestroyed`], and we "fixed" this on
the `ndk-glue` side by sending the `WindowDestroyed` event before
locking the window and removing it: this lock has to wait for any user
of `ndk-glue` - ie. `winit` - to give up its readlock on the window,
which is what we utilize here to give users of `winit` "time" to destroy
any resource created on top of a `RawWindowHandle`.

since we can't pass the user a `RawWindowHandle` through the
`HasRawWindowHandle` trait we have to document this case explicitly and
keep the lock alive on the `winit` side instead.

[`onNativeWindowDestroyed`]: https://developer.android.com/ndk/reference/struct/a-native-activity-callbacks#onnativewindowdestroyed
2022-07-14 12:35:49 +02:00
Markus Røyset
50dd7881b1 Fix changelog entry for EventLoopExtWebSys (#2372) 2022-07-13 17:54:06 +02:00
Liam Murphy
aa8f8db305 web: Add EventLoop::spawn (#2208)
* web: Add `EventLoop::spawn`

This is the same as `EventLoop::run`, but doesn't throw an exception in order to return `!`.

I decided to name it `spawn` rather than `run_web` because I think that's more descriptive, but I'm happy to change it to `run_web`.

Resolves #1714

* Update src/platform/web.rs

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Fix outdated names

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2022-07-13 17:17:18 +02:00
Lucas Kent
cdd9b1e1eb web: Manually emit focused event on mouse click (#2202)
* Manually emit focused event on mouse click

* Update CHANGELOG.md

Co-authored-by: Markus Røyset <maroider@protonmail.com>

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2022-07-13 00:46:15 +02:00
Kirill Chibisov
2d2ce70edc On Wayland, drop wl_surface on window close 2022-07-09 21:41:18 +03:00
Kirill Chibisov
78f1d1df38 On Wayland send Focused(false) for new window
On Wayland winit will always get an explicit focused event from the
system and will transfer it downstream. So send focused false to enforce
it.
2022-07-09 18:17:41 +03:00
Kirill Chibisov
a06bb3f992 Add refresh_rate_millihertz for MonitorHandle
This also alters `VideoMode::refresh_rate` to
`VideoMode::refresh_rate_millihertz` which now returns monitor refresh rate in
mHz.
2022-07-08 13:25:56 +03:00
trimental
e289f30e5d Add 'WindowEvent::Occluded(bool)'
This commits and an event to track window occlusion state,
which could help optimize rendering downstream.
2022-07-06 21:46:25 +03:00
Shinichi Tanaka
4b10993970 Fix infinite recursion in WindowId conversion methods 2022-07-05 20:09:40 +03:00
Diggory Hardy
d78a870e66 examples/multiwindow.rs: ignore synthetic key press events 2022-07-03 22:25:08 +03:00
Kirill Chibisov
cb41c58f21 Implement From<u64> for WindowId and vise-versa
This should help downstream applications to expose WindowId to the end
users via e.g. IPC to control particular windows in multi window
systems.
2022-07-02 14:27:19 +03:00
Diggory Hardy
c55d97183d Less redundancy and improve fullscreen in examples
Remove examples/minimize which is redundant
2022-07-01 14:07:10 +03:00
Aaron Hill
8646cbc9f5 Map XK_Caps_Lock to VirtualKeyCode::Capital (#1864)
This allows applications to handle events for the caps lock key under X11
2022-06-23 17:59:04 +02:00
Amr Bashir
64c1d4c5bb Fix conflict in WindowFlags on Windows 2022-06-22 20:44:00 +03:00
MarcusGrass
76b949c196 Disallow multiple EventLoop creation 2022-06-22 20:43:25 +03:00
Kirill Chibisov
c93ef47b9b Bump smithay-client-toolkit to v0.16.0 2022-06-20 10:19:49 +03:00
Marijn Suijten
2b414cd825 ci: Disallow warnings in rustdoc and test private items (#2341)
Make sure `cargo doc` runs cleanly without any warnings in the CI - some
recently introduced but still allowing a PR to get merged.

In case someone wishes to add docs on private items, make sure those
adhere to the same standards.
2022-06-17 14:19:09 +02:00
Nazarí González
ac42447459 macOS: disallow_highdpi will set explicity the value to avoid the SO value by default (#2339)
Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-06-17 01:12:05 +02:00
Markus Røyset
401d20fa1f Fix doubled device events on X11
Fixes #2332
2022-06-13 19:24:56 +03:00
Marijn Suijten
6b5b570b45 examples/window_run_return: Enable on Android (#2321)
Android also supports `EventLoopExtRunReturn`.  The user will still have
to follow the README to turn this example into a `cdylib` and add the
`ndk_glue::main()` initialization attribute, though.
2022-06-13 16:40:21 +02:00
Kirill Chibisov
9e6f666616 Refine Window::set_cursor_grab API
This commit renames `Window::set_cursor_grab` to
`Window::set_cursor_grab_mode`. The new API now accepts enumeration
to control the way cursor grab is performed. The value could be: `lock`,
`confine`, or `none`.

This commit also implements `Window::set_cursor_position` for Wayland,
since it's tied to locked cursor.

Implements API from #1677.
2022-06-13 09:43:14 +03:00
Kirill Chibisov
8ef9fe44c7 Add WindowBuilder::transparent
This is required to help hardware accelerated libraries like glutin
that accept WindowBuilder instead of RawWindowHandle, since the api
to access builder properties directly was removed.

Follow up to 44288f6.
2022-06-12 09:53:28 +03:00
Mads Marquart
3e0a544eb8 Documentation cleanup (#2328)
* Remove redundant documentation links

* Add note to README about windows not showing up on Wayland

* Fix documentation links

* Small documentation fixes

* Add note about doing stuff after StartCause::Init on macOS
2022-06-11 18:57:19 +02:00
Mads Marquart
6474891f1e Fix macOS 32bit (#2327) 2022-06-11 03:43:51 +02:00
Mads Marquart
40abb526cc Remove core-video-sys dependency (#2326)
Hasn't been updated in over 2 years - many open PRs, seems abandoned. Is the cause of several duplicate dependencies in our dependency tree!
2022-06-11 02:37:46 +02:00
Mads Marquart
c532d910c0 Build docs on docs.rs for iOS and Android as well (#2324) 2022-06-11 00:45:24 +02:00
Mads Marquart
44288f6280 Make WindowAttributes private (#2134)
* Make `WindowAttributes` private, and move its documentation

* Reorder WindowAttributes title and fullscreen to match method order
2022-06-10 19:05:28 +02:00
Kirill Chibisov
eec84ade86 Make set_device_event_filter non-mut
Commit f10a984 added `EventLoopWindowTarget::set_device_event_filter`
with for a mutable reference, however most winit APIs work with
immutable references, so altering API to play nicely with existing APIs.

This also disables device event filtering on debug example.
2022-06-10 15:39:02 +03:00
Kirill Chibisov
10419ff441 Run clippy on CI
Fixes #1402.
2022-06-10 13:43:33 +03:00
Marijn Suijten
57981b533d On Android, use HasRawWindowHandle directly from the ndk crate (#2318)
The `ndk` crate now implements [`HasRawWindowHandle` directly on
`NativeWindow`], relieving the burden to reimplement it on `winit`.

[`HasRawWindowHandle` directly on `NativeWindow`]: https://github.com/rust-windowing/android-ndk-rs/pull/274
2022-06-10 11:37:06 +02:00
tinaun
c5eaa0ab69 macOS: Emit LoopDestroyed on CMD+Q (#2073)
override applicationWillTerminate:

Co-authored-by: Mads Marquart <mads@marquart.dk>
2022-06-09 16:08:52 +02:00
James Liu
2c01e9e747 Migrate from lazy_static to once_cell 2022-06-08 21:50:26 +03:00
Kevin King
4c39b3188c Remove old dialog fix that is superseded by #2027 (#2292)
This fixes the run_return loop never returning on macos when using multiple windows
2022-06-08 17:22:54 +02:00
Kirill Chibisov
224872ce03 Prevent null dereference on X11 with bad locale 2022-06-08 01:04:33 +03:00
Christian Duerr
f10a984ba3 Add X11 opt-in function for device events
Previously on X11, by default all global events were broadcasted to
every winit application. This unnecessarily drains battery due to
excessive CPU usage when moving the mouse.

To resolve this, device events are now ignored by default and users must
manually opt into it using
`EventLoopWindowTarget::set_filter_device_events`.

Fixes (#1634) on Linux.
2022-06-08 00:17:45 +03:00
Lucas Kent
c7f7181388 Set WindowBuilder to must_use 2022-06-07 23:55:57 +03:00
Kirill Chibisov
92530299eb Revert "On Wayland, fix resize not propagating properly"
This reverts commit 78e5a395da.

It was discovered that in some cases mesa will lock the back
buffer, e.g. when making context current, leading to resize
missing. Given that applications can restructure their rendering
to account for that, and that winit isn't limited to playing
nice with mesa reverting the original commit.
2022-06-05 22:19:27 +03:00
Markus Siglreithmaier
58cd23d1ac On Windows, fix reported cursor position. (#2311)
When clicking and moving the cursor out of the window negative coordinates were not handled correctly.
2022-06-02 19:08:54 +02:00
Aron Parker
5d85c10a2c [Windows] Avoid GetModuleHandle(NULL) (#2301)
Use get_instance_handle() over GetModuleHandle(NULL)
2022-05-29 17:12:46 +02:00
Kevin Reid
f11270dac0 Reorganize EventLoopBuilder::build() platform documentation
Since there's a "Platform-specific" header, it makes sense to put the
Linux-specific part under it. On the other hand, "Can only be called on
the main thread." is true for all platforms, not just iOS, so there is
no reason to call it out for iOS specifically.
2022-05-29 14:51:27 +03:00
Phillip Hellewell
bcd76d4718 On macOS, emit resize event on frame_did_change
When the window switches mode from normal to tabbed one, it doesn't
get resized, however the frame gets resized. This commit makes
winit to track resizes when frame changes instead of window.

Fixes #2191.
2022-05-23 22:53:07 +03:00
Liam Murphy
4dd2b66aaa Fix warnings on nightly rust (#2295)
This was causing CI to fail: https://github.com/rust-windowing/winit/runs/6506026326
2022-05-20 17:03:35 +02:00
Bartłomiej Maryńczak
829a140d9b On Wayland, provide option for better CSD
While most compositors provide server side decorations, the GNOME
does not, and won't provide them. Also Wayland clients must render
client side decorations.

Winit was already drawing some decorations, however they were bad
looking and provided no text rendering, so the title was missing.
However this commit makes use of the SCTK external frame similar to
GTK's Adwaita theme supporting text rendering and looking similar to
other GTK applications.

Fixes #1967.
2022-05-20 03:09:23 +03:00
Kirill Chibisov
f04fa5d54f Add new Ime event for desktop platforms
This commit brings new Ime event to account for preedit state of input
method, also adding `Window::set_ime_allowed` to toggle IME input on
the particular window.

This commit implements API as designed in #1497 for desktop platforms.

Co-authored-by: Artur Kovacs <kovacs.artur.barnabas@gmail.com>
Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>
Co-authored-by: Murarth <murarth@gmail.com>
Co-authored-by: Yusuke Kominami <yukke.konan@gmail.com>
Co-authored-by: moko256 <koutaro.mo@gmail.com>
2022-05-07 05:29:25 +03:00
Markus Siglreithmaier
b4175c1454 Bump windows-sys version to 0.36 (#2277) 2022-05-03 12:39:29 +02:00
Tobias Menzi
0728105b2b On Wayland, fix hiding cursors on GNOME
`wl_pointer::set_cursor` expects a serial number of the last
`wl_pointer::enter` event. However other calls expect latest
observed pointer serial, so this commit tracks both and
use them as required by specification.

Fixes #2273.
2022-05-01 16:21:34 +03:00
Kas
ea09d1d10e Fix embedded NULs in C wide strings returned from Windows API (#2264) 2022-04-30 13:58:51 +02:00
Kas
e7f88588bf Fix assigning the wrong monitor when receiving Windows move events (#2266)
Co-authored-by: kas <exactly-one-kas@users.noreply.github.com>
2022-04-30 13:21:08 +02:00
Kirill Chibisov
ce890c3455 Unify behavior of resizable across platforms
This makes X11 and Wayland follow Windows and macOS, so the size of the
window could be set even though it has resizable attribute set to false.

Fixes #2242.
2022-04-24 23:35:18 +03:00
Kirill Chibisov
cbba00d360 Unify with_app_id and with_class methods
Both APIs are used to set application name. This commit unifies the API
between Wayland and X11, so downstream applications can remove platform
specific code when using `WindowBuilderExtUnix`.

Fixes #1739.
2022-04-20 01:56:56 +03:00
Markus Siglreithmaier
bf366cb99d Add cursor hittest window functionality (#2232)
Co-authored-by: z4122 <412213484@qq.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2022-04-12 19:10:46 +02:00
Dusty DeWeese
142d55ff24 Always send RedrawEventsCleared on iOS
This makes it consistent with the rest of the platforms in winit.
2022-04-11 20:51:21 +03:00
Simon Hausmann
a58400a82c Fix TouchPhase::Ended reporting on Wayland
When all the receive from the compositor is `TouchEvent::Down` and
`TouchEvent::Up` for the same id, we would record the touch position in
the touch_points vector the first time. On `TouchEvent::Up` we'd find it
and report `TouchPhase::Ended` with that location. The next time we
receive `TouchEvent::Down` for the same id, we'd however unconditionally
append a new `TouchPoint` to `inner.touch_points`, with the new
position. On release however we'd find the earlier point and report its
location, which basically means that `TouchPhase::Ended` always and
forever reported the location of the very first touch down event.

Instead, this patch updates an existing touch point location with the
same id on `TouchDown`.

Fixes #1996
2022-04-11 20:13:28 +03:00
Kirill Chibisov
aac28d24ac Force SCTK version to prevent pointer leaking
SCTK versions before 15.4 were leaking pointers when window got closed.
So the more windows you've got the pointers you'll keep around.

Fixes #2248.
2022-04-10 13:42:05 +03:00
Steve Wooster
d624a3e648 Add methods to set ControlFlow operation
This allows downstream users to avoid importing `ControlFlow` from winit.
2022-04-10 04:32:02 +03:00
Kirill Chibisov
c57294b41a On Wayland commit after setting all startup props
The commit without buffer attached should be done after setting all
top level size/application related properties. While c4df7ad7a added
commit after setting decorations, it accounted just for decorations,
however we should account for the min/max size and other attributes.
2022-04-10 03:56:01 +03:00
Kirill Chibisov
485e82dcb1 Add getters for visible, resizeable, etc on X11
This commit adds `Window::is_visible`, `Window::is_decorated`, and
`Window::is_resizable` APIs on X11.
2022-04-10 01:51:54 +03:00
Kirill Chibisov
e8d910ffd3 Add is_resizable and is_decorated on Wayland
This commit brings `is_resizable` and `is_decorated`. Since the client
is responsible for both of them, they could be tracked without deep
syncing with server.
2022-04-07 03:05:11 +03:00
Amr Bashir
ab1f636960 feat(Windows): add skip taskbar methods (#2177) 2022-04-01 20:21:09 +02:00
TÖRÖK Attila
52c4670237 android: Add mapping from NDK Keycode to VirtualKeyCode (#2226) 2022-04-01 18:16:59 +02:00
Benjamin Saunders
2ae12fb0a0 Discourage use of WaitUntil to implement VSync (#2230) 2022-03-31 22:38:02 +02:00
Daniel Müller
6c1d3c4fd8 Fix scale factor calculation when the only monitor is reconnected
The scale factor being sent when the only monitor is disconnected and
reconnected is hard coded to 1.0. That may work by chance, if that's the
scale factor in use currently, but it does not work in the general case.
As a result, clients may end up with wrongly scaled or laid out window
contents after reconnect, as was reported over in
https://github.com/alacritty/alacritty/issues/5703, for example.

The problem was introduced by change 125ee0b, which caused an additional
ScaleFactorChanged event to be sent on monitor reconnect, but got the
scale factor wrong when the only monitor is disconnected and
reconnected.
This change fixes the problem by using the current monitor's scale
factor in this case. The event is still being sent as intended by
125ee0b.

Fixes #2123.
2022-03-31 17:43:48 +03:00
Amr Bashir
08de2b3fc4 feat(Windows): add with_msg_hook (#2213) 2022-03-30 10:30:45 +02:00
Markus Siglreithmaier
945a9e3122 Windows: Remove owned DC context per window (#1910)
The flag is not required for OpenGL and comes with several limitations when used with other style flags
2022-03-26 22:59:13 +01:00
Johan Andersson
6e28ba8927 Fix fullscreen window messaging race on Windows (#2225) 2022-03-26 16:43:13 +01:00
Lucas Kent
7369551c02 Clippy fixes for windows platform (#2131) 2022-03-23 19:08:04 +01:00
Mads Marquart
e22c76b3ac macOS set_ime_position fixes (#2180)
* Use NSView's inputContext instead of creating our own

This means that `set_ime_position` now properly invalidates the character coordinates.

* Make `set_ime_position` robust against moving windows
2022-03-18 14:50:24 +01:00
Mads Marquart
a438091266 Rename internal structs for consistency (#2149)
Proxy -> EventLoopProxy
Id -> WindowId or DeviceId
WindowTarget -> EventLoopWindowTarget
Handle -> MonitorHandle
Mode -> VideoMode
PlatformSpecificBuilderAttributes -> PlatformSpecificWindowBuilderAttributes
SuperWindowId -> RootWindowId
2022-03-18 14:09:39 +01:00
Emil Ernerfeldt
85baf79d17 Reverse horizontal scroll direction (#2105) 2022-03-13 14:22:02 +01:00
Kirill Chibisov
1c68be0631 On Wayland, fix consecutive run_return not polling
If you try to use `EventLoop::run_return` API in a way that you do on
demand polling of events it won't actually poll, since in such strategy
the `ControlFlow::Exit` is sent right before Wayland backend starts to
poll.

This was observed with smithay compositor Anvil which was doing this
particular thing leading to GNOME thinking that app isn't responding,
due to connection not being polled.
2022-03-11 18:15:33 +03:00
Clemens Wasser
b222dde835 Adopt windows-sys (#2057) 2022-03-07 22:58:12 +01:00
Kirill Chibisov
78e5a395da On Wayland, fix resize not propagating properly
On Wayland window size and scaling are double buffered, so winit should
send redraw requested for a client on the next frame as well.
2022-02-28 11:47:38 +03:00
Chris Copeland
7846e6a31e Update Window::is_maximized doc about X11/Wayland
The support for `Window::is_maximized` on X11/Wayland was added in c916eb6,
however the doc comment on the method was stating that it's not supported.
2022-02-28 11:19:16 +03:00
Lucas Kent
b7e7755edd Improve web example (#2115)
* Improve web example

* Implement basic logger into the example webpage

* Repace bash script with xtask

* replace wasm-bindgen-cli with wasm-bindgen-cli-support

* refactor

* Move logic into external crate.

* Remove CI changes

* Review feedback
2022-02-25 12:57:46 +01:00
Markus Røyset
40f48cbeb4 Fix unsafe_op_in_unsafe_fn warning on nightly (#2207) 2022-02-25 12:27:52 +01:00
Nikolai Kuklin
fb8313aa97 Fix typo in deprecation message (#2199) 2022-02-19 16:21:37 +01:00
Amr Bashir
f9643917d3 feat: add Window::is_visible (#2169)
* feat: add `Window::is_visible`

* use `Option<bool>`

* update doc

* move it right after `set_visible`
2022-02-17 19:44:14 +01:00
Mads Marquart
ac1c9b1218 Fix Android CI (#2197)
Fixes https://github.com/rust-windowing/winit/issues/2196 until a better solution using `ndk-context` is possible
2022-02-17 18:50:18 +01:00
Amr Bashir
daf0d6b9a7 feat: add Window::is_resizable (#2171)
* feat: add `Window::is_resizable`

* move it right after `set_resizable`
2022-02-17 16:03:17 +01:00
Amr Bashir
fa14863284 feat: add Window::is_decorated (#2172)
* feat: add `Window::is_decorated`

* move it right after `set_decorations`
2022-02-17 14:31:13 +01:00
Mads Marquart
cd9ec0afc7 Bump dev-dependencies (#2181)
* Update image 0.23 -> 0.24 and simple_logger 1.9 -> 2.1

* Reduce feature set in `image` dev-dependency
2022-02-17 14:13:32 +01:00
Mads Marquart
f3f6f1008a Add EventLoopBuilder
This commit adds an `EventLoopBuilder` struct to simplify event loop
customization and providing options to it upon creation. It also
deprecates the use of `EventLoop::with_user_event` in favor of the same
method on new builder, and replaces old platforms specific extension
traits with the new ones on the `EventLoopBuilder`.
2022-02-17 00:09:03 +03:00
Artúr Kovács
0e52672f4a On X11, Fix for repeated event loop iteration when ControlFlow was Wait (#2155)
* On X11, Fix for repeated event loop iteration
when `ControlFlow` was `Wait`

* ControlFlow::Poll now runs continously as should
2022-02-04 12:13:04 +01:00
Lassi Pulkkinen
bc1dc1fd63 On Wayland, report unaccelerated mouse deltas in DeviceEvent::MouseMotion 2022-02-03 13:46:29 +03:00
David Ackerman
f93f2c158b Bump versions of ndk to 0.6, ndk-sys to 0.3, ndk-glue to 0.6 (#2163) 2022-02-01 00:14:36 +01:00
Mads Marquart
9229e2d88b macOS RAII trace guards (#2150)
* Add TraceGuard to make tracing simpler

* Add SharedStateMutexGuard to make tracing simpler

* Add trace_scope macro

* Add missing let binding in trace_scope!
2022-01-23 21:35:26 +01:00
Mads Marquart
51bb6b751e Remove WINIT_LINK_COLORSYNC (no longer needed) (#2136)
Since https://github.com/rust-windowing/winit/pull/2078 we link to `ApplicationServices`, which contains the `CGDisplayCreateUUIDFromDisplayID` symbol in all versions.
2022-01-23 20:38:08 +01:00
Mads Marquart
2cc87cab65 Update changelog guidelines to prevent conflicts from blocking PRs (#2145)
* Update changelog guidelines to prevent conflicts from blocking PRs

As per consensus in https://github.com/rust-windowing/winit/issues/2135

* Add note about whitespace in changelog

* Add note about maintainer creating new tag
2022-01-23 13:55:33 +01:00
Benjamin Brittain
7cd273ae58 Make WindowBuilder's with_app_id method more ergonomic 2022-01-22 03:42:46 +03:00
Lucas Kent
001fb7ef60 Clippy fixes macos platform (#2133) 2022-01-16 01:14:59 +01:00
Lucas Kent
cf4660841a Update to Rust 2021 Edition (#2114) 2022-01-13 06:59:57 +01:00
multisn8
a52f755ce8 Add exit code to ControlFlow::Exit (#2100)
* Add exit code to control flow and impl on linux

* Fix examples to have an exit code

* Fix doc examples to use an exit code

* Improve documentation wording on the exit code

* Add exit code example

* Add exit code on windows

* Change i32 as exit code to u8

This avoids nasty surprises with negative numbers on some unix-alikes
due to two's complement.

* Fix android usages of ControlFlow::Exit

* Fix ios usages of ControlFlow::Exit

* Fix web usages of ControlFlow::Exit

* Add macos exit code

* Add changelog note

* Document exit code on display server disconnection

* Revert "Change i32 as exit code to u8"

This reverts commit f88fba0253.

* Change Exit to ExitWithCode and make an Exit const

* Revert "Add exit code example"

This reverts commit fbd3d03de9.

* Revert "Fix doc examples to use an exit code"

This reverts commit daabcdf9ef.

* Revert "Fix examples to have an exit code"

This reverts commit 0df486896b.

* Fix unix-alike to use ExitWithCode instead of Exit

* Fix windows to use ExitWithCode rather than Exit

* Silence warning about non-uppercase Exit const

* Refactor exit code handling

* Fix macos Exit usage and recover original semantic

* Fix ios to use ExitWithCode instead of Exit

* Update documentation to reflect ExitWithCode

* Fix web to use ExitWithCode when needed, not Exit

* Fix android to use ExitWithCode, not Exit

* Apply documenation nits

* Apply even more documentation nits

* Move change in CHANGELOG.md under "Unreleased"

* Try to use OS error code as exit code on wayland
2022-01-11 01:23:20 +01:00
Mads Marquart
2a2abc4843 Fix some invalid msg_send! usage (#2138)
* Fix some invalid msg_send! usage

* Make the implementation of superclass clearer
2022-01-10 21:39:17 +01:00
Lucas Kent
8af222c1e3 Remove entries from PULL_REQUEST_TEMPLATE.md that are now covered by CI. (#2126) 2022-01-05 16:23:56 +01:00
Artúr Kovács
d3e6949007 Release 0.26.1 (#2125) 2022-01-05 15:38:59 +01:00
Mads Marquart
a033b25ecb Make CI run on changes to non-code files as well (#2130)
The repository is configured such that specific checks are required to pass before merging; since CI doesn't run on PRs that don't change code, they can't be merged without administrator intervention.

Also, while this definition is currently correct, we might in the future change something so that changes to other files (like markdown files) really should be run through CI.

And example of that could be:
```rust
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
extern "C" {}
```
2022-01-05 15:01:17 +01:00
Mads Marquart
39dd30c239 Fix CGDisplayCreateUUIDFromDisplayID linking (again) (#2078)
See also https://github.com/rust-windowing/winit/pull/1626.

The `cocoa` crate links to AppKit, which made the symbol `CGDisplayCreateUUIDFromDisplayID` from ApplicationServices/ColorSync (which AppKit uses internally) available to us on macOS 10.8 to 10.13.

However, this does not work on macOS 10.7 (where AppKit does not link to ColorSync internally). Instead of relying on this, we should just link to ApplicationServices directly.
2022-01-05 14:38:24 +01:00
TotalKrill
c5c99d2357 Add cursor grab for web target (#2025)
* Add cursor grab

* Update feature matrix, changelog and platform information

* Add proper error propagation

* Remove "expect" from fallible code

    code would crash if handling pointer capture outside of winit on
    every mouse click

    we swallow the error since we could not think of a case where this
    would fail in a way that would want to handle that it fails

* Remove unnecessary implementation comment

Co-authored-by: Will Crichton <wcrichto@cs.stanford.edu>
2022-01-05 11:13:46 +01:00
Shuoliu Yang
25ff30ee8c Fix transparent window crash on Windows 11 (#2121)
Maybe the transparent setting in WM_NCCREATE on Windows 11 will cause a block when calling DwmEnableBlureBehindWindow and will crash. Puts them into WM_CREATE and it works.
2022-01-03 13:54:31 +01:00
Artúr Kovács
6b250a74f8 Revert "Add composition event on macOS (#1979)" (#2119)
This reverts commit 8afeb910bd.

Reverting because this change made Pinyin input unusable
(only latin characters showed even after selecting the
desired Chinese character)
2022-01-02 22:01:51 +01:00
Lucas Kent
5331397c6c Provide examples for all window position/size setters (#2107) 2022-01-02 04:56:13 +01:00
Lucas Kent
0b39024133 Fix clippy warnings (#2108)
* Fix clippy warnings

* review feedback.
2022-01-01 03:00:11 +01:00
Mika
438d286fd5 Add new mappings for numlock, numpadenter and numpadcomma on X11 (#1937)
* Add X11 mappings

* Update CHANGELOG.md

Co-authored-by: Markus Røyset <maroider@protonmail.com>

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-12-11 03:14:31 +01:00
Philippe Renon
18a61f1058 Fix warnings (#2076)
* examples: Fix unused `Result` that must be used when initializing console_log

* examples: Fix unused imports

* Fix unread name field warning in linux x11 ime InputMethod struct

* Fix unread name field warning in linux x11 Device struct

* Ignore unread field warning in macos/ios MonitorHandle struct

* ci: Add `--deny warnings` to `RUSTFLAGS`
2021-12-11 03:02:48 +01:00
Markus Røyset
20d012ae3f Update contact links (#2079) 2021-12-07 11:27:30 -08:00
Mads Marquart
efc54ab8ba Add note about cargo update to the raw-window-handle changelog update (#2086) 2021-12-06 12:53:56 -08:00
Kirill Chibisov
ea1c031b54 Release 0.26.0 version 2021-12-01 14:43:38 +03:00
Mads Marquart
11a44081df macOS move impl details of platform into platform_impl 2021-12-01 14:20:56 +03:00
Mads Marquart
5eb9c9504b Update raw-window-handle to 0.4.1 (#1957)
* Update raw-window-handle to `0.4.2`

See:
- https://github.com/rust-windowing/raw-window-handle/issues/72
- https://github.com/rust-windowing/raw-window-handle/pull/73
- https://github.com/rust-windowing/raw-window-handle/pull/74

* Clean up raw_window_handle functions a bit
2021-11-30 17:50:23 +01:00
Adrien Bennadji
29a078f65c bump ndk dependencies to 0.5 (#2071) 2021-11-24 16:56:57 +01:00
Alphyr
be61ca13fe On X11, update 'mio' to 0.8 2021-11-20 03:42:23 +03:00
mahkoh
e9d5b2007a On X11, don't panic when getting EINTR
Fixes #1972.
2021-11-20 03:24:45 +03:00
Ian Hobson
f2de8475fc Show the menu bar in borderless fullscreen on macOS (#2053)
* In MacOS, only disable menu bar in exclusive fullscreen

* Save and restore fullscreen options in set_fullscreen

* Don't always cache presentation options when entering exclusive fullscreen

This commit caches presentation options when entering exclusive fullscreen
only if we're coming from borderless fullscreen.

Then, when transitioning from exclusive -> borderless, if no cached presentation
options are present, then the default borderless options are applied.

This fixes the menu bar being unavailable when taking the following path:
[not fullscreen] -> [exclusive fullscreen] -> [borderless fullscreen].

Without this commit, the presentation options from [not fullscreen] were being
cached and then applied to [borderless fullscreen].

* Restore the window level when switching to exclusive fullscreen

The hack of using `CGShieldingWindowLevel() + 1` in borderless fullscreen needs
to be undone when switching from [borderless] -> [exclusive] fullscreen,
otherwise there are menu bar glitches when following a path through
[borderless] -> [exclusive] -> [borderless] modes.

Now, this might appear to conflict with the 'always on top' feature which uses
the 'floating window' level, but this feature appears to be broken anyway when
entering and exiting fullscreen with an always-on-top window. So, rather than
introducing logic to attempt to restore to the 'floating' level here, I think
it's better to do the simple thing for now and then introduce logic for
always-on-top windows when fixing the overall fullscreen behaviour.

* Update the changelog

Co-authored-by: Ehden Sinai <ehdens@gmail.com>
Co-authored-by: Francesca Lovebloom <francesca@brainiumstudios.com>
2021-11-19 13:05:36 -08:00
Markus Siglreithmaier
3ecbea3c39 Windows: Split window initialization across NCCREATE and CREATE (#2062)
* Refactor window initialization by splitting NCCREATE and CREATE related tasks.

Fixes issue with invisible owner windows.

* address review comments

* Update src/platform_impl/windows/event_loop.rs

Co-authored-by: Markus Røyset <maroider@protonmail.com>

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-11-17 18:33:44 +01:00
cmeissl
c4df7ad7a5 On Wayland, commit the window surface after setting the decoration mode
Fixes #2064.
2021-11-15 01:23:54 +03:00
Emil Ernerfeldt
387567a917 macOS: Fix native file dialogs freezing the event loop (#2027)
* macOS: Ignore all events while in the callback

Previously all native dialogs, such as [rfd](https://github.com/PolyMeilex/rfd), would cause the event loop (event_loop.run) to freeze.

* Update changelog

* spelling

* Fix merge mistake

* Add link to issue in the code

Co-authored-by: Poly <marynczak.bartlomiej@gmail.com>
2021-11-04 11:37:02 -07:00
Markus Siglreithmaier
cfbe8462cc Windows: Increase wait timer resolution (#2007)
Windows: Increase wait timer resolution for more accurate timing when using `WaitUntil`.
2021-11-02 21:51:39 +01:00
Markus Siglreithmaier
5f4df54895 Android: Bump ndk/ndk-glue version (#2047) 2021-11-02 18:54:59 +01:00
Kirill Chibisov
ed698f2462 On Wayland, add wayland-dlopen feature to use dlopen
While winit was always using dlopen for opening system libs, it
provides a way now to disable dlopen feature helping with linking
on some targets.

Fixes #2037.
2021-10-31 17:06:00 +03:00
Kirill Chibisov
b4774861db On X11, if RANDR based scale factor is higher than 20 reset it to 1
Some video drivers could set display metrics to odd values, which can result in
extra large scale factors (e.g. winit is sending 720 for 5k screen on nvidia
binary drivers), so let's just drop them to prevent clients from using them.
The value 20 was picked, because the DPR for 8k @ 5 inch is ~18.36.

Fixes #1983.
2021-10-30 23:47:31 +03:00
Alexis Hildebrandt
9768f73bb7 Update smithay-client-toolkit
Fixes libxcbcommon linking on OpenBSD by using pkg-config when
building without dlopen feature. For details see [1].

[1] - https://github.com/Smithay/client-toolkit/pull/198
2021-10-30 22:35:36 +03:00
Arthur Kaukal Valladares
805249e27e Android: Window::config now initially returns accurate data. (#2021)
Initialize Android's static 'CONFIG' from NativeActivity's Asset Manager
2021-10-26 23:28:28 +02:00
Markus Siglreithmaier
5f24c40d05 Fix wasm CI failure (#2024)
* Fix wasm ci

* remove cargo-web step
2021-10-26 11:05:01 -07:00
Philippe Renon
1b3b82a3c1 Clippy fixes (#2011)
* windows: bump winapi version

* windows: address dark_mode FIXMEs

use now available winapi structures

* clippy: fix clippy::upper_case_acronyms warnings

* clippy: fix needless_arbitrary_self_type warnings

* clippy: fix clone_on_copy warnings

* clippy: fix unnecessary_mut_passed warnings

* clippy: fix identity_op warnings

* clippy: fix misc warnings

* prefix rustdoc lints with rustdoc::

the prefix was introduced in Rust 1.52

* windows: silence file_drop_handler is never read warning

* clippy: fix from_over_into warnings

and a bit of naming simplification

* clippy: fix missing_safety_doc warnings

* make dummy() functions const
2021-08-30 19:40:02 +02:00
Davester47
9e72396709 Fix X11 memory leak and remove mio-misc (#1987)
* Fix X11 memory leak and remove mio-misc

I also fixed a couple of clippy lints.
Fixes #1984

* Send the redraw event before waking up the main event

* Use .map instead of a match, and remove comments saved by git

* Remove unnecessary pub keywords on `WakeSender` in x11/mod.rs
2021-08-24 12:38:56 +02:00
oxalica
125ee0b446 Emit ScaleFactorChanged event on monitor reconnect (#1963)
When disconnect the only monitor, scale factor is reset to 1.0. We need
to set it back when the monitor is reconnected.

We previously assume current window must be on an existing monitor, but
that's not true in case of reconnecting the only one monitor.
2021-08-24 12:36:13 +02:00
sandmor
3bfb580d7a Fix potential bug (#2009)
* polish and failed to find visual warning

* improvement
2021-08-24 12:35:11 +02:00
sandmor
b54d47796d Fix transparency on X11 (#2006)
* find transparent in x11

* remove debug hooks

* update changelog

* polish and failed to find visual warning
2021-08-22 20:45:24 +02:00
Kirill Chibisov
b5d0d6ff3e On Wayland, implement 'request_user_attention'
This commit implements 'request_user_attention' on Wayland with
new 'xdg_activation_v1' protocol.
2021-08-17 07:59:57 +03:00
Kirill Chibisov
c9520deef8 Update smithay-client-toolkit to 'v0.15.0'
This commit also drops 'Theme' trait with its support types
in favor of 'FallbackFrame' meaning that winit will use some
predefined frame for the time being, since porting 'ConceptFrame'
will require adding font rendering librarires right into winit,
which is not desired.

Fixes #1889.
2021-08-15 22:31:59 +03:00
Steven Bosnick
ceab0f8c40 On Wayland, log error for failure to set cursor
The inability to set the cursor using any of the named cursor files
likely indicates an error in the system on which we are running.
'WinitPointer::set_cursor' also does not have any way of returning an
error so just log the error to assist users in diagnosing the problem.

Fixes: #1988.
2021-08-15 22:05:14 +03:00
Markus Siglreithmaier
b87757c552 Fix Window visibility regression (#1994)
On Windows, set windows visible on init before position update

Ensure that the style change is correctly applied, triggering the necessary events.
2021-08-12 18:57:07 +02:00
Nuno Ribeiro
1972eb952d Adds Android winit<->ndk_glue version match table (#1993)
* Adds Android winit<->ndk_glue version match table

* Fixes justification

* Adds crosses

* Address review and instead of a m:n table it shows a 1:1 version compatibility

* Addresses review
2021-08-11 14:28:49 -07:00
Osspial
f92803d80e Prevent ghost window from showing up on taskbar (#1977)
Add WS_EX_TOOLWINDOW to event target window
2021-08-11 20:02:40 +02:00
Yusuke Kominami
8afeb910bd Add composition event on macOS (#1979)
* Enable to show text when IME is active

* Remove unnecessary variable

* Enable to use IME

* fmt

* Remove println! for debug

* Fix handling of utf-8 string

* clear_marked_text should be rust function, not member function

* Store state information in ViewState

* Remove unnecessary function

* format

* Remove mut

* format

* Remove duplicate marked text

* Remove unused `is_preediting` field

Co-authored-by: Artúr Kovács <kovacs.artur.barnabas@gmail.com>
2021-08-09 11:14:13 +02:00
Sven Niederberger
f16ed98af4 On X11 and Wayland, fx window resize cursor orientation
Fixes #1912.
2021-08-01 11:19:00 +03:00
Aidan Dang
2a9916103b On Wayland, load "hand2" and "hand1" cursor icons for CursorIcon::Hand 2021-08-01 11:16:02 +03:00
Markus Røyset
63ad47a7bf Remove window subclassing (#1933)
* Remove window subclassing

* Always call `DefWindowProcW` when we don't process a message

* Improve window initialization

Note that the error path in `init` is kind of cursed at the moment.

* Rename `ThreadMsgTargetCallbackData` to `ThreadMsgTargetData`

* Simplify window initialization

* Fix compilation on 32-bit targets

* Simplify the creation of the event target window

* Use `.clone()` rather than `Rc::clone()`

* Use concrete types for args to `SetWindowLongPtrW`

On 32-bit targets, `SetWindowLongPtrW` is an alias to `SetWindowLongW`,
which returns `LONG` (`i32`) rather than `LONG_PTR` (`isisze`).

* Minor comment adjustments
2021-07-16 12:40:48 +02:00
jim jammer
27e6548343 macOS: Remove is_key_down from ViewState (#1489)
Fixes #1488.

`is_key_down` was only set to true when `insertText` was called.
Therefore `is_key_down` was actually meant to store whether the most
recently pressed key generated an `insertText` event, at which, winit
produces a `ReceivedCharacter`. The issue is that `insertText` is *not*
called for "key repeat", but winit wants to send `ReceivedCharacter`
events for "key repeat" too. To solve this, the `is_key_down` variable
was then checked in the `key_down` function to determine whether it was
valid to produce repeated `ReceivedCharacter` events during "key
repeat". However this check is not needed since `ReceivedCharacter` must
always be called if the key event has a non-empty `characters` property.

Furthermore `is_key_down` didn't actually store whether the previously
pressed character had an `insertText` event, because it was incorrectly
set to false on every "key up". This meant that if two keys were pressed
consecutively and then the first was released, then `is_key_down` was
set to false even if the most recent keypress did actually produce an
`insertText`.

Update changelog.
2021-07-13 17:38:01 +02:00
Markus Røyset
8c91986dd3 Remove libc dependency on non-linux platforms (#1976) 2021-07-13 17:27:47 +02:00
Aden Haussmann
5a65347c4e Changed description of window scale factor in Events (#1834)
* changed description of window scale factor in Events

* Update src/dpi.rs

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Fix intra-doc link

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-06-16 09:24:49 +02:00
Francesca Lovebloom
635180c8be Update Hall of Champions (#1959)
* Lionize Aubrey

* Lionize Victor

* Lionize Freya

* Stylization consistency
2021-06-14 13:55:13 -07:00
Onirik79
019ce9862f Fix typo in events documentation (#1960) 2021-06-13 14:26:20 +02:00
Artúr Kovács
c7f46876a7 Drop the event callback before exiting on macOS (#1954)
* Drop the event callback before exiting

* Update the changelog

* Apply suggestion from review

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Apply review suggestions

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-06-13 14:25:06 +02:00
garasubo
c916eb6137 On X11 and Wayland, add is_maximized support
Fixes #1845.

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2021-06-10 10:43:27 +03:00
Tilmann Meyer
67cca71524 Implement Window::request_redraw on Android (#1953) 2021-06-05 12:47:08 +02:00
i509VCB
1eff7ae004 Document how main_thread_id for Windows works (#1951) 2021-06-05 12:46:44 +02:00
Mads Marquart
982ad46c83 Use objc's autoreleasepool instead of manually with NSAutoreleasePool (#1936)
Ensures the pools are released even if we panic
2021-05-27 17:38:41 +02:00
Markus Røyset
657b4fd59e Remove support for stdweb (#1941)
* Remove support for `stdweb`

* Expunge `stdweb`; make `web-sys` the default

* Mark this change as a breaking change

* Re-insert accidental removal of space

* Use the correct cargo feature syntax

* Re-add some `cfg` attributes

* Remove `web-sys` feature from CI
2021-05-24 10:06:21 -07:00
Max de Danschutter
b371b406d5 Implemented focus_window (#1944) 2021-05-19 18:39:53 +02:00
Artúr Kovács
91591c4e94 Release 0.25.0 (#1939) 2021-05-15 19:17:08 +02:00
Luis Wirth
078b9719cc implement mint conversions (#1930)
Implement conversions for [mint](https://docs.rs/mint) (math interoperability standard types).

- `impl From<mint::Point2> for {Physical, Logical}Position`
- `impl From<{Physical, Logical}Position> for mint::Point2`

- `impl From<mint::Vector2> for {Physical, Logical}Size`
- `impl From<{Physical, Logical}Size> for mint::Vector2`
2021-05-09 00:56:52 +02:00
Markus Røyset
41d9826ee9 Fix incorrect changelog entry for #1524 (#1916)
* Fix incorrect changelog entry for #1524

* Fix incorrect changelog entry for #1524
2021-05-04 11:00:11 -07:00
Artúr Kovács
0152508a39 Allow preventing the creation of the default menu (#1923)
* Allow preventing the creation of the default menu

* Use more grammar friendly naming

* Update the changelog
2021-04-30 13:34:50 +02:00
Artúr Kovács
cdeb1c3828 Require setting the activation policy on the event loop (#1922)
* Require setting the activation policy on the event loop

* Run cargo fmt

* Update changelog

* Fixes and tweaks from review

* Correct comment in app_state.rs

Co-authored-by: Mads Marquart <mads@marquart.dk>
2021-04-30 11:31:28 +02:00
z4122
0986fae066 Add accept_first_mouse for macOS (#1882)
* feat: add accept_first_mouse for macOS

* Update the changelog

Co-authored-by: Artur Kovacs <kovacs.artur.barnabas@gmail.com>
2021-04-30 11:30:09 +02:00
Mads Marquart
277515636d MacOS: Only activate after the application has finished launching (#1903)
* MacOS: Only activate after the application has finished launching

This fixes the main menu not responding until you refocus, at least from what I can tell - though we might have to do something similar to https://github.com/linebender/druid/pull/994 to fix it fully?

* MacOS: Remove activation hack

* Stop unnecessarily calling `makeKeyWindow` on initially hidden windows

You can't make hidden windows the key window

* Add new, simpler activation hack

For activating multiple windows created before the application finished launching
2021-04-29 19:49:17 +02:00
Mads Marquart
45aacd8407 Use initialFirstResponder instead of makeFirstResponder (#1920)
As recommended by the documentation: https://developer.apple.com/documentation/appkit/nswindow/1419366-makefirstresponder?language=objc
2021-04-29 12:52:41 +02:00
Casper Rogild Storm
e8cdf8b092 Add MacOS menu (#1583)
* feat: added MacOS menu

* fix: ran fmt

* extracted function into variable

* idiomatic formatting

* Set the default menu only during app startup

* Don't set the activation policy in the menu init

Co-authored-by: Artur Kovacs <kovacs.artur.barnabas@gmail.com>
2021-04-24 16:56:46 +02:00
Artúr Kovács
1c4d6e7613 Correct the false documentation about macOS dpi (#1905) 2021-04-13 21:31:41 +02:00
LoganDark
04b4e48265 Derive Default, Hash, and Eq for some dpi types (#1833)
* Derive more things

* Changelog entry
2021-04-12 23:12:39 +02:00
Rodrigodd
dabcb1834d On Windows, allow the creation of popup window (#1895)
Add with_owner_window to WindowBuilderExtWindows.
Add set_enable to WindowExtWindows.
2021-04-10 15:47:19 +02:00
Mads Marquart
629cd86c7c Stop calling NSApplication.finishLaunching on window creation (#1902)
This is called internally by NSApplication.run, and is not something we should call - I couldn't find the reasoning behind this being there in the first place, git blame reveals c38110cac from 2014, so probably a piece of legacy code.

Removing this fixes creating new windows when you have assigned a main menu to the application.
2021-04-07 22:24:49 +02:00
Xiaopeng Li
ba704c4eb4 Mac: Redraw immediately to prevent shaking on window resize (#1901)
* Mac: Redraw immediately to prevent shaking on window resize

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: 李小鹏 <lixiaopeng.jetspark@bytedance.com>
Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-04-06 09:22:38 +02:00
Aleksandr Ovchinnikov
0487876826 On macOS, wake up the event loop immediately when a redraw is requested. (#1812)
We allow to have RunLoop running only on the main thread. Which means if
we call Window::request_redraw() from other the thread then we have to
wait until some other event arrives on the main thread. That situation
is even worse when we have ControlFlow set to the `Wait` mode then user
will not ever render anything.
2021-04-06 09:19:25 +02:00
Markus Røyset
ca9c05368e Fix CI warnings (#1898)
* Fix CI warnings

* Use the panic! macro rather than format! + panic_any
2021-03-30 21:27:32 +02:00
Michal Srb
0d634a0061 Add WindowBuilder::with_outer_position (#1866) 2021-03-25 19:18:51 +01:00
Norbert Nemec
86748fbc68 Fix communication of fractional RI_MOUSE_WHEEL events (Windows) (#1877) 2021-03-11 22:08:29 +01:00
Artúr Kovács
599477d754 Only try publishing when a version tag is pushed (#1876) 2021-03-10 14:10:35 -08:00
daxpedda
889258f538 Upgrade mio to 0.7 (#1875)
* Upgrade `mio` to 0.7
Replaced `mio-extras` with `mio-misc`.

* Possible improvement

* Remove leftover

* Wrong rebase

* Fix typo
2021-03-09 09:50:15 -07:00
Artúr Kovács
ffe2143d14 Fix for closure-captured values not being dropped on panic (#1853)
* Fix for #1850

* Update changelog

* Fix for compilation warnings

* Apply suggestions from code review

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Improve code quality

* Change Arc<Mutex> to Rc<RefCell>

* Panicking in the user callback is now well defined

* Address feedback

* Fix nightly warning

* The panic info is now not a global.

* Apply suggestions from code review

Co-authored-by: Francesca Lovebloom <francesca@brainiumstudios.com>

* Address feedback

Co-authored-by: Markus Røyset <maroider@protonmail.com>
Co-authored-by: Francesca Lovebloom <francesca@brainiumstudios.com>
2021-03-08 19:56:39 +01:00
daxpedda
98470393d1 Add dragging window with cursor feature (#1840)
* X11 implementation.

* Introduce example.

* Wayland implementation.

* Windows implementation.

* Improve Wayland seat passing.

* MacOS implementation.

* Correct windows implementation per specification.

* Update dependency smithay-client-toolkit from branch to master.

* Fixed blocking thread in windows implementation.

* Add multi-window example.

* Move Wayland to a different PR.

* Fix CHANGELOG.

* Improve example.

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Rename `set_drag_window` to `begin_drag`.

* Improve example.

* Fix CHANGELOG.

* Fix CHANGELOG.

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Rename to `drag_window`.

* Fix typo.

* Re-introduce Wayland implementation.

* Fixing Wayland build.

* Fixing Wayland build.

* Move SCTK to 0.12.3.

Co-authored-by: Markus Røyset <maroider@protonmail.com>
2021-03-07 10:43:23 +01:00
Artúr Kovács
4192d04a53 Fix seg-fault when using without a window (#1874)
* Fix seg-fault when using without a window #1869

* Update changelog
2021-03-06 11:17:23 +01:00
leafjolt
3571dcd68c Update window.rs (#1871) 2021-02-27 21:25:26 +01:00
mmacedo
952edcb804 Android: Add KeyEvent handling (#1839) 2021-02-23 22:35:38 +01:00
Axel Cocat
10a94c0794 Fix Windows' try_theme returning Theme::Dark when new theme is light (#1861) 2021-02-20 00:06:12 +01:00
Björn Steinbrink
dd32ace9ab Restore the ability to have fully transparent windows on Windows (#1815)
* Restore the ability to have fully transparent windows on Windows

Besides its original purpose, commit 6343059b "Fix Windows transparency
behavior to support fully-opaque regions (#1621)" also included some
changes considered cleanups, one of them was:

* Remove the `CreateRectRgn` call, since we want the entire window's region to
  have blur behind it, and `DwnEnableBlurBehindWindow` does that by default.

But the original code actually disabled the blur effect for the whole
window by creating an empty region for it, because that allows for the
window to be truely fully transparent. With the blur effect in place,
the areas meant to be transparent either blur the things behind it
(until Windows 8) or are darkened (since Windows 8). This also means
that on Windows 8 and newer, the resulting colors are darker than
intended in translucent areas when the blur effect is enabled.

This restores the behaviour from winit <0.24 and fixes #1814.

Arguably, one might want to expose the ability to control the blur
region, but that is outside the scope of this commit.

* Remove useless WS_EX_LAYERED from transparent windows on Windows

`WS_EX_LAYERED` is not supposed to be used in combination with
`CS_OWNDC`. In winit, as it is currently used, `WS_EX_LAYERED` actually
has no effect at all. The only relevant call is to
`SetLayeredWindowAttributes`, which is required to make the window
visible at all with `WS_EX_LAYERED` set, but is called with full
opacity, i.e. there's no transparency involved at all.

The actual transparency is already achieved by using
`DwmEnableBlurBehindWindow`, so `WS_EX_LAYERED` and the call to
`SetLayeredWindowAttributes` can both be removed.
2021-02-17 13:50:24 +01:00
Will Crichton
7e0c6ee097 Add DeviceEvent::MouseMove on web platform to support pointer lock (#1827)
* Add DeviceEvent::MouseMove on web platform to support pointer lock

* Update changelog

* Add support for stdweb too

* Add mouse_delta to stdweb

* Remove reference to pointer lock
2021-02-16 17:50:46 -05:00
Ssaely
b1be34c6a0 fix cursor blinking when clicking decorations bar on Windows (#1852) 2021-02-06 21:10:36 +01:00
Imberflur
b9307a9967 Change linking of CGDisplayCreateUUIDFromDisplayID on macos (#1626)
* Link CGDisplayCreateUUIDFromDisplayID through ColorSync instead of CoreGraphics

* Conditionally link through ColorSync only if WINIT_LINK_COLORSYNC is set
to true

* Document new macos env var in README
2021-02-05 08:58:55 +01:00
Mads Marquart
b1d353180b Add ability to assign a menu when creating a window on Windows (#1842) 2021-02-04 22:26:33 +01:00
Marijn Suijten
bd99eb1347 Android: Bump ndk/ndk-glue to 0.3 and use constants for event ident (#1847)
Following the changes in [1] this bumps ndk and ndk-glue to 0.3 and uses
the new constants. The minor version has been bumped to prevent
applications from running an older winit (without #1826) with a newer
ndk/ndk-glue that does not pass this `ident` through the `data` pointer
anymore.

[1]: https://github.com/rust-windowing/android-ndk-rs/pull/112
2021-01-30 19:43:26 +01:00
Mads Marquart
f79c01b0cf Fix HINSTANCE returned by raw_window_handle on 64 bit Windows (#1841) 2021-01-28 18:51:49 +01:00
Simas Toleikis
3f1e09ec0e Add Window::is_maximized method (#1804) 2021-01-27 19:01:17 +01:00
Markus Røyset
05125029c6 On Windows, fix deadlock caused by mouse capture (#1830)
The issue was caused by calling SetCapture on a window which already
had the capture. The WM_CAPTURECHANGED handler assumed that it would
only run if the capture was lost, but that wasn't the case. This made
the handler to try to lock the window state mutex while it was already
locked.

The issue was introduced in #1797 (932cbe4).
2021-01-19 17:41:02 +01:00
Marijn Suijten
05fe983757 android: Use event identifier instead of userdata pointer (#1826)
ndk-glue currently sets both the `ident` field and user-data pointer to
`0` or `1` for the event pipe and input queue respectively, to tell
these sources apart. While it works to reinterpret this `data` pointer
as integer identifier it shouldn't be abused for that, in particular
when one may wish to provide extra information with an event in the
future; then the `data` field is used as pointer (or abused as abstract
value) for that.
2021-01-13 23:02:55 +01:00
alula
d1a7749df5 Android: Do not mark unhandled events as handled. (#1820) 2021-01-12 08:25:56 +01:00
Markus Røyset
9d63fc7ca0 On Windows, set the cursor icon when the cursor first enters a window (#1807) 2021-01-05 17:39:13 +01:00
Markus Røyset
38fccebe1f On Windows, change the default window size (#1805) 2020-12-20 17:59:46 +01:00
Markus Røyset
c05952b813 On Windows, improve handling of window destruction (#1798) 2020-12-20 12:54:42 +01:00
Samuel
932cbe40bf On Windows, fix bug causing mouse capture to not be released. (#1797) 2020-12-15 07:31:13 +01:00
relrelb
39573d65d0 Windows: Preserve minimized/maximized state in fullscreen (#1784) 2020-12-13 19:06:53 +01:00
Kirill Chibisov
6db308f1e9 Release 0.24.0 2020-12-10 19:12:46 +03:00
Viktor Zoutman
6f70fd90b9 Windows: Changed thread_event_target_callback's WM_DESTROY to WM_NCDESTROY (#1780) 2020-12-10 12:09:08 +01:00
moko256
db038d943c On Windows, implement 'Window::set_ime_position' with IMM API 2020-12-09 23:16:59 +03:00
Kirill Chibisov
c5620efc9c On Wayland, don't drop extra mouse buttons
This commit forwards "unknown" Wayland mouse buttons downstream via
'MouseButton::Other'. Possible values for those could be found in
<linux/input-event-codes.h>.

Also, since Wayland just forwards buttons from the kernel, which are
'u16', we must adjust 'MouseButton::Other' to take 'u16' instead of
'u8'.
2020-12-09 23:11:25 +03:00
Marnix Kuijs
8fb7aa5cef Android: Improved multi-touch (#1783)
* Improved multi-touch

* Update feature matrix

* Generate cancelled events for all pointers

* Changed back features matrix layout

* Reduced code duplication

* Updated changelog

* Revert changelog update
2020-12-02 12:13:42 -08:00
Viktor Zoutman
6ddee9a8ac Ability to force a theme on Windows (#1666) 2020-11-30 19:04:26 +01:00
Max de Danschutter
5700359a61 Android: support multi-touch (#1776) 2020-11-28 17:41:11 +01:00
Max de Danschutter
0861a353d6 Add 'request_user_attention' to Window
This commit introduces a cross platform way to request a user attention
to the window via a 'request_user_attention' method on a Window struct.
This method is inspired by macOS's 'request_user_attention' method and
thus reuses its signature and semantics to some extent.
2020-11-27 05:03:08 +03:00
Philippe Renon
f79efec7ef Fix deprecation warning in the window icon example 2020-11-26 00:20:35 +00:00
Viktor Zoutman
77d5d20391 Windows: Delayed Message Boxes Fix. (#1769) 2020-11-24 23:05:29 +01:00
Kirill Chibisov
165e51d850 On Wayland, increase default font size in CSD
This commit increased default font size from 11 to 17 making it
identical to the one SCTK is using under the hood, since it's more
readable.
2020-11-22 01:53:56 +03:00
Max de Danschutter
1c38f113b3 Remove println call from Android's eventloop 2020-11-19 17:56:24 +00:00
msiglreith
66859607a3 Rename desktop eventloop extensions to run_return extension (#1738) 2020-11-12 20:49:44 +01:00
Wladimir J. van der Laan
edf396b1a4 On Wayland, add missing mappings for numpad arrows
The mappings for 'keysyms::XKB_KEY_KP_{Up,Down,Left,Rigt}' were missing making the arrow keys on the numpad not sending proper 'VirtualKeyCode's.
2020-11-11 00:55:29 +03:00
Murarth
cbeb51b436 X11: Fix multiple RedrawRequested events per event loop iteration (#1758)
* X11: Fix multiple RedrawRequested per event loop iteration

* Prevent infinite loop
2020-11-07 11:46:37 -07:00
Murarth
45e4fd6ec1 X11: Fix request_redraw not waking the event loop (#1756) 2020-11-05 16:42:03 -07:00
Mikko Lehtonen
3a077ff211 macos: Fix compile on aarch64 2020-11-02 21:06:00 +00:00
Brad
be850e483a Document Android raw_window_handle requirements (#1749)
* Add docs describing raw_winow_handle on android

* Run cargo fmt

* Change raw_window_handle panic to give more info
2020-10-29 14:23:46 -07:00
Simon Hausmann
33fb62bb25 Fix WindowEvent::ReceivedCharacter on web (#1747)
* Fix WindowEvent::ReceivedCharacter on web

The event was never sent to the application because of the unconditional
preventDefault() call on keydown.

Fixes #1741

* Don't scroll when pressing space on a focused canvas

After reaching keypress, we should prevent further propagation.

Relates to #1741
2020-10-29 17:13:21 -04:00
qthree
66c117e599 [Windows] Fix use after free during window destruction (#1746) 2020-10-23 19:04:18 +02:00
Waridley
8aa1be8336 On Unix, fix cross-compiling to wasm32
Aborting compilation by using 'compile_error!' macro in build.rs was resulting in failing cross
compilation, thus this commit removes build.rs. The compilation will now be aborted on existing 'compile_error!' macros in corresponding platform sources.
2020-10-22 07:14:33 +03:00
Kirill Chibisov
037d4121a1 On Wayland, fix 'with_min_inner_size' disabling resize
Building window with 'set_min_inner_size' was setting 'max_inner_size'
under the hood, thus completely disabling window resize, since
the window isn't resizeable on Wayland when its minimum size
is equal to its maximum size.
2020-10-20 03:30:19 +03:00
Vickles
fbd3918d3a Add prefix byte for extended scancodes on Windows (#1679) 2020-10-19 16:35:01 +02:00
Alex Butler
7c543a43a9 Windows: Fix alt tab bordless fullscreen (#1740) 2020-10-19 16:15:23 +02:00
Kirill Chibisov
ee3996cac6 Feature gate more dependencies
Wayland backend is self contained and only requires
smithay-client-toolkit to work, thus feature gate the
rest of the deps that are only for X11.
2020-10-18 02:05:08 +03:00
Murarth
96809ac659 Fix warnings (#1742) 2020-10-15 11:33:06 -07:00
Jim Porter
6343059bc0 Fix Windows transparency behavior to support fully-opaque regions (#1621)
This patch removes an unneeded workaround for transparent windows on the
Windows platform. In addition, it simplifies a couple of related API calls:

* Remove the `CreateRectRgn` call, since we want the entire window's region to
  have blur behind it, and `DwnEnableBlurBehindWindow` does that by default.
* Remove the `color_key` for `SetLayeredWindowAttributes`, since it's not used
  (we're not passing `winuser::LWA_COLORKEY` to the flags).
2020-10-14 12:23:34 +02:00
Simon Hausmann
5a78fe33e8 Fix failing assertion on start-up with Safari (#1736)
The initial media query that's used to watch for device pixel ratio
changes should match. Unfortunately it doesn't with Safari and the
corresponding assertion fails. This is because resolution is not a
supported support property for queries. As a workaround, this patch
extends the query to optionally match for the webkit specific DPR
property directly.

This fixes #1734
2020-10-10 00:31:51 -04:00
Max de Danschutter
676fb947f2 Added WindowHasFocus and WindowLostFocus events to Android (#1733)
* Added WindowHasFocus and WindowLostFocus events to Android

* Update changelog
2020-10-08 19:44:41 +02:00
Kirill Chibisov
d18afb4a50 Release 0.23.0 2020-10-02 18:05:07 +03:00
Nathan Lilienthal
fc336a76bf Fix incorrect modifiers state on startup
Fixes #1563.
2020-10-02 05:07:09 +03:00
Kirill Chibisov
b9f3d333e4 Update SCTK to 0.12
SCTK was a bit behind on Wayland protocol version, and so this release
brings it up to date. It also cleans up 'Environment'.
2020-10-01 01:19:15 +03:00
Kirill Chibisov
3d85af04be Update SCTK to 0.11.0
* Update SCTK to 0.11.0

Updates smithay-client-toolkit to 0.11.0. The major highlight
of that updated, is update of wayland-rs to 0.27.0. Switching
to wayland-cursor, instead of using libwayland-cursor. It
also fixes the following bugs:

  - Disabled repeat rate not being handled.
  - Decoration buttons not working after tty switch.
  - Scaling not being applied on output reenable.
  - Crash when `XCURSOR_SIZE` is `0`.
  - Pointer getting created in some cases without pointer capability.
  - On kwin, fix space between window and decorations on startup.
  - Incorrect size event when entering fullscreen when using
    client side decorations.
  - Client side decorations not being hided properly in fullscreen.
  - Size tracking between fullscreen/tiled state changes.
  - Repeat rate triggering multiple times from slow callback handler.
  - Resizable attribute not being applied properly on startup.
  - Not working IME

Besides those fixes it also adds a bunch of missing virtual key codes,
implements proper cursor grabbing, adds right click on decorations
to open application menu, disabled maximize button for non-resizeable
window, and fall back for cursor icon to similar ones, if the requested
is missing.

It also adds new methods to a `Theme` trait, such as:
  - `title_font(&self) -> Option<(String, f32)>` - The font for a title.
  - `title_color(&self, window_active: bool) -> [u8; 4]` - The color of
  the text in the title.

Fixes #1680.
Fixes #1678.
Fixes #1676.
Fixes #1646.
Fixes #1614.
Fixes #1601.
Fixes #1533.
Fixes #1509.
Fixes #952.
Fixes #947.
2020-09-29 00:11:43 +03:00
Logan Magee
471b1e003a Bump console_log from 0.1 to 0.2 2020-09-27 17:47:47 +03:00
alvinhochun
be2e17d605 Update readme info regarding WebAssembly and web target (#1726) 2020-09-24 10:52:11 -07:00
alvinhochun
9d6b9797c0 Clarify ControlFlow::Poll doc for web (#1725)
Make it clear that ControlFlow::Poll causing events to be sent on
`requestAnimationFrame` is an implementation detail which should not be
relied on.
2020-09-24 10:30:26 -04:00
Wang Kai
3cd6a18048 Fix WindowEvent::Moved ignoring DPI on macOS 2020-09-23 10:54:53 +00:00
Michael Hills
c9558c5f0e Fix view frame in portrait when starting iOS app in landscape (#1703)
Co-authored-by: Francesca Lovebloom <francesca@brainiumstudios.com>
2020-09-22 11:21:07 -07:00
Kirill Chibisov
71e3d25422 Rework 'Fullscreen::Borderless' enum variant
This changes 'Fullscreen::Borderless' enum variant from
'Fullscreen::Borderless(MonitorHandle)' to
'Fullscreen::Borderless(Option<MonitorHandle>)'. Providing
'None' to it will result in picking the current monitor.
2020-09-22 04:54:47 +03:00
alvinhochun
644dc13e00 web: Emit WindowEvent::Resized on Window::set_inner_size (#1717)
* web: Allow event to be queued from inside the EventLoop handler

The Runner is behind a RefCell, which is mutably borrowed when the event
handler is being called. To queue events, `send_events` needs to check
`is_closed()` and the `is_busy` flag, but it cannot be done since the
RefCell is already locked. This commit changes the conditions to work
without needing a successful borrow.

* web: Emit WindowEvent::Resized on Window::set_inner_size

* Update changelog
2020-09-21 18:19:00 -04:00
alvinhochun
47e7aa4209 Add cleanup code to web backend, mostly web-sys (#1715)
* web-sys: Impl. event listeners removal for canvas

* web-sys: Impl. media query listeners cleanup

* web: Emit WindowEvent::Destroyed after Window is dropped

* web-sys: Fix unload event closure being dropped early

* web: Impl. cleanup on ControlFlow::Exit

- Drops the Runner, which causes the event handler closure to be
  dropped.
- (web-sys only:) Remove event listeners from DOM.

* web: Do not remove canvas from DOM when dropping Window

The canvas was inserted by the user, so it should be up to the user
whether the canvas should be removed.

* Update changelog
2020-09-20 18:42:07 -04:00
Ryan G
1c97a310b1 Deprecate the stdweb backend (#1712)
* Deprecate the stdweb backend

* Add a changelog entry

* Fmt

* Move the deprecation notice
2020-09-20 18:41:44 -04:00
Kirill Chibisov
d612a1b5a1 Prefix numpad virtual key codes with Numpad
This commit is a follow up to a2db4c0a32
to make it clear which virtual key codes are located on numeric pad.

It also adds Asterisk and Plus virtual key codes.
2020-09-20 12:58:24 +03:00
msiglreith
386ead15a3 Android: bump ndk versions (#1708)
* Bump ndk versions

* Update README for new ndk proc attribute

* android: add CHANGELOG entry to ndk vesion bump
2020-09-18 11:14:56 -07:00
alvinhochun
83c95e774d Explicitly require simple_logger 1.9 for examples 2020-09-17 16:58:53 +03:00
Logan Magee
e4754999b7 Replace deprecated simple_logger initialization 2020-09-10 01:58:30 +00:00
Logan Magee
c66489dbb1 Bump parking_lot to 0.11
Fixes #1657.
2020-09-09 23:56:48 +03:00
Josh Groves
21f9aefc7e Update macOS dependencies
Fixes #1658.
2020-09-07 23:43:51 +03:00
Kirill Chibisov
d103dc2631 Make 'primary_monitor' return 'Option<MonitorHandle>'
Certain platforms like Wayland don't have a concept of
primary Monitor in particular. To indicate that
'primary_monitor' will return 'None' as well as in cases
where the primary monitor can't be detected.

Fixes #1683.
2020-09-07 20:20:47 +03:00
Kirill Chibisov
cac627ed05 Make 'current_monitor' return 'Option<MonitorHandle>'
On certain platforms window couldn't be on any monitor
resulting in failures of 'current_monitor' function.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning 'Option<MonitorHandle>' will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes #793.
2020-09-07 20:09:24 +03:00
Michael Kirk
e2cf2a5754 Fix inverted horizontal scroll on macOS
In winit the swipe from left to right on touchpad should
generate positive horizontal delta change, however on
macOS it was the other way around without
natural scrolling.

This commit inverses the horizontal scrolling delta
in 'MouseScrollDelta' events to match other platforms.

Fixes #1695.
2020-09-06 17:41:19 +03:00
alvinhochun
658a9a4ea8 Handle scale factor change on web-sys backend (#1690)
* Change web backend `event_handler` to without  'static lifetime

* Refactor web runner and fix ControlFlow::Exit not being sticky

* Impl. scaling change event for web-sys backend

* Improve `dpi` docs regarding the web backend

* Add changes to changelog

* Update features.md
2020-08-30 09:15:44 -04:00
Christian Duerr
a2db4c0a32 Unify Minus/Subtract virtual keycodes
On all platforms other than Linux/X11, the Subtract key was uniformly
used only for the Numpad. To make this cross-platform compatible, the
`-` key will now map to `Minus` on X11 instead of `Subtract`.

Since people have been confused about the difference between `Minus` and
`Subtract` in the past, the `Subtract` key has also been renamed to
`NumpadSubtract`. This is a breaking change that might be annoying to
downstream since there's no direct improvement, but it should help new
users in the future. Alternatively this could just be documented, rather
than explicitly mentioning the Numpad in the name.
2020-08-29 16:38:41 +03:00
alvinhochun
02a34a167a Impl. mouse capturing on web target (#1672)
* Impl. mouse capturing for web-sys with PointerEvent

* Impl. mouse capturing for web-sys with MouseEvent by manual tracking

* Reorganize web-sys backend mouse and pointer handling code

* Impl. mouse capturing for stdweb with PointerEvent

* Add mouse capturing for web target to changelog
2020-08-29 09:34:33 -04:00
alvinhochun
bea60930b6 Use send_events instead of send_event in web backend (#1681) 2020-08-26 12:11:27 -04:00
alvinhochun
0f7c82d38f Send CursorMove before mouse press event and note that touch is unimplemented on web target (#1668)
* Change to send CursorMove before mouse press event on web target

* Fix feature matrix to indicate touch being unimplemented on web
2020-08-21 20:23:08 -04:00
alvinhochun
6ba583d198 Fix vertical scroll being inverted on web targets (#1665) 2020-08-20 21:09:04 -04:00
Christian Duerr
89d4c06dec Fix crash on NetBSD
The `_lwp_self` function cannot be used to reliably determine the main
thread, see
https://github.com/alacritty/alacritty/issues/2631#issuecomment-676723289.

It might always be equal to the PID, but it's certainly not always 1
when the thread is the main thread.

However, Rust's built in `Thread::id` and `Thread::name` function will
always return `ThreadId(1)` and `Some("main")`. Since converting the
thread's ID to a number is not supported on stable Rust, checking that
the thread is labeled `Some("main")` seems like the most reliable
option. It should also be a good fallback in general.
2020-08-20 21:12:01 +03:00
Michael Kirk
9c72cc2a98 Fix HiDPI vs. set_cursor_icon for web (#1652)
PhysicalSize is recorded as canvas.size, whereas LogicalSize is stored
as canvas.style.size.

The previous cursor behavior on stdweb clobbered all style - thus losing
the LogicalSize.
2020-08-17 19:48:29 -04:00
simlay
412bd94ea4 Renamed NSString to NSStringRust to support Debug View Heirarchy in Xcode (#1631)
* Renamed NSString to NSStringRust to support Debug View Heirarchy

* Updated from comments

* Update CHANGELOG.md
2020-08-14 12:26:16 -07:00
TakWolf
514ab043f2 [macos] add NSWindow.hasShadow support (#1637)
* [macos] add NSWindow.hasShadow

* change log

* cargo fmt

* Update CHANGELOG.md

* Update src/platform_impl/macos/window.rs

* Update src/platform/macos.rs

* set_has_shadow() with cuter format

* adjust code

* cargo fmt

* changelog
2020-08-13 11:10:34 -07:00
msiglreith
68100102be android: fix event loop polling (#1638)
* android: poll looper for ControlFlow::Poll and don't exit when no new event received

* Add Android ControlFlow:Poll fix to CHANGELOG
2020-08-12 11:56:28 -07:00
josh65536
05fdcb5b27 Web: Use mouse events instead of pointer events if the latter isn't supported (#1630)
* Fixed Safari not getting mouse events

* Edited changelog

* Addressed compiler warnings

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
2020-08-04 21:39:09 -04:00
Christian Duerr
7a49c88200 Fix with_fullscreen signature 2020-08-02 02:10:33 +03:00
Christian Duerr
40232d48ba Use PhysicalPosition in PixelDelta event
This removes the `LogicalPosition` from the `PixelDelta`, since all
other APIs have been switched to use `PhysicalPosition` instead.

Fixes #1406.
2020-07-27 01:16:21 +03:00
Christian Duerr
55dff53a98 Fix Window platform support documentation
This resolves various problems with the documentation about platform
support on the Window struct.

It also completely removes pointless runtime errors in favor of
consistent no-ops on all platforms that do not support a certain
features.
2020-07-27 00:13:17 +03:00
Matt Kraai
6919c2fb2d Fix misspellings in comments (#1618) 2020-07-09 08:08:26 -07:00
Xavier L'Heureux
3d5d05eac7 Move available_monitors and primary_monitor to EventLoopWindowTarget (#1616) 2020-07-04 15:46:41 -04:00
Osspial
dd866a74a6 On Windows, fix bug where we'd try to emit MainEventsCleared events during nested win32 event loops (#1615) 2020-07-02 16:53:47 -04:00
Jurgis
b1e22aa559 Make drag and drop optional (fixes OleInitialize failure #1255) (#1524)
Co-authored-by: Osspial <osspial@gmail.com>
2020-06-28 18:17:27 -04:00
Andrey Lesnikov
2191e9ecd5 macOS: Support click-dragging out of a window (#1607)
* macos: Support click-dragging out of a window

* macos: Use NSEvent::pressedMouseButtons for click-dragging

* macos: Click-dragging: Move pressedMouseButtons inside
2020-06-19 17:42:19 -07:00
Viktor Zoutman
bf62103417 Android run return (#1604)
* Initial Draft

* Minor clean up

* cargo fmt

* Removed accidental change

* Update CHANGELOG.md

Co-authored-by: VZout <=>
2020-06-17 15:55:52 +02:00
Murarth
4b1b314ce2 Test x11 and wayland features on CI 2020-06-15 22:49:09 +03:00
Olivier Goffart
c1ea0dde92 On Unix, add option to pick backends
Add features 'x11'  and 'wayland' to pick backends on Linux/BSD, with
both enabled by default.

Fixes #774.
2020-06-15 10:15:27 +03:00
Viktor Zoutman
5a6cfc314e Macos fullscreen & dialog support with run_return (#1581)
* Fix for fullscreen with run_return on mac

* Cleanup

* Removed a comment

* fmt

* This doesn't break exiting run_return anymore

* Now you can also transition from code

* Fmt & cleanup

* Now using a atomic instead of a static bool

* reinserted a line

* Fmt

* Added support for dialogs and child windows

* Cargo fmt

* Dialogs are now being shutdown properly

* Cargo fmt

* Update CHANGELOG.md
2020-06-09 14:46:33 -07:00
Boqin Qin
a4121a2c2e platform_impl/linux/x11: fix deadlock in fn set_fullscreen_inner (#1579)
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2020-05-27 09:24:08 -07:00
Andrew Slater
03335cef85 macOS: add function to hide other applications 2020-05-24 19:26:29 +03:00
Kirill Chibisov
ff66bdda7c On Wayland, fix deadlock when calling set_inner_size from event loop
Fixes #1571.
2020-05-22 13:33:04 +03:00
Ryan G
6cfddfea21 Prevent the default browser behavior of events (#1576)
This stops things like page scrolling on spacebar / arrow keys
2020-05-21 13:13:33 -04:00
Osspial
49bcec1d27 Release 0.22.2 (#1570) 2020-05-16 12:27:16 -04:00
Michal Hornický
878c179761 Implement Clone for 'static events (#1478) 2020-05-15 14:58:12 -04:00
j4qfrost
bc19c04339 Fixed changelog line for core-* dependencies (#1561) 2020-05-15 14:32:04 -04:00
curldivergence
c7a33f926b Fixed a couple of typos in repo description (#1568) 2020-05-15 14:31:32 -04:00
j4qfrost
3c38afdb47 Update macOS dependencies (#1554)
* update macos libs

* modify dependency

* changelog

* update core-video-sys version
2020-05-07 22:32:09 -04:00
Jasper De Sutter
b8828105cf add android NDK event loop (#1556)
* add android NDK event loop

* add Android build documentation & cargo-apk to CI

Co-authored-by: David Craven <david@craven.ch>
2020-05-06 15:27:49 +02:00
Francesca Lovebloom
007b195a5e iOS: convert touch positions to physical (#1551) 2020-05-04 15:55:58 -07:00
Osspial
b4c6cdf9a3 Fix several crashes on Windows by heavily simplifying the event loop code (#1496) 2020-05-04 15:14:13 -04:00
Christian Duerr
26775fa0b6 Report mouse motion before click (#1490)
* Report mouse motion before click

This fixes an issue on macOS where a mouse click would be generated,
without ever getting a mouse motion to the position before the click.
This leads to the application thinking the mouse click occurred at a
position other than the actual mouse location.

This happens due to mouse motion above the window not automatically
giving focus to the window, unless it is actually clicked, making it
possible to move the window without motion events.

Fixes #942.

* Add additional mouse motion events

Co-authored-by: Ryan Goldstein <ryan@ryanisaacg.com>
2020-04-26 16:42:45 -04:00
Matthias Fauconneau
114fe9d502 wayland: rework scale factor handling (#1538)
- Always send Resized events in case of scale factor change
- Properly take into account the resize the user can do using the resize event.
2020-04-22 18:00:41 +02:00
Héctor Ramón
54bc41f68b Implement Drop for Proxy on macOS platform (#1526) 2020-04-20 17:48:42 -04:00
Osspial
47ff8d61d1 Document that platforms will display garbage data in the window by default (#1541) 2020-04-20 00:04:30 -04:00
Benjamin Saunders
849b8f5dce Clarify when RedrawRequested is useful (#1529)
Co-Authored-By: Osspial <osspial@gmail.com>
2020-04-19 17:09:08 -04:00
Yanchi Toth
aabe42d252 Preserve with_maximized on windows (#1515) 2020-04-19 15:52:48 -04:00
simlay
78a62ec547 Added more docs.rs targets (#1521) 2020-04-19 15:37:13 -04:00
Benjamin Saunders
6dae994bb4 Mention raw-window-handle in library docs (#1528) 2020-04-19 14:58:58 -04:00
Philippe Renon
4c4d0916fd control_flow example: fix wait_cancelled logic again (#1511) 2020-04-19 13:55:10 -04:00
Ryan G
d5609729cc Bump version to 0.22.1 (#1537)
There are a few relatively important bugfixes with no API impact in the
master branch. We might as well release this as a non-breaking change.
2020-04-17 13:36:42 -04:00
Jurgis
1f24a09570 Implement requestAnimationFrame for web (#1519)
* Use requestAnimationFrame for polling wasm

* Implement `requestAnimationFrame` for stdweb

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
2020-04-11 15:49:07 -04:00
Ryan G
a8e777a5df Fix a possible double-borrow during event handling (#1512) 2020-04-11 15:20:38 -04:00
Murarth
0bc58f695b Fix warnings (#1530) 2020-04-10 11:29:33 -07:00
Matthew Russo
28023d9f5b upgrades x11-dl to 2.18.5 to fix #376 (#1517)
x11-dl was using std::mem::uninitialized incorrectly and when
rustlang added MaybeUninit and intrinsic panics on UB caused
by improper use of uninitialized (see rust-lang/rust/pull/69922)
it caused issues with X11 initialization. x11-dl pr
erlepereira/x11-rs/pull/101 updated x11-dl to use MaybeUninit
correctly
2020-03-25 22:38:25 -07:00
Murarth
c2aed1979d X11: Fix ResumeTimeReached being fired early (#1505)
* X11: Fix `ResumeTimeReached` being fired early

* Update CHANGELOG.md

Co-authored-by: Osspial <osspial@gmail.com>
2020-03-11 21:54:23 -07:00
Osspial
7e04273719 Replace Travis and Appveyor CI badges with GitHub Actions CI badge 2020-03-09 18:23:03 -04:00
Osspial
0683bdcd42 Add Unreleased category back to changelog 2020-03-09 17:01:34 -04:00
Osspial
29ab0bb629 Correct 0.22.0 date 2020-03-09 16:59:39 -04:00
Christian Duerr
7a9c17a520 Bump version to 0.22.0 (#1500)
There are two PRs I'm aware of that should be relatively trivial to get
merged, which would fix some issues. Other than those, I don't think it
makes sense to wait on anything.

 - Fix Windows crash: https://github.com/rust-windowing/winit/pull/1459
 - Fix macOS mouse reports: https://github.com/rust-windowing/winit/pull/1490

While #1459 seems pretty essential to actually make winit run, #1490 is
much less important and can probably be ignored if there aren't any
resources to merge it.
2020-03-09 16:58:54 -04:00
Kirill Chibisov
b208daa271 Revert "on MacOS, Fix not sending ReceivedCharacter event for s… (#1501)
This reverts commit 9daa0738a9.

This commit introduced other bug #1453 with likely much more common bindings,
so reverting it for now.

Fixes #1453.

Co-authored-by: Osspial <osspial@gmail.com>
2020-03-09 16:57:04 -04:00
Imberflur
e85a80dd65 Fix freeze when pressing modifier keys on Windows (#1503) 2020-03-08 01:22:53 -05:00
Osspial
b1d8ce24e9 Use i32 instead of u32 for position type in WindowEvent::Moved (#1502)
* Use i32 instead of u32 for position type in WindowEvent::Moved

* Mark change as breaking
2020-03-08 00:21:04 -05:00
David Hewitt
098fd5d602 Add ability to create Icons from embedded resources on Windows (#1410)
* Add IconExtWindows trait

* Move changelog entries to unreleased category

Co-authored-by: Osspial <osspial@gmail.com>
2020-03-07 14:42:21 -05:00
Philippe Renon
2f27f64cdb On Windows, fix request_redraw() related panics (#1461)
* On Windows, fix request_redraw() related panics

These panics were introduced by 6a330a2894

Fixes https://github.com/rust-windowing/winit/issues/1391
Fixes https://github.com/rust-windowing/winit/issues/1400
Fixes https://github.com/rust-windowing/winit/issues/1466
Probably fixes other related issues

See https://github.com/rust-windowing/winit/issues/1429

* On Windows, replace all calls to UpdateWindow by calls to InvalidateRgn

This avoids directly sending a WM_PAINT message,
which might cause buffering of RedrawRequested events.

We don't want to buffer RedrawRequested events because:
- we wan't to handle RedrawRequested during processing of WM_PAINT messages
- state transitionning is broken when handling buffered RedrawRequested events

Fixes https://github.com/rust-windowing/winit/issues/1469

* On Windows, panic if we are trying to buffer a RedrawRequested event

* On Windows, move modal loop jumpstart to set_modal_loop() method

This fixes a panic.
Note that the WM_PAINT event is now sent to the modal_redraw_method
which is more correct and avoids an unecessary redraw of the window.

Relates to but does does not fix https://github.com/rust-windowing/winit/issues/1484

* On Window, filter by paint messages when draining paint messages

This seems to prevent PeekMessage from dispatching unrelated sent messages

* Change recently added panic/assert calls with warn calls

This makes the code less panicky...

And actually, winit's Windoww callbacks should not panic
because the panic will unwind into Windows code.

It is currently undefined behavior to unwind from Rust code into foreign code.
See https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

* add comments to clarify WM_PAINT handling in non modal loop

* made redraw_events_cleared more explicit and more comments
2020-03-07 14:04:24 -05:00
Christian Duerr
cbb60d29a2 Remove assertions from Windows dark mode code (#1459)
* Remove assertions from Windows dark mode code

In general, winit should never assert on anything unless it means that
it is impossible to continue the execution of the program. There are
several assertions in the Windows dark mode code where this is not the
case.

Based on surface level inspection, all existing assertions could be
easily replaced with just simple conditional checks, allowing the
execution of the program to proceed with sane default values.

Fixes #1458.

* Add changelog entry

* Format code

* Pass dark mode by mutable reference

* Format code

* Return bool instead of mutable reference

* Fix dark mode success reply

Co-Authored-By: daxpedda <daxpedda@gmail.com>

* Fix dark mode success reply

* Replace magic integers with constants

Co-authored-by: daxpedda <daxpedda@gmail.com>
2020-03-07 13:56:33 -05:00
Murarth
e707052f66 Move ModifiersChanged variant to WindowEvent (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`

* macos: Fix flags_changed for ModifiersChanged variant move

I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* macos: Fire a ModifiersChanged event on window_did_resign_key

From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent.  It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* windows: Fix build

I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS

Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.

It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.

[1]: f79f21641a

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* macos: Add a hook to update stale modifiers

Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags.  These are internally stored as a bitmask in
the latter and an enum in the former.

We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`.  That's what the hook does.

This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* Only call event_mods once when determining whether to update state

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* flags_changed: Memoize window_id collection

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* window_did_resign_key: Remove synthetic ModifiersChanged event

We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* mouse_motion: Add a call to update_potentially_stale_modifiers

Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave.  Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* key_up: Add a call to update_potentially_stale_modifiers

We also want to make sure modifiers state is synchronized here, too.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* mouse_motion: Remove update_potentially_stale_modifiers invocation

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* Retry CI

* ViewState: Promote visibility of modifiers to the macos impl

This is so that we can interact with the ViewState directly from the
WindowDelegate.

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* window_delegate: Synthetically set modifiers state to empty on resignKey

This logic is implemented similarly on other platforms, so we wish to
regain parity here.  Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.

This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).

Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>

* Check for modifiers change in window events

* Fix modifier changed on macOS

Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.

The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.

This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.

* Fix unused variable warning

* Move changelog entry into `Unreleased` section

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
Philippe Renon
71bd6e73ca windows: ignore spurious mouse move messages (#1435)
Fixes https://github.com/rust-windowing/winit/issues/1428
2020-03-06 16:15:49 -05:00
Philippe Renon
b8326f6452 In control_flow example, don't schedule a new WaitUntil if wait was cancelled (#1482) 2020-03-06 10:48:54 -07:00
HeroicKatora
ece2e70a53 Update image to 0.23 (#1485)
Also makes use of a few ergonomics improvements that were introduced or
optimized in the more recent version.
2020-03-03 16:13:53 -07:00
Murarth
2b14ec23d5 Fix GitHub Actions (#1479)
* Replaces `actions/checkout@v1` with `actions/checkout@v2` to get a bug fix
2020-02-25 09:10:31 -07:00
Murarth
9999f53329 X11: Fix deadlock when an error occurs during startup (#1475) 2020-02-19 10:38:59 -07:00
Philippe Renon
522a6e3298 fix issues in wait_until_time_or_msg function (#1423)
also removed unused return value
2020-02-18 19:27:47 -05:00
Kirill Chibisov
76d0dd7ec3 On Wayland, Hide CSD for fullscreen windows (#1473) 2020-02-18 16:58:48 -07:00
daxpedda
d1073dcecb Implement ThemeChanged for web target. (#1462)
* Implement ThemeChanged for web target.

* Add TODO upstream to stdweb.

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
2020-02-17 14:25:27 -05:00
Héctor Ramón
e88e8bc194 Map UserEvent properly in Event::to_static (#1468) 2020-02-16 10:53:02 -07:00
Philippe Renon
bc29931434 Add an example that calls request_redraw() from a thread (#1467)
reproduces https://github.com/rust-windowing/winit/issues/1466
2020-02-15 11:38:29 -07:00
Philippe Renon
505f312d5f Add new example that demonstrates the different control flow schemes (#1460)
User can switch between Wait, WaitUntil and Poll modes with key '1', '2' and '3' respectivly.
User can toggle request_redraw calls with the 'R' key.

Helpful for testing all control flow modes and use of request_redraw.
2020-02-13 15:20:32 -07:00
Philippe Renon
f0093d3c54 rename dpi_factor to scale_factor where appropriate (#1463)
fixes https://github.com/rust-windowing/winit/issues/1457
2020-02-13 12:41:41 -07:00
Kirill Chibisov
83b60beba6 on Wayland, Add HiDPI cursor support (#1454)
Fixes #727.
2020-02-12 19:48:58 -07:00
hatoo
5f52d7c9d0 On macOS, Fix set_simple_screen to remember frame excluding title bar (#1430)
* On macOS, Fix `set_simple_screen` to remember frame excluding title bar

* Add CHANGELOG
2020-02-12 11:27:11 +03:00
Julien Sanchez
a1b65f7080 Ignore locale if unsupported by X11 backend (#1445)
This restores default portable 'C' locale when target locale is unsupported
by X11 backend (Xlib).

When target locale is unsupported by X11, some locale-dependent Xlib
functions like `XSetLocaleModifiers` fail or have no effect triggering
later failures and panics.

When target locale is not valid, `setLocale` should normally leave the
locale unchanged (`setLocale` returns 'C'). However, in some situations,
locale is accepted by `setLocale` (`setLocale` returns the new locale)
but the accepted locale is unsupported by Xlib (`XSupportsLocale` returns
`false`).

Fix #636
2020-02-09 22:37:06 -07:00
Kirill Chibisov
96df858961 On Wayland, fix color from close_button_icon_color not applying (#1444) 2020-02-08 19:36:44 -07:00
Kirill Chibisov
4eddd1e5bc On Wayland, fix coordinates in touch events when scale factor isn't 1 (#1439)
* On Wayland, fix coordinates in touch events when scale factor isn't 1

* Explicitly state that Wayland is using LogicalPosition internally

* Fix CHANGELOG
2020-02-08 01:25:08 -07:00
Freya Gentz
28f0eb598d Release 0.21.0 (#1440)
* Update CHANGELOG.md

* Update README.md

* Update Cargo.toml

* Update Cargo.toml

* Update README.md

* Update CHANGELOG.md
2020-02-04 19:07:31 -07:00
David Craven
c1eb7f9629 Fix deadlock wayland. (#1438) 2020-02-04 16:46:19 -07:00
Murarth
2f8aa5c52a Remove armv7-apple-ios target from CI (#1433) 2020-02-03 17:42:52 -07:00
hatoo
22dcc19898 Fix set_minimized(true) works only with decorations on macOS (#1411)
* On macOS, Fix set_minimized(true) works only with decorations

* Add CHANGELOG
2020-01-31 18:07:36 +03:00
Christian Duerr
e295104199 Remove Wayland theme intermediates (#1209)
* Remove Wayland theme intermediates

This removes the intermediate struct for passing a Wayland theme to
allow the user direct implementation of the trait.

By passing the trait directly, it is possible for downstream users to
have more freedom with customization without relying on winit to offer
these options as fields.

It should also make maintenance easier, since winit already doesn't
implement all the functions which are offered by the smithay client
toolkit.

* Reimplement SCTK's Theme and ButtonState

* Fix style issues

* Remove public signature

* Format code

* Add change log entry

Co-authored-by: Murarth <murarth@gmail.com>
2020-01-26 19:56:54 -07:00
Murarth
66fe69edd9 Fix warnings on macos (#1419) 2020-01-26 13:55:27 -07:00
Ryan G
fd946feac4 Web backend refactor and documentation (#1415)
The current implementation of the event loop runner has some significant
problems. It can't handle multiple events being emitted at once (for
example, when a keyboard event causes a key input, a text input, and a
modifier change.) It's also relatively easy to introduce bugs for the
different possible control flow states.

The new model separates intentionally emitting a NewEvents (poll
completed, wait completed, init) and emitting a normal event, as well as
providing a method for emitting multiple events in a single call.
2020-01-25 19:04:03 -05:00
Freya Gentz
8856b6ecb7 Remove unused code in X11 backend. (#1416)
Signed-off-by: Freya Gentz <zegentzy@protonmail.com>
2020-01-23 12:42:15 -07:00
Osspial
0ae78db6cb Fix building on Windows 7 and 8 (#1398)
* Fix building on Windows 7 and 8

* Format
2020-01-21 12:43:36 -07:00
David Yamnitsky
3e3bb8a8f1 add hide_application on macos (#1364)
Co-authored-by: Osspial <osspial@gmail.com>
Co-authored-by: Bogaevsky <vbogaevsky@gmail.com>
2020-01-19 16:38:52 -07:00
Steven Sheldon
e48262a797 Simplify code by switching to higher-level dispatch APIs (#1409)
* Switch to higher-level dispatch APIs

* Inline all the functions

* Switch to autoreleasepool from objc
2020-01-19 11:47:55 -07:00
Diggory Hardy
d934f94704 Fix: deadlock when requesting redraw on X11 (#1408) 2020-01-18 10:49:02 -07:00
Ryan G
1fe4a7a4ea Add the ability to pass a prebuilt canvas (#1394)
This allows Winit to take control of existing canvas elements in the
DOM, which is useful for web applications with other content in the
page.
2020-01-15 21:20:14 -05:00
hatoo
9daa0738a9 on MacOS, Fix not sending ReceivedCharacter event for some key combination (#1347)
* MacOS FIX #1267

* Add CHANGELOG

* Remove unnecessary trace!
2020-01-15 00:52:18 +03:00
Philippe Renon
ad7d4939a8 doc: change remaining EventsCleared references to MainEventsCleared (#1390) 2020-01-13 12:15:44 -07:00
Ryan G
c4d07952cb Remove TODOs from the web backen (#1395) 2020-01-13 12:14:25 -07:00
Héctor Ramón
dc302b0db4 Return physical position in CursorMoved on macOS (#1378) 2020-01-12 20:50:34 +03:00
Kirill Chibisov
a6d180cefb On Wayland, fix coordinates in mouse events when scale factor isn't 1 (#1385)
* On Wayland, fix coordinates in mouse events when scale factor isn't 1

* Refactor mouse_focus to be a surface instead of WindowId
2020-01-11 01:45:52 -07:00
Francesca Plebani
1ddceeb063 macOS: Unbundled window activation hack (#1318)
* `ns_string_id_ref` convenience fn

* Unbundled app activation hack

* Greatly improved solution

* Shortened names

* Remove cruft I left here a year ago

* Doc improvements

* Use `AtomicBool` for `activationHackFlag`

* Add CHANGELOG entry

* Doc improvements

* Fix `did_finish_launching` return type + delay more

* More reliable activation checking

* Fix merge goof

* ...fix other merge goof

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Bogaevsky <vbogaevsky@gmail.com>
2020-01-10 16:02:42 -08:00
hatoo
633d0deeae Fix run_return does not return on macOS unless it receives a message (#1380)
* On MacOS, fix `run_return` not exit immediately

* Add CHANGELOG
2020-01-10 18:25:55 +03:00
Murarth
9e3844ddd9 Fix warnings on all platforms (#1383)
* Fix warnings on all platforms

* Also fixed a trait impl bound that I noticed along the way
2020-01-09 22:29:31 -07:00
Benjamin Saunders
4b618bd6a6 Don't discard high-precision cursor position data (#1375)
* Don't discard high-precision cursor position data

Most platforms (X11, wayland, macos, stdweb, ...) provide physical
positions in f64 units, which can contain meaningful fractional
data. For example, this can be empirically observed on modern X11
using a typical laptop touchpad. This is useful for e.g. content
creation tools, where cursor motion might map to brush strokes on a
canvas with higher-than-screen resolution, or positioning of an object
in a vector space.

* Update CHANGELOG.md

Co-Authored-By: Murarth <murarth@gmail.com>

Co-authored-by: Murarth <murarth@gmail.com>
2020-01-09 21:19:50 -07:00
Osspial
09c4ed0694 Remove util from gitignore 2020-01-09 12:24:57 -05:00
Murarth
d15eb04f9e Make docs set control_flow in a more realistic way (#1376) 2020-01-07 22:55:18 -05:00
Bastian Kauschke
02ac7456e4 impl Default for WindowBuilder (#1373) 2020-01-07 14:33:56 -05:00
Murarth
6b0875728c X11: Fix deadlock on window state with certain window events (#1369) 2020-01-06 20:54:22 -07:00
Osspial
6a330a2894 On Windows, fix bug where RedrawRequested would only get emitted every other iteration of the event loop (#1366)
* Fix bug causing RedrawRequested events to only get emitted every other iteration of the event loop.

* Initialize simple_logger in examples.

This PR's primary bug was discovered because a friend of mine reported
that winit was emitting concerning log messages, which I'd never seen
since none of the examples print out the log messages. This addresses
that, to hopefully reduce the chance of bugs going unnoticed in the
future.

* Add changelog entry

* Format
2020-01-06 15:28:58 -05:00
Osspial
627a127f1b we did it bois (#1352) 2020-01-05 17:11:25 -05:00
Murarth
ec1ae68cfc X11: Properly update window size constraints on DPI change (#1356)
* In `WindowBuilderExtUnix` methods, use `Size` instead of `LogicalSize`
2020-01-05 17:04:31 -05:00
Osspial
3aa3880e69 Add changelog entry 2020-01-05 16:57:32 -05:00
Osspial
a1b8d265d0 Refine DPI docs 2020-01-05 16:34:37 -05:00
Osspial
9b122c3804 Update the DPI module docs (#1349)
* Update the DPI module docs

* Fix HiDpiFactorChanged doc link

* Incorporate lokathor and icefox feedback

* Adjust documented desktop resolution range

* X11 is one of the reasons I use Windows

* Address DPI generics and float->int rounding

* Revise DPI value statement to better reflect best practices

* Address some of freya's feedback

* phrasing

* Rephrase X11 DPI stuff
2020-01-05 14:15:12 -05:00
Osspial
28b82fb9aa Try to fix iOS build 2020-01-05 14:15:12 -05:00
Murarth
7753bbba94 Fix examples 2020-01-05 14:15:12 -05:00
Murarth
ac69a9c0dc Silence warnings about use of deprecated fields 2020-01-05 14:15:12 -05:00
Osspial
d29f7f34aa Rename hidpi_factor to scale_factor (#1334)
* Rename hidpi_factor to scale_factor

* Deprecate WINIT_HIDPI_FACTOR environment variable in favor of WINIT_X11_SCALE_FACTOR

* Rename HiDpiFactorChanged to DpiChanged and update docs

I'm renaming it to DpiChanged instead of ScaleFactorChanged, since I'd
like Winit to expose the raw DPI value at some point in the near future,
and DpiChanged is a more apt name for that purpose.

* Format

* Fix macos and ios again

* Fix bad macos rebase
2020-01-05 14:15:12 -05:00
Osspial
85ea3f1d5d Use i32 in Position::Physical (#1350)
* Use i32 in Position::Physical

* Fix multithreaded example

* format
2020-01-05 14:15:12 -05:00
Osspial
55166da437 Remove Option from HiDpiFactorChanged in favor of a bare PhysicalSize (#1346)
* Remove Option from HiDpiFactorChanged in favor of a bare PhysicalSize

* Fix macos and ios builds
2020-01-05 14:15:12 -05:00
Michael Tang
777d9edeaa Implement hidpi for web platform (#1233)
* fix: use a 'static lifetime for the web backend's `Event` types

* implement hidpi for stdweb (web-sys wip?)

* fix: make all canvas resizes go through backend::set_canvas_size

* update Window docs for web, make `inner/outer_position` return the position in the viewport
2020-01-05 14:15:11 -05:00
Antonino Siena
28a20aec10 Dpi Type conversions into/from arrays (#1283)
* Added array conversion methods

* Cargo fmt

* Undo wrong fmt
2020-01-05 14:15:11 -05:00
Osspial
3a1e694c2f Make size/position types generic over pixel type (#1277)
* Begin implementing DPI generics

* Fix multithreaded example

* Format

* Fix serde test

* hopefully fix most of the errors

* Fix dpi module errors

* More error fixings

* Format

* fix macos errors

* Another error pass

* Replace bad type signatures

* more fixins
2020-01-05 14:15:11 -05:00
Bogaevsky
b16042a047 iOS: Dpi overhaul (#1223)
* WIP - Make EL2 DPI changes and implement on Windows (#895)

* Modify DPI API publicly and on Windows

* Add generic Position and make dpi creation functions const

* Make examples work

* Fix fullscreen windows not appearing

* Replace Logical coordinates in window events with Physical coordinates

* Update HiDpiFactorChanged

* Document to_static

* On Windows, make AdjustRect calls DPI-aware when possible (#1015)

* Use AdjustWidowRectExForDPI when available

* Prioritize presevering logical size when handling WM_DPICHANGED

* Format

* Add changelog entry

* macOS: Dpi overhaul (#997)

* WIP - Make EL2 DPI changes and implement on Windows (#895)

* Modify DPI API publicly and on Windows

* Add generic Position and make dpi creation functions const

* Make examples work

* Fix fullscreen windows not appearing

* Replace Logical coordinates in window events with Physical coordinates

* Update HiDpiFactorChanged

* Document to_static

* fix app_state errors

* fixes hidpi related errors in window_delegate

* fix bad merge

* dpi_factor edits in window_delegate

* fixes type and lifetime errors in window and window_delegate

* applies fmt

* complies with @aleksijuvani requested changes

* modifies Handler lifetimes

* fixes lifetime isues, adds propper handling for HiDpiChanged

* applies fmt

* restore original lifetimes

* solution is somewhere out there

* applies fmt

* pass as references

* resolves issue with HANDLER

* crate visible type error

* fixes visibility issues

* applies fmt

* deals with warnings

* simplifies new_inner_size setting algorthm

* moves proxy instead of referencing it and removes double deref from proxy.ns_window

* makes @Osspial tests (https://github.com/rust-windowing/winit/pull/997\#discussion_r301852354) pass

* complies with @aleksijuvani suggested changes

* makes max window size std::f32::MAX

* On Windows, fix new DPI API not setting window size properly (#1130)

* First attempt

* Second attempt

* Maintain cursor horizontal ratio

* Fix DPI change handling when maximized

* Revert window example

* Make new DPI code more understandable

* Format

* Implement DPI Usability Upgrades for X11 and Wayland (#1098)

* Fix compile errors

* Use `mio` for the X11 event loop

* Removes `calloop` from the X11 event loop, as the method of draining a
  source using a closure provided to the `calloop::EventLoop` instance
  conflicts with the need to deliver events directly to the callback
  provided to `EventLoop::run`, in order to respond to the value provided by
  `WindowEvent::HiDpiFactorChanged`.

* Implement interactive `HiDpiFactorChanged` event for X11

* Implement interactive `HiDpiFactorChanged` event for Wayland

* Run cargo fmt

* Fix Wayland not processing events from EventQueue

* Backport #981

* some lifetime tinkering

* finishes lifetime tinkering

* fixes all type errors

* adds support ffi functions

* adds wrappers for nonstatic events

* replaces events with event wrappers

* reimplementing hidpichanged event in app_state

* implements HiDpiFactorChanged for iOS

* applies formatter

* complies with @aleksijuvani requested changes

* resolves conflicts

* applies fmt

* removes merge blurp

* corrects state of CHANGELOG

* fix fmt check error

* fixes hidpi_factor for armv7-apple-ios
2020-01-05 14:15:11 -05:00
Osspial
cbf61e5cb9 Fix window rectangle change being in wrong changelog entry 2020-01-05 14:15:11 -05:00
Vladimir Bogaevsky
077ee4d851 macOS: Dpi overhaul (#997) (and rebase changes)
* WIP - Make EL2 DPI changes and implement on Windows (#895)

* Modify DPI API publicly and on Windows

* Add generic Position and make dpi creation functions const

* Make examples work

* Fix fullscreen windows not appearing

* Replace Logical coordinates in window events with Physical coordinates

* Update HiDpiFactorChanged

* Document to_static

* fix app_state errors

* fixes hidpi related errors in window_delegate

* fix bad merge

* dpi_factor edits in window_delegate

* fixes type and lifetime errors in window and window_delegate

* applies fmt

* complies with @aleksijuvani requested changes

* modifies Handler lifetimes

* fixes lifetime isues, adds propper handling for HiDpiChanged

* applies fmt

* restore original lifetimes

* solution is somewhere out there

* applies fmt

* pass as references

* resolves issue with HANDLER

* crate visible type error

* fixes visibility issues

* applies fmt

* deals with warnings

* simplifies new_inner_size setting algorthm

* moves proxy instead of referencing it and removes double deref from proxy.ns_window

* makes @Osspial tests (https://github.com/rust-windowing/winit/pull/997\#discussion_r301852354) pass

* complies with @aleksijuvani suggested changes

* makes max window size std::f32::MAX

Changes from rebasing:

* fixes compile errors

* applies fmt

* reimplements HiDpiFactorChanged after #1173 merge

* uses EventWrappers
2020-01-05 14:15:11 -05:00
Murarth
7b43b0bc94 Implement DPI Usability Upgrades for X11 and Wayland (#1098)
* Fix compile errors

* Use `mio` for the X11 event loop

* Removes `calloop` from the X11 event loop, as the method of draining a
  source using a closure provided to the `calloop::EventLoop` instance
  conflicts with the need to deliver events directly to the callback
  provided to `EventLoop::run`, in order to respond to the value provided by
  `WindowEvent::HiDpiFactorChanged`.

* Implement interactive `HiDpiFactorChanged` event for X11

* Implement interactive `HiDpiFactorChanged` event for Wayland

* Run cargo fmt

* Fix Wayland not processing events from EventQueue

* Backport #981
2020-01-05 14:15:11 -05:00
Osspial
6bb7db7c11 On Windows, fix new DPI API not setting window size properly (#1130)
* First attempt

* Second attempt

* Maintain cursor horizontal ratio

* Fix DPI change handling when maximized

* Revert window example

* Make new DPI code more understandable

* Format
2020-01-05 14:15:11 -05:00
Osspial
6ffd78767f On Windows, make AdjustRect calls DPI-aware when possible (#1015)
* Use AdjustWidowRectExForDPI when available

* Prioritize presevering logical size when handling WM_DPICHANGED

* Format

* Add changelog entry
2020-01-05 14:15:11 -05:00
Osspial
f379d069b9 WIP - Make EL2 DPI changes and implement on Windows (#895)
* Modify DPI API publicly and on Windows

* Add generic Position and make dpi creation functions const

* Make examples work

* Fix fullscreen windows not appearing

* Replace Logical coordinates in window events with Physical coordinates

* Update HiDpiFactorChanged

* Document to_static
2020-01-05 14:15:11 -05:00
Osspial
2da24089de Replace Appveyor and Travis with Github Actions (#1309)
* Experiment with github actions

* Only use stable for testing simplicity

* Disable fail-fast

* Never fail when rustup target add fails

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Update rust.yml

* Split formatting check into separate job

* Update and rename rust.yml to ci.yml

* Attempt to add web support

* Fix things

* Fixings

* The "I'm not familiar with YAML" update

* The empty string update

* Fix target interpolation

* Add gcc-multilib on linux x86

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Use correct host on Windows GNU

* Update ci.yml

* Update ci.yml

* in my defense it was like 2 AM when I wrote this

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* try caching

* Update ci.yml

* Update ci.yml

* Update on

* Update ci.yml

* Update ci.yml

* Remove travis and appveyor testing

* Cache entire cargo folder

* Make cargo cache key more appropriately named

* Reduce key collisions

* Make key work

* Add publish workflow and path qualifiers

* Remove -f in cargo install cargo-web

* continue-on-error for cargo web

* ping

* Try to shorten matrix

* attempt two

* attempt three

* attempt four

* Use bash

* web feature formatting

* ping
2020-01-05 14:13:05 -05:00
icefoxen
57f29aa6d7 Added some "how" and "why" docs to event handling. (#1032)
* Added some "how" and "why" docs to event handling.

Basically I had these questions when I started exploring the new
event API's, and as I figured out the answers I put down more info
about how everything works.  This is not final, and suggestions
are welcome -- the code example in the `event` module docs is
particularly dubious, but it's how I'm used to thinking abou things
so it only made sense to me once I wrote that.

Note that my bias is towards using winit for writing games, so that's
the sort of things I was interested in.  This may not be valid for
more general use cases.

* cargo fmt

* Fix minor typos

* Revise event documentation

* Update lib.rs docs

* Update root docs

Co-authored-by: Osspial <osspial@gmail.com>
2020-01-05 11:02:41 -05:00
Osspial
028d3ec16d Make examples set control_flow in a more realistic way (#1363)
* Make examples set control_flow in a more realistic way

* Format
2020-01-05 02:12:03 -05:00
Christian Duerr
d1c6506865 Fix ModifiersChanged event on X11 (#1358) 2020-01-03 22:11:00 -07:00
Osspial
c0b46a03b5 Relase alpha 6 (#1338)
* Relase alpha 6

* Update CHANGELOG.md

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
2020-01-03 18:17:05 -05:00
Kirill Chibisov
114c18e70d On X11, make WINIT_HIDPI_FACTOR dominate Xft.dpi in some cases (#1354)
* On X11, make `WINIT_HIDPI_FACTOR` dominate `Xft.dpi` in some cases

This commit makes `WINIT_HIDPI_FACTOR` dominate `Xft.dpi` in general and
adds a special value `0` for `WINIT_HIDPI_FACTOR` to use winit computed
DPI factor with randr over Xft.dpi.

* Use `randr` instead of `0` for auto dpi scaling

* Update CHANGELOG

* blow up on wrong env var

* Allow empty string for env var
2020-01-03 18:15:47 -05:00
hatoo
7367b8be6c On Macos, Hide cursor only inside window (#1348)
* On MacOS, hide cursor by invisible cursor

* Add CHANGELOG

* Fix variable name

* Add comments for `CURSOR_BYTES`
2020-01-03 03:34:14 +03:00
hatoo
dd768fe655 MacOS fix CursorEntered and CursorLeft events fired at old window size. (#1335)
* On macOS, Fix `CursorEntered` and `CursorLeft`

* Add CHANGELOG

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
2019-12-30 13:32:37 -07:00
Osspial
d9bda3e985 Implement ModifiersChanged on Windows, and fix bugs discovered in implementation process (#1344)
* Move DeviceEvent handling to the message target window.

Previously, device events seem to have only been sent to one particular
window, and when that window was closed Winit would stop receiving
device events. This also allows users to create windowless event loops
that process device events - an intriguing idea, to say the least.

* Emit LWin and RWin VirtualKeyCodes on Windows

* Implement ModifiersChanged on Windows

* Make ModifiersChanged a tuple variant instead of a struct variant

* Add changelog entries

* Format

* Update changelog entry

* Fix AltGr handling

* Reformat

* Publicly expose ModifiersChanged and deprecate misc. modifiers fields
2019-12-30 14:11:11 -05:00
hatoo
fa7a3025ec [MacOS] Fix memory management (#1342)
* macOS, Reduce memory usage

* macOS, Fix memory leak
2019-12-29 15:16:12 -07:00
Osspial
e4451d6786 Fix Window::set_visible not setting internal flags correctly (#1345) 2019-12-29 10:39:15 -05:00
Michael Tang
468b6b83ec fix: remove deprecated usage of mem::uninitialized. (#1341) 2019-12-28 18:53:41 -05:00
Osspial
8a3a32f286 Properly mark a few changes as breaking 2019-12-28 16:22:51 -05:00
Osspial
20e81695ca Change ModifiersState to a bitflags struct (#1306)
* Change ModifiersState to a bitflags struct

* Make examples work

* Add modifier state methods

* all things considered, only erroring out in one file throughout all of these changes is kinda impressive

* Make expansion plans more clear

* Move changelog entry

* Try to fix macos build

* Revert modifiers println in cursor_grab

* Make serde serialization less bug-prone
2019-12-28 15:36:06 -05:00
Osspial
027c52171d Fix changelog 2019-12-27 16:28:06 -05:00
Osspial
cc206d31b7 Implement windows focus key press/release on Windows (#1307)
* X11: Sync key press/release with window focus

* When a window loses focus, key release events are issued for all pressed keys
* When a window gains focus, key press events are issued for all pressed keys
* Adds `is_synthetic` field to `WindowEvent` variant `KeyboardInput`
  to indicate that these events are synthetic.
* Adds `is_synthetic: false` to `WindowEvent::KeyboardInput` events issued
  on all other platforms

* Implement windows focus key press/release on Windows

* Docs

Co-authored-by: Murarth <murarth@gmail.com>
2019-12-27 16:26:23 -05:00
hatoo
5d99316c96 macOS: Don't change fullscreen state during fullscreen transition (#1331)
* Register windowWillExitFullScreen

* On macOS: Do not toggle fullscreen during fullscreen transition

* Add CHANGELOG

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
2019-12-24 11:56:56 -07:00
David Hewitt
d59eec4633 Add support for Windows Dark Mode (#1217)
* Add support for Windows Dark Mode

* Add is_dark_mode() getter to WindowExtWindows

* Add WindowEvent::DarkModeChanged

* Add support for dark mode in Windows 10 builds > 18362

* Change strategy for querying windows 10 build version

* Drop window state before sending event

Co-Authored-By: daxpedda <daxpedda@gmail.com>

* Change implementation of windows dark mode support

* Expand supported range of windows 10 versions with dark mode

* Use get_function! macro where possible

* Minor style fixes

* Improve documentation for ThemeChanged

* Use `as` conversion for `BOOL`

* Correct CHANGELOG entry for dark mode

Co-authored-by: daxpedda <daxpedda@gmail.com>
Co-authored-by: Osspial <osspial@gmail.com>
2019-12-22 12:04:09 -07:00
Osspial
25e018d1ce Fix extraneous # in 0.20.0 Alpha 5 2019-12-22 11:24:49 -05:00
Osspial
25123bed23 Rebasing moved the RedrawRequested changelog entry to the wrong position
:/
2019-12-22 11:23:27 -05:00
Osspial
a8d6db0fc1 Update alpha version in readme.md 2019-12-22 11:19:17 -05:00
Osspial
8a9a9cd92d Move changelog entry into proper position
Fix window_run_return

Make docs build
2019-12-22 11:17:24 -05:00
simlay
530ff5420b Implement revamped RedrawRequested on iOS. (#1299)
* Implement revamped `RedrawRequested` on iOS

* Added RedrawEventsCleared to events_cleared logic

* Fixed from comments

* Added RedrawEventsCleared to draw_rect handler.

* Fixed out of order `RedrawEventsCleared` events.

* cargo fmt
2019-12-22 11:17:23 -05:00
Héctor Ramón
133b11fa6d Implement revamped RedrawRequested on Web (#1301)
* Implement revamped `RedrawRequested` on Web

* Add `web` example
2019-12-22 11:17:23 -05:00
Héctor Ramón
5b489284e4 Implement revamped RedrawRequested on macOS (#1235) 2019-12-22 11:17:23 -05:00
Heghedus Razvan
cdc32eb817 Implemented revamped RedrawRequested for linux wayland (#1237)
Signed-off-by: Heghedus Razvan <heghedus.razvan@gmail.com>
2019-12-22 11:17:23 -05:00
Osspial
eb38ff453a Run rustfmt 2019-12-22 11:17:23 -05:00
Osspial
8eb7853a1a Implement revamped RedrawRequested on Windows (#1050)
* Move event loop runner to runner module

* Implement new redraw API
2019-12-22 11:17:23 -05:00
Murarth
0c151f9fb3 Implement changes to RedrawRequested event (#1062)
* Implement changes to `RedrawRequested` event

Implements the changes described in #1041 for the X11 platform and for
platform-independent public-facing code.

* Fix `request_redraw` example

* Fix examples in lib docs

* Only issue `RedrawRequested` on final `Expose` event
2019-12-22 11:17:23 -05:00
simlay
c10c820311 Reimplement NativeDisplayMode on iOS for #1310 (#1330)
* Reimplement NativeDisplayMode on iOS for #1310

* Type annotations from code review.

Co-Authored-By: Aleksi Juvani <3168386+aleksijuvani@users.noreply.github.com>

Co-authored-by: Aleksi Juvani <3168386+aleksijuvani@users.noreply.github.com>
2019-12-22 01:39:22 -07:00
Justin Miller
82889e2367 Window::set_minimized (#985) (#990)
* Expose set_minimized. Implement for macOS (#985)

* Implement set_minimized for Wayland (#985)

Co-Authored-By: Victor Berger <vberger@users.noreply.github.com>

* Implement set_minimized for Windows (#985)

* Remove debug logs (#985)

* Implement Window::set_minimized for X11

* Remove extra param from set_window_flags call

* Cargo fmt

* Add example of usage

* Update changelog

* Update feature matrix

* Cargo fmt

* Update example to remove unnecessary event var

* Stop setting window styles when minimizing (#985)

* Add stub for WASM (#985)

Co-authored-by: Victor Berger <vberger@users.noreply.github.com>
Co-authored-by: Murarth <murarth@gmail.com>
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Osspial <osspial@gmail.com>
2019-12-22 01:04:11 -05:00
Osspial
92741aa4ec Fix array_into_iter warning on Windows (#1329) 2019-12-21 17:49:44 -07:00
Murarth
2f352ca5cf X11: Fix CursorEntered event for non-winit window (#1320)
* X11: Fix CursorEntered event for non-winit window

* Retry CI

Co-authored-by: Osspial <osspial@gmail.com>
2019-12-21 17:47:29 -07:00
hatoo
38c8cb9f4a FIX Crash on macOS when starting maximized without decorations (#1323)
* FIX #1288

* Fix CHANGELOG.md

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
2019-12-19 18:03:41 -07:00
Kirill Chibisov
73248bdced On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode (#1324)
Mutter can reposition window on resize, if it is behind mutter's "bounding box".
So, when you start winit window in maximized mode with CSD, mutter places its CSD
behind the GNOME's status bar initially, and then sends configure with the
exact same size as your current window. If winit decides to optimize calling
frame.resize(..) in this case, we won't call set_geometry(we're calling
it through resize) and GNOME won't reposition your window to be inside the
"bounding box", which is not a desired behavior for the end user.
2019-12-19 17:08:28 -07:00
hatoo
01203b247b Fix run_return in MacOS (#1321)
* Fix run_return in MacOS

* MacOS: Fix the way of getting a window in run_return

* Fix CHANGELOG.md
2019-12-19 12:10:47 +03:00
Kirill Chibisov
3e1d169160 On Wayland, fix cursor icon updates on window borders when using CSD (#1322)
* On Wayland, fix cursor icon updates on window borders when using CSD

* Move changelog entry to a right place
2019-12-18 06:41:44 -07:00
Christian Duerr
c1b93fc3d0 Add ModifiersChanged event for macOS (#1268)
* Add ModifiersChanged event for macOS

This implements the macOS portion of #1124.

* Fix ModifiersChanged event import

* Fix event passing window instead of device id
2019-12-13 00:48:32 +03:00
Murarth
1f81e5c872 X11: Report CursorMoved when touch event occurs (#1297)
* X11: Report `CursorMoved` when touch event occurs

* Only trigger CursorMoved events for the first touch ID

* Fix testing for current touch events

* Fix first touch logic
2019-12-11 17:23:55 -07:00
Manish Goregaokar
e5291c9e28 Release 0.20.0-alpha5 (#1315) 2019-12-09 17:29:50 -07:00
Murarth
35505a3114 X11: Sync key press/release with window focus (#1296)
* X11: Sync key press/release with window focus

* When a window loses focus, key release events are issued for all pressed keys
* When a window gains focus, key press events are issued for all pressed keys
* Adds `is_synthetic` field to `WindowEvent` variant `KeyboardInput`
  to indicate that these events are synthetic.
* Adds `is_synthetic: false` to `WindowEvent::KeyboardInput` events issued
  on all other platforms

* Clarify code with comments
2019-12-07 15:51:37 -07:00
zserik
830d47a5f7 Have EventLoopClosed contain the original event (#1294)
* Fix issue #1292

* Remove "optionally" from changelog entry
2019-12-07 10:22:03 -07:00
Murarth
1a514dff38 X11: Fix incorrect DPI factor when waking from suspend (#1303) 2019-12-04 10:18:20 -07:00
Osspial
2888d5c6cf Fix array_into_iter warning on Windows (#1308) 2019-12-04 12:02:33 -05:00
Osspial
400f75a2b3 Make WindowStore::for_each less terrifying to rebase (#1304) 2019-12-04 03:55:49 -05:00
Charles Helmich
07bdd3e218 Fix ReceivedCharacter not working with Alt held on Windows (#1282)
* Fix ReceivedCharacter with Alt held on Windows

* Update CHANGELOG.md
2019-11-29 15:49:43 -05:00
Héctor Ramón
35a11ae24f Stop emitting corporate characters in macOS (#1254) 2019-11-27 12:14:36 +03:00
Ryan G
3d28283a81 Only use 'extern crate stdweb' on web targets (#1291)
The 'extern crate' declaration shouldn't be there even if the stdweb feature is on, unless the crate is being compiled for web.
2019-11-27 00:38:18 -05:00
daxpedda
aec5a9fa09 Stop refocusing window when switching from fullscreen to windowed (#1285)
* Stop refocusing window when switching from fullscreen to windowed

* Update Changelog.
2019-11-26 22:49:14 -05:00
Manish Goregaokar
0f94f62025 Bump parking_lot to 0.10 (#1287) 2019-11-25 18:05:44 -07:00
Murarth
a95ebc5ee6 X11: Fix incorrect modifiers when events are missed (#1279)
* X11: Fix incorrect modifiers when events are missed

* Syncs modifier state with state data in X key/button/motion events.
* Fixes modifier state in XWayland, as xinput2 raw input events will
  not be received when a window does not have focus.
* Removes `impl From<_> for ModifiersState` on X11/Wayland API types,
  replacing them with `pub(crate)` methods.

* Cleanup modifier state update using a macro

* Remove keys from modifier state when updating
2019-11-22 17:11:30 -07:00
Murarth
a70ac1531e X11: Fix window creation hangs when another application is fullscreen (#1248)
* X11: Fix window creation hangs when another application is fullscreen

Previously, the X11 backend would block until a `VisibilityNotify` event
is received when creating a Window that is visible or when calling
`set_visible(true)` on a Window that is not currently visible. This
could cause winit to hang in situations where the WM does not quickly
send this event to the application, such as another window being
fullscreen at the time.

This behavior existed to prevent an X protocol error caused by setting
fullscreen state on an invisible window. This fix instead stores desired
fullscreen state when `set_fullscreen` is called (iff the window is not
visible or not yet visible) and issues X commands to set fullscreen
state when a `VisibilityNotify` event is received through the normal
processing of events in the event loop.

* Add window_debug example to facilitate testing

* Add a CHANGELOG entry

* Call `XUnmapWindow` if `VisibilityNotify` is received on an invisible window
2019-11-22 17:11:04 -07:00
ariesfluctus
b6e8dd0d8a Fixed typo (#1273) 2019-11-14 00:10:31 -05:00
Murarth
af80ce842d Fix cargo doc on nightly builds (#1274) 2019-11-12 16:51:46 -07:00
Osspial
08bae037f0 Use paths for intra-doc links, and verify that links are valid in CI (#1244)
* Use paths to generate intra-doc links

* Add entry to PR checklist
2019-11-11 16:05:59 -07:00
Thom Chiovoloni
cd39327ea2 Fix invalid_value lint triggering on mem::zeroed of CFRunLoopSourceContext (#1271) 2019-11-11 15:50:31 -07:00
Murarth
9828f368d6 X11: Fix misreporting DPI factor at startup (#1252)
* X11: Fix misreporting DPI factor at startup

* Add a CHANGELOG entry
2019-11-10 13:55:29 -07:00
Murarth
1ed15c7ec7 X11: Fix events not being reported when using run_return (#1245)
* X11: Fix events not being reported using `run_return`

* Adapt examples to be more practical

* Add CHANGELOG entry
2019-11-10 11:24:43 -07:00
Murarth
c66784995d X11: Fix modifiers being reported after release (#1262)
* X11: Fix modifiers being reported after release

* Moves `ModifiersChanged` variant from `WindowEvent` to `DeviceEvent`

* Add CHANGELOG entry
2019-11-10 00:16:44 -07:00
Murarth
dba21c06ed Run cargo fmt on Rust stable 1.39.0 (#1264) 2019-11-07 13:48:34 -07:00
Kirill Chibisov
72fc6a74ec on Wayland, drop resize events equal to the current window size (#1249)
* on Wayland, drop resize events equal to the current window size

* Add changelog entry
2019-10-31 20:45:45 -04:00
Michael Tang
f916311744 Add error message when building for web without selecting a feature. (#1253) 2019-10-31 12:45:12 -04:00
David Sinclair
05a1f4280c Miscellaneous small changes (#1238)
* Use a slice instead of a new object

* Remove unnecessary 'into_iter'

* Use 'and_then' instead of 'map_or'
2019-10-23 19:45:25 -04:00
Bogaevsky
6608a0241d macOS: fixes app termination (#1234)
* fixes app termination

* applies fmt

* fmt all

* updates changelog

* keeps formating consistent

* fixes misstype
2019-10-23 17:24:50 +03:00
Osspial
429bbfade0 Release Alpha 4 (#1187)
* Release Alpha 4. TODO CHANGELOG RELEASE DATE

* Add changelog date
2019-10-18 13:25:12 -04:00
Osspial
28e3c35547 Prevent EventLoop from getting initialized outside the main thread in cross-platform functions (#1186)
* Prevent EventLoop from getting initialized outside the main thread

This only applies to the cross-platform functions. We expose functions
to do this in a platform-specific manner, when available.

* Add CHANGELOG entry

* Formatting has changed since the latest stable update...

* Fix error spacing

* Unix: Prevent initializing EventLoop outside main thread

* Updates libc dependency to 0.2.64, as required by BSD platforms

* Update CHANGELOG.md for Linux implementation

* Finish sentence

* Consolidate documentation
2019-10-18 11:51:06 -04:00
Steven Sheldon
af3ef52252 Fix so the compiler can infer msg_send! return types (#1227)
* Fix so the compiler can infer msg_send! return type

Currently, due to a quirk in Rust's type inference interacting with the
structure of the msg_send! macro, a () return type will be inferred when
the compiler cannot otherwise determine the return type. This behavior
is expected to change, and in the future could resolve to a ! return
type, which results in undefined behavior.

Linting has previously been added for this in rust-lang/rust#39216, but
it did not catch these cases due to SSheldon/rust-objc#62. An upcoming
version of objc will be fixed to stop hiding these errors, at which
point they will become compile errors.

This change fixes these errors and allows winit to compile with the
fixed version of objc.

* Bump cocoa to 0.19.1
2019-10-18 11:33:40 -04:00
Osspial
2b5f9c52a6 Always dispatch a RedrawRequested event after creating a new window (#1175) 2019-10-17 10:59:07 -04:00
Ryan G
5631cc2528 Remove test files that stuck around on accident (#1226) 2019-10-16 22:46:16 -04:00
Aleksi Juvani
de33a92a1b Fix panic upon closing the app on iOS (#1168) 2019-10-16 18:52:10 -04:00
Ryan Goldstein
1c6353aa3a Merge branch 'web' 2019-10-16 16:09:39 -04:00
Marcus Willock
08cb950226 Link WindowBuilder documentation to corresponding Window methods (fixes #1070) (#1216)
* fixes #1070

* Continuing adding documentation links for #1070
2019-10-16 12:18:02 -04:00
Kirill Chibisov
765225d918 Wayland: Fix panic when calling set_cursor_grab from a different thread than evlp's one. (#1206)
This commit also start following X11 behavior on cursor icon update when
cursor is invisible.

Fixes regression introdced in 5ced36e319
2019-10-16 12:16:23 -04:00
Ryan Goldstein
35bc65f6fa Remove usage of derivative 2019-10-13 14:36:54 -04:00
Ryan Goldstein
676268d461 Merge remote-tracking branch 'upstream/master' into web 2019-10-13 14:09:52 -04:00
Osspial
34dce8069f Test all windows targets and allow nightly Appveyor failures (#1222)
* Test all windows targets

* Allow nightly failures
2019-10-13 13:19:46 -04:00
Ryan G
f62bb33317 Merge branch 'master' into web 2019-10-12 23:51:34 -04:00
Ryan G
a557b3cfb6 Add web targets to travis (#1220)
* Add web targets to travis

* Fix some bash syntax

* Avoid crash on providing no features

* Fix syntax error

* Syntax?

* Fix pleas

* Fix features check

* Add a comment

* Add nightly builds
2019-10-12 23:44:30 -04:00
Ryan G
3ff4834bd5 Add web fullscreen support (#1142)
Adds fullscreen using native web APIs to the stdweb and web-sys backends.

Due to limitations of browser APIs, requests for fullscreen can only be fulfilled during a short-lived user-triggered event. This commit does automatically handle that under the hood, but it does introduce unavoidable latency in full-screening the canvas.
2019-10-11 11:45:07 -04:00
Ryan G
bedb889693 Fix the event key code variable name (#1219) 2019-10-11 11:41:49 -04:00
Ryan G
157ca9cd17 Update the feature matrix for wasm (#1218) 2019-10-09 19:49:12 -04:00
Osspial
6f5e7e170c Update raw-window-handle to 0.3 (#1215) 2019-10-05 21:34:27 -04:00
Osspial
df7571b369 Improve interaction between fullscreen windows and monitor-switching keyboard shortcuts (#1171)
* Update to 1.38.0 formatting

* Improve fullscreen window monitor switching on Windows

* Format
2019-10-05 16:23:30 -04:00
Aleksi Juvani
d69e41eba8 Update fullscreen state on macOS before entering fullscreen (#1196) 2019-10-05 16:23:06 -04:00
Benjamin Saunders
2d41a7d1b0 Fix use-after-free in XConnection::get_output_info (#1211) 2019-10-05 15:00:54 -04:00
Antonino Siena
42e0ccfa1c Implemented a HINSTANCE getter function for Windows (#1213)
* Expose HINSTANCE now using a getter function

* Missing changes

* remove unused import

* Required changes for the PR

* Rust fmt

* Use GetWindowLong

* Use GetWindowLong
2019-10-05 14:52:40 -04:00
Lúcás Meier
55640a91ae Use consistent return types for available_monitors() (#1207)
* [#1111] Use consistent return types for available_monitors()

Always use `impl Iterator<Item = MonitorHandle>` instead of
`AvailableMonitorsIter`. Fix an example that used the Debug
implementation of `AvailableMonitorsIter`.

* [#1111] Update changelog

* [#1111] Remove AvailableMonitorsIter type completely

* [#1111] Remove doc references to AvailableMonitorsIter
2019-10-05 10:49:24 -04:00
Alex Butler
4f6ca8792c Remove derivative dependency (#1201)
* Remove derivative dependency

* Update CHANGELOG.md
2019-10-03 16:19:10 -04:00
Kirill Chibisov
5ced36e319 Wayland support for set_cursor_icon (#1204) 2019-10-03 06:02:59 -07:00
andersrein
237e7ee2e6 Wayland support for set_cursor_grab and set_cursor_visible (#1180)
* Fixed relative_pointer not being set up when the "zwp_relative_pointer_manager_v1" callback comes after the "wl_seat" callback

* Ran cargo fmt

* Updated changelog

* Added wayland support for set_grab_cursor and set_cursor_visible

* Updated changelog

* Ran cargo fmt

* Fixed set_cursor_visible and set_cursor_grab so they can be called from any thread.

* Ran cargo_fmt

* Improved CHANGELOG

* Added workaround so that when cursor is hidden it takes effect before the cursor enters the surface. Making the cursor visible again still only happens once the cursor re-enters the surface

* Switched to using Rc<RefCell> instead of Arc<Mutex> since all accesses to the relative_pointer_manager_proxy will happen on the same thread.

* Forgot to run cargo fmt

* Switched to using Rc and RefCell instead of Arc and Mutex where applicable.

* Improved comments and documentation relating to changing a hidden cursor back to visible on wayland.

* Wayland: Fixed cursor not appearing immendiately when setting the cursor to visible.

* Forgot to run cargo fmt

* Switched to only storing the pointers in CursorManager as AutoPointer.

* Fixed typo and removed println

* Update CHANGELOG.md

Co-Authored-By: Kirill Chibisov <wchibisovkirill@gmail.com>
2019-10-01 18:25:59 -07:00
Ryan Goldstein
02f281569d Update cargo fmt 2019-09-30 16:33:41 -04:00
Ryan Goldstein
ab4d971c5e Fix imports in the multithreaded example 2019-09-30 15:55:27 -04:00
Ryan Goldstein
e21df5831e Merge branch 'master' into merge-master-to-web 2019-09-30 11:19:12 -04:00
msiglreith
18a0119b06 Update raw-window-handle to 0.2 (#1191) 2019-09-30 11:17:01 -04:00
Osspial
34348435fd Update to 1.38.0 formatting (#1188) 2019-09-27 17:35:16 -04:00
Ryan Goldstein
cf3b0f3b70 Attach the raw handle data attribute 2019-09-27 17:06:14 -04:00
Ryan Goldstein
a336e9e959 Fix the formatting in the changelog 2019-09-27 16:57:25 -04:00
Ryan Goldstein
ea93a0130d Switch to the released version 2019-09-27 16:17:40 -04:00
Ryan Goldstein
dcd9ddde50 Fix the examples 2019-09-24 19:44:43 -04:00
Ryan Goldstein
86bafdc104 Merge branch 'web' into merge-master-to-web 2019-09-24 19:41:59 -04:00
Ryan Goldstein
6732fa731d Fix compilation errors 2019-09-24 19:39:13 -04:00
Ryan G
8cea3e262b Update the documentation to reflect web support (#1183)
* Update the documentation to reflect web support

Indicate which methods have platform-specific web behavior

* cargo fmt
2019-09-24 19:33:32 -04:00
Ryan Goldstein
3e8669ea7f Merge branch 'master' into merge-master-to-web 2019-09-24 14:21:18 -04:00
andersrein
7df040f451 Wayland: Switched to using a reference to relative_pointer_manager_proxy when creating SeatData (#1179)
* Fixed relative_pointer not being set up when the "zwp_relative_pointer_manager_v1" callback comes after the "wl_seat" callback

* Ran cargo fmt

* Updated changelog

* Improved CHANGELOG

* Switched to using Rc<RefCell> instead of Arc<Mutex> since all accesses to the relative_pointer_manager_proxy will happen on the same thread.

* Forgot to run cargo fmt
2019-09-23 14:50:06 -04:00
Murarth
472eddcc1b X11: Fix panic when no monitors are available (#1158)
* X11: Fix panic when no monitors are available

* Set dummy monitor's dimensions to `(1, 1)`

* X11: Avoid panicking when there are no monitors in Window::new
2019-09-23 14:45:29 -04:00
Michael Palmos
c0a7900341 Allow using multiple XWindowTypes on X11 (#1140) (#1147)
* Allow using multiple `XWindowType`s on X11 (#1140)

* Update documentation to make combining window types clearer

* Update build flags because X11 runs on more than just Linux

* Revert "Update build flags because X11 runs on more than just Linux"

This reverts commit 882b910046.

* Revert "Update documentation to make combining window types clearer"

This reverts commit da00ad391a.

* Revert "Allow using multiple `XWindowType`s on X11 (#1140)"

This reverts commit a230333456.

* Allow using multiple `XWindowType`s on X11 (slice variant) (#1140)

* Multiple `XWindowType`s, with non-static lifetime.

* Multiple `XWindowType`s (#1140) (`Vec` variant)

* Append change to changelog.

* Fix formatting.
2019-09-23 07:10:33 -07:00
Ryan G
28a50817af Fix web redraw requested (#1181)
* Keep track of what windows have requested redraw

Instead of using request_animation_frame and sending redraw request
events, just keep track of all windows that have asked for a redraw.
This doesn't handle dispatching the events

* Issue redraw events to windows that request it

* Cargo fmt
2019-09-23 09:14:26 -04:00
Ryan G
2c47c43f47 Implement WindowID on the web platform (#1177)
* Use actual numeric IDs to differentiate Windows

This is generally important to identifying which window should
recieve which event, but is also specifically crucial for fixing
RedrawRequested on web.

* Cargo fmt
2019-09-19 18:40:18 -04:00
Osspial
2ef39651eb Fix fullscreen window shrinking upon getting restored to a normal window (#1172) 2019-09-19 11:48:20 -04:00
Murarth
eb20612d77 Prevent stealing focus on new windows (#1176) 2019-09-19 11:47:51 -04:00
Aleksi Juvani
695547f4ca Fix events not being emitted during modal loops on macOS (#1173) 2019-09-17 22:49:29 -04:00
Osspial
d35ee0d580 Fix hovering the mouse over the active window creating an endless stream of CursorMoved events (#1170)
* Fix hovering the mouse over the active window creating an endless stream of CursorMoved events

* Format
2019-09-17 11:34:48 -04:00
Aleksi Juvani
95581ab92f Fix null window on initial HiDpiFactorChanged event on iOS (#1167) 2019-09-16 14:27:46 -04:00
Osspial
3716f13d8e Flush high surrogate if not followed by low surrogate (#1166)
* Flush high surrogate if not followed by low surrogate

* Remove transmute from WM_CHAR handler

* Fix window_state being locked while dispatching ReceivedCharacter for surrogate codepoints.

* Format
2019-09-16 14:26:56 -04:00
Osspial
c03ef852a4 Fix surrogate pair handling on Windows (#1165)
* Fix surrogate pair handling on Windows

* Change high_surrogate to Option<u16>

* Format
2019-09-15 22:09:08 -04:00
Aleksi Juvani
28a5feef28 Fix freeze upon exiting exclusive fullscreen on macOS 10.15 (#1127) 2019-09-15 19:59:37 -04:00
Osspial
57a53bda74 Officially remove the Emscripten backend (#1159) 2019-09-13 19:09:45 -04:00
hafiz
36f4eccb5c fix: distinguish grab and grabbing cursors (#1154)
On macOS, there is a difference between a "grab" cursor and a "grabbing"
cursor, where "grab" is an open-hand cursor used during a hover, and
"grabbing" is a closed-hand cursor used on a click. These, and other
native MacOS cursors, can be seen at the [NSCursor documentation](https://developer.apple.com/documentation/appkit/nscursor?language=objc).

See https://github.com/hecrj/iced/issues/9 for the motivation for this
PR.
2019-09-12 16:38:44 -07:00
Victor Berger
b6de19e92e Changelog entry for #1153 (#1157) 2019-09-11 15:22:41 -07:00
Ryan G
e87bc3db20 Send a LoopDestroyed event when the browser is closed (#1155)
* Add the plumbing for handling browser closes

* Implement the business logic for handling closes
2019-09-11 11:47:03 -04:00
Victor Berger
a3739d6bad wayland: instantly wake up if events are pending (#1153)
Just before starting to poll/wait on calloop(mio), check if there
are already events pending in the internal buffer of our wayland
event queue. If so, dispatch them and force an instant wakeup from
the polling, in order to behave as if we were instantly woken up by
incoming wayland events.

When using OpenGL, mesa shares our wayland socket, and also reads
from it, especially if vsync is enabled as it'll do blocking reads.
When doing so, it may enqueue events in the internal buffer of our
event queue.

As the socket has been read, mio will thus not notify it to calloop
as read, and thus calloop will not know it needs to dispatch. In some
cases this can lead to some events being delivered much later than
they should. Combined with key repetition this can actually cause some
flooding of the event queue making this effect event worse.

Fixes #1148
2019-09-11 08:28:21 +02:00
dam4rus
068d114740 Add touch pressure information for touch events on Windows (#1134)
* Add touch pressure information for touch events on Windows

* Modified CHANGELOG.md and FEATURES.md to reflect changes

* Updated documentation of struct Touch to reflect changes

* Replaced mem::uninitalized() with mem::MaybeUninit
Fixed warnings in platform_impl/windows/dpi.rs
2019-09-09 14:15:49 -04:00
Hal Gentz
3273c14dea Hide ModifiersChanged from the docs. (#1152)
We wouldn't want users stumbling on it until all platforms implement it.
2019-09-08 12:57:43 -07:00
Murarth
206c3c246c Implement WindowEvent ModifiersChanged for X11 and Wayland (#1132)
* Implement WindowEvent ModifiersChanged for X11 and Wayland

* Fix modifier key state desync on X11

* Run cargo fmt
2019-09-08 11:43:28 -07:00
mtak-
bfcd85ab15 [ios] Groundwork for new Redraw API, refactoring AppState, and bugfixes (#1133)
* fix #1087. the CFRunLoopTimer was never started if the user never changed the controlflow.

* RedrawRequested ordering matches the new redraw api
consistent asserts
lots of appstate refactoring to rely less on unsafe, and hopefully make it easier to maintain

* ios: dpi bugfix. inputs to setContentScaleFactor are not to be trusted as iOS uses 0.0 as a sentinel value for "default device dpi".

the fix is to always go through the getter.

* move touch handling onto uiview

* update changelog

* rustfmt weirdness

* fix use option around nullable function pointers in ffi

* Document why gl and metal views don't use setNeedsDisplay

* change main events cleared observer priority to 0 instead of magic number
log when processing non-redraw events when we expect to only be processing redraw events
2019-09-04 14:23:11 -07:00
Murarth
c99bba1655 Remove unused unix dlopen module (#1138) 2019-08-31 01:58:45 -07:00
Osspial
1e7376847b Move changelog entries into proper position (#1131) 2019-08-27 19:20:24 -04:00
Osspial
b03e589987 On Windows, Unset maximized when transforming window (#1014)
* Unset maximized when functionally transforming window

* Add docs

* Fix compile issues
2019-08-26 22:07:15 -04:00
Murarth
0b497b62d8 X11: Improve performance of Window::set_cursor_icon (#1116)
* X11: Fix performance issue with rapidly resetting cursor icon

* When setting cursor icon, if the new icon value is the same as the
  current value, no messages are sent the X server.

* X11: Cache cursor objects in XConnection

* Add changelog entry
2019-08-26 22:06:59 -04:00
Osspial
f085b7349c Remove outdated noop comment (#1126) 2019-08-26 22:06:40 -04:00
Aleksi Juvani
dd99b3bd73 Fix inverted parameter in set_prefers_home_indicator_hidden on iOS (#1123) 2019-08-26 19:56:10 -04:00
mtak-
f53683f01f iOS os version checking around certain APIs (#1094)
* iOS os version checking

* iOS, fix some incorrect msg_send return types

* address nits, and fix OS version check for unsupported os versions

* source for 60fps guarantee
2019-08-26 18:47:23 -04:00
Kirill Chibisov
7b707e7d75 macos: Implement run_return (#1108)
* macos: Implement run_return

* Update comments

* Fix CHANGELOG.md
2019-08-23 02:30:53 -07:00
Osspial
31110be396 Release alpha 3 (#1106) 2019-08-14 11:09:47 -04:00
Osspial
604016d69d Implement raw_window_handle::HasRawWindowHandle for Window type (#1105)
* Implement raw_window_handle::HasRawWindowHandle for Window type

* Format

* Address compilation issues

* Fix Linux build hopefully

* Fix iOS build
2019-08-14 07:57:16 -04:00
Zakarum
7ee9d5639b Disable web module on other targets than wasm32 (#1102) 2019-08-14 01:20:05 -07:00
mtak-
1aab328e2a macos: fix an incorrect type signature on NSView drawRect (#1104) 2019-08-14 00:01:22 -04:00
Aleksi Juvani
1366dc326a Add touch pressure information for touch events on iOS (#1090)
* Add touch pressure information for touch events on iOS

* Add a variant for calibrated touch pressure
2019-08-13 18:12:13 -04:00
satrix321
8e73287646 Change 'proxy.rs' into 'custom_events.rs" (#1101)
* changed i32 to CustomEvent enum
* added a match case for custom event
* minor cleanup
* fixes #953
2019-08-13 18:09:34 -04:00
Emmanouil Katefidis
7eed52a97a Update parking_lot to 0.9 (#1097) (#1099) 2019-08-11 13:31:30 -07:00
YVT
31ada5a052 macOS/iOS: Fix auto trait impls of EventLoopProxy (#1084)
* macOS/iOS: Fix auto trait impls of `EventLoopProxy`

`EventLoopProxy<T>` allows sending `T` from an arbitrary thread that
owns the proxy object. Thus, if `T` is `!Send`, `EventLoopProxy<T>` must
not be allowed to leave the main thread.

`EventLoopProxy<T>` uses `std::sync::mpsc::Sender` under the hood,
meaning the `!Sync` restriction of it also applies to
`EventLoopProxy<T>`. That is, even if `T` is thread-safe, a single
`EventLoopProxy` object cannot be shared between threads.

* Update `CHANGELOG.md`
2019-08-08 17:13:13 -07:00
Aleksi Juvani
30b4f8dc9f Replace set_decorations with set_prefers_status_bar_hidden on iOS (#1092) 2019-08-08 16:10:54 -07:00
Héctor Ramón
dbdde3d781 Stop appending canvas to document in web platform (#1089)
* Stop appending canvas to document in web platform

* Remove `tabindex` TODO in web backend

* Return `OsError` instead of panicking on web canvas creation
2019-08-08 14:51:41 -07:00
Hal Gentz
cf0b8babbd Add new EventLoopWindowTargetExtUnix trait. (#1026)
* Add new `EventLoopWindowTargetExtUnix` trait.

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

* Slide.

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

* Travis, damn you.

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

* Update CHANGELOG.md
2019-08-08 14:50:22 -07:00
Aleksi Juvani
c0c22c8ff1 Disable overscan compensation for external displays on iOS (#1088) 2019-08-06 16:47:00 -04:00
YVT
73cf10e4f3 Do not require T: Clone for EventLoopProxy<T>: Clone (#1086)
* Do not require `T: Clone` for `EventLoopProxy<T>: Clone`

* Update `CHANGELOG.md`

* Remove the conflicting `Clone` impl

* Fix match statement
2019-08-05 16:51:42 -04:00
mtak-
8a1c5277eb iOS: update feature table (#1085) 2019-08-01 15:07:22 -06:00
Aleksi Juvani
1e4c176506 Fix armv7-apple-ios compile target (#1083) 2019-08-01 01:30:05 -06:00
mtak-
3c27e7d88f iOS: add support for controlling the home indicator, and Exclusive video mode (#1078)
* iOS: platform specific edge home indicator control

* iOS: exclusive video mode support

* address nits, and linkify all the ios documentation
2019-07-31 00:57:31 -06:00
Aleksi Juvani
5bc3cf18d9 Add exclusive fullscreen mode (#925)
* Add exclusive fullscreen mode

* Add `WindowExtMacOS::set_fullscreen_presentation_options`

* Capture display for exclusive fullscreen on macOS

* Fix applying video mode on macOS after a fullscreen cycle

* Fix compilation on iOS

* Set monitor appropriately for fullscreen on macOS

* Fix exclusive to borderless fullscreen transitions on macOS

* Fix borderless to exclusive fullscreen transition on macOS

* Sort video modes on Windows

* Fix fullscreen issues on Windows

* Fix video mode changes during exclusive fullscreen on Windows

* Add video mode sorting for macOS and iOS

* Fix monitor `ns_screen` returning `None` after video mode change

* Fix "multithreaded" example on macOS

* Restore video mode upon closing an exclusive fullscreen window

* Fix "multithreaded" example closing multiple windows at once

* Fix compilation on Linux

* Update FEATURES.md

* Don't care about logical monitor groups on X11

* Add exclusive fullscreen for X11

* Update FEATURES.md

* Fix transitions between exclusive and borderless fullscreen on X11

* Update CHANGELOG.md

* Document that Wayland doesn't support exclusive fullscreen

* Replace core-graphics display mode bindings on macOS

* Use `panic!()` instead of `unreachable!()` in "fullscreen" example

* Fix fullscreen "always on top" flag on Windows

* Track current monitor for fullscreen in "multithreaded" example

* Fix exclusive fullscreen sometimes not positioning window properly

* Format

* More formatting and fix CI issues

* Fix formatting

* Fix changelog formatting
2019-07-29 14:16:14 -04:00
Brian Kabiro
131e67ddc1 Rename new_user_event method to with_user_event (#1057) (#1068)
Finishes #1057
2019-07-29 08:58:16 -06:00
dam4rus
e5ba79db04 Process WM_SYSCOMMAND to forbid screen savers in fullscreen mode (#1065)
* Process WM_SYSCOMMAND to forbid screen savers in fullscreen mode

Fixes #1047

* Update CHANGELOG.md and documentation to reflect changes from issue #1065

* Updated documentation of window.Window.set_fullscreen to match the documentation of window.WindowBuilder.with_fullscreen.
2019-07-29 03:18:23 -06:00
t嘎
f4e9bf51db add macos with_disallow_hidpi (#1073)
* add macos with_disallow_hidpi

add CHANGELOG

* Always use stable rustfmt for CI. (#1074)

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

* add macos with_disallow_hidpi

add CHANGELOG
2019-07-29 02:07:36 -06:00
Hal Gentz
03f9e8fce0 Always use stable rustfmt for CI. (#1074)
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2019-07-28 03:09:31 -06:00
Felix Rabe
4ae9900363 PULL_REQUEST_TEMPLATE.md: Add entry on warnings (#1017) 2019-07-26 01:14:48 -06:00
dam4rus
454d4190b7 Use himetric values in WM_POINTER events (#1053)
* Use himetric location for WM_POINTER events

* Ran rustfmt
2019-07-26 01:12:06 -06:00
Austin Lasher
a28b60578d Fix run_return example build error on non-desktop platforms (#1067) 2019-07-25 14:56:24 -04:00
Tilman Schmidt
5a206de620 macOS: Drop the closure on exit. (Fixes #1058) (#1063) 2019-07-23 14:44:06 -06:00
Simon Sapin
b547531499 Update the percent-encoding crate to 2.0 (#1066) 2019-07-23 13:38:45 -04:00
Murarth
39e668ffb0 Fix CHANGELOG.md (#1061) 2019-07-22 19:26:52 -06:00
Murarth
bd1ac6cb1e X11: Fix events not being reported promptly (#1048)
* X11: Fix events not being reported promptly

* Add an entry to the changelog
2019-07-17 14:09:02 -04:00
dam4rus
8567758156 Touch events emit screen coordinates instead of client coordinates on Windows (#1042)
* Touch events emit screen coordinates instead of client coordinates on Windows

Fixes #1002

* Don't lose precision of WM_TOUCH events when converting from screen space to client space

* Updated CHANGELOG.md to reflect changes from issue: #1042
2019-07-17 12:25:35 -04:00
Ryan G
e897d70733 Bump the stdweb version to 0.4.18 (#1049)
This removes the need to patch to a git version
2019-07-16 21:56:58 -06:00
Ryan Goldstein
fe12996382 Update the web backend todo list 2019-07-16 20:00:03 -07:00
Murarth
e8e4d4ce66 X11: Fix request_redraw deadlock while handling RedrawRequested (#1046) 2019-07-16 16:53:41 -06:00
Felix Rabe
44af4f4f52 Minor doc changes (#1024)
* Minor doc changes

* More typos
2019-07-12 19:05:07 -04:00
Murarth
7daf146801 Replace std::mem::uninitialized with MaybeUninit (#1027)
* Replace `std::mem::uninitialized` with `MaybeUninit`

* Avoid undefined behavior when using `MaybeUninit`

* Restore unused `PointerState` fields as internally public

* Zero-initialize some struct values in Xlib FFI calls

* Reform usage of `MaybeUninit` in Xlib FFI

* Prefer safe zero-initialization using `Default`, when possible
* Zero-initialize integers and floats using `0` or `0.0`
* Use `MaybeUninit::uninit` for large byte buffers and union types
* Use `MaybeUninit::uninit` when the resulting value is ignored
2019-07-11 10:34:32 -06:00
Héctor Ramón
7b23d190b1 Fix web errors (#1040)
* Fix old `use` declarations

* Fix hidden lifetime parameter

* Fix missing methods in `web::Monitor`.

Originally fixed by @ryanisaacg in 94387c4bf5.

* Disable some tests and examples on `wasm32`
2019-07-10 18:54:54 -04:00
Osspial
17b8310517 Update Windows Multitouch in FEATURES.md (#1039)
It seems we were already implementing multitouch on Windows, and the question mark was inaccurate.
2019-07-10 18:54:34 -04:00
Osspial
5ca828d445 Merge pull request #1031 from rikusalminen/event_loop_test
Add NewEvents(Init) callback to x11
2019-07-10 11:29:21 -04:00
Riku Salminen
1ea29b4de0 x11: NewEvents(StartCause::Init) callback at start
Before starting the event loop, invoke callback with
NewEvents(StartCause::Init).
2019-07-10 15:27:57 +03:00
Osspial
b00cdadb5b Merge pull request #991 from dam4rus/master
Handle WM_POINTER* events in favor of WM_TOUCH
2019-07-10 02:30:09 -04:00
Osspial
53e646dabc Merge pull request #1038 from ZeGentzy/web
Webmerge4
2019-07-10 02:17:21 -04:00
Hal Gentz
613fafdfdf Merge branch 'web' into webmerge2 2019-07-09 22:50:51 -06:00
Osspial
5d0bc5f607 Correct 0.20.0 Alpha 2 release date 2019-07-09 19:19:00 -04:00
Osspial
ce5cf97e17 Release Alpha 2 (#996) 2019-07-09 18:25:32 -04:00
Felix Rabe
3ee59696e5 Always use f as the argument name for &mut std::fmt::Formatter (#1023) 2019-07-09 17:49:07 -04:00
aloucks
f5c624bcd6 Handle RedrawRequested event in request_redraw example (#1030) 2019-07-08 22:22:10 -06:00
Kalmár Róbert
026b331ba5 Handle WM_POINTER* events in favor of WM_TOUCH
Fixes #975
2019-07-08 10:13:02 +02:00
Kalmar Robert
93c36ccf78 Handle WM_POINTER* events in favor of WM_TOUCH
Fixes #975.
2019-07-08 10:12:47 +02:00
Felix Rabe
c1f314ccdc MacOS: request_user_attention(bool -> enum) (#1021) 2019-07-07 14:14:00 -06:00
Felix Rabe
53a89f28a0 Remove dead code (unused as of d5391686a) (#1022) 2019-07-07 14:13:17 -06:00
Felix Rabe
f874d76289 Fix warnings (#1020)
* Windows: Fix warning

* iOS: Fix warning
2019-07-07 14:12:39 -06:00
Héctor Ramón Jiménez
76645f3b5a Bump version 2019-07-07 05:51:06 +02:00
Bradley Smith
28775be115 Fix transparent window with decorations (#1011)
* Fix transparent window with decorations

* To changelog, added fix for transparent decorated windows.
2019-07-06 13:29:15 -04:00
Felix Rabe
7d3ff3d2d9 Fix warning (#1016) 2019-07-06 13:28:50 -04:00
Osspial
4a5d639d74 On Windows, fix with_maximized not properly setting window size to entire window. (#1013) 2019-07-05 17:28:11 -04:00
Osspial
74a7cf55ea Fix issues with redraw_requested when called during EventsCleared (#994)
* Fix issues with redraw_requested when called during EventsCleared

* Format

* Fix event dispatch after RedrawRequested but before EventsCleared

This could happen if the event queue was cleared, we processed WM_PAINT,
but the event queue got re-filled before we checked to see it was empty.

* Fix paint ordering issues when resizing window

* Format
2019-07-04 16:14:15 -04:00
Murarth
9393b14b01 X11: Disable maximize on non-resizable windows (#1000)
* X11: Disable maximize on non-resizable windows

* Add a note for the source for Motif WM constants
2019-07-04 04:43:44 -06:00
Aleksi Juvani
f8bd671073 Remove Metal dependency on macOS (#1003) 2019-07-03 14:19:07 -04:00
Murarth
2af753f307 Fix warnings on Linux (#1004) 2019-07-03 14:18:42 -04:00
Héctor Ramón Jiménez
5cc84f32db Improve feature names to enable web backends 2019-07-01 20:43:54 +02:00
Héctor Ramón Jiménez
e89674d337 Add dyn keyword where necessary 2019-07-01 20:23:42 +02:00
Héctor Ramón Jiménez
de120280e3 Fix mouse release/press events 2019-06-29 17:48:22 +02:00
Héctor Ramón Jiménez
7f2ba0ee3e Fix set_cursor_icon 2019-06-29 17:48:01 +02:00
Michael Streif
5bf303fd26 Improve handling of file paths in the windows DnD handler (#980)
* Make FileDropHandler::iterate_filenames more robust

by replacing the call to mem::uninitialized with mem::zeroed and change
file name retrieval to use buffers of exact length as reported
by DragQueryFileW instead of relying on MAX_PATH.

* Change remaining calls of uninitialized to zeroed

* Run rustfmt

* Add CHANGELOG entry and comment
2019-06-28 18:07:36 -04:00
Felix Rabe
e37e46b155 Remove comment that contradicts code (#992) 2019-06-28 15:32:27 -04:00
Victor Berger
b8192ef6f6 Revert "wayland: use an invisible surface as shell surface (#835)" (#981)
This reverts commit 65587ef43a.

It introduced sublte bugs in its interaction with OpenGL and glutin,
so we should better revert it for now.
2019-06-28 15:31:54 -04:00
Ho-Yon Mak
23354cf1a5 Implement _NET_WM_PING for X11 (#977) 2019-06-27 18:40:27 -06:00
Felix Rabe
dd38fab2f3 examples/window_icon.rs: De-duplicate code (#988) 2019-06-27 11:59:13 -04:00
Tristam MacDonald
ac08601b40 Implement DeviceEvent::Button on Mac (#967)
* Add deviceevent logging to cursor_grab example

* Implement DeviceEvent::Button on Mac
2019-06-27 02:58:21 -04:00
Héctor Ramón Jiménez
ea73dac753 Fix feature names 2019-06-27 01:18:46 +02:00
Héctor Ramón Jiménez
2a35646520 Use latest stdweb revision 2019-06-27 00:23:58 +02:00
Héctor Ramón Jiménez
bb285984da Implement stdweb backend for web platform 2019-06-27 00:02:46 +02:00
Austin Lasher
34db2d7d4c Fix broken links to mod DPI on various documentation pages (#984) 2019-06-26 15:35:54 +02:00
chichid
0e20973bdb Fix 968: Invisible windows steal focus from visible windows Win32 (#968) 2019-06-26 00:04:49 -04:00
Murarth
29e2481597 Remove XFlush call in event loop (#982)
Internally, `XFlush` calls `_XSend` to write data. It then calls
`XEventsQueued(display, QueuedAfterReading)`, which reads data from the
X server connection. This prevents the event loop source callback from
being run, as there is no longer data waiting on the socket.

Ideally, we would want to call `_XSend` directly to ensure that no
output is buffered by Xlib. However, this function is not exported as
part of Xlib's public API.

Testing with the `XFlush` call removed does not appear to adversely
affect the performance of an application. If any bugs should eventually
arise from this change, perhaps another function may be used in place of
`XFlush`, such as `XPending`, which writes buffered output but does not
so aggressively read from the X server connection.

Closes #865
2019-06-25 15:29:52 -06:00
Héctor Ramón Jiménez
1596cc5d9e Avoid leaking implementation details in Canvas API 2019-06-25 21:36:24 +02:00
Héctor Ramón Jiménez
8f66d96915 Support ReceivedCharacter event 2019-06-25 21:18:11 +02:00
Héctor Ramón Jiménez
8ad078b964 Implement keyboard and blur/focus events 2019-06-25 21:01:13 +02:00
Héctor Ramón Jiménez
d5368d7979 Implement Canvas::request_redraw 2019-06-25 18:39:41 +02:00
Héctor Ramón Jiménez
9c5657b86c Remove Canvas when dropped 2019-06-25 18:19:22 +02:00
Héctor Ramón Jiménez
b79089ea57 Implement web_sys::Canvas event listeners 2019-06-25 18:07:47 +02:00
Cherser-s
3555de114a Wayland: Add relative pointer movement (#973)
* Add relative pointer movement for Wayland

* Format changed code with rustfmt

* Wayland: merge window and device event queues into one

* Replace map_or_else call for simplification
2019-06-25 03:00:41 -06:00
Héctor Ramón Jiménez
c5703eb00a Draft web platform structure 2019-06-25 03:15:34 +02:00
Austin Lasher
dbe6a1bcdf Update docs to differentiate DeviceEvents and WindowEvents (#976) 2019-06-24 17:30:06 -04:00
Héctor Ramón Jiménez
eea9530f38 Merge remote-tracking branch 'blm/web-sys' into stdweb-eventloop-2 2019-06-24 18:31:56 +02:00
Osspial
a195ce8146 Re-format on stable rustfmt (#974) 2019-06-24 12:14:55 -04:00
Ryan Goldstein
a0f280e71f Update how timeouts are cleared to avoid possible double-clearing 2019-06-23 14:38:35 -07:00
Ryan Goldstein
cf28751ae3 Remove unnecessary set-to-wait in example 2019-06-23 14:38:16 -07:00
Felix Rabe
9dd15d00d8 Update PULL_REQUEST_TEMPLATE.md (#969) 2019-06-23 14:05:37 -04:00
Felix Rabe
2442305bb7 Forward porting (#966)
* README: Use shields.io instead of Herokuapp (#859)

* README: Link to FEATURES.md and missing features wiki page (#860)

Closes #854

* Update URLs (#863)

* CHANGELOG.md: Add line from #861 (legacy) that is missing from equivalent #964 (EL 2)
2019-06-23 02:39:26 -04:00
Felix Rabe
063648368d CHANGELOG.md: Move entries for #805 to 0.19.1 (#965) 2019-06-22 13:57:56 -04:00
Osspial
918b2efce7 Improve the example in lib.rs (#957) 2019-06-22 13:26:06 -04:00
Abendstolz
2467a997f4 [#963] Change XRandR display size check to also take height into account (#964) 2019-06-22 18:48:51 +02:00
Felix Rabe
f457c6a0b8 Change Suspended(true/false) => Suspended/Resumed (#959) 2019-06-21 20:59:31 -06:00
Felix Rabe
1193cada46 Minor spelling changes (#960) 2019-06-21 18:34:55 -06:00
Felix Rabe
b0e09b8ffe Rephrase (#958) 2019-06-21 17:35:08 -06:00
Osspial
8d6e8bb8d1 Release 0.20.0 Alpha 1 (#913) 2019-06-21 11:33:44 -04:00
Osspial
e2c84725de Format everything and add rustfmt to travis (#951)
* Format everything and add rustfmt to travis

* Remove extern crate winit from examples and add force_multiline_blocks

* Format the code properly

* Fix inconsistent period in PULL_REQUEST_TEMPLATE.md

* Only run rustfmt on nightly

* Travis fixings
2019-06-21 11:33:15 -04:00
Ryan Goldstein
b571362bf1 Fix a panic due to double-borrow 2019-06-20 21:46:01 -07:00
Osspial
b1b5aefc4b Implement fix described in #851 (#945)
* Implement fix described in #851

* Add changelog entry
2019-06-20 23:59:27 -04:00
Osspial
06244dd492 Remove window resize call in timer example (#938)
* Remove window resize call in timer example

* Move timer_length to separate variable

* Re-add _window
2019-06-19 22:06:09 -04:00
Osspial
de2f0740f7 Move contributors table to wiki (#934)
* Add stub wiki link instead of inline table

* Replace with real link

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md
2019-06-19 15:12:27 -04:00
Felix Rabe
c56a66cb90 Fix warnings (#929)
* Fix warnings

* Bring back derivatives crate for Windows
2019-06-19 15:12:01 -04:00
Felix Rabe
c1329ff156 Linkify HALL_OF_CHAMPIONS.md (#935) 2019-06-18 16:30:37 -06:00
Osspial
72509b5b42 Update example in README.md and add move prefix to window.rs example closure (#921)
* Update example in README.md and add move prefix to window.rs example

* Make Window and README example trivially capture window

* Update README.md
2019-06-18 11:15:55 -04:00
Aleksi Juvani
c35fdc8d61 Fix thread-safety of set_maximized and set_title on macOS (#922) 2019-06-18 00:34:27 -06:00
Ben Merritt
5d31f73302 Clean up Cargo.toml after incorrect rebase 2019-06-17 22:56:37 -07:00
Ben Merritt
7de1261555 Fix some warnings 2019-06-17 22:54:07 -07:00
Ben Merritt
91a511ba8c Replace JS snippet with throw_str 2019-06-17 22:54:07 -07:00
Ben Merritt
94f6294c0a Prevent callbacks from being destroyed too early 2019-06-17 22:54:07 -07:00
Ben Merritt
77cd3adb01 TEMPORARY: add testing example 2019-06-17 22:54:07 -07:00
Ben Merritt
7dabad4d71 Fix throwToEscapeEventLoop function 2019-06-17 22:51:23 -07:00
Ben Merritt
54b4074369 Port remaining modules to web_sys 2019-06-17 22:51:23 -07:00
Ben Merritt
e4d8e22846 Start implementing web-sys backend 2019-06-17 22:51:23 -07:00
Felix Rabe
403dcc02f4 CONTRIBUTING.md: Linkify project members (#933) 2019-06-17 16:52:30 -06:00
Felix Rabe
64be6e5c5e Typo (#932) 2019-06-17 16:22:01 -06:00
Felix Rabe
c661006683 Use dbg!() macro in monitor list example (#931) 2019-06-17 16:13:35 -06:00
CrLF0710
f879bca21c Migrate to 2018 edition. (#924)
* Migrate to 2018 edition.

* Use impl Iterator at one site.

* Fix more rust 2018 idioms.
2019-06-17 14:27:00 -04:00
Ryan Goldstein
182beb4f8b Indicate that I will be maintaing the stdweb backend 2019-06-16 21:34:54 -07:00
Ryan Goldstein
2690306f4a Implement Poll and WaitUntil in the stdweb backend 2019-06-16 21:30:05 -07:00
Ryan Goldstein
b59e3c670b WIP 2019-06-14 21:15:43 -07:00
Osspial
2e0bbc091f Set CHANGELOG.md merge style to union (#919) 2019-06-13 16:11:44 -04:00
Aleksi Juvani
91f05e940f Fix initial dimensions of a fullscreen window on Windows (#909) 2019-06-13 15:17:56 -04:00
Aleksi Juvani
db794b976c Disable caching on Travis (#918) 2019-06-13 14:24:44 -04:00
Victor Berger
9a11f90a02 x11/wayland: Don't reset control flow between loop ticks (#916) 2019-06-13 12:52:10 -04:00
Osspial
412516159f Document the caveats of run_return (#914) 2019-06-13 12:51:44 -04:00
Victor Berger
65587ef43a wayland: use an invisible surface as shell surface (#835)
This decorelates the window management from the actual user content,
meaning:

- the created window no longer needs the user to draw something to
  start existing
- it reduces our need to do roundtrips during initialization to
  avoid protocol errors
2019-06-13 12:50:02 -04:00
Osspial
cf713bef31 Remove CircleCI (#915)
None of the platforms that use it are supported right now, so it seems
silly to fail builds for other platforms when these ones can't possibly
succeed.

This should be reverted in stages as the platforms regain support.
2019-06-13 00:34:21 -06:00
Osspial
ea5c21950c Change Monitor dimensions functions to size functions (#911) 2019-06-13 00:33:44 -06:00
Aleksi Juvani
47b5dfa034 Support listing available video modes for a monitor (#896)
* Support listing available video modes for a monitor

* Use derivative for Windows `MonitorHandle`

* Update FEATURES.md

* Fix multiline if statement

* Add documentation for `VideoMode` type
2019-06-12 14:07:25 -04:00
Osspial
2b89ddec15 Fix WindowBuilder function names that missed first pass (#910) 2019-06-12 13:34:09 -04:00
Nikolai Vazquez
f256ff7d58 Make ns identifiers use snake_case on macOS (#904)
This makes the macOS API style consistent with that of iOS.
2019-06-10 19:09:38 -04:00
Christian Duerr
07356b9634 Update cursor visibility docs (#893)
The cursor visibility docs were still outdated from the rename and
talking about setting the invisibility, rather than visibility.

The platform-specific docs are unchanged since those should be fine and
the rest has been adapted using similar docs.
2019-06-01 18:06:41 -06:00
Ryan Goldstein
f2b6ef2edd Merge master into stdweb-eventloop-2
Update the internal APIs to match the new API changes
2019-06-01 13:21:50 -07:00
Ryan Goldstein
1409f83fb9 Add support for mouse wheel 2019-05-31 21:50:34 -07:00
Ryan Goldstein
37dadab745 Add access to the canvas in the Window 2019-05-31 21:50:25 -07:00
Osspial
0eefa3ba42 Fix compiler warning of potential undefined behavior (#892) 2019-05-30 20:42:53 -04:00
aloucks
08f8f89702 Fix control flow issues with Window::request_redraw (eventloop-2.0) (#890)
* Fix request_redraw with Poll and WaitUntil(time_in_the_past) on Windows

`Window::request_redraw` now fires a `RedrawRequested` event when
called from an `Event::EventsCleared` callback while the control
flow is set to `Poll`. A control flow of `WaitUntil(resume_time)`,
will now also fire the `RedrawRequested` event when `resume_time`
is in the past.

* Prevent panic on x11 when WaitUntil(resume_time) is in the past

* Prevent panic on wayland when WaitUntil(resume_time) is in the past
2019-05-29 22:33:52 -06:00
Osspial
0df436901a Refine function names and type signatures (#886)
* First name consistency pass. More to come!

* Remove multitouch variable (hopefully this compiles!)

* Remove CreationError::NotSupported

* Add new error handling types

* Remove `get_` prefix from getters.

This is as per the Rust naming conventions recommended in
https://rust-lang-nursery.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter

* Make changes to Window position and size function signatures

* Remove CreationError in favor of OsError

* Begin updating iOS backend

* Change MonitorHandle::outer_position to just position

* Fix build on Windows and Linux

* Add Display and Error implementations to Error types

* Attempt to fix iOS build.

I can't actually check that this works since I can't cross-compile to
iOS on a Windows machine (thanks apple :/) but this should be one of
several commits to get it working.

* Attempt to fix iOS errors, and muck up Travis to make debugging easier

* More iOS fixins

* Add Debug and Display impls to OsError

* Fix Display impl

* Fix unused code warnings and travis

* Rename set_ime_spot to set_ime_position

* Add CHANGELOG entry

* Rename set_cursor to set_cursor_icon and MouseCursor to CursorIcon

* Organize Window functions into multiple, categorized impls

* Improve clarity of function ordering and docs in EventLoop
2019-05-29 21:29:54 -04:00
Osspial
ae63fbdbbb Merge branch 'eventloop-2.0' of https://github.com/tomaka/winit into eventloop-2.0 2019-05-29 21:28:39 -04:00
Osspial
4f29618c73 I forgot to remove the backtrace dependency in the EL2 rework 2019-05-29 21:22:35 -04:00
Osspial
76660f3621 Fix Windows backend invoking unreachable! with Exit and run_return (#887) 2019-05-27 13:45:26 -04:00
mtak-
3a7350cbb9 El2.0 ios (#871)
* port ios winit el2.0 implementation to the new rust-windowing repo

* unimplemented! => unreachable
trailing comma in CFRunLoopTimerCallback

* implement get_fullscreen

* add iOS specific platform documentation. Add a TODO about how to possibly extend the iOS backend to work have methods callable from more than just the main thread

* assert that window is only dropped from the main thread

* assert_main_thread called from fewer places
2019-05-25 21:10:41 -04:00
aloucks
e5aa906b01 Fix macos compile error in fullscreen example (#885) 2019-05-25 15:23:54 -06:00
aloucks
4b0162a013 Update parking_lot to 0.8 (for windows, too) (#884)
The previous attempt to update parking_lot missed the windows platform.

The parking_lot dependency is now no longer specified twice to help
prevent that mistake from happening again.
2019-05-25 15:23:09 -06:00
Bastien Orivel
5be88e79b0 Update parking_lot to 0.8 (#882) 2019-05-25 10:12:07 -06:00
Lucas Kent
93502e0cda Fix warning (#880) 2019-05-24 05:10:31 -06:00
Osspial
8d6a857ba5 Merge branch 'evl2' into eventloop-2.0 2019-05-16 00:26:59 -04:00
Osspial
6ff1370035 Fix crash caused by WM_PAINT getting invoked at inopportune times. (#866) 2019-05-16 00:00:30 -04:00
Hal Gentz
d5391686ae Squashed commit of the following: (#853)
commit fa95f204d3c10ceca70e794870657a0f33349761
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Sun Apr 28 00:14:01 2019 -0600

    xrender

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit b62cee51c7b22f6f150bfe04f9b28f024e641323
Merge: 3f021ea7 a6551f46
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Thu Apr 25 18:13:43 2019 -0600

    Merge branch 'macos-gentz' of github.com:ZeGentzy/winit into macos-gentz

commit 3f021ea7f7ac6bc2a697a5b6e4e6424e838a2139
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Thu Apr 25 18:04:02 2019 -0600

    Get rid of warnings.

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit a6551f4607ea0bc26df8716dee8115371ef367db
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Thu Apr 25 07:40:56 2019 -0600

    Fix example

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit cbfda6c57e9740b49d2b496bda43197f611cb48c
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:47:46 2019 -0600

    Fixes

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 86bc86f3d3add4a6125aa9b2eca79061c0dfcd91
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:39:19 2019 -0600

    Backport 9a23ec3c37 (diff-1d95fe39cdbaa708c975380a16c314cb)

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 742a688efe2f0eeacc2ffbf49b1157c4aaffccbd
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:09:14 2019 -0600

    Backports 45a4281413 (diff-1d95fe39cdbaa708c975380a16c314cb)

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 6c81f2a517d4e2d5ba2ff3eddca030bce972cb2a
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:05:57 2019 -0600

    Francesca's macos changes

    Also backports bfbcab3a01 (diff-1d95fe39cdbaa708c975380a16c314cb)

commit 7c2e1300c26a0634ad505ce72b90eb6dc2fdcac7
Author: Francesca Plebani <franplebani@gmail.com>
Date:   Wed Apr 24 20:58:26 2019 -0600

    Squashed commit of the following:

    commit 5f4aa9f01a719eef98c6d894801c20ee8f96d30f
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 17:14:14 2018 -0500

        Protect against reentrancy (messily)

    commit b75073a5b2a8d65ab8806a00ffee390752255c8c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 15:15:27 2018 -0500

        Send resize events immediately

    commit 8e9fc01bd6b404f59488b130413f48e4e5f89b0d
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 16:07:43 2018 -0500

        Don't use struct for window delegate

    commit c6853b0c4a8fe357f463604bb879dc1be424860e
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 21:17:48 2018 -0500

        Split up util

    commit 262c46b148413130fa239099f1151c1f1bd5c13c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 20:55:00 2018 -0500

        Use dispatch crate

    commit 63152c2f475794d1a36a5b3687c777664d7d5613
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 20:29:13 2018 -0500

        RedrawRequested

    commit 27e475c7c78b059fd9b5e8350cd26756eecdfc94
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 19:24:44 2018 -0500

        User events

    commit 157418d7dedace9c571e977d98ea92464c3188b2
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 18 22:38:05 2018 -0500

        Moved out cursor loading

    commit b4925641c973979a38743202b4269efe09ac43b4
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 18 21:32:12 2018 -0500

        Fixed a bunch of threading issues

    commit 4aef63dfb78dfaf38c83cb0e88d4ea9d8d0578a6
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 17 13:54:59 2018 -0500

        Wait works

    commit 72ed426c695df5dc410902263bd74188059b8ddd
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 20:49:10 2018 -0500

        Fixed drag and dropg

    commit 658209f4a20acd536218f41a01fb8cbbebc705e0
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 20:42:42 2018 -0500

        Made mutexes finer for less deadlock risk

    commit 8e6b9866084690da900c4d058e412cab8ebb30c4
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 16:45:06 2018 -0500

        Dump (encapsulate) everything into AppState

    commit d2dc83df15939d89301e2cff0ffa2d98c48b406f
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Thu Dec 13 17:36:47 2018 -0500

        All window events work!

    commit 7c7fcc98872b3c35bd7767b5c6235a74bc105e06
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 12 17:11:09 2018 -0500

        Very rough usage of CFRunLoop

    commit 3c7a52ff4df683b5b7e1751e4051ec445a818774
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 11 15:45:23 2018 -0500

        Fixed deadlocks

    commit b74c7fe1bcd173e9b0c0e004956c257e805bc2a2
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 10 18:59:46 2018 -0500

        Fix keyDown deadlock

    commit 3798f9c1a4bef2a3d1552f846b26efc31b1bbb6c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 10 18:44:40 2018 -0500

        It builds!

    commit 8c8620214357714c5cd0b3beefda6704512e3f64
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 7 21:09:55 2018 -0500

        Horribly broken so far

    commit 8269ed2a92
    Author: Osspial <osspial@gmail.com>
    Date:   Mon Nov 19 23:51:20 2018 -0500

        Fix crash with runner refcell not getting dropped

    commit 54ce6a21a0
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Nov 18 19:12:45 2018 -0500

        Fix buffered events not getting dispatched

    commit 2c18b804df
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Nov 18 18:51:24 2018 -0500

        Fix thread executor not executing closure when called from non-loop thread

    commit 5a3a5e2293
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 22:43:59 2018 -0500

        Fix some deadlocks that could occur when changing window state

    commit 2a3cefd8c5
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 16:45:17 2018 -0500

        Document and implement Debug for EventLoopWindowTarget

    commit fa46825a28
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 16:40:48 2018 -0500

        Replace &EventLoop in callback with &EventLoopWindowTarget

    commit 9f36a7a68e
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Nov 14 21:28:38 2018 -0500

        Fix freeze when setting decorations

    commit d9c3daca9b
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Nov 9 20:41:15 2018 -0500

        Fix 1.24.1 build

    commit 5289d22372
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Nov 9 00:00:27 2018 -0500

        Remove serde implementations from ControlFlow

    commit 92ac3d6ac7
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 8 23:46:41 2018 -0500

        Remove crossbeam dependency and make drop events work again

    commit 8299eb2f03
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Sep 13 22:39:40 2018 -0400

        Fix crash when running in release mode

    commit bb6ab1bb6e
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 14:28:16 2018 -0400

        Fix unreachable panic after setting ControlFlow to Poll during some RedrawRequested events.

    commit 5068ff4ee1
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 14:14:28 2018 -0400

        Improve clarity/fix typos in docs

    commit 8ed575ff4a
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 00:19:53 2018 -0400

        Update send test and errors that broke some examples/APIs

    commit bf7bfa82eb
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Sep 5 22:36:05 2018 -0400

        Fix resize lag when waiting in some situations

    commit 70722cc4c3
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Sep 5 19:58:52 2018 -1100

        When SendEvent is called during event closure, buffer events

    commit 53370924b2
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Aug 26 21:55:51 2018 -0400

        Improve WaitUntil timer precision

    commit a654400e73
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 21:06:19 2018 -0400

        Add CHANGELOG entry

    commit deb7d379b7
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:19:56 2018 -0400

        Rename MonitorId to MonitorHandle

    commit 8d8d9b7cd1
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:16:52 2018 -0400

        Change instances of "events_loop" to "event_loop"

    commit 0f34408763
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:13:53 2018 -0400

        Improve docs for run and run_return

    commit fba41f7a7e
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 19:09:53 2018 -0400

        Small changes to examples

    commit 42e8a0d2cf
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 19:09:19 2018 -0400

        Improve documentation

    commit 4377680a44
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 23:01:36 2018 -0400

        Re-organize into module structure

    commit f20fac99f6
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 22:07:39 2018 -0400

        Add platform::desktop module with EventLoopExt::run_return

    commit dad24d086a
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 18:03:41 2018 -0400

        Rename os to platform, add Ext trait postfixes

    commit 7df59c60a0
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 17:59:36 2018 -0400

        Rename platform to platform_impl

    commit 99c0f84a9f
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 17:55:27 2018 -0400

        Add request_redraw

    commit a0fef1a5fa
    Author: Osspial <osspial@gmail.com>
    Date:   Mon Aug 20 01:47:11 2018 -0400

        Fully invert windows control flow so win32 calls into winit's callback

    commit 2c607ff87f
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Aug 19 13:44:22 2018 -0400

        Add ability to send custom user events

    commit a0b2bb3695
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Aug 17 17:49:46 2018 -0400

        Add StartCause::Init support, timer example

    commit 02f922f003
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Aug 17 17:31:04 2018 -0400

        Implement new ControlFlow and associated events

    commit 8b8a7675ec
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Jul 13 01:48:26 2018 -0400

        Replace windows Mutex with parking_lot Mutex

    commit 9feada206f
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Jul 13 01:39:53 2018 -0400

        Update run_forever to hijack thread

    commit 2e83bac99c
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 23:43:58 2018 -0400

        Remove second thread from win32 backend

    commit 64b8a9c6a5
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 22:13:07 2018 -0400

        Rename WindowEvent::Refresh to WindowEvent::Redraw

    commit 529c08555f
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 22:04:38 2018 -0400

        Rename EventsLoop and associated types to EventLoop

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

    Co-authored-by: Hal Gentz <zegentzy@protonmail.com>

commit cfb929ba0a9e787f8bb1a6dae4e05e4c7776bc97
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Thu Apr 25 07:40:56 2019 -0600

    Fix example

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 68d3317ff58381d55f5f9bd3db0860d66544fe12
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:47:46 2019 -0600

    Fixes

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 02d1aae4db27df054b703aa935ca118f31e17123
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:39:19 2019 -0600

    Backport 9a23ec3c37 (diff-1d95fe39cdbaa708c975380a16c314cb)

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit dd9de5a6d444a9ab17afe470f4cf2a57e3ed76ae
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:09:14 2019 -0600

    Backports 45a4281413 (diff-1d95fe39cdbaa708c975380a16c314cb)

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 533e2adc1d1e417742475786635848b1620e476c
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 23:05:57 2019 -0600

    Francesca's macos changes

    Also backports bfbcab3a01 (diff-1d95fe39cdbaa708c975380a16c314cb)

commit 73b52221080bd3a881ae3a58c2dbb19bc8d954c6
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Wed Apr 24 20:58:26 2019 -0600

    Squashed commit of the following:

    commit 5f4aa9f01a719eef98c6d894801c20ee8f96d30f
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 17:14:14 2018 -0500

        Protect against reentrancy (messily)

    commit b75073a5b2a8d65ab8806a00ffee390752255c8c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 15:15:27 2018 -0500

        Send resize events immediately

    commit 8e9fc01bd6b404f59488b130413f48e4e5f89b0d
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 21 16:07:43 2018 -0500

        Don't use struct for window delegate

    commit c6853b0c4a8fe357f463604bb879dc1be424860e
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 21:17:48 2018 -0500

        Split up util

    commit 262c46b148413130fa239099f1151c1f1bd5c13c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 20:55:00 2018 -0500

        Use dispatch crate

    commit 63152c2f475794d1a36a5b3687c777664d7d5613
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 20:29:13 2018 -0500

        RedrawRequested

    commit 27e475c7c78b059fd9b5e8350cd26756eecdfc94
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 19 19:24:44 2018 -0500

        User events

    commit 157418d7dedace9c571e977d98ea92464c3188b2
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 18 22:38:05 2018 -0500

        Moved out cursor loading

    commit b4925641c973979a38743202b4269efe09ac43b4
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 18 21:32:12 2018 -0500

        Fixed a bunch of threading issues

    commit 4aef63dfb78dfaf38c83cb0e88d4ea9d8d0578a6
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 17 13:54:59 2018 -0500

        Wait works

    commit 72ed426c695df5dc410902263bd74188059b8ddd
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 20:49:10 2018 -0500

        Fixed drag and dropg

    commit 658209f4a20acd536218f41a01fb8cbbebc705e0
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 20:42:42 2018 -0500

        Made mutexes finer for less deadlock risk

    commit 8e6b9866084690da900c4d058e412cab8ebb30c4
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 14 16:45:06 2018 -0500

        Dump (encapsulate) everything into AppState

    commit d2dc83df15939d89301e2cff0ffa2d98c48b406f
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Thu Dec 13 17:36:47 2018 -0500

        All window events work!

    commit 7c7fcc98872b3c35bd7767b5c6235a74bc105e06
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Wed Dec 12 17:11:09 2018 -0500

        Very rough usage of CFRunLoop

    commit 3c7a52ff4df683b5b7e1751e4051ec445a818774
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Tue Dec 11 15:45:23 2018 -0500

        Fixed deadlocks

    commit b74c7fe1bcd173e9b0c0e004956c257e805bc2a2
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 10 18:59:46 2018 -0500

        Fix keyDown deadlock

    commit 3798f9c1a4bef2a3d1552f846b26efc31b1bbb6c
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Mon Dec 10 18:44:40 2018 -0500

        It builds!

    commit 8c8620214357714c5cd0b3beefda6704512e3f64
    Author: Francesca Plebani <franplebani@gmail.com>
    Date:   Fri Dec 7 21:09:55 2018 -0500

        Horribly broken so far

    commit 8269ed2a92
    Author: Osspial <osspial@gmail.com>
    Date:   Mon Nov 19 23:51:20 2018 -0500

        Fix crash with runner refcell not getting dropped

    commit 54ce6a21a0
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Nov 18 19:12:45 2018 -0500

        Fix buffered events not getting dispatched

    commit 2c18b804df
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Nov 18 18:51:24 2018 -0500

        Fix thread executor not executing closure when called from non-loop thread

    commit 5a3a5e2293
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 22:43:59 2018 -0500

        Fix some deadlocks that could occur when changing window state

    commit 2a3cefd8c5
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 16:45:17 2018 -0500

        Document and implement Debug for EventLoopWindowTarget

    commit fa46825a28
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 15 16:40:48 2018 -0500

        Replace &EventLoop in callback with &EventLoopWindowTarget

    commit 9f36a7a68e
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Nov 14 21:28:38 2018 -0500

        Fix freeze when setting decorations

    commit d9c3daca9b
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Nov 9 20:41:15 2018 -0500

        Fix 1.24.1 build

    commit 5289d22372
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Nov 9 00:00:27 2018 -0500

        Remove serde implementations from ControlFlow

    commit 92ac3d6ac7
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Nov 8 23:46:41 2018 -0500

        Remove crossbeam dependency and make drop events work again

    commit 8299eb2f03
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Sep 13 22:39:40 2018 -0400

        Fix crash when running in release mode

    commit bb6ab1bb6e
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 14:28:16 2018 -0400

        Fix unreachable panic after setting ControlFlow to Poll during some RedrawRequested events.

    commit 5068ff4ee1
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 14:14:28 2018 -0400

        Improve clarity/fix typos in docs

    commit 8ed575ff4a
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Sep 9 00:19:53 2018 -0400

        Update send test and errors that broke some examples/APIs

    commit bf7bfa82eb
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Sep 5 22:36:05 2018 -0400

        Fix resize lag when waiting in some situations

    commit 70722cc4c3
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Sep 5 19:58:52 2018 -1100

        When SendEvent is called during event closure, buffer events

    commit 53370924b2
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Aug 26 21:55:51 2018 -0400

        Improve WaitUntil timer precision

    commit a654400e73
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 21:06:19 2018 -0400

        Add CHANGELOG entry

    commit deb7d379b7
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:19:56 2018 -0400

        Rename MonitorId to MonitorHandle

    commit 8d8d9b7cd1
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:16:52 2018 -0400

        Change instances of "events_loop" to "event_loop"

    commit 0f34408763
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 20:13:53 2018 -0400

        Improve docs for run and run_return

    commit fba41f7a7e
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 19:09:53 2018 -0400

        Small changes to examples

    commit 42e8a0d2cf
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Aug 23 19:09:19 2018 -0400

        Improve documentation

    commit 4377680a44
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 23:01:36 2018 -0400

        Re-organize into module structure

    commit f20fac99f6
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 22:07:39 2018 -0400

        Add platform::desktop module with EventLoopExt::run_return

    commit dad24d086a
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 18:03:41 2018 -0400

        Rename os to platform, add Ext trait postfixes

    commit 7df59c60a0
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 17:59:36 2018 -0400

        Rename platform to platform_impl

    commit 99c0f84a9f
    Author: Osspial <osspial@gmail.com>
    Date:   Wed Aug 22 17:55:27 2018 -0400

        Add request_redraw

    commit a0fef1a5fa
    Author: Osspial <osspial@gmail.com>
    Date:   Mon Aug 20 01:47:11 2018 -0400

        Fully invert windows control flow so win32 calls into winit's callback

    commit 2c607ff87f
    Author: Osspial <osspial@gmail.com>
    Date:   Sun Aug 19 13:44:22 2018 -0400

        Add ability to send custom user events

    commit a0b2bb3695
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Aug 17 17:49:46 2018 -0400

        Add StartCause::Init support, timer example

    commit 02f922f003
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Aug 17 17:31:04 2018 -0400

        Implement new ControlFlow and associated events

    commit 8b8a7675ec
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Jul 13 01:48:26 2018 -0400

        Replace windows Mutex with parking_lot Mutex

    commit 9feada206f
    Author: Osspial <osspial@gmail.com>
    Date:   Fri Jul 13 01:39:53 2018 -0400

        Update run_forever to hijack thread

    commit 2e83bac99c
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 23:43:58 2018 -0400

        Remove second thread from win32 backend

    commit 64b8a9c6a5
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 22:13:07 2018 -0400

        Rename WindowEvent::Refresh to WindowEvent::Redraw

    commit 529c08555f
    Author: Osspial <osspial@gmail.com>
    Date:   Thu Jul 12 22:04:38 2018 -0400

        Rename EventsLoop and associated types to EventLoop

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit ab1dfaaaa53a3acd206bf494ac90e3fe130dc609
Author: Hal Gentz <zegentzy@protonmail.com>
Date:   Tue Apr 23 21:52:17 2019 -0600

    Minor

    Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

commit 7933209d60
Author: Victor Berger <victor.berger@m4x.org>
Date:   Thu Apr 18 09:10:41 2019 +0200

    wayland/x11: Make ControlFlow::Exit sticky

commit 8355a7513e
Author: Victor Berger <victor.berger@m4x.org>
Date:   Tue Apr 16 12:21:33 2019 +0200

    x11: Implement run_return using calloop

commit f64edb60cc
Author: Victor Berger <victor.berger@m4x.org>
Date:   Tue Apr 16 10:42:04 2019 +0200

    x11: port to evl2 with stubs

commit be372898dd
Author: Victor Berger <victor.berger@m4x.org>
Date:   Mon Apr 15 17:35:59 2019 +0200

    Fix compilation on Linux.

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

Co-authored-by: Francesca Plebani <franplebani@gmail.com>
2019-05-13 22:20:51 -04:00
Ryan Goldstein
70c7382a09 Fix the request_animation_frame lifetimes 2019-05-01 21:20:54 -04:00
Ryan Goldstein
9f801cf79e Only send the request-redraw on the next animation frame 2019-04-29 15:39:43 -04:00
acheronfail
062e0e52ee Feat/fullscreen getters (#838)
* feat: [macos] add get_fullscreen and get_simple_fullscreen

* feat: [windows] add get_fullscreen

* feat: [ios] add get_fullscreen

* feat: [android] add get_fullscreen

* feat: [emscripten] add get_fullscreen

* feat: [linux] add get_fullscreen

* feedback: `get_fullscreen() -> bool` -> `get_fullscreen() -> Option<Id>`
2019-04-27 20:29:55 +02:00
Osspial
fa99b9ff5a Fix CI links in README.md (#852) 2019-04-27 18:29:02 +02:00
Felix Rabe
8f6e80917f Popup windows are also known as modal windows (#848) 2019-04-27 18:28:51 +02:00
Osspial
e087ebd1c7 Makes changes to CONTRIBUTING.md's table as discussed in #830 (#841)
This includes de-listing @francesca64 from the table, as I suggested. I
realize that this is a controversial decision, and it's not a decision I
make lightly, but I believe I have justification for doing so:

I contacted @francesca64 last month asking her about her inactivity as a
maintainer on this project. She replied on March 26th as follows. For the
sake of her privacy, I've removed removed certain sections of her response,
as it contains some personal details that I'm not comfortable sharing with
the world at large without her explicit permission.

> Hello! Thanks for reaching out!❤

> In short, I've moved on. <removed> ...in November, I was hired by a
> company that recently started using Rust. I'm very happily building
> infrastructure there!

> I'm simply not interested in spending more than 8 hours a day
> programming. You couldn't even pay me to do it! My time is best spent
> going on adventures with my beloved.

> I'll still be active in the Rust ecosystem, but only insofar as the
> company I work for is. We use winit on iOS, Android, and (to a limited
> extent) macOS, so I'll work on those backends as needed.

> Thank you for taking care of winit. I hope you're taking care of
> yourself too; <removed>.

I don't begrudge her for her decision, and others shouldn't either - I
firmly believe that, as this is unpaid, volunteer work, everybody should
have the right to move on when they decide they no longer have the time
or will to contribute.

The exact impliciation of this in regards to her status as maintainer
is open to interpretation. I would argue that this means, should she in
her work stumble upon an issue in any of her listed backends, she would be
willing to submit PRs addressing those issues. However, it also means
that she is not able to put in the time to be active as a maintainer on
those platforms, or review PRs and issues for those platforms.

On March 28th I responded to her email as follows:

> Hey, thanks for responding.

> <removed, personal details>

> In the meanwhile, there are still a few loose ends from your time as
> maintainer that I'd like to get cleaned up. It's okay if you aren't
> going to be spending much time on Winit, but there's still a broad
> assumption that you're able to review PRs for them and that doesn't seem
> to be the case. Would you be able to do a couple things to ease the
> transition to whoever next takes over the macOS, X11, and Android
> backends?

> 1) Submit a PR downgrading yourself from maintainer for macOS, X11, and
>    Android, so somebody else can more actively take them over.
> 2) Post your WIP macOS backend for EL2.0 as well as the issues it
>    currently has, so whoever next maintains macOS can finish it.

> Going forward, I'd like to reach out to the broader Rust community and
> find more active maintainers so Winit can get to 1.0 and I can mostly
> move on from it.

I recieved no response to that email. On April 4th, I followed up on
that email:

> If you aren't able to act as a maintainer for Winit, and aren't able to
> submit a PR updating your official status as maintainer to reflect
> reality, would you mind if I submitted a PR removing you as maintainer?
> That's not something I want to do since it's a bad image for me, a bad
> image for Winit, and sets an extremely uncomfortable precedent, but I'd
> like to start more aggressive outreach to ensure each backend is less
> dependent on one specific person and I don't want to see new
> contributors pinging you for help when you're unable to provide it.

> If you don't reply by the 11th that's the path I'm going to take, but I
> consider it the nuclear option and I want to avoid invoking it if at all
> possible.

Up to this date (April 13th), I have recieved no response. Given the
amount of time I've given her to respond, as well as her lack of
response, I believe we have the justification to remove her from the
table. Should she show back up again, any clarifications on her status
would be welcome, and she is welcome to submit a PR re-listing herself
on the table with a more accurate description of her current contributor
status. However, once we begin the contributor marketing push discussed
in #830, I don't want new contributors to attempt to ask her questions
on the macOS, X11, or Android backends when she isn't able to give a
response.

-----------------------------------------------------------------------

This PR also introduces HALL_OF_CHAMPIONS.md, which commends the efforts
of former maintainers that have contributed greatly to the Winit project.
This wasn't discussed previously, but I think it's important to recognize
the people that brought us to where we are today. It currently lists
@tomaka and @francesca64, as they are the two individuals I'm aware of
that both deserve such recognition and no longer actively contribute to
Winit, but if there's anybody I missed feel free to suggest them and a
blurb describing their work.
2019-04-27 18:28:40 +02:00
Osspial
0d3e75d6b0 Fix TODO in CONTRIBUTING.md 2019-04-27 18:28:32 +02:00
Osspial
873f7bcec7 Fix link in PULL_REQUEST_TEMPLATE.md 2019-04-27 18:28:20 +02:00
Osspial
e579a03035 Winit Features and Scope (#695)
* Add initial draft of SCOPE document

* Rephrase/rename feature tiers

* Rename to FEATURES and add a few annotations

* Fix API Reworks table

* Add more annotations

* Some phrasing

* Split compat matrix into seperate section, to be moved into wiki

* Mention compatibility in CONTRIBUTING

* Remove some discuss annotations

* Apply review changes and rename child windows feature to popup windows

* Update based on discussion

* Add issue for Android HiDPI

* Update FEATURES.md

* Update FEATURES.md

* Update PULL_REQUEST_TEMPLATE.md

* Update PULL_REQUEST_TEMPLATE.md

* Reformat FEATURES.MD

* Remove comments

* Improve formatting and add guide for extending #Features
2019-04-27 18:28:10 +02:00
Victor Berger
94f998af0a Port X11 backend to the EVL2.0 API (#842)
* Fix compilation on Linux.

* x11: port to evl2 with stubs

* x11: Implement run_return using calloop

* wayland/x11: Make ControlFlow::Exit sticky

* x11: Send LoopDestroyed on exit

* x11: Fix RedrawRequested semandics

* wayland: Fix RedrawRequested semandics

* x11/wayland: reduce code duplication for sticky callback
2019-04-27 18:06:51 +02:00
Ryan Goldstein
fe5e300062 Clean up and document the core of stdweb event handling 2019-04-25 00:02:13 -04:00
aloucks
2253565db5 Prevent the event loop from pausing when entering modal loop (eventloop-2.0) (#839)
* Prevent the event loop from pausing after entering modal loop

After clicking the window title bar or border (for a drag or resize),
the event loop pauses until the mouse is moved. This change relays
the WM_NCLBUTTONDOWN message to the dummy window where it queues
a redraw and consumes the message. This effectively jumpstarts
the modal loop and it continues to fire draw requests.

* Handle WM_NCLBUTTONDOWN in public_window_callback instead of relaying.

Relaying the WM_NCLBUTTONDOWN message to the modal window turned out
to be unnecessary.
2019-04-14 11:48:31 -04:00
Osspial
2ead1c1c59 Update for 0.19.1 (#823) 2019-04-08 08:35:36 +02:00
Hal Gentz
746e99c958 Add ability to get wayland display from events loop. (#829)
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2019-04-08 08:34:49 +02:00
Osspial
47194b5f3c Fix window icon (#831)
* Fix window icon

* Add CHANGELOG entry
2019-04-08 08:30:37 +02:00
mitchmindtree
4515b77aa5 [Rebased] [x11-backend] Retrieve DPI from Xft.dpi XResource (#824)
* [x11-backend] Retrieve DPI from Xft.dpi XResource

* Update CHANGELOG.md

* Update window.rs

* Update CHANGELOG.md
2019-04-08 08:30:09 +02:00
Christian Duerr
20b09c4514 Add additional numpad key mappings (#805)
* Add additional numpad key mappings

Since some platforms have already used the existing `Add`, `Subtract`
and `Divide` codes to map numpad keys, the X11 and Wayland platform has
been updated to achieve parity between platforms. On macOS only the
`Subtract` numpad key had to be added.

Since the numpad key is different from the normal keys, an alternative
option would be to add new `NumpadAdd`, `NumpadSubtract` and
`NumpadDivide` actions, however I think in this case it should be fine
to map them to the same virtual key code.

* Add Numpad PageUp/Down, Home and End on Wayland
2019-04-07 16:41:52 +02:00
TakWolf
9874181ccd fix command key event left and right reverse on macOS (#810)
* fix command key event left and right reverse on macOS

https://github.com/tomaka/winit/issues/808

* update changelog
2019-04-07 16:41:52 +02:00
Tobias Kortkamp
cb93554938 Fix build on FreeBSD (#815)
* Fix build on FreeBSD

error[E0432]: unresolved import `libc::__errno_location`
  --> src/platform/linux/x11/mod.rs:22:85
   |
22 | use libc::{select, fd_set, FD_SET, FD_ZERO, FD_ISSET, EINTR, EINVAL, ENOMEM, EBADF, __errno_location};
   |                                                                                     ^^^^^^^^^^^^^^^^ no `__errno_location` in the root

__errno_location is called __error on FreeBSD and __errno on Open- and NetBSD.

Signed-off-by: Tobias Kortkamp <t@tobik.me>

* Import __error / __errno on *BSD as __errno_location

Signed-off-by: Tobias Kortkamp <t@tobik.me>

* Add changelog entry

Signed-off-by: Tobias Kortkamp <t@tobik.me>
2019-04-07 16:41:52 +02:00
Hal Gentz
6b7bd32c8e Add contact info. (#818)
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2019-04-07 16:41:52 +02:00
Osspial
17a240cd43 On Windows, fix CursorMoved(0, 0) getting sent on focus (#819)
* On Windows, fix CursorMoved(0, 0) getting sent on focus

* Add changelog entry
2019-04-07 16:41:52 +02:00
Osspial
fc481b6d6d Update winit to 0.19.0 (#798)
* Update winit to 0.19.0

* Update date for 0.19
2019-04-07 16:41:52 +02:00
Hal Gentz
09182dc093 Use XRRGetScreenResourcesCurrent when avail. (#801)
* Use `XRRGetScreenResourcesCurrent` when avail.

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>

* Changelog

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2019-04-07 16:41:52 +02:00
Osspial
b682c3dfb5 Ignore the AltGr key when populating ModifersState (#763)
* When building ModifiersState, ignore AltGr on Windows

* Add CHANGELOG entry

* Also filter out Control when pressing AltGr
2019-04-07 16:41:52 +02:00
Riku Salminen
ab0a34012f x11: thread safe replacement for XNextEvent (#782)
XNextEvent will block for input while holding the global Xlib mutex.

This will cause a deadlock in even the most trivial multi-threaded
application because OpenGL functions will need to hold the Xlib mutex
too.

Add EventsLoop::poll_one_event and EventsLoop::wait_for_input to provide
thread-safe functions to poll and wait events from the X11 event queue
using unix select(2) and XCheckIfEvent.

This is a somewhat ugly workaround to an ugly problem.

Fixes #779
2019-04-07 16:41:52 +02:00
Michael Palmos
f000b82d74 Fix incorrect keycodes when using a non-US keyboard layout. (#755)
* Fix incorrect keycodes when using a non-US keyboard layout.

This commit fixes the issue described in #752, and uses the advised
method to fix it.

* Style fixes

Co-Authored-By: Toqozz <toqoz@hotmail.com>

* Refactoring of macOS `virtualkeycode` fix (#752)

* Applies requested changes as per pull request discussion (#755).
2019-04-07 16:41:52 +02:00
Torkel Danielsson
dad8de82fa Handle horizontal wheel input (Windows) (#792)
* add handler for horizontal wheel input

* add changlelog message re now handling horiz scroll on windows
2019-04-07 16:41:51 +02:00
trimental
3fea477bfd On wayland, fix with_title() not setting the windows title (#770) 2019-04-07 16:39:55 +02:00
Victor Berger
f7d7acb3c5 Cleanup some previous merge errors 2019-04-07 15:58:47 +02:00
Ryan Goldstein
9e25561edf Fix compile failures and add canvas positioning 2019-04-02 22:31:30 -04:00
Ryan Goldstein
7c6bdcc459 Handle ControlFlow::Exit and dealing with events-in-events 2019-03-22 22:15:49 -04:00
Ryan Goldstein
b09629f1d4 Handle ControlFlow::Exit 2019-03-18 22:13:30 -04:00
Ryan Goldstein
85446d81f3 Fix warnings 2019-03-16 18:51:11 -04:00
Ryan Goldstein
96786bbb87 Implement focus event 2019-03-16 18:44:13 -04:00
Ryan Goldstein
a5166baba2 Implement request_redraw 2019-03-16 18:40:35 -04:00
Ryan Goldstein
d1deba8620 Rename modules 2019-03-11 22:22:21 -04:00
Ryan Goldstein
aaee72422a Rearchitect to allow API compliance 2019-03-11 22:18:58 -04:00
Ryan Goldstein
3dd0e31cc4 Merge eventloop-2.0 into stdweb-eventloop-2 2019-03-11 15:52:04 -04:00
Ryan Goldstein
283a8dec37 Refactor out the stdweb functionality into different modules 2019-03-09 22:23:39 -05:00
Ryan Goldstein
37d354cf7f Get to a state where a canvas is spawned 2019-03-09 21:54:29 -05:00
Ryan Goldstein
f698d451df Add key and mouse event support that typechecks 2019-03-02 12:31:16 -05:00
Ryan Goldstein
c088f8bd03 Create the outline of event input and handler calls 2019-02-26 13:36:48 -05:00
Osspial
3cd40ef655 Remove icon loading feature (#799) 2019-02-23 20:59:00 -05:00
Victor Berger
6513351e0c Wayland's eventloop 2.0 (#790)
* match unix common API to evl 2.0

* wayland: eventloop2.0

* make EventLoopProxy require T: 'static

* Fix linux build and tests

* wayland: update sctk & small fixes
2019-02-21 10:51:43 +01:00
Ryan Goldstein
f44e98ddc9 Implemented a few easy methods 2019-02-19 20:08:18 -05:00
Ryan Goldstein
fd4db4000c Create the type layout
Everything typechecks, but nothing is implemented
2019-02-12 20:47:31 -05:00
Osspial
9602716ed2 Event Loop 2.0 API and Windows implementation (#638)
* Rename EventsLoop and associated types to EventLoop

* Rename WindowEvent::Refresh to WindowEvent::Redraw

* Remove second thread from win32 backend

* Update run_forever to hijack thread

* Replace windows Mutex with parking_lot Mutex

* Implement new ControlFlow and associated events

* Add StartCause::Init support, timer example

* Add ability to send custom user events

* Fully invert windows control flow so win32 calls into winit's callback

* Add request_redraw

* Rename platform to platform_impl

* Rename os to platform, add Ext trait postfixes

* Add platform::desktop module with EventLoopExt::run_return

* Re-organize into module structure

* Improve documentation

* Small changes to examples

* Improve docs for run and run_return

* Change instances of "events_loop" to "event_loop"

* Rename MonitorId to MonitorHandle

* Add CHANGELOG entry

* Improve WaitUntil timer precision

* When SendEvent is called during event closure, buffer events

* Fix resize lag when waiting in some situations

* Update send test and errors that broke some examples/APIs

* Improve clarity/fix typos in docs

* Fix unreachable panic after setting ControlFlow to Poll during some RedrawRequested events.

* Fix crash when running in release mode

* Remove crossbeam dependency and make drop events work again

* Remove serde implementations from ControlFlow

* Fix 1.24.1 build

* Fix freeze when setting decorations

* Replace &EventLoop in callback with &EventLoopWindowTarget

* Document and implement Debug for EventLoopWindowTarget

* Fix some deadlocks that could occur when changing window state

* Fix thread executor not executing closure when called from non-loop thread

* Fix buffered events not getting dispatched

* Fix crash with runner refcell not getting dropped

* Address review feedback

* Fix CHANGELOG typo

* Catch panics in user callback
2019-02-05 10:30:33 -05:00
Osspial
7be1d16263 Refactor win32 window state code (#730)
* Overhaul win32 window state

* Fix warnings

* Add CHANGELOG entry

* Rephrase CHANGELOG entries

* Fix 1.28.0 build

* Remove WS_POPUP styling

* Slight style correction

* Make set_maximized work

* Fix rect restore not working after winit set_maximized call

* Add a few comments
2019-02-04 11:52:00 -05:00
trimental
c91dfdd6fe Wayland: add set_wayland_theme() to control client decoration color… (#775)
* Wayland: add `set_wayland_theme()` to control client decoration color theme

* Change &mut self to &self

* Remove endianness comment
2019-01-29 11:04:15 +01:00
Anthony Ramine
8e733543cd Update image to 0.21 (#758) 2019-01-16 14:36:46 -05:00
Sascha Grunert
26e37590e8 Allow serialization for WindowType (#762)
* Allow serialization for WindowType

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-Authored-By: saschagrunert <sgrunert@suse.com>
2019-01-15 09:30:02 -08:00
Osspial
ddf133dd66 Version 0.18.1 (#749)
* Version 0.18.1

* Change to 0.18.1
2019-01-09 03:16:41 -11:00
Osspial
4584e7629a Remove MSRV guarantee (#746)
* Remove MSRV guarantee

* Update CHANGELOG
2018-12-29 15:02:02 -11:00
Francesca Plebani
139686ddce macOS: Improve set_cursor (#740)
* Improve set_cursor on macOS

* Check for nil
2018-12-28 15:29:29 -05:00
Francesca Plebani
5a0b4dba47 macOS: Implement Refresh (#742)
* macOS: Implement Refresh

* drawRect should take NSRect
2018-12-27 15:16:58 -05:00
Francesca Plebani
33c8aa660f macOS: Correct prepareForDragOperation: signature (#741) 2018-12-27 14:22:00 -05:00
Francesca Plebani
cb76dcae2a Change francesca64 to maintainer for macOS and Android (#744) 2018-12-24 13:08:33 -05:00
Bastien Orivel
d622de4797 Update parking_lot to 0.7 (#747) 2018-12-23 06:12:11 -11:00
Jacob Kiesel
9ae75c0c03 Add support for generating dummy DeviceIDs and WindowIDs (#738)
* Add support for generating dummy DeviceIDs and WindowIDs

* Fix linux

* Improve docs and move dummy to unsafe

* Strengthen guarantees a bit

* Add backticks to CHANGELOG.md

Co-Authored-By: Xaeroxe <xaeroxe@amethyst-engine.org>
2018-12-21 05:51:48 -11:00
Alisue
45a4281413 Support Yen in macOS (#739)
* Support Yen in macOS

* Add entry to CHANGELOG
2018-12-19 13:32:14 -05:00
acheronfail
bfbcab3a01 feat: add macos simple fullscreen (#692)
* feat: add macos simple fullscreen

* move impl to WindowExt

* feedback: remove warning, unused file and rename param

* feedback: combine fullscreen examples into one example

* fix: ensure decorations and maximize do not toggle while in fullscreen

* fix: prevent warning on non-macos platforms

* feedback: make changelog more explicit

* fix: prevent unconditional construction of NSRect

* fix: don't try to set_simple_fullscreen if already using native fullscreen

* fix: ensure set_simple_fullscreen plays nicely with set_fullscreen

* fix: do not enter native fullscreen if simple fullscreen is active
2018-12-18 23:07:33 -05:00
Jasper Mattsson
4b4c73cee4 Fix high CPU usage on tiling WMs when moving windows across monitors (#737)
This commit restricts an Xfwm4-specific DPI-preserving hack to Xfwm4
only. The hack saves and restores the DPI-adjusted size until the actual
size matches. On tiling WMs like i3 this fails, since the size is
constrained by the layout. This in turn causes a never-ending
XResizeWindow vs. XConfigureWindow fight between the WM and the client,
making the WM, winit client, and Xorg consume all CPU cycles available.
2018-12-18 22:20:31 -05:00
David Craven
fd349f1822 Use smithay-client-toolkit's dpi handling. (#724)
* Use smithay-client-toolkit's dpi handling.

* Add CHANGELOG entry.
2018-12-10 14:55:40 -05:00
Francesca Plebani
cb0a085968 X11: WindowBuilder min/max size accounts for DPI (#729) 2018-11-30 16:19:50 -05:00
Osspial
aabf0e13b7 On Windows, fix window shrinking when leaving fullscreen in some situations (#718)
* Fix resize border appearing in some cases after leaving fullscreen.

* On fullscreen, save client rect instead of window rect

* Add CHANGELOG entry

* Revert test changes to fullscreen example

* Update panic message when unable to get client area
2018-11-20 15:57:06 -05:00
Andreas Johansson
92873b06ed Handle removed wl_outputs (#719)
* Move the event managent to the closure

In preparation of more events not relating to the SeatManager being
captured.

* Handle wl_output remove events

In some cases, wl_outputs can be removed without the compositor
notifying the surfaces using leave/enter events. This breaks the DPI and
resize stuff since the windows' list of monitors were not updated.

Now, wl_output removals are handled and windows are updated accordingly.

* Add changelog entry for disappearing wl_outputs

* Clearer changelog message for wl_output removal changes
2018-11-20 15:21:58 -05:00
Artúr Kovács
04ca2cf9f4 Fix panic when dragging text onto a window on Windws (#697) (#711)
* Fix panic when dragging text onto a window on Windws (#697)

* Changed `panic` to `debug` (log) when unknow error occurs in `GetData` while processing a drag-drop / hover event. Plus added appropriate cursor effect if hovered item can not be processed.

* Improved code clarity.

* Add documentation to clarify behaviour of `DroppedFile`, `HoveredFile`, and `HoveredFileCancelled`

* Add period at the end of sentences in documentation.
2018-11-20 03:28:26 -05:00
Oskar Gustafsson
b049a4dc66 Add ordering traits to VirtualKeyCode (#713)
Motivation:
This allows VirtualKeyCode variants to be stored in a BTreeSet.
Unlike HashSets, BTreeSets implement Ord and Hash, allowing them to be
keys in a {Hash|BTree}Maps. This is nice, e.g. when implementing
keyboard shortcuts functionality, which maps a set of pressed keys to
some action.
2018-11-19 16:59:04 -05:00
Francesca Plebani
5be52c9753 Increase MSRV to 1.28.0 (#716) 2018-11-19 16:56:11 -05:00
Francesca Plebani
3c59283b3f X11: Check if XRRGetOutputInfo returned NULL (#709)
* X11: Check if XRRGetOutputInfo returned NULL

Fixes #693

* Change X11 error logging to actually use log
2018-11-17 15:51:39 -05:00
Osspial
3ba808e3c6 On Windows, catch window callback panics and forward them to the calling thread (#703)
* Catch windows callback panics

* Unwind through calling thread

* Add CHANGELOG entry

* Fix 1.24.1 builds

* Reformat CHANGELOG entry

* Make changes from review

* Wrap thread event target in panic catcher, reformat panic resume message

* Fix me being bad at git
2018-11-17 14:20:04 -05:00
Osspial
df5d66b5e8 Replace thread messages with messages to dummy window (#710)
* Replace thread messages with messages to dummy window

* Add CHANGELOG entry

* Style changes

* Make review changes
2018-11-16 22:17:32 -05:00
Victor Berger
7fe90e6c80 Introduce WindowBuilderExt::with_app_id for wayland (#700) 2018-11-15 16:59:56 -05:00
mtak-
8dcd514393 add mtak- to CONTRIBUTING.md as iOS maintainer, change francesca64 to a reviewer (#702) 2018-11-12 21:49:15 -05:00
Victor Berger
2c3e420f82 travis: freeze dependencies that silently broke 1.24.1 compat (#701) 2018-11-12 20:37:51 -05:00
Francesca Plebani
917db35a84 X11: Fix panic when dropping window before running event loop (#694)
Fixes #691

Dropping a window before running the `EventsLoop` results in events
still being queued when `XDestroyWindow` is called, so events like
`XI_Enter` (the culprit in this case) will still be processed.
Simply checking that the window still exists before calling
`query_pointer` was enough to solve the problem.
2018-11-10 13:54:50 -05:00
Victor Berger
dd52364d33 [META] Add a CONTRIBUTING.md (#674) 2018-11-10 11:56:40 +01:00
Joe Moon
30aa5a5057 version 0.18.0 (#680)
* version 0.18.0

* Changelog: F16-F24 support was a breaking change

* fix version in README

* bump image dep

* Updated release date
2018-11-07 00:43:15 -05:00
Barret Rennie
a46fcaee31 Support requesting user attention on macOS (#664)
* Support requesting user attention on macOS

* Documentation improvements
2018-11-06 23:50:40 -05:00
Osspial
52e2748869 Remove From<NSApplicationActivationPolicy> impl from ActivationPolicy (#690)
* Remove From<NSApplicationActivationPolicy> impl from ActivationPolicy

* Update CHANGELOG
2018-11-05 18:54:22 -05:00
Patrick Walton
d2d127a4c4 Make views explicitly layer-backed on macOS Mojave. (#685)
On Mojave, views automatically become layer-backed shortly after being added to
a window. Changing the layer-backedness of a view breaks the association
between the view and its associated OpenGL context. To work around this, on
Mojave we explicitly make the view layer-backed up front so that AppKit doesn't
do it itself and break the association with its context.

This was breaking the `window` example in `glutin`.
2018-11-05 14:34:54 -05:00
Francesca Plebani
0fca8e8cb5 X11: Fix DND freezing the WM (#688)
Fixes #687

`XdndFinished` isn't supposed to be sent when rejecting a `XdndPosition`; it should only be
sent in response to `XdndDrop`.

https://freedesktop.org/wiki/Specifications/XDND/
2018-11-02 17:41:51 -04:00
Osspial
6bec912961 Add optional Serde implementations and missing derivable traits (#652)
* Add optional serde feature

* Document features in README

* Add changelog entry

* Implement some missing derivable traits

* Add changelog entry for std derives

* Remove extraneous space on serde doc comments

* Add period to end of serde line in readme

* Remove serde impls from WindowAttributes

* Add serde impls for TouchPhase

* Add serde test file

* Add feature lines to testing CIs

* Remove WindowAttributes from changelog
2018-11-01 04:24:56 -04:00
Artúr Kovács
214e157e5d Implement HoveredFile and HoveredFileCancelled on Windows (#662)
* Implement HoveredFile and HoveredFileCancelled on Windows (#448)

* Update CHANGELOG.

* Applied code organizational corrections and fixed IDropHandler leak on window destroy.

* Moved FileDropHandle to a separate file.
2018-10-24 14:40:12 -04:00
Lucas Kent
da1d479e55 update to image 0.20 (#683) 2018-10-23 20:29:11 -04:00
Eleanore Young
062bb0cef2 On linux without X11 or Wayland, reduced the panic message to a single line (#681) 2018-10-21 18:12:51 -04:00
Victor Berger
c744b016ce x11: compute resize logical size with new dpi (#668)
* x11: compute resize logical size with new dpi

Whenever a dpi change occurs, trigger a Resized event as well with the
new logical size. Given X11 primarily deals in physical pixels, a change
in DPI also changes the logical size (as the physical size remains
fixed).

* Doc tweaks
2018-10-19 16:32:57 -04:00
George Burton
f486845f7f Implement Debug trait on exported opaque types (#677)
* Implement `Debug` trait on exported opaque types

* Make formatting consistent
2018-10-17 23:20:12 -04:00
trimental
7baa96c5c7 Provide current modifiers state with pointer events on wayland (#676) 2018-10-17 22:34:02 -04:00
Joe Moon
ea07ec1fda macOS: fix modifiers during key repeat (#666)
* macOS: fix modifiers during key repeat

* fix compile warnings
2018-10-17 22:03:26 -04:00
Alex Taylor
26b70e457b Windows: Fix transparency (#675)
* Windows: Fix transparency (#260)

* Windows: Only enable WS_EX_LAYERED for transparent windows

* Update winapi to 0.3.6

* Windows: Amend transparency code

* Add transparency fix to CHANGELOG.md
2018-10-17 20:23:59 -04:00
Rob Horswell
5d5fcb3911 Windows: Fix window.set_maximized() (#672)
* Windows: Fix window.set_maximized()

* Add window.set_maximized fix to CHANGELOG.

* Windows: use same style for set_maximized as other set_x(bool) methods
2018-10-14 19:47:08 -04:00
trimental
50008dff3d Upgrade to smithay-client-toolkit 0.4 (#671)
* Upgrade to smithay-client-toolkit 0.4

* Fix PR points
2018-10-14 19:15:43 -04:00
Francesca Plebani
808638fee3 Windows: Fix set_cursor delay (#660) 2018-09-22 21:03:38 -04:00
Tobias Umbach
b0e3865562 Don't include NUL byte in _NET_WM_NAME (#658)
> The contents of the property are not required to be null-terminated;
> any terminating null should not be included in text_prop.nitems.

https://tronche.com/gui/x/xlib/ICC/client-to-window-manager/XmbTextPropertyToTextList.html
2018-09-20 17:59:37 -04:00
Tobias Umbach
bc03ffb317 Add X11-specific with_gtk_theme_variant option (#659) 2018-09-20 17:00:04 -04:00
trimental
1edbca1775 Wayland: use init_from_env() to create windows and allow server-sid… (#655)
* Wayland: use `init_from_env()` to create windows and allow server-side decorations

* Change the CHANGELOG.md entrys wording
2018-09-20 13:48:36 -04:00
Kirill Chibisov
5a0bc016e7 Add support for F16-F24 (#641)
* Added support for F16-F19 keys.

* Documented support for F16-F19 keys

* Added support for F20 key

* Added support for F21-F24 on platforms except macOs

* Added support for F21-F24 on macOs

* Documented addition of F16-F24 keys

* Added missing ref qualifier

* Fixed compilation error on 1.24.1

* Refactored methods in macOs events_loop and view files
2018-09-12 13:04:16 -04:00
Sven-Hendrik Haase
bb66b7f28e Update wm spec hints (#646)
* Update wm-spec hints to v1.5

* Update changelog

* Fix CHANGELOG entry

* Remove trailing quote
2018-09-11 15:03:42 -04:00
Sven-Hendrik Haase
0331491b2b Put badges next to each other instead of below eachother (#649) 2018-09-11 14:59:04 -04:00
Kornel
54a782c8ae Syntax fix in Cargo.toml (#644) 2018-09-11 00:23:48 -04:00
Osspial
a70bc20829 Remove resize block on Windows (#634)
* Remove Windows block on resize

* Add CHANGELOG entry

* Move CHANGELOG entry to Unreleased

* Further edits to CHANGELOG entry
2018-08-24 13:48:57 -04:00
trimental
102ed3b800 Wayland: commit frame surface on resize (#635) 2018-08-23 13:20:02 -04:00
Joe Moon
c8e339fe6d version 0.17.2 (#630)
* version 0.17.2

* Update release date
2018-08-19 18:27:57 -04:00
trimental
e4e53fe315 Add key repetition for the wayland backend (#628)
* Add key repetition for the wayland backend

* Upgrade smithay-client-toolkit to 0.3.0
2018-08-19 17:17:40 -04:00
Joe Moon
1c795c3f1c 625 macos modifiers (#629)
* fix <C-Tab>

* fix <CMD-{key}>

* move the NSKeyUp special handling into the match statement

* add special handling for `<Cmd-.>`

* formatting

* add return type to msg_send!
2018-08-15 19:42:57 -04:00
Francesca Frangipane
b2b740fed7 Windows: Fix fullscreen deadlock + release 0.17.1 (#622)
* Windows: Fix fullscreen deadlock

* Release winit 0.17.1
2018-08-07 14:24:43 -04:00
Azriel Hoh
09550397d7 Maintenance/620/fix x11 release mode compilation (#621)
* Raised minimum version of `x11-dl`.

This fixes a compilation error in release mode on X11.

Issue #620

* Updated `CHANGELOG.md` about X11 release mode compilation issue.
2018-08-05 02:24:49 -04:00
Paul Rouget
a32f7f2ec5 Update cocoa and core-graphics (#608)
* Update cocoa and core-graphics

* Release winit 0.17.0

* Updated date / README version
2018-08-02 16:26:30 -04:00
Dennis Möhlmann
e8e9fa2418 fix assertion failed: validate_hidpi_factor(dpi_factor) (#607) (#618)
* fix assertion failed: validate_hidpi_factor(dpi_factor) (#607)

* added changelog entry
2018-08-02 13:03:15 -04:00
Felix Rabe
1a119bdfe9 Use consistent order inside #[cfg(any(...))] (#619) 2018-08-01 15:22:14 -04:00
Andrew Hickman
21ff2e0ffc Fix unsoundness on Windows (#601)
* Fix unsoundness in windows backend

* Synchronize window state properly

* update changelog and add a comment to execute_in_thread

* Formatting fixes and improve changelog message
2018-07-27 18:34:08 -04:00
Felix Rabe
df9b23c96a Typo: retreiv... -> retriev... (#614) 2018-07-27 14:59:53 -04:00
mtak-
4c117aa282 iOS: Fix the longjmp/setjmp ffi (#613)
* iOS: Fix the `longjmp`/`setjmp` ffi. `jmp_buf` was the wrong size (too small) causing crashes on application launch, make longjmp return Never

* remove extra parentheses around JBLEN, and add a changelog entry about the JmpBuf fix
2018-07-26 19:27:26 -04:00
Francesca Frangipane
88427262a6 macOS: Fix cursor hiding thread unsafety (#611) 2018-07-26 17:14:16 -04:00
mtak-
72b24a9348 iOS Abstract Out the UIView type from winit (#609)
* remove opengl code from winit

* iOS: restrict EventsLoop to be created on the main thread
iOS: Window can only be made once, make Drop on Window thread safe
iOS: make DelegateState owned by Window, cleanup
iOS: fixes from merge (class! macro)

* update the changelog

* Fixed nitpicks
2018-07-25 14:49:46 -04:00
Paul Rouget
01cb8e59e3 Fix key state on MacOS (#610) 2018-07-25 13:36:33 -04:00
trimental
3910326709 Update wayland-client and client-toolkit (#602) 2018-07-20 12:08:55 -04:00
Josh Groves
7ee46d80e6 Use class macro (#605) 2018-07-19 12:02:33 -04:00
Victor Berger
0cb5450999 Clarify DPI docs to highlight WindowEvent::HiDpiFactorChanged (#598)
* Clarify DPI docs to highlight WindowEvent::HiDpiFactorChanged

* Address review of #598

* dpi docs: grammar corrections

* The final nitpick
2018-07-16 10:44:29 -04:00
Iku Iwasa
8c78013257 Support NetBSD platform (#603)
* Support NetBSD platform

* CHANGELOG tweak + target ordering
2018-07-16 10:25:26 -04:00
mtak-
bd944898f0 set the UIViewController's view to the one that was just created (#595)
* set the UIViewController's view to the one that was just created

* capture the return value in a Unit to avoid SIGILL/SIGSEGV's.
change whitespace to be more idiomatic of Obj-C

* CHANGELOG entry
2018-07-13 15:10:12 -04:00
Bastien Orivel
c1ef1acfc0 Update parking_lot and bump version (#593) 2018-07-07 17:21:53 -04:00
Francesca Frangipane
040d3f5d8b Remove incorrect unreachable usage when guessing DPI factor (#592) 2018-07-05 11:52:25 -04:00
Joshua Minter
ec393e4a90 Disable maximize button on non-resizable windows (#588)
* Disabled maximize button

When creating a non resizable window in win32.
Also added example code to test.

* Added to changelog

* Added to documentation

* Removed non_resizable test

* Other suggested PR changes

* Documentation changes

* CHANGELOG nits
2018-07-03 20:15:19 -04:00
Francesca Frangipane
1703d0417a Release winit 0.16.1 (#587) 2018-07-02 20:14:38 -04:00
Francesca Frangipane
fad72c0441 X11: Fix compilation when c_char==c_uchar (#586) 2018-07-02 11:05:25 -04:00
Francesca Frangipane
2f7321a076 X11+Windows: Guess initial DPI factor (#583)
* X11: Guess initial DPI factor

* Windows: Guess initial DPI factor
2018-07-01 11:01:46 -04:00
icefoxen
85ee422acd Define "DPI" in docs. (#580)
It makes my pedant reflexes tingle.
2018-06-28 14:05:56 -04:00
Francesca Frangipane
089816d9ba Release winit 0.16.0 (#578) 2018-06-25 16:47:10 -04:00
Francesca Frangipane
c873c2db15 Wayland: Fix window creation dimensions (#577)
* Wayland: Fix window creation dimensions

* Wayland: Fix window creation min/max
2018-06-24 08:28:57 -04:00
えちょ
047c67baf3 windows feature WS_EX_NOREDIRECTIONBITMAP (#575)
* set WS_EX_NOREDIRECTIONBITMAP

* add CHANGELOG.md

* more flexibility.

* Skip DwmEnableBlurBehindWindow if no_redirection_bitmap is enabled.
2018-06-21 21:33:29 -04:00
aloucks
8f394f117b Change set_cursor_position to return Result<(), String> (#562)
* Change set_cursor_position to return Result<(), String>

This is now consistent with `grab_cursor`, and
enables `window.set_cursor_position(x, y)?` in functions
that return `Result<_, Box<Error>>`.

* Adjust error handling of unimplemented cusor opertions in wayland

* The final nitpick

* Actually one more
2018-06-19 10:30:15 -04:00
Francesca Frangipane
fb7528c239 grab_cursor and hide_cursor (#571)
* Windows: Use new cursor state API

* X11: Use new cursor state API

* macOS: Use new cursor state API

* Android+iOS: Stubbed new cursor state API

* Emscripten: Use new cursor state API

* Prevent multiple inc/dec of display count on Windows

* Fixed missing imports (no idea where those went)

* Remove NoneCursor

* Improved documentation

* Fix Emscripten build

* Windows: Re-grab before and after fullscreen
2018-06-18 12:32:18 -04:00
Hal Gentz
042f5fe4b3 Shares the XConnection between all event loops instead of just all event (#572)
loops on the same thread.

This is needed for adding shared context support to glutin, as contexts
must be made with the same native display (and therefore the same
connection.)

Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2018-06-17 20:44:38 -04:00
Francesca Frangipane
289fb47a34 macOS: Fix doubled key repeats (#570) 2018-06-17 15:08:26 -04:00
Nikolai Vazquez
38bc6babb7 Change Travis badge to SVG (#573)
PNG on GitHub does not render well on HiDPI screens.
2018-06-17 15:08:01 -04:00
Francesca Frangipane
e7a8efcfa0 Mirror monitor list methods on Window (#567)
* macOS: Monitor list methods on Window

* X11+Wayland: Monitor list methods on Window

* Windows: Monitor list methods on Window

* iOS: Monitor list methods on Window

* Android: Monitor list methods on Window

* Emscripten: Monitor list methods on Window

* Fixed Wayland implementation
2018-06-16 10:14:12 -04:00
Francesca Frangipane
1b74822cfc DPI for everyone (#548) 2018-06-14 19:42:18 -04:00
Lucas Kent
f083dae328 Windows creates Alt event instead of Menu event. (to match other platforms) (#551)
* Removed VirtualKeyCode::LMenu + VirtualKeyCode::RMenu, Windows now generates VirtualKeyCode::LAlt + VirtualKeyCode::RAlt instead.

* CHANGELOG nits
2018-06-13 13:24:33 -04:00
Francesca Frangipane
23c384bd30 Release winit 0.15.1 (#564) 2018-06-13 12:06:22 -04:00
Victor Berger
ced1616e51 wayland: implement set_resizable (#565) 2018-06-13 11:18:44 -04:00
Peter Atashian
233ac4aed2 Update to winapi 0.3.5 (#563) 2018-06-12 11:58:18 -04:00
Danny Fritz
be5a2b0e87 Windows & X11: Window::set_resizable (#558)
* Windows: Window::set_resizable

* X11: Window::set_resizable

* Code style regarding resizable

* X11: set_resizable remember max/min window size

* Stub out set_resizable on Android, iOS, and emscripten

* remove comment block from docs

* Windows: set_resizable in fullscreen

* Special case Xfwm

* Added fun provisos to docs
2018-06-11 18:47:50 -04:00
Francesca Frangipane
2b4b64f499 macOS: Only detect clicks+motion within client area (#561)
* macOS: Only detect clicks within client area

* macOS: Only track mouse motion within client area

* Add CHANGELOG entry about #463 fix
2018-06-11 11:16:39 -04:00
Francesca Frangipane
262490d074 X11: Fix super fun race conditions (#554)
* X11: Fix super fun race conditions

* Fix build on rustc<1.26
2018-06-07 14:08:19 -04:00
Francesca Frangipane
8891cfd85e macOS: Resizable without decorations (#553)
* macOS: Resizable without decorations

* Fix style mask regressions
2018-06-07 13:29:23 -04:00
Danny Fritz
2cc8fa1eac X11: implement with_resizable (#540) (#556) 2018-06-07 12:46:15 -04:00
Francesca Frangipane
79aebf06dc macOS: Fix alt and win keycodes (#552)
* macOS: Generate LAlt/RAlt VirtualKeyCode

* macOS: Correct RWin/LWin
2018-06-06 11:30:26 -04:00
Francesca Frangipane
19dd961752 X11: Fix flickering when resizing with transparency enabled (#546)
* X11: Fix flickering when resizing with transparency enabled

* X11: Fix with_override_redirect
2018-06-03 13:11:54 -04:00
Christian Duerr
bf413ecb83 Fix DPI with 0 width/hight reported by xorg (#544)
* Fix DPI with 0 width/hight reported by xorg

* Add `WINIT_HIDPI_FACTOR` env variable

It is now possible to override the DPI factor using the
`WINIT_HIDPI_FACTOR` environment variable on X11.

The changelog also has been updated to introduce all current changes
made.

* Add documentation for the environment variable

* Fix nitpicks

* Learning the alphabet

* Panic with error message if DPI env var is <= 0
2018-06-03 12:41:47 -04:00
Francesca Frangipane
fd1a3eda1c Test against rustc 1.24.1 on Travis (#547) 2018-06-02 22:59:59 -04:00
Danny Fritz
0e2488db32 Added a GitHub PULL_REQUEST_TEMPLATE (#542)
* Added a GitHub PULL_REQUEST_TEMPLATE

* Updated to better reflect my dictatorial demands
2018-06-02 11:04:08 -04:00
Danny Fritz
58a00bffbb Windows: implement with_resizable (#540) (#541)
* Windows: implement with_resizable (#540)

* Fixed typo
2018-06-02 10:51:24 -04:00
Johannes Hofmann
bbfe57400d appveyor.yml: Test additional Rust channels (#539)
* In addition to nightly, also test the current stable version and Rust
  1.24.1
* Use rustup-init.exe to install the different versions
2018-05-30 07:57:40 -04:00
Francesca Frangipane
4372f6fdac X11: Flatten window model (#536) 2018-05-29 07:48:47 -04:00
Francesca Frangipane
30f798b246 X11: util design improvements (#534) 2018-05-27 08:49:35 -04:00
Francesca Frangipane
282770f11a Release winit 0.15.0 (#530) 2018-05-22 14:17:41 -04:00
Francesca Frangipane
17373a4e91 X11: Fix primary monitor fallback regression (#532) 2018-05-22 09:07:46 -04:00
Francesca Frangipane
a34147b602 macOS: Fix keyboard regressions (#533)
* Emit `ReceivedCharacter` for key repeats
* Enter emits `\r` instead of `\n`
2018-05-22 09:05:33 -04:00
Francesca Frangipane
cebd15bfd1 X11: Improve hint support (#529)
Fixes #257
2018-05-20 10:47:22 -04:00
Francesca Frangipane
f51f7c0ca8 Add option to make window "always on top" (#528)
* macOS: always_on_top

* Windows: always_on_top

* X11: always_on_top

* Stub set_always_on_top on other platforms
2018-05-20 10:24:05 -04:00
Francesca Frangipane
f6d26df64d Windows: CursorState improvements (#526)
* Windows: CursorState improvements

Fixes #523

Prior to changing the cursor state, we now check the current grab
state, since it can be invalidated by alt-tabbing and other things.

`CursorState::Hide` is also implemented now.

The cursor name is now wrapped in a `Cursor` struct to allow
multithreaded access.

`Window::set_cursor_state` has been reworked to use
`execute_in_thread`. Two unneeded `transmute` calls were also
removed.

The `WM_SETCURSOR` handler is much more readable now.

`MonitorId::get_adapter_name` has been removed, since it's dead
code and appears to be a relic from 4 years ago.

* Windows: CursorState::Grab no longer hides cursor

`MouseCursor::NoneCursor` has been implemented to allow for
equivalent behavior to the older implementation.

Windows and X11 now have consistent cursor grabbing behavior.
macOS still needs to be updated.

* Windows: Grabbing auto-hides again (for now)

This API needs more work, so let's stick to a bug fix and some
refactoring. However, it now hides using a different technique
than it did originally, which applies instantly instead of after
mouse movement.
2018-05-19 12:02:57 -04:00
Francesca Frangipane
fddfb2e2d6 Windows: Fix detection of Pause and Scroll keys (#525)
Fixes #524
2018-05-18 18:48:19 -04:00
Francesca Frangipane
dec728cfa2 macOS: Implement NSTextInputClient (#518)
Fixes #263
2018-05-17 21:28:30 -04:00
Francesca Frangipane
8440091a4e macOS: Implement with_resize_increments (#519)
Fixes #135
2018-05-16 10:16:36 -04:00
Francesca Frangipane
2464a135b3 macOS: Fix Window::get_current_monitor (#521)
* macOS: Implement MonitorId::get_position

* macOS: Fix Window::get_current_monitor
2018-05-16 09:41:45 -04:00
Francesca Frangipane
87fa120ebb macOS: Fix re-enabling decorations after the window is built without them (#520)
Fixes #517
2018-05-16 08:51:56 -04:00
Francesca Frangipane
d86f53a02c X11: Fix get_current_monitor (#515)
* X11: Fix get_current_monitor

Fixes #64

* impl Debug for MonitorId on all platforms
2018-05-14 08:14:57 -04:00
Francesca Frangipane
15a4fec3d9 X11: Fix scroll wheel delta on i3/etc. (#514)
Fixes #447
2018-05-13 08:44:23 -04:00
OJ Kwon
1819be1173 fix(mac_platform): forward keyevent to system (#511)
* fix(mac_platform): forward keyevent to system

* doc(changelog): update changelog
2018-05-12 22:10:57 -04:00
Victor Berger
ffa9b51d27 wayland: improve diagnostic of failed init (#512) 2018-05-12 07:58:11 -04:00
tinaun
b4a8c08f43 compile with icon_loading feature on docs.rs (#509)
* compile with icon_loading feature on docs.rs

these functions should be more visible now.

* Explicitly document which functions require icon_loading
2018-05-11 10:33:06 -04:00
Francesca Frangipane
741bcc4672 Correct privacy for Icon::to_cardinals (#510) 2018-05-10 18:42:41 -04:00
Francesca Frangipane
e48f1fc5f1 Release winit 0.14.0 (#503) 2018-05-09 10:58:06 -04:00
Johannes Hofmann
374f131f1e Update wayland-client to version 0.20.4 (#505)
Fixes #504
2018-05-08 19:00:54 -04:00
Jack Magnus
363261077f Windows: Fix panic when calling set_fullscreen(None) (#502)
* Windows: Fix panic for set_fullscreen(None) (#501)

* Add condition to prevent panic

Trying to call set_fullscreen(None) on a window that has never been in
fullscreen mode caused a panic before this change.
The responsible method now simply checks if this precondition is met and
returns (does nothing) otherwise.

* Add entry to CHANGELOG

* Add platform specification to CHANGELOG entry

Forgot to add that the to_fullscreen(None) bugfix is Windows only in
CHANGELOG.
2018-05-08 08:16:49 -04:00
Francesca Frangipane
102dd07456 Window icons (#497) 2018-05-07 17:36:21 -04:00
Victor Berger
1e97103094 wayland: migrate to smithay-client-toolkit (#490)
* wayland: migrate to smithay-client-toolkit

* Update smithay-client-toolkit

* Add changelog entry for wayland rework
2018-05-05 13:36:34 -04:00
Francesca Frangipane
cc8907b956 X11: Implement resize increments and base size (#494) 2018-05-03 09:41:11 -04:00
Francesca Frangipane
c4b92ebd45 X11: General cleanup (#491)
* X11: General cleanup

This is almost entirely internal changes, and as usual, doesn't actually
fix any problems people have complained about.

- `XSetInputFocus` can't be called before the window is visible. This
was previously handled by looping (with a sleep) and querying for the
window's state until it was visible. Now we use `XIfEvent`, which blocks
until we receive `VisibilityNotify`. Note that this can't be replaced
with an `XSync` (I tried).
- We now call `XSync` at the end of window creation and check for
errors, assuring that broken windows are never returned. When creating
invisible windows, this is the only time the output buffer is flushed
during the entire window creation process (AFAIK). For visible windows,
`XIfEvent` will generally flush, but window creation has overall been
reduced to the minimum number of flushes.
- `check_errors().expect()` has been a common pattern throughout the
backend, but it seems that people (myself included) didn't make a
distinction between using it after synchronous requests and asynchronous
requests. Now we only use it after async requests if we flush first,
though this still isn't correct (since the request likely hasn't been
processed yet). The only real solution (besides forcing a sync *every
time*) is to handle asynchronous errors *asynchronously*. For future
work, I plan on adding logging, though I don't plan on actually
*handling* those errors; that's more of something to hope for in the
hypothetical async/await XCB paradise.
- We now flush whenever it makes sense to. `util::Flusher` was added to
force contributors to be aware of the output buffer.
- `Window::get_position`, `Window::get_inner_position`,
`Window::get_inner_size`, and `Window::get_outer_size` previously all
required *several* round-trips. On my machine, it took an average of
around 80µs. They've now been reduced to one round-trip each, which
reduces my measurement to 16µs. This was accomplished simply by caching
the frame extents, which are expensive to calculate (due to various
queries and heuristics), but change infrequently and predictably. I
still recommend that application developers use these methods sparingly
and generally prefer storing the values from `Resized`/`Moved`, as
that's zero overhead.
- The above change enabled me to change the `Moved` event to supply
window positions, rather than client area positions. Additionally, we no
longer generate `Moved` for real (as in, not synthetic)
`ConfigureNotify` events. Real `ConfigureNotify` events contain
positions relative to the parent window, which are typically constant
and useless. Since that position would be completely different from the
root-relative positions supplied by synthetic `ConfigureNotify` events
(which are the vast majority of them), that meant real `ConfigureNotify`
events would *always* be detected as the position having changed, so the
resultant `Moved` was multiple levels of misleading. In practice, this
meant a garbage `Moved` would be sent every time the window was resized;
now a resize has to actually change the window's position to be
accompanied by `Moved`.
- Every time we processed an `XI_Enter` event, we would leak 4 bytes via
`util::query_pointer` (`XIQueryPointer`). `XIButtonState` contains a
dynamically-allocated mask field which we weren't freeing. As this event
occurs with fairly high frequency, long-running applications could
easily accumulate substantial leaks. `util::PointerState::drop` now
takes care of this.
- The `util` module has been split up into several sub-modules, as it
was getting rather lengthy. This accounts for a significant part of this
diff, unfortunately.
- Atoms are now cached. Xlib caches them too, so `XInternAtom` wouldn't
typically be a round-trip anyway, but the added complexity is
negligible.
- Switched from `std::sync::Mutex` to `parking_lot::Mutex` (within this
backend). There appears to be no downside to this, but if anyone finds
one, this would be easy to revert.
- The WM name and supported hints are now global to the application, and
are updated upon `ReparentNotify`, which should detect when the WM was
replaced (assuming a reparenting WM was involved, that is). Previously,
these values were per-window and would never update, meaning replacing
the WM could potentially lead to (admittedly very minor) problems.
- The result of `Window2::create_empty_cursor` will now only be used if
it actually succeeds.
- `Window2::load_cursor` no longer re-allocates the cursor name.
- `util::lookup_utf8` previously allocated a 16-byte buffer on the heap.
Now it allocates a 1024-byte buffer on the stack, and falls back to
dynamic allocation if the buffer is too small. This base buffer size is
admittedly gratuitous, but less so if you're using IME.
- `with_c_str` was finally removed.
- Added `util::Format` enum to help prevent goofs when dealing with
format arguments.
- `util::get_property`, something I added way back in my first winit PR,
only calculated offsets correctly for `util::Format::Char`. This was
concealed by the accomodating buffer size, as it would be very rare for
the offset to be needed; however, testing with a buffer size of 1,
`util::Format::Long` would read from the same offset multiple times, and
`util::Format::Short` would miss data. This function now works correctly
for all formats, relying on the simple fact that the offset increases by
the buffer size on each iteration. We also account for the extra byte
that `XGetWindowProperty` allocates at the end of the buffer, and copy
data from the buffer instead of moving it and taking ownership of the
pointer.
- Drag and drop now reliably works in release mode. This is presumably
related to the `util::get_property` changes.
- `util::change_property` now exists, which should make it easier to add
features in the future.
- The `EventsLoop` device map is no longer in a mutex.
- `XConnection` now implements `Debug`.
- Valgrind no longer complains about anything related to winit (with
either the system allocator or jemalloc, though "not having valgrind
complain about jemalloc" isn't something to strive for).

* X11: Add better diagnostics when initialization fails

* X11: Handle XIQueryDevice failure

* X11: Use correct types in error handler
2018-05-03 09:15:49 -04:00
Christian Duerr
fee874b5b7 Add Copy/Paste keys (#495)
* Add Copy/Paste keys

This is only a tiny update which introduces the `Copy` and `Paste` keys
which are present on X11/Wayland/Windows. I'm not sure if this exists on
MacOS too, but I'm not able to test that and it doesn't have names but
just matches on the hex key values.

The "Copy" element is a reserved keyword in Rust but shouldn't cause any
conflicts in this scenario, this behavior falls in line with
https://docs.rs/winit/0.13.1/winit/enum.MouseCursor.html#variant.Copy,
but it would be possible to rename it. However `Copy` seems like the
most intuitive choice.

* Add Cut key, fix windows and update CHANGELOG

This introduces a bunch of minor fixes:
 * The changes introduced by this branch have been added to the changelog
 * Since related, the `Cut` key has also been added
 * An attempt has been made to fix Windows

* Fix position of fallback comment

The new keys have been inserted at the wrong position, so the fallback
comment has been moved to the `_ => ...` section again.

* Fix windows build

Apparently there are no keys for Cut/Paste on Windows, so for now those
have been removed on Windows and only the `Copy` key has been added on
Windows, the changelog has been updated to reflect that.

Linux still implements Copy/Clone/Paste, but `Copy` is now working
properly on Wayland.

MacOS still does not have any of these keys.

* Remove Windows changes

Because the Windows design wasn't completely clear the VirtualKeyCode
variants are now only used on Linux with X11 and Wayland and ignored on
both MacOS and Windows.

The CHANGELOG has also been updated. Windows has been removed from it
and the Linux section has been clarified a bit.
2018-05-02 19:18:52 -04:00
Joe Moon
eba888207e macos platform attributes regression (#488)
* macOS: fix regression in 03c3e79409

fixed !decorations case and refactored logic to be a little easier to
read

* fix default case to inlude closable mask

* add comment to default case of macos platform attrs
2018-04-29 18:51:57 -04:00
Johannes Hofmann
ea28791da6 x11: Always receive Awakened event in run_forever (#489)
* x11: Always receive Awakened event in run_forever

Do not reset the pending_wakeup boolean at the start of run_forever so
that each call to EventsLoopProxy::wakeup results in an Awakened event.

Fixes #462

* Update CHANGELOG.md
2018-04-28 19:03:06 -04:00
Francesca Frangipane
fe2d37fcdc Windows: Implement DeviceEvents (#482)
Fixes #467

All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.

Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.

This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
  DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.

There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.

I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.

Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
Vladimir
3407a8dd78 Macos multi windows leak (#481)
* adding a multiwindow example

* Added NSAutoReleasepool for WindowDelegate::Drop
as setDelegate:nil autoreleases WindowDelegate during work.

Added NSAutoReleasepool for Window2::Create,
as it uses autorelease on objects while doing work.

Added NSAutoreleasepool for Window2::Drop
as nswindow::close uses autorelease on objects.

Added NSAutoreleasepool for IdRef.

Moved Window2 WinitWindow objc class to a static var, as we are creating
multiple windows.

* specifying return type for msg_send!

* removing example/recreate_window_leak.rs

* EventLoop, Shared, no need to retain dead weak ptr

* Change log entry added

* added comment about Shared.find_and_remove_window

* fixed code style errors
2018-04-28 12:10:06 -04:00
Joe Moon
5761fb6b30 macOS: fix subtle regression introduced in 0474dc986 (#487)
* macOS: fix subtle regression introduced in 0474dc986

* update changelog
2018-04-28 00:12:50 -04:00
Francesca Frangipane
7aeb2c083b macOS: Implement Moved (#478)
* macOS: Implement Moved

Fixes #67

* Also emit Moved after resizes that change position
2018-04-27 20:46:20 -04:00
Francesca Frangipane
8f47fdbe67 Windows: Position fixes (#479)
* Remove executable flag from os/macos.rs

This was causing me some grief while working on Windows, and it
doesn't belong here to begin with.

* Windows: get_position returns screen coordinates instead of workspace coordinates

Previously, get_position used GetWindowPlacement. As per the
documentation of WINDOWSTRUCT, the returned coordinates are in
workspace space, meaning they're relative to the taskbar. It's
also explicitly remarked that these coordinates should only be
used in conjunction with SetWindowPlacement, as mixing them with
functions expecting screen coordinates can cause unpleasantness.
Since our set_position (correctly) uses SetWindowPos, this meant
that passing the return of get_position to set_position would
cause the window to move.

We now use GetWindowRect, which returns screen coordinates. This
gives us both better consistency within the Windows backend and
across platforms.

Note that this only makes a difference if the taskbar is visible.
With the taskbar hidden, the values are exactly the same as before.

* Windows: Moved event position values are consistent with get_position

The old Moved values had two problems:

* They were obtained by casting a WORD (u16) straight to an i32.
This meant wrap-around would never be interpreted as negative,
thus negative positions (which are ubiquitous when using multiple
monitors) would result in positions around u16::MAX.

* WM_MOVE supplies client area positions, not window positions.

Switching to handling WM_WINDOWPOSCHANGED solves both of these
problems.

* Better documentation for Moved and Resized
2018-04-26 20:09:33 -04:00
Francesca Frangipane
2ea42b3947 Release winit 0.13.1 (#486) 2018-04-26 18:53:16 -04:00
Branan Riley
7510b95d8c Set minimum x11-dl version to include Z (#484)
Without this pin, an existing cargo.lock for an older winit will not
update the x11-dl dependency, and thus will select a version that is
missing required new XIM features.
2018-04-26 11:53:11 -04:00
254 changed files with 47235 additions and 15406 deletions

2
.cargo/config.toml Normal file
View File

@@ -0,0 +1,2 @@
[alias]
run-wasm = ["run", "--release", "--package", "run-wasm", "--"]

View File

@@ -1,56 +0,0 @@
version: 2
jobs:
android-test:
working_directory: ~/winit
docker:
- image: tomaka/cargo-apk
steps:
- run: apt-get -qq update && apt-get install -y git
- checkout
- restore_cache:
key: android-test-cache-{{ checksum "Cargo.toml" }}
- run: cargo apk build --example window
- save_cache:
key: android-test-cache-{{ checksum "Cargo.toml" }}
paths:
- target
asmjs-test:
working_directory: ~/winit
docker:
- image: tomaka/rustc-emscripten
steps:
- run: apt-get -qq update && apt-get install -y git
- checkout
- restore_cache:
key: asmjs-test-cache-{{ checksum "Cargo.toml" }}
- run: cargo build --example window --target asmjs-unknown-emscripten
- save_cache:
key: asmjs-test-cache-{{ checksum "Cargo.toml" }}
paths:
- target
wasm-test:
working_directory: ~/winit
docker:
- image: tomaka/rustc-emscripten
steps:
- run: apt-get -qq update && apt-get install -y git
- checkout
- restore_cache:
key: wasm-test-cache-{{ checksum "Cargo.toml" }}
- run: cargo build --example window --target wasm32-unknown-emscripten
- save_cache:
key: wasm-test-cache-{{ checksum "Cargo.toml" }}
paths:
- target
workflows:
version: 2
build-test-and-deploy:
jobs:
- android-test
- asmjs-test
- wasm-test

40
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,40 @@
# Core maintainers:
# - @msiglreith
# - @kchibisov
# - @madsmtm
# - @maroider
# Android
/src/platform/android.rs @msiglreith
/src/platform_impl/android @msiglreith
# iOS
/src/platform/ios.rs @madsmtm
/src/platform_impl/ios @madsmtm
# Unix
/src/platform_impl/linux/mod.rs @kchibisov
# Wayland
/src/platform/wayland.rs @kchibisov
/src/platform_impl/linux/wayland @kchibisov
# X11
/src/platform/x11.rs @kchibisov
/src/platform_impl/linux/x11 @kchibisov
# macOS
/src/platform/macos.rs @madsmtm
/src/platform_impl/macos @madsmtm
# Web (no maintainer)
/src/platform/web.rs
/src/platform_impl/web
# Windows
/src/platform/windows.rs @msiglreith
/src/platform_impl/windows @msiglreith
# Orbital (Redox OS)
/src/platform/orbital.rs @jackpot51
/src/platform_impl/orbital @jackpot51

5
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,5 @@
- [ ] Tested on all platforms changed
- [ ] Added an entry to `CHANGELOG.md` if knowledge of this change could be valuable to users
- [ ] Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
- [ ] Created or updated an example program if it would help users understand this functionality
- [ ] Updated [feature matrix](https://github.com/rust-windowing/winit/blob/master/FEATURES.md), if new features were added or implemented

121
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,121 @@
name: CI
on:
pull_request:
push:
branches: [master]
jobs:
Check_Formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1
with:
rust-version: stable
components: rustfmt
- name: Check Formatting
run: cargo +stable fmt --all -- --check
tests:
name: Tests
strategy:
fail-fast: false
matrix:
rust_version: ['1.60.0', stable, nightly]
platform:
# Note: Make sure that we test all the `docs.rs` targets defined in Cargo.toml!
- { target: x86_64-pc-windows-msvc, os: windows-latest, }
- { target: i686-pc-windows-msvc, os: windows-latest, }
- { target: x86_64-pc-windows-gnu, os: windows-latest, host: -x86_64-pc-windows-gnu }
- { target: i686-pc-windows-gnu, os: windows-latest, host: -i686-pc-windows-gnu }
- { target: i686-unknown-linux-gnu, os: ubuntu-latest, }
- { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, }
- { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: --no-default-features, features: x11 }
- { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: --no-default-features, features: "wayland,wayland-dlopen" }
- { target: aarch64-linux-android, os: ubuntu-latest, options: -p winit, cmd: 'apk --', features: "android-native-activity" }
- { target: x86_64-unknown-redox, os: ubuntu-latest, }
- { target: x86_64-apple-darwin, os: macos-latest, }
- { target: x86_64-apple-ios, os: macos-latest, }
- { target: aarch64-apple-ios, os: macos-latest, }
# We're using Windows rather than Ubuntu to run the wasm tests because caching cargo-web
# doesn't currently work on Linux.
- { target: wasm32-unknown-unknown, os: windows-latest, }
env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-C debuginfo=0 --deny warnings"
OPTIONS: ${{ matrix.platform.options }}
FEATURES: ${{ format(',{0}', matrix.platform.features ) }}
CMD: ${{ matrix.platform.cmd }}
RUSTDOCFLAGS: -Dwarnings
runs-on: ${{ matrix.platform.os }}
steps:
- uses: actions/checkout@v2
# Used to cache cargo-web
- name: Cache cargo folder
uses: actions/cache@v1
with:
path: ~/.cargo
key: ${{ matrix.platform.target }}-cargo-${{ matrix.rust_version }}
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }}
targets: ${{ matrix.platform.target }}
components: clippy
- name: Install GCC Multilib
if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686')
run: sudo apt-get update && sudo apt-get install gcc-multilib
- name: Install cargo-apk
if: contains(matrix.platform.target, 'android')
run: cargo install cargo-apk
- name: Check documentation
shell: bash
run: cargo doc --no-deps --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES --document-private-items
- name: Build crate
shell: bash
run: cargo $CMD build --verbose --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES
- name: Build tests
shell: bash
if: >
!contains(matrix.platform.target, 'redox') &&
matrix.rust_version != '1.60.0'
run: cargo $CMD test --no-run --verbose --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES
- name: Run tests
shell: bash
if: >
!contains(matrix.platform.target, 'android') &&
!contains(matrix.platform.target, 'ios') &&
!contains(matrix.platform.target, 'wasm32') &&
!contains(matrix.platform.target, 'redox') &&
matrix.rust_version != '1.60.0'
run: cargo $CMD test --verbose --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES
- name: Lint with clippy
shell: bash
if: (matrix.rust_version == 'stable') && !contains(matrix.platform.options, '--no-default-features')
run: cargo clippy --all-targets --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES -- -Dwarnings
- name: Build tests with serde enabled
shell: bash
if: >
!contains(matrix.platform.target, 'redox') &&
matrix.rust_version != '1.60.0'
run: cargo $CMD test --no-run --verbose --target ${{ matrix.platform.target }} $OPTIONS --features serde,$FEATURES
- name: Run tests with serde enabled
shell: bash
if: >
!contains(matrix.platform.target, 'android') &&
!contains(matrix.platform.target, 'ios') &&
!contains(matrix.platform.target, 'wasm32') &&
!contains(matrix.platform.target, 'redox') &&
matrix.rust_version != '1.60.0'
run: cargo $CMD test --verbose --target ${{ matrix.platform.target }} $OPTIONS --features serde,$FEATURES

6
.gitignore vendored
View File

@@ -1,4 +1,10 @@
Cargo.lock
target/
rls/
.vscode/
*~
*.wasm
*.ts
*.js
#*#
.DS_Store

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "deps/apk-builder"]
path = deps/apk-builder
url = https://github.com/tomaka/android-rs-glue
url = https://github.com/rust-windowing/android-rs-glue

View File

@@ -1,60 +0,0 @@
language: rust
cache: cargo
matrix:
include:
# Linux 32bit
- env: TARGET=i686-unknown-linux-gnu
os: linux
rust: nightly
addons:
apt:
# Cross compiler and cross compiled C libraries
packages: &i686_packages
- gcc-multilib
- env: TARGET=i686-unknown-linux-gnu
os: linux
rust: stable
addons:
apt:
packages: *i686_packages
# Linux 64bit
- env: TARGET=x86_64-unknown-linux-gnu
os: linux
rust: nightly
- env: TARGET=x86_64-unknown-linux-gnu
os: linux
rust: stable
# macOS
- env: TARGET=x86_64-apple-darwin
os: osx
rust: nightly
- env: TARGET=x86_64-apple-darwin
os: osx
rust: stable
# iOS
- env: TARGET=x86_64-apple-ios
os: osx
rust: nightly
- env: TARGET=x86_64-apple-ios
os: osx
rust: stable
install:
- rustup self update
- rustup target add $TARGET; true
script:
- cargo build --target $TARGET --verbose
# Running iOS apps on OSX requires the simulator so we skip that for now
- if [ "$TARGET" != "x86_64-apple-ios" ]; then cargo test --target $TARGET --verbose; fi
after_success:
- |
[ $TRAVIS_BRANCH = master ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo publish --token ${CRATESIO_TOKEN}

View File

@@ -1,5 +1,840 @@
# Changelog
All notable changes to this project will be documented in this file.
Please keep one empty line before and after all headers. (This is required for `git` to produce a conflict when a release is made while a PR is open and the PR's changelog entry would go into the wrong section).
And please only add new entries to the top of this list, right below the `# Unreleased` header.
# Unreleased
# 0.28.5
- On macOS, fix `key_up` beind ignored when `Ime` is disabled.
# 0.28.4
- On macOS, fix empty marked text blocking regular input.
- On macOS, fixed potential panic when getting refresh rate.
- On macOS, fix crash when calling `Window::set_ime_position` from another thread.
# 0.28.3
- Fix macOS memory leaks.
# 0.28.2
- Implement `HasRawDisplayHandle` for `EventLoop`.
- On macOS, set resize increments only for live resizes.
- On Wayland, fix rare crash on DPI change
- Web: Added support for `Window::theme`.
- On Wayland, fix rounding issues when doing resize.
- On macOS, fix wrong focused state on startup.
- On Windows, fix crash on setting taskbar when using Visual Studio debugger.
- On macOS, resize simple fullscreen windows on windowDidChangeScreen events.
# 0.28.1
- On Wayland, fix crash when dropping a window in multi-window setup.
# 0.28.0
- On macOS, fixed `Ime::Commit` persisting for all input after interacting with `Ime`.
- On macOS, added `WindowExtMacOS::option_as_alt` and `WindowExtMacOS::set_option_as_alt`.
- On Windows, fix window size for maximized, undecorated windows.
- On Windows and macOS, add `WindowBuilder::with_active`.
- Add `Window::is_minimized`.
- On X11, fix errors handled during `register_xlib_error_hook` invocation bleeding into winit.
- Add `Window::has_focus`.
- On Windows, fix `Window::set_minimized(false)` not working for windows minimized by `Win + D` hotkey.
- **Breaking:** On Web, touch input no longer fires `WindowEvent::Cursor*`, `WindowEvent::MouseInput`, or `DeviceEvent::MouseMotion` like other platforms, but instead it fires `WindowEvent::Touch`.
- **Breaking:** Removed platform specific `WindowBuilder::with_parent` API in favor of `WindowBuilder::with_parent_window`.
- On Windows, retain `WS_MAXIMIZE` window style when un-minimizing a maximized window.
- On Windows, fix left mouse button release event not being sent after `Window::drag_window`.
- On macOS, run most actions on the main thread, which is strictly more correct, but might make multithreaded applications block slightly more.
- On macOS, fix panic when getting current monitor without any monitor attached.
- On Windows and MacOS, add API to enable/disable window buttons (close, minimize, ...etc).
- On Windows, macOS, X11 and Wayland, add `Window::set_theme`.
- **Breaking:** Remove `WindowExtWayland::wayland_set_csd_theme` and `WindowBuilderExtX11::with_gtk_theme_variant`.
- On Windows, revert window background to an empty brush to avoid white flashes when changing scaling.
- **Breaking:** Removed `Window::set_always_on_top` and related APIs in favor of `Window::set_window_level`.
- On Windows, MacOS and X11, add always on bottom APIs.
- On Windows, fix the value in `MouseButton::Other`.
- On macOS, add `WindowExtMacOS::is_document_edited` and `WindowExtMacOS::set_document_edited` APIs.
- **Breaking:** Removed `WindowBuilderExtIOS::with_root_view_class`; instead, you should use `[[view layer] addSublayer: ...]` to add an instance of the desired layer class (e.g. `CAEAGLLayer` or `CAMetalLayer`). See `vulkano-win` or `wgpu` for examples of this.
- On MacOS and Windows, add `Window::set_content_protected`.
- On MacOS, add `EventLoopBuilderExtMacOS::with_activate_ignoring_other_apps`.
- On Windows, fix icons specified on `WindowBuilder` not taking effect for windows created after the first one.
- On Windows and macOS, add `Window::title` to query the current window title.
- On Windows, fix focusing menubar when pressing `Alt`.
- On MacOS, made `accepts_first_mouse` configurable.
- Migrated `WindowBuilderExtUnix::with_resize_increments` to `WindowBuilder`.
- Added `Window::resize_increments`/`Window::set_resize_increments` to update resize increments at runtime for X11/macOS.
- macOS/iOS: Use `objc2` instead of `objc` internally.
- **Breaking:** Bump MSRV from `1.57` to `1.60`.
- **Breaking:** Split the `platform::unix` module into `platform::x11` and `platform::wayland`. The extension types are similarly renamed.
- **Breaking:**: Removed deprecated method `platform::unix::WindowExtUnix::is_ready`.
- Removed `parking_lot` dependency.
- **Breaking:** On macOS, add support for two-finger touchpad magnification and rotation gestures with new events `WindowEvent::TouchpadMagnify` and `WindowEvent::TouchpadRotate`. Also add support for touchpad smart-magnification gesture with a new event `WindowEvent::SmartMagnify`.
- **Breaking:** On web, the `WindowBuilderExtWebSys::with_prevent_default` setting (enabled by default), now additionally prevents scrolling of the webpage in mobile browsers, previously it only disabled scrolling on desktop.
- On Wayland, `wayland-csd-adwaita` now uses `ab_glyph` instead of `crossfont` to render the title for decorations.
- On Wayland, a new `wayland-csd-adwaita-crossfont` feature was added to use `crossfont` instead of `ab_glyph` for decorations.
- On Wayland, if not otherwise specified use upstream automatic CSD theme selection.
- On X11, added `WindowExtX11::with_parent` to create child windows.
- Added support for `WindowBuilder::with_theme` and `Window::theme` to support per-window dark/light/system theme configuration on macos, windows and wayland.
- On macOS, added support for `WindowEvent::ThemeChanged`.
- **Breaking:** Removed `WindowBuilderExtWindows::with_theme` and `WindowBuilderExtWayland::with_wayland_csd_theme` in favour of `WindowBuilder::with_theme`.
- **Breaking:** Removed `WindowExtWindows::theme` in favour of `Window::theme`.
- Enabled `doc_auto_cfg` when generating docs on docs.rs for feature labels.
- **Breaking:** On Android, switched to using [`android-activity`](https://github.com/rib/android-activity) crate as a glue layer instead of [`ndk-glue`](https://github.com/rust-windowing/android-ndk-rs/tree/master/ndk-glue). See [README.md#Android](https://github.com/rust-windowing/winit#Android) for more details. ([#2444](https://github.com/rust-windowing/winit/pull/2444))
- **Breaking:** Removed support for `raw-window-handle` version `0.4`
- On Wayland, `RedrawRequested` not emitted during resize.
- Add a `set_wait_timeout` function to `ControlFlow` to allow waiting for a `Duration`.
- **Breaking:** Remove the unstable `xlib_xconnection()` function from the private interface.
- Added Orbital support for Redox OS
- On X11, added `drag_resize_window` method.
- Added `Window::set_transparent` to provide a hint about transparency of the window on Wayland and macOS.
- On macOS, fix the mouse buttons other than left/right/middle being reported as middle.
- On Wayland, support fractional scaling via the wp-fractional-scale protocol.
- On web, fix removal of mouse event listeners from the global object upon window distruction.
- Add WindowAttributes getter to WindowBuilder to allow introspection of default values.
- Added `Window::set_ime_purpose` for setting the IME purpose, currently implemented on Wayland only.
# 0.27.5
- On Wayland, fix byte offset in `Ime::Preedit` pointing to invalid bytes.
# 0.27.4
- On Windows, emit `ReceivedCharacter` events on system keybindings.
- On Windows, fixed focus event emission on minimize.
- On X11, fixed IME crashing during reload.
# 0.27.3
- On Windows, added `WindowExtWindows::set_undecorated_shadow` and `WindowBuilderExtWindows::with_undecorated_shadow` to draw the drop shadow behind a borderless window.
- On Windows, fixed default window features (ie snap, animations, shake, etc.) when decorations are disabled.
- On Windows, fixed ALT+Space shortcut to open window menu.
- On Wayland, fixed `Ime::Preedit` not being sent on IME reset.
- Fixed unbound version specified for `raw-window-handle` leading to compilation failures.
- Empty `Ime::Preedit` event will be sent before `Ime::Commit` to help clearing preedit.
- On X11, fixed IME context picking by querying for supported styles beforehand.
# 0.27.2 (2022-8-12)
- On macOS, fixed touch phase reporting when scrolling.
- On X11, fix min, max and resize increment hints not persisting for resizable windows (e.g. on DPI change).
- On Windows, respect min/max inner sizes when creating the window.
- For backwards compatibility, `Window` now (additionally) implements the old version (`0.4`) of the `HasRawWindowHandle` trait
- On Windows, added support for `EventLoopWindowTarget::set_device_event_filter`.
- On Wayland, fix user requested `WindowEvent::RedrawRequested` being delayed by a frame.
# 0.27.1 (2022-07-30)
- The minimum supported Rust version was lowered to `1.57.0` and now explicitly tested.
- On X11, fix crash on start due to inability to create an IME context without any preedit.
# 0.27.0 (2022-07-26)
- On Windows, fix hiding a maximized window.
- On Android, `ndk-glue`'s `NativeWindow` lock is now held between `Event::Resumed` and `Event::Suspended`.
- On Web, added `EventLoopExtWebSys` with a `spawn` method to start the event loop without throwing an exception.
- Added `WindowEvent::Occluded(bool)`, currently implemented on macOS and X11.
- On X11, fix events for caps lock key not being sent
- Build docs on `docs.rs` for iOS and Android as well.
- **Breaking:** Removed the `WindowAttributes` struct, since all its functionality is accessible from `WindowBuilder`.
- Added `WindowBuilder::transparent` getter to check if the user set `transparent` attribute.
- On macOS, Fix emitting `Event::LoopDestroyed` on CMD+Q.
- On macOS, fixed an issue where having multiple windows would prevent run_return from ever returning.
- On Wayland, fix bug where the cursor wouldn't hide in GNOME.
- On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events.
- On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`.
- On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`.
- On Windows, remove internally unique DC per window.
- On macOS, remove the need to call `set_ime_position` after moving the window.
- Added `Window::is_visible`.
- Added `Window::is_resizable`.
- Added `Window::is_decorated`.
- On X11, fix for repeated event loop iteration when `ControlFlow` was `Wait`
- On X11, fix scale factor calculation when the only monitor is reconnected
- On Wayland, report unaccelerated mouse deltas in `DeviceEvent::MouseMotion`.
- On Web, a focused event is manually generated when a click occurs to emulate behaviour of other backends.
- **Breaking:** Bump `ndk` version to 0.6, ndk-sys to `v0.3`, `ndk-glue` to `0.6`.
- Remove no longer needed `WINIT_LINK_COLORSYNC` environment variable.
- **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs.
- Add `EventLoopBuilder`, which allows you to create and tweak the settings of an event loop before creating it.
- Deprecated `EventLoop::with_user_event`; use `EventLoopBuilder::with_user_event` instead.
- **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods).
- **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods).
- **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods).
- **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies.
- The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings.
- On Wayland, fix polling during consecutive `EventLoop::run_return` invocations.
- On Windows, fix race issue creating fullscreen windows with `WindowBuilder::with_fullscreen`
- On Android, `virtual_keycode` for `KeyboardInput` events is now filled in where a suitable match is found.
- Added helper methods on `ControlFlow` to set its value.
- On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor
sent a cancel or frame event.
- On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms.
- **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`.
- On Wayland, fallback CSD was replaced with proper one:
- `WindowBuilderExtUnix::with_wayland_csd_theme` to set color theme in builder.
- `WindowExtUnix::wayland_set_csd_theme` to set color theme when creating a window.
- `WINIT_WAYLAND_CSD_THEME` env variable was added, it can be used to set "dark"/"light" theme in apps that don't expose theme setting.
- `wayland-csd-adwaita` feature that enables proper CSD with title rendering using FreeType system library.
- `wayland-csd-adwaita-notitle` feature that enables CSD but without title rendering.
- On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`.
- On Windows, fix wrong fullscreen monitors being recognized when handling WM_WINDOWPOSCHANGING messages
- **Breaking:** Added new `WindowEvent::Ime` supported on desktop platforms.
- Added `Window::set_ime_allowed` supported on desktop platforms.
- **Breaking:** IME input on desktop platforms won't be received unless it's explicitly allowed via `Window::set_ime_allowed` and new `WindowEvent::Ime` events are handled.
- On macOS, `WindowEvent::Resized` is now emitted in `frameDidChange` instead of `windowDidResize`.
- **Breaking:** On X11, device events are now ignored for unfocused windows by default, use `EventLoopWindowTarget::set_device_event_filter` to set the filter level.
- Implemented `Default` on `EventLoop<()>`.
- Implemented `Eq` for `Fullscreen`, `Theme`, and `UserAttentionType`.
- **Breaking:** `Window::set_cursor_grab` now accepts `CursorGrabMode` to control grabbing behavior.
- On Wayland, add support for `Window::set_cursor_position`.
- Fix on macOS `WindowBuilder::with_disallow_hidpi`, setting true or false by the user no matter the SO default value.
- `EventLoopBuilder::build` will now panic when the `EventLoop` is being created more than once.
- Added `From<u64>` for `WindowId` and `From<WindowId>` for `u64`.
- Added `MonitorHandle::refresh_rate_millihertz` to get monitor's refresh rate.
- **Breaking**, Replaced `VideoMode::refresh_rate` with `VideoMode::refresh_rate_millihertz` providing better precision.
- On Web, add `with_prevent_default` and `with_focusable` to `WindowBuilderExtWebSys` to control whether events should be propagated.
- On Windows, fix focus events being sent to inactive windows.
- **Breaking**, update `raw-window-handle` to `v0.5` and implement `HasRawDisplayHandle` for `Window` and `EventLoopWindowTarget`.
- On X11, add function `register_xlib_error_hook` into `winit::platform::unix` to subscribe for errors comming from Xlib.
- On Android, upgrade `ndk` and `ndk-glue` dependencies to the recently released `0.7.0`.
- All platforms can now be relied on to emit a `Resumed` event. Applications are recommended to lazily initialize graphics state and windows on first resume for portability.
- **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down.
- On MacOS, fix deadlock when calling `set_maximized` from event loop.
# 0.26.1 (2022-01-05)
- Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions.
- On Web, implement cursor grabbing through the pointer lock API.
- On X11, add mappings for numpad comma, numpad enter, numlock and pause.
- On macOS, fix Pinyin IME input by reverting a change that intended to improve IME.
- On Windows, fix a crash with transparent windows on Windows 11.
# 0.26.0 (2021-12-01)
- Update `raw-window-handle` to `v0.4`. This is _not_ a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading.
- On X11, bump `mio` to 0.8.
- On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`.
- On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0.
- On X11, select an appropriate visual for transparency if is requested
- On Wayland and X11, fix diagonal window resize cursor orientation.
- On macOS, drop the event callback before exiting.
- On Android, implement `Window::request_redraw`
- **Breaking:** On Web, remove the `stdweb` backend.
- Added `Window::focus_window`to bring the window to the front and set input focus.
- On Wayland and X11, implement `is_maximized` method on `Window`.
- On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`.
- On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events.
- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`.
- **Breaking:** On Wayland, Theme trait and its support types are dropped.
- On Wayland, bump `smithay-client-toolkit` to 0.15.1.
- On Wayland, implement `request_user_attention` with `xdg_activation_v1`.
- On X11, emit missing `WindowEvent::ScaleFactorChanged` when the only monitor gets reconnected.
- On X11, if RANDR based scale factor is higher than 20 reset it to 1
- On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries.
- **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.5.
- On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`.
- On macOS, fix native file dialogs hanging the event loop.
- On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland`
- On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode.
- On X11, EINTR while polling for events no longer causes a panic. Instead it will be treated as a spurious wakeup.
# 0.25.0 (2021-05-15)
- **Breaking:** On macOS, replace `WindowBuilderExtMacOS::with_activation_policy` with `EventLoopExtMacOS::set_activation_policy`
- On macOS, wait with activating the application until the application has initialized.
- On macOS, fix creating new windows when the application has a main menu.
- On Windows, fix fractional deltas for mouse wheel device events.
- On macOS, fix segmentation fault after dropping the main window.
- On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode.
- Added `is_maximized` method to `Window`.
- On Windows, fix bug where clicking the decoration bar would make the cursor blink.
- On Windows, fix bug causing newly created windows to erroneously display the "wait" (spinning) cursor.
- On macOS, wake up the event loop immediately when a redraw is requested.
- On Windows, change the default window size (1024x768) to match the default on other desktop platforms (800x600).
- On Windows, fix bug causing mouse capture to not be released.
- On Windows, fix fullscreen not preserving minimized/maximized state.
- On Android, unimplemented events are marked as unhandled on the native event loop.
- On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time.
- On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`.
- On macOS, fix objects captured by the event loop closure not being dropped on panic.
- On Windows, fixed `WindowEvent::ThemeChanged` not properly firing and fixed `Window::theme` returning the wrong theme.
- On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements.
- Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11.
- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland.
- On X11, bump `mio` to 0.7.
- On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows.
- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows.
- On macOS, emit `RedrawRequested` events immediately while the window is being resized.
- Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`.
- On macOS, initialize the Menu Bar with minimal defaults. (Can be prevented using `enable_default_menu_creation`)
- On macOS, change the default behavior for first click when the window was unfocused. Now the window becomes focused and then emits a `MouseInput` event on a "first mouse click".
- Implement mint (math interoperability standard types) conversions (under feature flag `mint`).
# 0.24.0 (2020-12-09)
- On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory.
- On Windows, implement `Window::set_ime_position`.
- **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`.
- **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`.
- On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme.
- On Windows, fix bug causing message boxes to appear delayed.
- On Android, calling `WindowEvent::Focused` now works properly instead of always returning false.
- On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag.
- On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions.
- **Breaking:** On Windows, include prefix byte in scancodes.
- On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`.
- On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland.
- On Windows, fix use-after-free crash during window destruction.
- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input.
- On macOS, fix compilation when targeting aarch64.
- On X11, fix `Window::request_redraw` not waking the event loop.
- On Wayland, the keypad arrow keys are now recognized.
- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`.
- Added `request_user_attention` method to `Window`.
- **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`.
- **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`.
- On Wayland, default font size in CSD increased from 11 to 17.
- On Windows, fix bug causing message boxes to appear delayed.
- On Android, support multi-touch.
- On Wayland, extra mouse buttons are not dropped anymore.
- **Breaking**: `MouseButton::Other` now uses `u16`.
# 0.23.0 (2020-10-02)
- On iOS, fixed support for the "Debug View Heirarchy" feature in Xcode.
- On all platforms, `available_monitors` and `primary_monitor` are now on `EventLoopWindowTarget` rather than `EventLoop` to list monitors event in the event loop.
- On Unix, X11 and Wayland are now optional features (enabled by default)
- On X11, fix deadlock when calling `set_fullscreen_inner`.
- On Web, prevent the webpage from scrolling when the user is focused on a winit canvas
- On Web, calling `window.set_cursor_icon` no longer breaks HiDPI scaling
- On Windows, drag and drop is now optional (enabled by default) and can be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`.
- On Wayland, fix deadlock when calling to `set_inner_size` from a callback.
- On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`.
- On android added support for `run_return`.
- On MacOS, Fixed fullscreen and dialog support for `run_return`.
- On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops.
- On Web, use mouse events if pointer events aren't supported. This affects Safari.
- On Windows, `set_ime_position` is now a no-op instead of a runtime crash.
- On Android, `set_fullscreen` is now a no-op instead of a runtime crash.
- On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash.
- On Android, fix `ControlFlow::Poll` not polling the Android event queue.
- On macOS, add `NSWindow.hasShadow` support.
- On Web, fix vertical mouse wheel scrolling being inverted.
- On Web, implement mouse capturing for click-dragging out of the canvas.
- On Web, fix `ControlFlow::Exit` not properly handled.
- On Web (web-sys only), send `WindowEvent::ScaleFactorChanged` event when `window.devicePixelRatio` is changed.
- **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error.
- **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`.
- On NetBSD, fixed crash due to incorrect detection of the main thread.
- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`.
- On macOS, fix inverted horizontal scroll.
- **Breaking:** `current_monitor` now returns `Option<MonitorHandle>`.
- **Breaking:** `primary_monitor` now returns `Option<MonitorHandle>`.
- On macOS, updated core-* dependencies and cocoa.
- Bump `parking_lot` to 0.11
- On Android, bump `ndk`, `ndk-sys` and `ndk-glue` to 0.2. Checkout the new ndk-glue main proc attribute.
- On iOS, fixed starting the app in landscape where the view still had portrait dimensions.
- Deprecate the stdweb backend, to be removed in a future release
- **Breaking:** Prefixed virtual key codes `Add`, `Multiply`, `Divide`, `Decimal`, and `Subtract` with `Numpad`.
- Added `Asterisk` and `Plus` virtual key codes.
- On Web (web-sys only), the `Event::LoopDestroyed` event is correctly emitted when leaving the page.
- On Web, the `WindowEvent::Destroyed` event now gets emitted when a `Window` is dropped.
- On Web (web-sys only), the event listeners are now removed when a `Window` is dropped or when the event loop is destroyed.
- On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed.
- **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped.
- On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called.
- **Breaking:** `Fullscreen` enum now uses `Borderless(Option<MonitorHandle>)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor.
- On MacOS, fix `WindowEvent::Moved` ignoring the scale factor.
- On Wayland, add missing virtual keycodes.
- On Wayland, implement proper `set_cursor_grab`.
- On Wayland, the cursor will use similar icons if the requested one isn't available.
- On Wayland, right clicking on client side decorations will request application menu.
- On Wayland, fix tracking of window size after state changes.
- On Wayland, fix client side decorations not being hidden properly in fullscreen.
- On Wayland, fix incorrect size event when entering fullscreen with client side decorations.
- On Wayland, fix `resizable` attribute not being applied properly on startup.
- On Wayland, fix disabled repeat rate not being handled.
- On Wayland, fix decoration buttons not working after tty switch.
- On Wayland, fix scaling not being applied on output re-enable.
- On Wayland, fix crash when `XCURSOR_SIZE` is `0`.
- On Wayland, fix pointer getting created in some cases without pointer capability.
- On Wayland, on kwin, fix space between window and decorations on startup.
- **Breaking:** On Wayland, `Theme` trait was reworked.
- On Wayland, disable maximize button for non-resizable window.
- On Wayland, added support for `set_ime_position`.
- On Wayland, fix crash on startup since GNOME 3.37.90.
- On X11, fix incorrect modifiers state on startup.
# 0.22.2 (2020-05-16)
- Added Clone implementation for 'static events.
- On Windows, fix window intermittently hanging when `ControlFlow` was set to `Poll`.
- On Windows, fix `WindowBuilder::with_maximized` being ignored.
- On Android, minimal platform support.
- On iOS, touch positions are now properly converted to physical pixels.
- On macOS, updated core-* dependencies and cocoa
# 0.22.1 (2020-04-16)
- On X11, fix `ResumeTimeReached` being fired too early.
- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame`
- On Web, fix a possible panic during event handling
- On macOS, fix `EventLoopProxy` leaking memory for every instance.
# 0.22.0 (2020-03-09)
- On Windows, fix minor timing issue in wait_until_time_or_msg
- On Windows, rework handling of request_redraw() to address panics.
- On macOS, fix `set_simple_screen` to remember frame excluding title bar.
- On Wayland, fix coordinates in touch events when scale factor isn't 1.
- On Wayland, fix color from `close_button_icon_color` not applying.
- Ignore locale if unsupported by X11 backend
- On Wayland, Add HiDPI cursor support
- On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change.
- Fix `Event::to_static` returning `None` for user events.
- On Wayland, Hide CSD for fullscreen windows.
- On Windows, ignore spurious mouse move messages.
- **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`.
- On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource
- Add `BadIcon::OsError` variant for when OS icon functionality fails
- On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode
- Revert On macOS, fix not sending ReceivedCharacter event for specific keys combinations.
- on macOS, fix incorrect ReceivedCharacter events for some key combinations.
- **Breaking:** Use `i32` instead of `u32` for position type in `WindowEvent::Moved`.
- On macOS, a mouse motion event is now generated before every mouse click.
# 0.21.0 (2020-02-04)
- On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows.
- On macOS, fix set_minimized(true) works only with decorations.
- On macOS, add `hide_application` to `EventLoopWindowTarget` via a new `EventLoopWindowTargetExtMacOS` trait. `hide_application` will hide the entire application by calling `-[NSApplication hide: nil]`.
- On macOS, fix not sending ReceivedCharacter event for specific keys combinations.
- On macOS, fix `CursorMoved` event reporting the cursor position using logical coordinates.
- On macOS, fix issue where unbundled applications would sometimes open without being focused.
- On macOS, fix `run_return` does not return unless it receives a message.
- On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop.
- On X11, fix deadlock on window state when handling certain window events.
- `WindowBuilder` now implements `Default`.
- **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends
- On Wayland, fix coordinates in mouse events when scale factor isn't 1
- On Web, add the ability to provide a custom canvas
- **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration
# 0.20.0 (2020-01-05)
- On X11, fix `ModifiersChanged` emitting incorrect modifier change events
- **Breaking**: Overhaul how Winit handles DPI:
- Window functions and events now return `PhysicalSize` instead of `LogicalSize`.
- Functions that take `Size` or `Position` types can now take either `Logical` or `Physical` types.
- `hidpi_factor` has been renamed to `scale_factor`.
- `HiDpiFactorChanged` has been renamed to `ScaleFactorChanged`, and lets you control how the OS
resizes the window in response to the change.
- On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`.
- `Size` and `Position` types are now generic over their exact pixel type.
# 0.20.0 Alpha 6 (2020-01-03)
- On macOS, fix `set_cursor_visible` hides cursor outside of window.
- On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size.
- On macOS, fix error when `set_fullscreen` is called during fullscreen transition.
- On all platforms except mobile and WASM, implement `Window::set_minimized`.
- On X11, fix `CursorEntered` event being generated for non-winit windows.
- On macOS, fix crash when starting maximized without decorations.
- On macOS, fix application not terminating on `run_return`.
- On Wayland, fix cursor icon updates on window borders when using CSD.
- On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode.
- On Windows, theme the title bar according to whether the system theme is "Light" or "Dark".
- Added `WindowEvent::ThemeChanged` variant to handle changes to the system theme. Currently only implemented on Windows.
- **Breaking**: Changes to the `RedrawRequested` event (#1041):
- `RedrawRequested` has been moved from `WindowEvent` to `Event`.
- `EventsCleared` has been renamed to `MainEventsCleared`.
- `RedrawRequested` is now issued only after `MainEventsCleared`.
- `RedrawEventsCleared` is issued after each set of `RedrawRequested` events.
- Implement synthetic window focus key events on Windows.
- **Breaking**: Change `ModifiersState` to a `bitflags` struct.
- On Windows, implement `VirtualKeyCode` translation for `LWin` and `RWin`.
- On Windows, fix closing the last opened window causing `DeviceEvent`s to stop getting emitted.
- On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior.
- Add `DeviceEvent::ModifiersChanged`.
- Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`.
- On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output.
- On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`.
# 0.20.0 Alpha 5 (2019-12-09)
- On macOS, fix application termination on `ControlFlow::Exit`
- On Windows, fix missing `ReceivedCharacter` events when Alt is held.
- On macOS, stop emitting private corporate characters in `ReceivedCharacter` events.
- On X11, fix misreporting DPI factor at startup.
- On X11, fix events not being reported when using `run_return`.
- On X11, fix key modifiers being incorrectly reported.
- On X11, fix window creation hanging when another window is fullscreen.
- On Windows, fix focusing unfocused windows when switching from fullscreen to windowed.
- On X11, fix reporting incorrect DPI factor when waking from suspend.
- Change `EventLoopClosed` to contain the original event.
- **Breaking**: Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`,
indicating that the event is generated by winit.
- On X11, generate synthetic key events for keys held when a window gains or loses focus.
- On X11, issue a `CursorMoved` event when a `Touch` event occurs,
as X11 implicitly moves the cursor for such events.
# 0.20.0 Alpha 4 (2019-10-18)
- Add web support via the 'stdweb' or 'web-sys' features
- On Windows, implemented function to get HINSTANCE
- On macOS, implement `run_return`.
- On iOS, fix inverted parameter in `set_prefers_home_indicator_hidden`.
- On X11, performance is improved when rapidly calling `Window::set_cursor_icon`.
- On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized.
- On Windows, unset `maximized` when manually changing the window's position or size.
- On Windows, add touch pressure information for touch events.
- On macOS, differentiate between `CursorIcon::Grab` and `CursorIcon::Grabbing`.
- On Wayland, fix event processing sometimes stalling when using OpenGL with vsync.
- Officially remove the Emscripten backend.
- On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`.
- On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode.
- On iOS, fix panic upon closing the app.
- On X11, allow setting mulitple `XWindowType`s.
- On iOS, fix null window on initial `HiDpiFactorChanged` event.
- On Windows, fix fullscreen window shrinking upon getting restored to a normal window.
- On macOS, fix events not being emitted during modal loops, such as when windows are being resized
by the user.
- On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events.
- Always dispatch a `RedrawRequested` event after creating a new window.
- On X11, return dummy monitor data to avoid panicking when no monitors exist.
- On X11, prevent stealing input focus when creating a new window.
Only steal input focus when entering fullscreen mode.
- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced
- On Wayland, add support for set_cursor_visible and set_cursor_grab.
- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced.
- Removed `derivative` crate dependency.
- On Wayland, add support for set_cursor_icon.
- Use `impl Iterator<Item = MonitorHandle>` instead of `AvailableMonitorsIter` consistently.
- On macOS, fix fullscreen state being updated after entering fullscreen instead of before,
resulting in `Window::fullscreen` returning the old state in `Resized` events instead of
reflecting the new fullscreen state
- On X11, fix use-after-free during window creation
- On Windows, disable monitor change keyboard shortcut while in exclusive fullscreen.
- On Windows, ensure that changing a borderless fullscreen window's monitor via keyboard shortcuts keeps the window fullscreen on the new monitor.
- Prevent `EventLoop::new` and `EventLoop::with_user_event` from getting called outside the main thread.
- This is because some platforms cannot run the event loop outside the main thread. Preventing this
reduces the potential for cross-platform compatibility gotchyas.
- On Windows and Linux X11/Wayland, add platform-specific functions for creating an `EventLoop` outside the main thread.
- On Wayland, drop resize events identical to the current window size.
- On Windows, fix window rectangle not getting set correctly on high-DPI systems.
# 0.20.0 Alpha 3 (2019-08-14)
- On macOS, drop the run closure on exit.
- On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates.
- On X11, fix delayed events after window redraw.
- On macOS, add `WindowBuilderExt::with_disallow_hidpi` to have the option to turn off best resolution openGL surface.
- On Windows, screen saver won't start if the window is in fullscreen mode.
- Change all occurrences of the `new_user_event` method to `with_user_event`.
- On macOS, the dock and the menu bar are now hidden in fullscreen mode.
- `Window::set_fullscreen` now takes `Option<Fullscreen>` where `Fullscreen`
consists of `Fullscreen::Exclusive(VideoMode)` and
`Fullscreen::Borderless(MonitorHandle)` variants.
- Adds support for exclusive fullscreen mode.
- On iOS, add support for hiding the home indicator.
- On iOS, add support for deferring system gestures.
- On iOS, fix a crash that occurred while acquiring a monitor's name.
- On iOS, fix armv7-apple-ios compile target.
- Removed the `T: Clone` requirement from the `Clone` impl of `EventLoopProxy<T>`.
- On iOS, disable overscan compensation for external displays (removes black
bars surrounding the image).
- On Linux, the functions `is_wayland`, `is_x11`, `xlib_xconnection` and `wayland_display` have been moved to a new `EventLoopWindowTargetExtUnix` trait.
- On iOS, add `set_prefers_status_bar_hidden` extension function instead of
hijacking `set_decorations` for this purpose.
- On macOS and iOS, corrected the auto trait impls of `EventLoopProxy`.
- On iOS, add touch pressure information for touch events.
- Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms.
- On macOS, fix the signature of `-[NSView drawRect:]`.
- On iOS, fix the behavior of `ControlFlow::Poll`. It wasn't polling if that was the only mode ever used by the application.
- On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number.
- On iOS, RedrawRequested now works for gl/metal backed views.
- On iOS, RedrawRequested is generally ordered after EventsCleared.
# 0.20.0 Alpha 2 (2019-07-09)
- On X11, non-resizable windows now have maximize explicitly disabled.
- On Windows, support paths longer than MAX_PATH (260 characters) in `WindowEvent::DroppedFile`
and `WindowEvent::HoveredFile`.
- On Mac, implement `DeviceEvent::Button`.
- Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`.
- On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor.
- Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835)
- On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs.
- On Windows, when a window is initially invisible, it won't take focus from the existing visible windows.
- On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.`
- On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration.
- On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`.
- On macOS, drop unused Metal dependency.
- On Windows, fix the trail effect happening on transparent decorated windows. Borderless (or un-decorated) windows were not affected.
- On Windows, fix `with_maximized` not properly setting window size to entire window.
- On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`.
# 0.20.0 Alpha 1 (2019-06-21)
- Changes below are considered **breaking**.
- Change all occurrences of `EventsLoop` to `EventLoop`.
- Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules.
- `os` module changes:
- Renamed to `platform`.
- All traits now have platform-specific suffixes.
- Exposes new `desktop` module on Windows, Mac, and Linux.
- Changes to event loop types:
- `EventLoopProxy::wakeup` has been removed in favor of `send_event`.
- **Major:** New `run` method drives winit event loop.
- Returns `!` to ensure API behaves identically across all supported platforms.
- This allows `emscripten` implementation to work without lying about the API.
- `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`.
- Is read after `EventsCleared` is processed.
- `Wait` waits until new events are available.
- `WaitUntil` waits until either new events are available or the provided time has been reached.
- `Poll` instantly resumes the event loop.
- `Exit` aborts the event loop.
- Takes a closure that implements `'static + FnMut(Event<T>, &EventLoop<T>, &mut ControlFlow)`.
- `&EventLoop<T>` is provided to allow new `Window`s to be created.
- **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method.
- Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures.
- `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`.
- Changes to events:
- Remove `Event::Awakened` in favor of `Event::UserEvent(T)`.
- Can be sent with `EventLoopProxy::send_event`.
- Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`.
- `RedrawRequested` can be sent by the user with the `Window::request_redraw` method.
- `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`.
- **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`.
- `NewEvents` is emitted when new events are ready to be processed by event loop.
- `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop).
- `EventsCleared` is emitted when all available events have been processed.
- Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop).
- `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit.
- Rename `MonitorId` to `MonitorHandle`.
- Removed `serde` implementations from `ControlFlow`.
- Rename several functions to improve both internal consistency and compliance with Rust API guidelines.
- Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now.
- **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers.
- Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor.
- On Wayland, the window now exists even if nothing has been drawn.
- On Windows, fix initial dimensions of a fullscreen window.
- On Windows, Fix transparent borderless windows rendering wrong.
# Version 0.19.1 (2019-04-08)
- On Wayland, added a `get_wayland_display` function to `EventsLoopExt`.
- On Windows, fix `CursorMoved(0, 0)` getting dispatched on window focus.
- On macOS, fix command key event left and right reverse.
- On FreeBSD, NetBSD, and OpenBSD, fix build of X11 backend.
- On Linux, the numpad's add, subtract and divide keys are now mapped to the `Add`, `Subtract` and `Divide` virtual key codes
- On macOS, the numpad's subtract key has been added to the `Subtract` mapping
- On Wayland, the numpad's home, end, page up and page down keys are now mapped to the `Home`, `End`, `PageUp` and `PageDown` virtual key codes
- On Windows, fix icon not showing up in corner of window.
- On X11, change DPI scaling factor behavior. First, winit tries to read it from "Xft.dpi" XResource, and uses DPI calculation from xrandr dimensions as fallback behavior.
# Version 0.19.0 (2019-03-06)
- On X11, we will use the faster `XRRGetScreenResourcesCurrent` function instead of `XRRGetScreenResources` when available.
- On macOS, fix keycodes being incorrect when using a non-US keyboard layout.
- On Wayland, fix `with_title()` not setting the windows title
- On Wayland, add `set_wayland_theme()` to control client decoration color theme
- Added serde serialization to `os::unix::XWindowType`.
- **Breaking:** Remove the `icon_loading` feature and the associated `image` dependency.
- On X11, make event loop thread safe by replacing XNextEvent with select(2) and XCheckIfEvent
- On Windows, fix malformed function pointer typecast that could invoke undefined behavior.
- Refactored Windows state/flag-setting code.
- On Windows, hiding the cursor no longer hides the cursor for all Winit windows - just the one `hide_cursor` was called on.
- On Windows, cursor grabs used to get perpetually canceled when the grabbing window lost focus. Now, cursor grabs automatically get re-initialized when the window regains focus and the mouse moves over the client area.
- On Windows, only vertical mouse wheel events were handled. Now, horizontal mouse wheel events are also handled.
- On Windows, ignore the AltGr key when populating the `ModifersState` type.
# Version 0.18.1 (2018-12-30)
- On macOS, fix `Yen` (JIS) so applications receive the event.
- On X11 with a tiling WM, fixed high CPU usage when moving windows across monitors.
- On X11, fixed panic caused by dropping the window before running the event loop.
- on macOS, added `WindowExt::set_simple_fullscreen` which does not require a separate space
- Introduce `WindowBuilderExt::with_app_id` to allow setting the application ID on Wayland.
- On Windows, catch panics in event loop child thread and forward them to the parent thread. This prevents an invocation of undefined behavior due to unwinding into foreign code.
- On Windows, fix issue where resizing or moving window combined with grabbing the cursor would freeze program.
- On Windows, fix issue where resizing or moving window would eat `Awakened` events.
- On Windows, exiting fullscreen after entering fullscreen with disabled decorations no longer shrinks window.
- On X11, fixed a segfault when using virtual monitors with XRandR.
- Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum.
- On Windows, fix issue where hovering or dropping a non file item would create a panic.
- On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop.
- On Wayland, DPI calculation is handled by smithay-client-toolkit.
- On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI.
- Added support for generating dummy `DeviceId`s and `WindowId`s to better support unit testing.
- On macOS, fixed unsoundness in drag-and-drop that could result in drops being rejected.
- On macOS, implemented `WindowEvent::Refresh`.
- On macOS, all `MouseCursor` variants are now implemented and the cursor will no longer reset after unfocusing.
- Removed minimum supported Rust version guarantee.
# Version 0.18.0 (2018-11-07)
- **Breaking:** `image` crate upgraded to 0.20. This is exposed as part of the `icon_loading` API.
- On Wayland, pointer events will now provide the current modifiers state.
- On Wayland, titles will now be displayed in the window header decoration.
- On Wayland, key repetition is now ended when keyboard loses focus.
- On Wayland, windows will now use more stylish and modern client side decorations.
- On Wayland, windows will use server-side decorations when available.
- **Breaking:** Added support for F16-F24 keys (variants were added to the `VirtualKeyCode` enum).
- Fixed graphical glitches when resizing on Wayland.
- On Windows, fix freezes when performing certain actions after a window resize has been triggered. Reintroduces some visual artifacts when resizing.
- Updated window manager hints under X11 to v1.5 of [Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#idm140200472629520).
- Added `WindowBuilderExt::with_gtk_theme_variant` to X11-specific `WindowBuilder` functions.
- Fixed UTF8 handling bug in X11 `set_title` function.
- On Windows, `Window::set_cursor` now applies immediately instead of requiring specific events to occur first.
- On Windows, the `HoveredFile` and `HoveredFileCancelled` events are now implemented.
- On Windows, fix `Window::set_maximized`.
- On Windows 10, fix transparency (#260).
- On macOS, fix modifiers during key repeat.
- Implemented the `Debug` trait for `Window`, `EventsLoop`, `EventsLoopProxy` and `WindowBuilder`.
- On X11, now a `Resized` event will always be generated after a DPI change to ensure the window's logical size is consistent with the new DPI.
- Added further clarifications to the DPI docs.
- On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only.
- Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types.
- Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them.
- On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze.
- Fix issue whereby the OpenGL context would not appear at startup on macOS Mojave (#1069).
- **Breaking:** Removed `From<NSApplicationActivationPolicy>` impl from `ActivationPolicy` on macOS.
- On macOS, the application can request the user's attention with `WindowExt::request_user_attention`.
# Version 0.17.2 (2018-08-19)
- On macOS, fix `<C-Tab>` so applications receive the event.
- On macOS, fix `<Cmd-{key}>` so applications receive the event.
- On Wayland, key press events will now be repeated.
# Version 0.17.1 (2018-08-05)
- On X11, prevent a compilation failure in release mode for versions of Rust greater than or equal to 1.30.
- Fixed deadlock that broke fullscreen mode on Windows.
# Version 0.17.0 (2018-08-02)
- Cocoa and core-graphics updates.
- Fixed thread-safety issues in several `Window` functions on Windows.
- On MacOS, the key state for modifiers key events is now properly set.
- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again.
- Added NetBSD support.
- **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK).
- On iOS, the `UIApplication` is not started until `Window::new` is called.
- Fixed thread unsafety with cursor hiding on macOS.
- On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures.
- On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7.
# Version 0.16.2 (2018-07-07)
- On Windows, non-resizable windows now have the maximization button disabled. This is consistent with behavior on macOS and popular X11 WMs.
- Corrected incorrect `unreachable!` usage when guessing the DPI factor with no detected monitors.
# Version 0.16.1 (2018-07-02)
- Added logging through `log`. Logging will become more extensive over time.
- On X11 and Windows, the window's DPI factor is guessed before creating the window. This _greatly_ cuts back on unsightly auto-resizing that would occur immediately after window creation.
- Fixed X11 backend compilation for environments where `c_char` is unsigned.
# Version 0.16.0 (2018-06-25)
- Windows additionally has `WindowBuilderExt::with_no_redirection_bitmap`.
- **Breaking:** Removed `VirtualKeyCode::LMenu` and `VirtualKeyCode::RMenu`; Windows now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead.
- On X11, exiting fullscreen no longer leaves the window in the monitor's top left corner.
- **Breaking:** `Window::hidpi_factor` has been renamed to `Window::get_hidpi_factor` for better consistency. `WindowEvent::HiDPIFactorChanged` has been renamed to `WindowEvent::HiDpiFactorChanged`. DPI factors are always represented as `f64` instead of `f32` now.
- The Windows backend is now DPI aware. `WindowEvent::HiDpiFactorChanged` is implemented, and `MonitorId::get_hidpi_factor` and `Window::hidpi_factor` return accurate values.
- Implemented `WindowEvent::HiDpiFactorChanged` on X11.
- On macOS, `Window::set_cursor_position` is now relative to the client area.
- On macOS, setting the maximum and minimum dimensions now applies to the client area dimensions rather than to the window dimensions.
- On iOS, `MonitorId::get_dimensions` has been implemented and both `MonitorId::get_hidpi_factor` and `Window::get_hidpi_factor` return accurate values.
- On Emscripten, `MonitorId::get_hidpi_factor` now returns the same value as `Window::get_hidpi_factor` (it previously would always return 1.0).
- **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes.
- **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed.
- HiDPI support for Wayland.
- `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow.
- `AvailableMonitorsIter` now implements `Debug`.
- Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down.
- On X11, all event loops now share the same `XConnection`.
- **Breaking:** `Window::set_cursor_state` and `CursorState` enum removed in favor of the more composable `Window::grab_cursor` and `Window::hide_cursor`. As a result, grabbing the cursor no longer automatically hides it; you must call both methods to retain the old behavior on Windows and macOS. `Cursor::NoneCursor` has been removed, as it's no longer useful.
- **Breaking:** `Window::set_cursor_position` now returns `Result<(), String>`, thus allowing for `Box<Error>` conversion via `?`.
# Version 0.15.1 (2018-06-13)
- On X11, the `Moved` event is no longer sent when the window is resized without changing position.
- `MouseCursor` and `CursorState` now implement `Default`.
- `WindowBuilder::with_resizable` implemented for Windows, X11, Wayland, and macOS.
- `Window::set_resizable` implemented for Windows, X11, Wayland, and macOS.
- On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf.
- On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor.
- On X11, enabling transparency no longer causes the window contents to flicker when resizing.
- On X11, `with_override_redirect` now actually enables override redirect.
- macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both.
- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched.
- On macOS, windows without decorations can once again be resized.
- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue".
- On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area.
- On macOS, resizing the window no longer generates a spurious `MouseInput` event.
# Version 0.15.0 (2018-05-22)
- `Icon::to_cardinals` is no longer public, since it was never supposed to be.
- Wayland: improve diagnostics if initialization fails
- Fix some system event key doesn't work when focused, do not block keyevent forward to system on macOS
- On X11, the scroll wheel position is now correctly reset on i3 and other WMs that have the same quirk.
- On X11, `Window::get_current_monitor` now reliably returns the correct monitor.
- On X11, `Window::hidpi_factor` returns values from XRandR rather than the inaccurate values previously queried from the core protocol.
- On X11, the primary monitor is detected correctly even when using versions of XRandR less than 1.5.
- `MonitorId` now implements `Debug`.
- Fixed bug on macOS where using `with_decorations(false)` would cause `set_decorations(true)` to produce a transparent titlebar with no title.
- Implemented `MonitorId::get_position` on macOS.
- On macOS, `Window::get_current_monitor` now returns accurate values.
- Added `WindowBuilderExt::with_resize_increments` to macOS.
- **Breaking:** On X11, `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` now take `u32` values rather than `i32`.
- macOS keyboard handling has been overhauled, allowing for the use of dead keys, IME, etc. Right modifier keys are also no longer reported as being left.
- Added the `Window::set_ime_spot(x: i32, y: i32)` method, which is implemented on X11 and macOS.
- **Breaking**: `os::unix::WindowExt::send_xim_spot(x: i16, y: i16)` no longer exists. Switch to the new `Window::set_ime_spot(x: i32, y: i32)`, which has equivalent functionality.
- Fixed detection of `Pause` and `Scroll` keys on Windows.
- On Windows, alt-tabbing while the cursor is grabbed no longer makes it impossible to re-grab the cursor.
- On Windows, using `CursorState::Hide` when the cursor is grabbed now ungrabs the cursor first.
- Implemented `MouseCursor::NoneCursor` on Windows.
- Added `WindowBuilder::with_always_on_top` and `Window::set_always_on_top`. Implemented on Windows, macOS, and X11.
- On X11, `WindowBuilderExt` now has `with_class`, `with_override_redirect`, and `with_x11_window_type` to allow for more control over window creation. `WindowExt` additionally has `set_urgent`.
- More hints are set by default on X11, including `_NET_WM_PID` and `WM_CLIENT_MACHINE`. Note that prior to this, the `WM_CLASS` hint was automatically set to whatever value was passed to `with_title`. It's now set to the executable name to better conform to expectations and the specification; if this is undesirable, you must explicitly use `WindowBuilderExt::with_class`.
# Version 0.14.0 (2018-05-09)
- Created the `Copy`, `Paste` and `Cut` `VirtualKeyCode`s and added support for them on X11 and Wayland
- Fix `.with_decorations(false)` in macOS
- On Mac, `NSWindow` and supporting objects might be alive long after they were `closed` which resulted in apps consuming more heap then needed. Mainly it was affecting multi window applications. Not expecting any user visible change of behaviour after the fix.
- Fix regression of Window platform extensions for macOS where `NSFullSizeContentViewWindowMask` was not being correctly applied to `.fullsize_content_view`.
- Corrected `get_position` on Windows to be relative to the screen rather than to the taskbar.
- Corrected `Moved` event on Windows to use position values equivalent to those returned by `get_position`. It previously supplied client area positions instead of window positions, and would additionally interpret negative values as being very large (around `u16::MAX`).
- Implemented `Moved` event on macOS.
- On X11, the `Moved` event correctly use window positions rather than client area positions. Additionally, a stray `Moved` that unconditionally accompanied `Resized` with the client area position relative to the parent has been eliminated; `Moved` is still received alongside `Resized`, but now only once and always correctly.
- On Windows, implemented all variants of `DeviceEvent` other than `Text`. Mouse `DeviceEvent`s are now received even if the window isn't in the foreground.
- `DeviceId` on Windows is no longer a unit struct, and now contains a `u32`. For `WindowEvent`s, this will always be 0, but on `DeviceEvent`s it will be the handle to that device. `DeviceIdExt::get_persistent_identifier` can be used to acquire a unique identifier for that device that persists across replugs/reboots/etc.
- Corrected `run_forever` on X11 to stop discarding `Awakened` events.
- Various safety and correctness improvements to the X11 backend internals.
- Fixed memory leak on X11 every time the mouse entered the window.
- On X11, drag and drop now works reliably in release mode.
- Added `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` to X11, allowing for more optional hints to be set.
- Rework of the wayland backend, migrating it to use [Smithay's Client Toolkit](https://github.com/Smithay/client-toolkit).
- Added `WindowBuilder::with_window_icon` and `Window::set_window_icon`, finally making it possible to set the window icon on Windows and X11. The `icon_loading` feature can be enabled to allow for icons to be easily loaded; see example program `window_icon.rs` for usage.
- Windows additionally has `WindowBuilderExt::with_taskbar_icon` and `WindowExt::set_taskbar_icon`.
- On Windows, fix panic when trying to call `set_fullscreen(None)` on a window that has not been fullscreened prior.
# Version 0.13.1 (2018-04-26)
- Ensure necessary `x11-dl` version is used.
# Version 0.13.0 (2018-04-25)
- Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for MacOS.
@@ -56,7 +891,7 @@
# Version 0.10.1 (2018-02-05)
*Yanked*
_Yanked_
# Version 0.10.0 (2017-12-27)

72
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,72 @@
# Winit Contributing Guidelines
## Scope
[See `FEATURES.md`](./FEATURES.md). When requesting or implementing a new Winit feature, you should
consider whether or not it's directly related to window creation or input handling. If it isn't, it
may be worth creating a separate crate that extends Winit's API to add that functionality.
## Reporting an issue
When reporting an issue, in order to help the maintainers understand what the problem is, please make
your description of the issue as detailed as possible:
- if it is a bug, please provide clear explanation of what happens, what should happen, and how to
reproduce the issue, ideally by providing a minimal program exhibiting the problem
- if it is a feature request, please provide a clear argumentation about why you believe this feature
should be supported by winit
## Making a pull request
When making a code contribution to winit, before opening your pull request, please make sure that:
- your patch builds with Winit's minimal supported rust version - Rust 1.60.
- you tested your modifications on all the platforms impacted, or if not possible detail which platforms
were not tested, and what should be tested, so that a maintainer or another contributor can test them
- you updated any relevant documentation in winit
- you left comments in your code explaining any part that is not straightforward, so that the
maintainers and future contributors don't have to try to guess what your code is supposed to do
- your PR adds an entry to the changelog file if the introduced change is relevant to winit users.
You needn't worry about the added entry causing conflicts, the maintainer that merges the PR will
handle those for you when merging (see below).
- if your PR affects the platform compatibility of one or more features or adds another feature, the
relevant sections in [`FEATURES.md`](https://github.com/rust-windowing/winit/blob/master/FEATURES.md#features)
should be updated.
Once your PR is open, you can ask for review by a maintainer of your platform. Winit's merging policy
is that a PR must be approved by at least two maintainers of winit before being merged, including
at least a maintainer of the platform (a maintainer making a PR themselves counts as approving it).
Once your PR is deemed ready, the merging maintainer will take care of resolving conflicts in
`CHANGELOG.md` (but you must resolve other conflicts yourself). Doing this requires that you check the
"give contributors write access to the branch" checkbox when creating the PR.
## Maintainers & Testers
The current maintainers are listed in the [CODEOWNERS](.github/CODEOWNERS) file.
If you are interested in being pinged when testing is needed for a certain platform, please add yourself to the [Testers and Contributors](https://github.com/rust-windowing/winit/wiki/Testers-and-Contributors) table!
## Release process
Given that winit is a widely used library we should be able to make a patch
releases at any time we want without blocking the development of new features.
To achieve these goals, a new branch is created for every new release. Releases
and later patch releases are committed and tagged in this branch.
The exact steps for an exemplary `0.2.0` release might look like this:
1. Initially the version on the latest master is `0.1.0`
2. A new `v0.2.x` branch is created for the release
3. In the branch, the version is bumped to `v0.2.0`
4. The new commit in the branch is tagged `v0.2.0`
5. The version is pushed to crates.io
6. A GitHub release is created for the `v0.2.0` tag
7. On master, the version is bumped to `0.2.0` and the CHANGELOG is updated
When doing a patch release the process is similar:
1. Initially the version of the latest release is `0.2.0`
2. Checkout the `v0.2.x` branch
3. Cherry-pick the required non-breaking changes into the `v0.2.x`
4. Follow steps 3-7 of the regular release example

View File

@@ -1,52 +1,161 @@
[package]
name = "winit"
version = "0.13.0"
authors = ["The winit contributors, Pierre Krieger <pierre.krieger1708@gmail.com>"]
version = "0.28.5"
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
description = "Cross-platform window creation library."
edition = "2021"
keywords = ["windowing"]
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/tomaka/winit"
repository = "https://github.com/rust-windowing/winit"
documentation = "https://docs.rs/winit"
categories = ["gui"]
rust-version = "1.60.0"
[package.metadata.docs.rs]
features = ["serde"]
default-target = "x86_64-unknown-linux-gnu"
# These are all tested in CI
targets = [
# Windows
"i686-pc-windows-msvc",
"x86_64-pc-windows-msvc",
# macOS
"x86_64-apple-darwin",
# Unix (X11 & Wayland)
"i686-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
# iOS
"x86_64-apple-ios",
# Android
"aarch64-linux-android",
# WebAssembly
"wasm32-unknown-unknown",
]
rustdoc-args = ["--cfg", "docsrs"]
[features]
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
x11 = ["x11-dl", "mio", "percent-encoding"]
wayland = ["wayland-client", "wayland-protocols", "sctk", "wayland-commons"]
wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"]
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
wayland-csd-adwaita-notitle = ["sctk-adwaita"]
android-native-activity = [ "android-activity/native-activity" ]
android-game-activity = [ "android-activity/game-activity" ]
[build-dependencies]
cfg_aliases = "0.1.1"
[dependencies]
lazy_static = "1"
libc = "0.2"
bitflags = "1"
instant = { version = "0.1", features = ["wasm-bindgen"] }
log = "0.4"
mint = { version = "0.5.6", optional = true }
once_cell = "1.12"
raw_window_handle = { package = "raw-window-handle", version = "0.5" }
serde = { version = "1", optional = true, features = ["serde_derive"] }
[target.'cfg(target_os = "android")'.dependencies.android_glue]
version = "0.2"
[dev-dependencies]
image = { version = "0.24.0", default-features = false, features = ["png"] }
simple_logger = { version = "2.1.0", default_features = false }
[target.'cfg(target_os = "ios")'.dependencies]
objc = "0.2"
[target.'cfg(target_os = "android")'.dependencies]
# Coordinate the next winit release with android-ndk-rs: https://github.com/rust-windowing/winit/issues/1995
android-activity = "0.4.0"
ndk = "0.7.0"
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
core-foundation = "0.9.3"
objc2 = ">=0.3.0-beta.3, <0.3.0-beta.4" # Allow `0.3.0-beta.3.patch-leaks`
[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2"
cocoa = "0.14"
core-foundation = "0.5"
core-graphics = "0.13"
core-graphics = "0.22.3"
dispatch = "0.2.0"
[target.'cfg(target_os = "windows")'.dependencies.winapi]
version = "0.3"
[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.45"
features = [
"winnt",
"winuser",
"wingdi",
"shellapi",
"dwmapi",
"processthreadsapi",
"libloaderapi",
"windowsx",
"hidusage",
"combaseapi",
"objbase",
"unknwnbase",
"Win32_Devices_HumanInterfaceDevice",
"Win32_Foundation",
"Win32_Globalization",
"Win32_Graphics_Dwm",
"Win32_Graphics_Gdi",
"Win32_Media",
"Win32_System_Com_StructuredStorage",
"Win32_System_Com",
"Win32_System_LibraryLoader",
"Win32_System_Ole",
"Win32_System_SystemInformation",
"Win32_System_SystemServices",
"Win32_System_Threading",
"Win32_System_WindowsProgramming",
"Win32_UI_Accessibility",
"Win32_UI_Controls",
"Win32_UI_HiDpi",
"Win32_UI_Input_Ime",
"Win32_UI_Input_KeyboardAndMouse",
"Win32_UI_Input_Pointer",
"Win32_UI_Input_Touch",
"Win32_UI_Shell",
"Win32_UI_TextServices",
"Win32_UI_WindowsAndMessaging",
]
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
wayland-client = { version = "0.12.0", features = ["dlopen"] }
wayland-protocols = { version = "0.12.0", features = ["unstable_protocols"] }
wayland-kbd = "0.13.0"
wayland-window = "0.13.0"
x11-dl = "2.17"
percent-encoding = "1.0"
[target.'cfg(all(unix, not(any(target_os = "redox", target_arch = "wasm32", target_os = "android", target_os = "ios", target_os = "macos"))))'.dependencies]
libc = "0.2.64"
mio = { version = "0.8", features = ["os-ext"], optional = true }
percent-encoding = { version = "2.0", optional = true }
sctk = { package = "smithay-client-toolkit", version = "0.16.0", default_features = false, features = ["calloop"], optional = true }
sctk-adwaita = { version = "0.5.1", default_features = false, optional = true }
wayland-client = { version = "0.29.5", default_features = false, features = ["use_system_lib"], optional = true }
wayland-protocols = { version = "0.29.5", features = [ "staging_protocols"], optional = true }
wayland-commons = { version = "0.29.5", optional = true }
x11-dl = { version = "2.18.5", optional = true }
[target.'cfg(target_os = "redox")'.dependencies]
orbclient = { version = "0.3.42", default-features = false }
redox_syscall = "0.3"
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.build-dependencies]
wayland-scanner = "0.29.5"
[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys]
package = "web-sys"
version = "0.3.22"
features = [
'console',
"AddEventListenerOptions",
'CssStyleDeclaration',
'BeforeUnloadEvent',
'Document',
'DomRect',
'Element',
'Event',
"EventListenerOptions",
'EventTarget',
'FocusEvent',
'HtmlCanvasElement',
'HtmlElement',
'KeyboardEvent',
'MediaQueryList',
'MediaQueryListEvent',
'MouseEvent',
'Node',
'PointerEvent',
'Window',
'WheelEvent'
]
[target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen]
version = "0.2.45"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
console_log = "0.2"
web-sys = { version = "0.3.22", features = ['CanvasRenderingContext2d'] }
[workspace]
members = [
"run-wasm",
]

247
FEATURES.md Normal file
View File

@@ -0,0 +1,247 @@
# 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. It supports the following main graphical platforms:
- Desktop
- Windows 7+ (10+ is tested regularly)
- macOS 10.7+ (10.14+ is tested regularly)
- Unix
- via X11
- via Wayland
- Redox OS, via Orbital
- Mobile
- iOS
- Android
- Web
- via WASM
Most platforms expose capabilities that cannot be meaningfully transposed onto others. Winit does not
aim to support every single feature of every platform, but rather to abstract over the common features
available everywhere. In this context, APIs exposed in winit can be split into different "support tiers":
- **Core:** Features that are essential to providing a well-formed abstraction over each platform's
windowing and input APIs.
- **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and
cannot be implemented outside of Winit without exposing a significant amount of Winit's internals
or interfering with Winit's abstractions.
- **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful
usability improvements and cannot be reasonably implemented in an external crate. These are
generally optional and exposed through Cargo features.
Core features are taken care of by the core Winit maintainers. Platform features are not.
When a platform feature is submitted, the submitter is considered the expert in the
feature and may be asked to support the feature should it break in the future.
Winit ***does not*** directly expose functionality for drawing inside windows or creating native
menus, but ***does*** commit to providing APIs that higher-level crates can use to implement that
functionality.
## `1.0` and stability
When all core features are implemented to the satisfaction of the Winit maintainers, Winit 1.0 will
be released and the library will enter maintenance mode. For the most part, new core features will not
be added past this point. New platform features may be accepted and exposed through point releases.
### Tier upgrades
Some platform features could in theory be exposed across multiple platforms, but have not gone
through the implementation work necessary to function on all platforms. When one of these features
gets implemented across all platforms, a PR can be opened to upgrade the feature to a core feature.
If that gets accepted, the platform-specific functions gets deprecated and become permanently
exposed through the core, cross-platform API.
# Features
## Extending this section
If your PR makes notable changes to Winit's features, please update this section as follows:
- If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core
feature, add a row to the feature matrix and describe what platforms the feature has been implemented on.
- If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the
API rework on all relevant platforms, please move it to the `Completed API Reworks` table.
- If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*,
or mark it as *mostly completed* and link to an issue describing the problems with the implementation.
## Core
### Windowing
- **Window initialization**: Winit allows the creation of a window
- **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context
- **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan
- **Window decorations**: The windows created by winit are properly decorated, and the decorations can
be deactivated
- **Window decorations toggle**: Decorations can be turned on or off after window creation
- **Window resizing**: The windows created by winit can be resized and generate the appropriate events
when they are. The application can precisely control its window size if desired.
- **Window resize increments**: When the window gets resized, the application can choose to snap the window's
size to specific values.
- **Window transparency**: Winit allows the creation of windows with a transparent background.
- **Window maximization**: The windows created by winit can be maximized upon creation.
- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after
creation.
- **Window minimization**: The windows created by winit can be minimized after creation.
- **Fullscreen**: The windows created by winit can be put into fullscreen mode.
- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after
creation.
- **Exclusive fullscreen**: Winit allows changing the video mode of the monitor
for fullscreen windows, and if applicable, captures the monitor for exclusive
use by this application.
- **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content.
- **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent
windows can be disabled in favor of popup windows. This feature also guarantees that popup windows
get drawn above their owner.
### System Information
- **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary.
- **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth).
### Input Handling
- **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events.
- **Mouse set location**: Forcibly changing the location of the pointer.
- **Cursor locking**: Locking the cursor inside the window so it cannot move.
- **Cursor confining**: Confining the cursor to the window bounds so it cannot leave them.
- **Cursor icon**: Changing the cursor icon, or hiding the cursor.
- **Cursor hittest**: Handle or ignore mouse events for a window.
- **Touch events**: Single-touch events.
- **Touch pressure**: Touch events contain information about the amount of force being applied.
- **Multitouch**: Multi-touch events, including cancellation of a gesture.
- **Keyboard events**: Properly processing keyboard events using the user-specified keymap and
translating keypresses into UTF-8 characters, handling dead keys and IMEs.
- **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled.
- **Raw Device Events**: Capturing input from input devices without any OS filtering.
- **Gamepad/Joystick events**: Capturing input from gamepads and joysticks.
- **Device movement events**: Capturing input from the device gyroscope and accelerometer.
## Platform
### Windows
* Setting the taskbar icon
* Setting the parent window
* Setting a menu bar
* `WS_EX_NOREDIRECTIONBITMAP` support
* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme
### macOS
* Window activation policy
* Window movable by background
* Transparent titlebar
* Hidden titlebar
* Hidden titlebar buttons
* Full-size content view
* Accepts first mouse
* Set a preferred theme and get current theme.
### Unix
* Window urgency
* X11 Window Class
* X11 Override Redirect Flag
* GTK Theme Variant
* Base window size
* Setting the X11 parent window
### iOS
* `winit` has a minimum OS requirement of iOS 8
* Get the `UIWindow` object pointer
* Get the `UIViewController` object pointer
* Get the `UIView` object pointer
* Get the `UIScreen` object pointer
* Setting the `UIView` hidpi factor
* Valid orientations
* Home indicator visibility
* Status bar visibility
* Deferrring system gestures
* Getting the device idiom
* Getting the preferred video mode
### Web
* Get if systems preferred color scheme is "dark"
## Usability
* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial)
## Compatibility Matrix
Legend:
- ✔️: Works as intended
- ▢: Mostly works but some bugs are known
- ❌: Missing feature or large bugs making it unusable
- **N/A**: Not applicable for this platform
- ❓: Unknown status
### Windowing
|Feature |Windows|MacOS |Linux x11 |Linux Wayland |Android|iOS |WASM |Redox OS|
|-------------------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------ |
|Window initialization |✔️ |✔️ |▢[#5] |✔️ |▢[#33]|▢[#33] |✔️ |✔️ |
|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |
|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |**N/A**|**N/A** |
|Window decorations |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|✔️ |
|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|**N/A** |
|Window resizing |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ |✔️ |
|Window resize increments |❌ |✔️ |✔️ |❌ |**N/A**|**N/A**|**N/A**|**N/A** |
|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|N/A |✔️ |
|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|**N/A** |
|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|**N/A** |
|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|**N/A** |
|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ |**N/A** |
|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ |**N/A** |
|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |✔️ |**N/A**|**N/A** |
|HiDPI support |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ |
|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**|**N/A** |
### System information
|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
|---------------- | ----- | ---- | ------- | ----------- | ----- | ------- | -------- | ------ |
|Monitor list |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|❌ |
|Video mode query |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|❌ |
### Input handling
|Feature |Windows |MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------ |
|Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ |✔️ |
|Mouse set location |✔️ |✔️ |✔️ |✔️(when locked) |**N/A**|**N/A**|**N/A**|**N/A** |
|Cursor locking |❌ |✔️ |❌ |✔️ |**N/A**|**N/A**|✔️ |❌ |
|Cursor confining |✔️ |❌ |✔️ |✔️ |**N/A**|**N/A**|❌ |❌ |
|Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ |**N/A** |
|Cursor hittest |✔️ |✔️ |❌ |✔️ |**N/A**|**N/A**|❌ |❌ |
|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A** |
|Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |✔️ |**N/A** |
|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ |**N/A** |
|Keyboard events |✔️ |✔️ |✔️ |✔️ |✔️ |❌ |✔️ |✔️ |
|Drag & Drop |▢[#720] |▢[#720] |▢[#720] |▢[#720] |**N/A**|**N/A**|❓ |**N/A** |
|Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |❌ |❌ |❓ |**N/A** |
|Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❓ |**N/A** |
|Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❓ |**N/A** |
|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A** |**N/A** |
|Resize with cursor |❌ |❌ |✔️ |❌ |**N/A**|**N/A**|**N/A** |**N/A** |
### Pending API Reworks
Changes in the API that have been agreed upon but aren't implemented across all platforms.
|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------ |
|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |❓ |
|Event Loop 2.0 ([#459]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |❓ |
|Keyboard Input ([#812]) |❌ |❌ |❌ |❌ |❌ |❌ |❓ |❓ |
### Completed API Reworks
|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------ |
[#165]: https://github.com/rust-windowing/winit/issues/165
[#219]: https://github.com/rust-windowing/winit/issues/219
[#242]: https://github.com/rust-windowing/winit/issues/242
[#306]: https://github.com/rust-windowing/winit/issues/306
[#315]: https://github.com/rust-windowing/winit/issues/315
[#319]: https://github.com/rust-windowing/winit/issues/319
[#33]: https://github.com/rust-windowing/winit/issues/33
[#459]: https://github.com/rust-windowing/winit/issues/459
[#5]: https://github.com/rust-windowing/winit/issues/5
[#63]: https://github.com/rust-windowing/winit/issues/63
[#720]: https://github.com/rust-windowing/winit/issues/720
[#721]: https://github.com/rust-windowing/winit/issues/721
[#750]: https://github.com/rust-windowing/winit/issues/750
[#804]: https://github.com/rust-windowing/winit/issues/804
[#812]: https://github.com/rust-windowing/winit/issues/812

26
HALL_OF_CHAMPIONS.md Normal file
View File

@@ -0,0 +1,26 @@
# Hall of Champions
The winit maintainers would like to recognize the following former winit
contributors, without whom winit would not exist in its current form. We thank
them deeply for their time and efforts, and wish them best of luck in their
future endeavors:
* [@tomaka]: For creating the winit project and guiding it through its early
years of existence.
* [@vberger]: For diligently creating the Wayland backend, and being its
extremely helpful and benevolent maintainer for years.
* [@francesca64]: For taking over the responsibility of maintaining almost every
winit backend, and standardizing HiDPI support across all of them.
* [@Osspial]: For heroically landing EventLoop 2.0, and valiantly ushering in a
vastly more sustainable era of winit.
* [@goddessfreya]: For selflessly taking over maintainership of glutin, and her
stellar dedication to improving both winit and glutin.
* [@ArturKovacs]: For consistently maintaining the macOS backend, and his
immense involvement in designing and implementing the new keyboard API.
[@tomaka]: https://github.com/tomaka
[@vberger]: https://github.com/vberger
[@francesca64]: https://github.com/francesca64
[@Osspial]: https://github.com/Osspial
[@goddessfreya]: https://github.com/goddessfreya
[@ArturKovacs]: https://github.com/ArturKovacs

204
README.md
View File

@@ -1,19 +1,27 @@
# winit - Cross-platform window creation and management in Rust
[![](http://meritbadge.herokuapp.com/winit)](https://crates.io/crates/winit)
[![Crates.io](https://img.shields.io/crates/v/winit.svg)](https://crates.io/crates/winit)
[![Docs.rs](https://docs.rs/winit/badge.svg)](https://docs.rs/winit)
[![Build Status](https://travis-ci.org/tomaka/winit.png?branch=master)](https://travis-ci.org/tomaka/winit)
[![Build status](https://ci.appveyor.com/api/projects/status/5h87hj0g4q2xe3j9/branch/master?svg=true)](https://ci.appveyor.com/project/tomaka/winit/branch/master)
[![CI Status](https://github.com/rust-windowing/winit/workflows/CI/badge.svg)](https://github.com/rust-windowing/winit/actions)
```toml
[dependencies]
winit = "0.13"
winit = "0.28.5"
```
## [Documentation](https://docs.rs/winit)
For features _within_ the scope of winit, see [FEATURES.md](FEATURES.md).
For features _outside_ the scope of winit, see [Missing features provided by other crates](https://github.com/rust-windowing/winit/wiki/Missing-features-provided-by-other-crates) in the wiki.
## Contact Us
Join us in any of these:
[![Matrix](https://img.shields.io/badge/Matrix-%23rust--windowing%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#rust-windowing:matrix.org)
[![Libera.Chat](https://img.shields.io/badge/libera.chat-%23winit-red.svg)](https://web.libera.chat/#winit)
## Usage
Winit is a window creation and management library. It can create windows and lets you handle
@@ -25,32 +33,184 @@ show something on the window you need to use the platform-specific getters provi
another library.
```rust
extern crate winit;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let window = winit::Window::new(&events_loop).unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
events_loop.run_forever(|event| {
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,
..
} => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => *control_flow = ControlFlow::Exit,
_ => (),
}
});
}
```
Winit is only officially supported on the latest stable version of the Rust compiler.
### Cargo Features
Winit provides the following features, which can be enabled in your `Cargo.toml` file:
* `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde).
* `x11` (enabled by default): On Unix platform, compiles with the X11 backend
* `wayland` (enabled by default): On Unix platform, compiles with the Wayland backend
* `mint`: Enables mint (math interoperability standard types) conversions.
### Platform-specific usage
#### Emscripten and WebAssembly
#### Wayland
Building a binary will yield a `.js` file. In order to use it in an HTML file, you need to:
Note that windows don't appear on Wayland until you draw/present to them.
- Put a `<canvas id="my_id"></canvas>` element somewhere. A canvas corresponds to a winit "window".
- Write a Javascript code that creates a global variable named `Module`. Set `Module.canvas` to
the element of the `<canvas>` element (in the example you would retrieve it via `document.getElementById("my_id")`).
More information [here](https://kripken.github.io/emscripten-site/docs/api_reference/module.html).
- Make sure that you insert the `.js` file generated by Rust after the `Module` variable is created.
`winit` doesn't do drawing, try the examples in [`glutin`] instead.
[`glutin`]: https://github.com/rust-windowing/glutin
#### WebAssembly
To run the web example: `cargo run-wasm --example web`
Winit supports compiling to the `wasm32-unknown-unknown` target with `web-sys`.
On the web platform, a Winit window is backed by a `<canvas>` element. You can
either [provide Winit with a `<canvas>` element][web with_canvas], or [let Winit
create a `<canvas>` element which you can then retrieve][web canvas getter] and
insert it into the DOM yourself.
For example code using Winit with WebAssembly, check out the [web example]. For
information on using Rust on WebAssembly, check out the [Rust and WebAssembly
book].
[web with_canvas]: https://docs.rs/winit/latest/wasm32-unknown-unknown/winit/platform/web/trait.WindowBuilderExtWebSys.html#tymethod.with_canvas
[web canvas getter]: https://docs.rs/winit/latest/wasm32-unknown-unknown/winit/platform/web/trait.WindowExtWebSys.html#tymethod.canvas
[web example]: ./examples/web.rs
[Rust and WebAssembly book]: https://rustwasm.github.io/book/
#### Android
The Android backend builds on (and exposes types from) the [`ndk`](https://docs.rs/ndk/0.7.0/ndk/) crate.
Native Android applications need some form of "glue" crate that is responsible
for defining the main entry point for your Rust application as well as tracking
various life-cycle events and synchronizing with the main JVM thread.
Winit uses the [android-activity](https://github.com/rib/android-activity) as a
glue crate (prior to `0.28` it used
[ndk-glue](https://github.com/rust-windowing/android-ndk-rs/tree/master/ndk-glue)).
The version of the glue crate that your application depends on _must_ match the
version that Winit depends on because the glue crate is responsible for your
application's main entrypoint. If Cargo resolves multiple versions they will
clash.
`winit` glue compatibility table:
| winit | ndk-glue |
| :---: | :--------------------------: |
| 0.28 | `android-activity = "0.4"` |
| 0.27 | `ndk-glue = "0.7"` |
| 0.26 | `ndk-glue = "0.5"` |
| 0.25 | `ndk-glue = "0.3"` |
| 0.24 | `ndk-glue = "0.2"` |
The recommended way to avoid a conflict with the glue version is to avoid explicitly
depending on the `android-activity` crate, and instead consume the API that
is re-exported by Winit under `winit::platform::android::activity::*`
Running on an Android device needs a dynamic system library, add this to Cargo.toml:
```toml
[lib]
name = "main"
crate-type = ["cdylib"]
```
All Android applications are based on an `Activity` subclass and the
`android-activity` crate is designed to support different choices for this base
class. Your application _must_ specify the base class it needs via a feature flag:
| Base Class | Feature Flag | Notes |
| :--------------: | :---------------: | :-----: |
| `NativeActivity` | `android-native-activity` | Built-in to Android - it is possible to use without compiling any Java or Kotlin code. Java or Kotlin code may be needed to subclass `NativeActivity` to access some platform features. It does not derive from the [`AndroidAppCompat`] base class.|
| [`GameActivity`] | `android-game-activity` | Derives from [`AndroidAppCompat`] which is a defacto standard `Activity` base class that helps support a wider range of Android versions. Requires a build system that can compile Java or Kotlin and fetch Android dependencies from a [Maven repository][agdk_jetpack] (or link with an embedded [release][agdk_releases] of [`GameActivity`]) |
[`GameActivity`]: https://developer.android.com/games/agdk/game-activity
[`GameTextInput`]: https://developer.android.com/games/agdk/add-support-for-text-input
[`AndroidAppCompat`]: https://developer.android.com/reference/androidx/appcompat/app/AppCompatActivity
[agdk_jetpack]: https://developer.android.com/jetpack/androidx/releases/games
[agdk_releases]: https://developer.android.com/games/agdk/download#agdk-libraries
[Gradle]: https://developer.android.com/studio/build
For example, add this to Cargo.toml:
```toml
winit = { version = "0.28", features = [ "android-native-activity" ] }
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
```
And, for example, define an entry point for your library like this:
```rust
#[cfg(target_os = "android")]
use winit::platform::android::activity::AndroidApp;
#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(app: AndroidApp) {
use winit::platform::android::EventLoopBuilderExtAndroid;
android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Trace));
let event_loop = EventLoopBuilder::with_user_event()
.with_android_app(app)
.build();
_main(event_loop);
}
```
For more details, refer to these `android-activity` [example applications](https://github.com/rib/android-activity/tree/main/examples).
##### Converting from `ndk-glue` to `android-activity`
If your application is currently based on `NativeActivity` via the `ndk-glue` crate and building with `cargo apk` then the minimal changes would be:
1. Remove `ndk-glue` from your `Cargo.toml`
2. Enable the `"android-native-activity"` feature for Winit: `winit = { version = "0.28", features = [ "android-native-activity" ] }`
3. Add an `android_main` entrypoint (as above), instead of using the '`[ndk_glue::main]` proc macro from `ndk-macros` (optionally add a dependency on `android_logger` and initialize logging as above).
4. Pass a clone of the `AndroidApp` that your application receives to Winit when building your event loop (as shown above).
#### MacOS
A lot of functionality expects the application to be ready before you start
doing anything; this includes creating windows, fetching monitors, drawing,
and so on, see issues [#2238], [#2051] and [#2087].
If you encounter problems, you should try doing your initialization inside
`Event::NewEvents(StartCause::Init)`.
#### iOS
Similar to macOS, iOS's main `UIApplicationMain` does some init work that's required
by all UI related code, see issue [#1705]. You should consider creating your windows
inside `Event::NewEvents(StartCause::Init)`.
[#2238]: https://github.com/rust-windowing/winit/issues/2238
[#2051]: https://github.com/rust-windowing/winit/issues/2051
[#2087]: https://github.com/rust-windowing/winit/issues/2087
[#1705]: https://github.com/rust-windowing/winit/issues/1705
#### Redox OS
Redox OS has some functionality not present yet, that will be implemented when
its orbital display server provides it.

View File

@@ -1,17 +0,0 @@
environment:
matrix:
- TARGET: x86_64-pc-windows-msvc
- TARGET: i686-pc-windows-msvc
- TARGET: i686-pc-windows-gnu
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- SET PATH=%PATH%;C:\MinGW\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test --verbose

64
build.rs Normal file
View File

@@ -0,0 +1,64 @@
use cfg_aliases::cfg_aliases;
#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
),
feature = "wayland",
))]
mod wayland {
use std::env;
use std::path::PathBuf;
use wayland_scanner::Side;
pub fn main() {
let mut path = PathBuf::from(env::var("OUT_DIR").unwrap());
path.push("fractional_scale_v1.rs");
wayland_scanner::generate_code(
"wayland_protocols/fractional-scale-v1.xml",
&path,
Side::Client,
);
}
}
fn main() {
// The script doesn't depend on our code
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=wayland_protocols");
// Setup cfg aliases
cfg_aliases! {
// Systems.
android_platform: { target_os = "android" },
wasm_platform: { target_arch = "wasm32" },
macos_platform: { target_os = "macos" },
ios_platform: { target_os = "ios" },
windows_platform: { target_os = "windows" },
apple: { any(target_os = "ios", target_os = "macos") },
free_unix: { all(unix, not(apple), not(android_platform)) },
redox: { target_os = "redox" },
// Native displays.
x11_platform: { all(feature = "x11", free_unix, not(wasm), not(redox)) },
wayland_platform: { all(feature = "wayland", free_unix, not(wasm), not(redox)) },
orbital_platform: { redox },
}
// XXX aliases are not available for the build script itself.
#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
),
feature = "wayland",
))]
wayland::main();
}

80
examples/child_window.rs Normal file
View File

@@ -0,0 +1,80 @@
#[cfg(any(x11_platform, macos_platform, windows_platform))]
fn main() {
use std::collections::HashMap;
use raw_window_handle::HasRawWindowHandle;
use winit::{
dpi::{LogicalPosition, LogicalSize, Position},
event::{ElementState, Event, KeyboardInput, WindowEvent},
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
window::{Window, WindowBuilder, WindowId},
};
fn spawn_child_window(
parent: &Window,
event_loop: &EventLoopWindowTarget<()>,
windows: &mut HashMap<WindowId, Window>,
) {
let parent = parent.raw_window_handle();
let mut builder = WindowBuilder::new()
.with_title("child window")
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_visible(true);
// `with_parent_window` is unsafe. Parent window must be a valid window.
builder = unsafe { builder.with_parent_window(Some(parent)) };
let child_window = builder.build(event_loop).unwrap();
let id = child_window.id();
windows.insert(id, child_window);
println!("child window created with id: {id:?}");
}
let mut windows = HashMap::new();
let event_loop: EventLoop<()> = EventLoop::new();
let parent_window = WindowBuilder::new()
.with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32))
.build(&event_loop)
.unwrap();
println!("parent window: {parent_window:?})");
event_loop.run(move |event: Event<'_, ()>, event_loop, control_flow| {
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent { event, window_id } = event {
match event {
WindowEvent::CloseRequested => {
windows.clear();
*control_flow = ControlFlow::Exit;
}
WindowEvent::CursorEntered { device_id: _ } => {
// On x11, println when the cursor entered in a window even if the child window is created
// by some key inputs.
// the child windows are always placed at (0, 0) with size (200, 200) in the parent window,
// so we also can see this log when we move the cursor arround (200, 200) in parent window.
println!("cursor entered in the window {window_id:?}");
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
..
},
..
} => {
spawn_child_window(&parent_window, event_loop, &mut windows);
}
_ => (),
}
}
})
}
#[cfg(not(any(x11_platform, macos_platform, windows_platform)))]
fn main() {
panic!("This example is supported only on x11, macOS, and Windows.");
}

114
examples/control_flow.rs Normal file
View File

@@ -0,0 +1,114 @@
#![allow(clippy::single_match)]
use std::{thread, time};
use simple_logger::SimpleLogger;
use winit::{
event::{Event, KeyboardInput, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Mode {
Wait,
WaitUntil,
Poll,
}
const WAIT_TIME: time::Duration = time::Duration::from_millis(100);
const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100);
fn main() {
SimpleLogger::new().init().unwrap();
println!("Press '1' to switch to Wait mode.");
println!("Press '2' to switch to WaitUntil mode.");
println!("Press '3' to switch to Poll mode.");
println!("Press 'R' to toggle request_redraw() calls.");
println!("Press 'Esc' to close the window.");
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.")
.build(&event_loop)
.unwrap();
let mut mode = Mode::Wait;
let mut request_redraw = false;
let mut wait_cancelled = false;
let mut close_requested = false;
event_loop.run(move |event, _, control_flow| {
use winit::event::{ElementState, StartCause, VirtualKeyCode};
println!("{event:?}");
match event {
Event::NewEvents(start_cause) => {
wait_cancelled = match start_cause {
StartCause::WaitCancelled { .. } => mode == Mode::WaitUntil,
_ => false,
}
}
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
close_requested = true;
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(virtual_code),
state: ElementState::Pressed,
..
},
..
} => match virtual_code {
VirtualKeyCode::Key1 => {
mode = Mode::Wait;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::Key2 => {
mode = Mode::WaitUntil;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::Key3 => {
mode = Mode::Poll;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::R => {
request_redraw = !request_redraw;
println!("\nrequest_redraw: {request_redraw}\n");
}
VirtualKeyCode::Escape => {
close_requested = true;
}
_ => (),
},
_ => (),
},
Event::MainEventsCleared => {
if request_redraw && !wait_cancelled && !close_requested {
window.request_redraw();
}
if close_requested {
control_flow.set_exit();
}
}
Event::RedrawRequested(_window_id) => {}
Event::RedrawEventsCleared => {
match mode {
Mode::Wait => control_flow.set_wait(),
Mode::WaitUntil => {
if !wait_cancelled {
control_flow.set_wait_until(instant::Instant::now() + WAIT_TIME);
}
}
Mode::Poll => {
thread::sleep(POLL_SLEEP_TIME);
control_flow.set_poll();
}
};
}
_ => (),
}
});
}

View File

@@ -1,32 +1,90 @@
extern crate winit;
#![allow(clippy::single_match)]
use winit::{Event, ElementState, MouseCursor, WindowEvent, KeyboardInput, ControlFlow};
use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, KeyboardInput, WindowEvent},
event_loop::EventLoop,
window::{CursorIcon, WindowBuilder},
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = winit::WindowBuilder::new().build(&events_loop).unwrap();
let window = WindowBuilder::new().build(&event_loop).unwrap();
window.set_title("A fantastic window!");
let cursors = [MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand, MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text, MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress, MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::NoneCursor, MouseCursor::Cell, MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy, MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing, MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut, MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize, MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize, MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize, MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize, MouseCursor::ColResize, MouseCursor::RowResize];
let mut cursor_idx = 0;
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. }, .. } => {
println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
window.set_cursor(cursors[cursor_idx]);
if cursor_idx < cursors.len() - 1 {
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
..
},
..
},
..
} => {
println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]);
window.set_cursor_icon(CURSORS[cursor_idx]);
if cursor_idx < CURSORS.len() - 1 {
cursor_idx += 1;
} else {
cursor_idx = 0;
}
},
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
return ControlFlow::Break;
},
_ => ()
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
control_flow.set_exit();
}
_ => (),
}
ControlFlow::Continue
});
}
const CURSORS: &[CursorIcon] = &[
CursorIcon::Default,
CursorIcon::Crosshair,
CursorIcon::Hand,
CursorIcon::Arrow,
CursorIcon::Move,
CursorIcon::Text,
CursorIcon::Wait,
CursorIcon::Help,
CursorIcon::Progress,
CursorIcon::NotAllowed,
CursorIcon::ContextMenu,
CursorIcon::Cell,
CursorIcon::VerticalText,
CursorIcon::Alias,
CursorIcon::Copy,
CursorIcon::NoDrop,
CursorIcon::Grab,
CursorIcon::Grabbing,
CursorIcon::AllScroll,
CursorIcon::ZoomIn,
CursorIcon::ZoomOut,
CursorIcon::EResize,
CursorIcon::NResize,
CursorIcon::NeResize,
CursorIcon::NwResize,
CursorIcon::SResize,
CursorIcon::SeResize,
CursorIcon::SwResize,
CursorIcon::WResize,
CursorIcon::EwResize,
CursorIcon::NsResize,
CursorIcon::NeswResize,
CursorIcon::NwseResize,
CursorIcon::ColResize,
CursorIcon::RowResize,
];

70
examples/cursor_grab.rs Normal file
View File

@@ -0,0 +1,70 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, WindowEvent},
event_loop::EventLoop,
window::{CursorGrabMode, WindowBuilder},
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("Super Cursor Grab'n'Hide Simulator 9000")
.build(&event_loop)
.unwrap();
let mut modifiers = ModifiersState::default();
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(key),
..
},
..
} => {
use winit::event::VirtualKeyCode::*;
let result = match key {
Escape => {
control_flow.set_exit();
Ok(())
}
G => window.set_cursor_grab(CursorGrabMode::Confined),
L => window.set_cursor_grab(CursorGrabMode::Locked),
A => window.set_cursor_grab(CursorGrabMode::None),
H => {
window.set_cursor_visible(modifiers.shift());
Ok(())
}
_ => Ok(()),
};
if let Err(err) = result {
println!("error: {err}");
}
}
WindowEvent::ModifiersChanged(m) => modifiers = m,
_ => (),
},
Event::DeviceEvent { event, .. } => match event {
DeviceEvent::MouseMotion { delta } => println!("mouse moved: {delta:?}"),
DeviceEvent::Button { button, state } => match state {
ElementState::Pressed => println!("mouse button {button} pressed"),
ElementState::Released => println!("mouse button {button} released"),
},
_ => (),
},
_ => (),
}
});
}

55
examples/custom_events.rs Normal file
View File

@@ -0,0 +1,55 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoopBuilder,
window::WindowBuilder,
};
#[derive(Debug, Clone, Copy)]
enum CustomEvent {
Timer,
}
SimpleLogger::new().init().unwrap();
let event_loop = EventLoopBuilder::<CustomEvent>::with_user_event().build();
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
// `EventLoopProxy` allows you to dispatch custom events to the main Winit event
// loop from any thread.
let event_loop_proxy = event_loop.create_proxy();
std::thread::spawn(move || {
// Wake up the `event_loop` once every second and dispatch a custom event
// from a different thread.
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
event_loop_proxy.send_event(CustomEvent::Timer).ok();
}
});
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::UserEvent(event) => println!("user event: {event:?}"),
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => control_flow.set_exit(),
_ => (),
}
});
}
#[cfg(wasm_platform)]
fn main() {
panic!("This example is not supported on web.");
}

75
examples/drag_window.rs Normal file
View File

@@ -0,0 +1,75 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{
ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent,
},
event_loop::EventLoop,
window::{Window, WindowBuilder, WindowId},
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window_1 = WindowBuilder::new().build(&event_loop).unwrap();
let window_2 = WindowBuilder::new().build(&event_loop).unwrap();
let mut switched = false;
let mut entered_id = window_2.id();
event_loop.run(move |event, _, control_flow| match event {
Event::NewEvents(StartCause::Init) => {
eprintln!("Switch which window is to be dragged by pressing \"x\".")
}
Event::WindowEvent { event, window_id } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
..
} => {
let window = if (window_id == window_1.id() && switched)
|| (window_id == window_2.id() && !switched)
{
&window_2
} else {
&window_1
};
window.drag_window().unwrap()
}
WindowEvent::CursorEntered { .. } => {
entered_id = window_id;
name_windows(entered_id, switched, &window_1, &window_2)
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(VirtualKeyCode::X),
..
},
..
} => {
switched = !switched;
name_windows(entered_id, switched, &window_1, &window_2);
println!("Switched!")
}
_ => (),
},
_ => (),
});
}
fn name_windows(window_id: WindowId, switched: bool, window_1: &Window, window_2: &Window) {
let (drag_target, other) =
if (window_id == window_1.id() && switched) || (window_id == window_2.id() && !switched) {
(&window_2, &window_1)
} else {
(&window_1, &window_2)
};
drag_target.set_title("drag target");
other.set_title("winit window");
}

View File

@@ -1,79 +1,122 @@
extern crate winit;
#![allow(clippy::single_match)]
use std::io::{self, Write};
use winit::{ControlFlow, Event, WindowEvent};
use simple_logger::SimpleLogger;
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use winit::event_loop::EventLoop;
use winit::window::{Fullscreen, WindowBuilder};
#[cfg(target_os = "macos")]
use winit::platform::macos::WindowExtMacOS;
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
// enumerating monitors
let monitor = {
for (num, monitor) in events_loop.get_available_monitors().enumerate() {
println!("Monitor #{}: {:?}", num, monitor.get_name());
}
let mut decorations = true;
let mut minimized = false;
print!("Please write the number of the monitor to use: ");
io::stdout().flush().unwrap();
let mut num = String::new();
io::stdin().read_line(&mut num).unwrap();
let num = num.trim().parse().ok().expect("Please enter a number");
let monitor = events_loop.get_available_monitors().nth(num).expect("Please enter a valid ID");
println!("Using {:?}", monitor.get_name());
monitor
};
let window = winit::WindowBuilder::new()
let window = WindowBuilder::new()
.with_title("Hello world!")
.with_fullscreen(Some(monitor))
.build(&events_loop)
.build(&event_loop)
.unwrap();
let mut is_fullscreen = true;
let mut is_maximized = false;
let mut decorations = true;
let mut monitor_index = 0;
let mut monitor = event_loop
.available_monitors()
.next()
.expect("no monitor found!");
println!("Monitor: {:?}", monitor.name());
events_loop.run_forever(|event| {
println!("{:?}", event);
let mut mode_index = 0;
let mut mode = monitor.video_modes().next().expect("no mode found");
println!("Mode: {mode}");
println!("Keys:");
println!("- Esc\tExit");
println!("- F\tToggle exclusive fullscreen mode");
println!("- B\tToggle borderless mode");
#[cfg(target_os = "macos")]
println!("- C\tToggle simple fullscreen mode");
println!("- S\tNext screen");
println!("- M\tNext mode for this screen");
println!("- D\tToggle window decorations");
println!("- X\tMaximize window");
println!("- Z\tMinimize window");
event_loop.run(move |event, elwt, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => return ControlFlow::Break,
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::KeyboardInput {
input:
winit::KeyboardInput {
KeyboardInput {
virtual_keycode: Some(virtual_code),
state,
state: ElementState::Pressed,
..
},
..
} => match (virtual_code, state) {
(winit::VirtualKeyCode::Escape, _) => return ControlFlow::Break,
(winit::VirtualKeyCode::F, winit::ElementState::Pressed) => {
is_fullscreen = !is_fullscreen;
if !is_fullscreen {
window.set_fullscreen(None);
} => match virtual_code {
VirtualKeyCode::Escape => control_flow.set_exit(),
VirtualKeyCode::F | VirtualKeyCode::B if window.fullscreen().is_some() => {
window.set_fullscreen(None);
}
VirtualKeyCode::F => {
let fullscreen = Some(Fullscreen::Exclusive(mode.clone()));
println!("Setting mode: {fullscreen:?}");
window.set_fullscreen(fullscreen);
}
VirtualKeyCode::B => {
let fullscreen = Some(Fullscreen::Borderless(Some(monitor.clone())));
println!("Setting mode: {fullscreen:?}");
window.set_fullscreen(fullscreen);
}
#[cfg(target_os = "macos")]
VirtualKeyCode::C => {
window.set_simple_fullscreen(!window.simple_fullscreen());
}
VirtualKeyCode::S => {
monitor_index += 1;
if let Some(mon) = elwt.available_monitors().nth(monitor_index) {
monitor = mon;
} else {
window.set_fullscreen(Some(window.get_current_monitor()));
monitor_index = 0;
monitor = elwt.available_monitors().next().expect("no monitor found!");
}
println!("Monitor: {:?}", monitor.name());
mode_index = 0;
mode = monitor.video_modes().next().expect("no mode found");
println!("Mode: {mode}");
}
(winit::VirtualKeyCode::M, winit::ElementState::Pressed) => {
is_maximized = !is_maximized;
window.set_maximized(is_maximized);
VirtualKeyCode::M => {
mode_index += 1;
if let Some(m) = monitor.video_modes().nth(mode_index) {
mode = m;
} else {
mode_index = 0;
mode = monitor.video_modes().next().expect("no mode found");
}
println!("Mode: {mode}");
}
(winit::VirtualKeyCode::D, winit::ElementState::Pressed) => {
VirtualKeyCode::D => {
decorations = !decorations;
window.set_decorations(decorations);
}
VirtualKeyCode::X => {
let is_maximized = window.is_maximized();
window.set_maximized(!is_maximized);
}
VirtualKeyCode::Z => {
minimized = !minimized;
window.set_minimized(minimized);
}
_ => (),
},
_ => (),
},
_ => {}
}
ControlFlow::Continue
});
}

View File

@@ -1,45 +0,0 @@
extern crate winit;
use winit::{ControlFlow, WindowEvent, ElementState, KeyboardInput};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new().build(&events_loop).unwrap();
window.set_title("winit - Cursor grabbing test");
let mut grabbed = false;
events_loop.run_forever(|event| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event, .. } => {
match event {
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. } => {
if grabbed {
grabbed = false;
window.set_cursor_state(winit::CursorState::Normal)
.ok().expect("could not ungrab mouse cursor");
} else {
grabbed = true;
window.set_cursor_state(winit::CursorState::Grab)
.ok().expect("could not grab mouse cursor");
}
},
WindowEvent::CloseRequested => return ControlFlow::Break,
a @ WindowEvent::CursorMoved { .. } => {
println!("{:?}", a);
},
_ => (),
}
}
_ => {}
}
ControlFlow::Continue
});
}

View File

@@ -1,74 +1,86 @@
extern crate winit;
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{Event, KeyboardInput, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let _window = winit::WindowBuilder::new()
let _window = WindowBuilder::new()
.with_title("Your faithful window")
.build(&events_loop)
.build(&event_loop)
.unwrap();
let mut close_requested = false;
events_loop.run_forever(|event| {
use winit::WindowEvent::*;
use winit::ElementState::Released;
use winit::VirtualKeyCode::{N, Y};
event_loop.run(move |event, _, control_flow| {
use winit::event::{
ElementState::Released,
VirtualKeyCode::{N, Y},
};
control_flow.set_wait();
match event {
winit::Event::WindowEvent { event, .. } => match event {
CloseRequested => {
// `CloseRequested` is sent when the close button on the window is pressed (or
// through whatever other mechanisms the window manager provides for closing a
// window). If you don't handle this event, the close button won't actually do
// anything.
Event::WindowEvent { event, .. } => {
match event {
WindowEvent::CloseRequested => {
// `CloseRequested` is sent when the close button on the window is pressed (or
// through whatever other mechanisms the window manager provides for closing a
// window). If you don't handle this event, the close button won't actually do
// anything.
// A common thing to do here is prompt the user if they have unsaved work.
// Creating a proper dialog box for that is far beyond the scope of this
// example, so here we'll just respond to the Y and N keys.
println!("Are you ready to bid your window farewell? [Y/N]");
close_requested = true;
// A common thing to do here is prompt the user if they have unsaved work.
// Creating a proper dialog box for that is far beyond the scope of this
// example, so here we'll just respond to the Y and N keys.
println!("Are you ready to bid your window farewell? [Y/N]");
close_requested = true;
// In applications where you can safely close the window without further
// action from the user, this is generally where you'd handle cleanup before
// closing the window. How to close the window is detailed in the handler for
// the Y key.
}
KeyboardInput {
input:
winit::KeyboardInput {
virtual_keycode: Some(virtual_code),
state: Released,
..
},
..
} => match virtual_code {
Y => {
if close_requested {
// This is where you'll want to do any cleanup you need.
println!("Buh-bye!");
// For a single-window application like this, you'd normally just
// break out of the event loop here. If you wanted to keep running the
// event loop (i.e. if it's a multi-window application), you need to
// drop the window. That closes it, and results in `Destroyed` being
// sent.
return winit::ControlFlow::Break;
}
// In applications where you can safely close the window without further
// action from the user, this is generally where you'd handle cleanup before
// closing the window. How to close the window is detailed in the handler for
// the Y key.
}
N => {
if close_requested {
println!("Your window will continue to stay by your side.");
close_requested = false;
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(virtual_code),
state: Released,
..
},
..
} => {
match virtual_code {
Y => {
if close_requested {
// This is where you'll want to do any cleanup you need.
println!("Buh-bye!");
// For a single-window application like this, you'd normally just
// break out of the event loop here. If you wanted to keep running the
// event loop (i.e. if it's a multi-window application), you need to
// drop the window. That closes it, and results in `Destroyed` being
// sent.
control_flow.set_exit();
}
}
N => {
if close_requested {
println!("Your window will continue to stay by your side.");
close_requested = false;
}
}
_ => (),
}
}
_ => (),
},
_ => (),
},
}
}
_ => (),
}
winit::ControlFlow::Continue
});
}

BIN
examples/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

112
examples/ime.rs Normal file
View File

@@ -0,0 +1,112 @@
#![allow(clippy::single_match)]
use log::LevelFilter;
use simple_logger::SimpleLogger;
use winit::{
dpi::PhysicalPosition,
event::{ElementState, Event, Ime, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{ImePurpose, WindowBuilder},
};
fn main() {
SimpleLogger::new()
.with_level(LevelFilter::Trace)
.init()
.unwrap();
println!("IME position will system default");
println!("Click to set IME position to cursor's");
println!("Press F2 to toggle IME. See the documentation of `set_ime_allowed` for more info");
println!("Press F3 to cycle through IME purposes.");
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(winit::dpi::LogicalSize::new(256f64, 128f64))
.build(&event_loop)
.unwrap();
let mut ime_purpose = ImePurpose::Normal;
let mut ime_allowed = true;
window.set_ime_allowed(ime_allowed);
let mut may_show_ime = false;
let mut cursor_position = PhysicalPosition::new(0.0, 0.0);
let mut ime_pos = PhysicalPosition::new(0.0, 0.0);
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => {
cursor_position = position;
}
Event::WindowEvent {
event:
WindowEvent::MouseInput {
state: ElementState::Released,
..
},
..
} => {
println!(
"Setting ime position to {}, {}",
cursor_position.x, cursor_position.y
);
ime_pos = cursor_position;
if may_show_ime {
window.set_ime_position(ime_pos);
}
}
Event::WindowEvent {
event: WindowEvent::Ime(event),
..
} => {
println!("{event:?}");
may_show_ime = event != Ime::Disabled;
if may_show_ime {
window.set_ime_position(ime_pos);
}
}
Event::WindowEvent {
event: WindowEvent::ReceivedCharacter(ch),
..
} => {
println!("ch: {ch:?}");
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput { input, .. },
..
} => {
println!("key: {input:?}");
if input.state == ElementState::Pressed
&& input.virtual_keycode == Some(VirtualKeyCode::F2)
{
ime_allowed = !ime_allowed;
window.set_ime_allowed(ime_allowed);
println!("\nIME allowed: {ime_allowed}\n");
}
if input.state == ElementState::Pressed
&& input.virtual_keycode == Some(VirtualKeyCode::F3)
{
ime_purpose = match ime_purpose {
ImePurpose::Normal => ImePurpose::Password,
ImePurpose::Password => ImePurpose::Terminal,
_ => ImePurpose::Normal,
};
window.set_ime_purpose(ime_purpose);
println!("\nIME purpose: {ime_purpose:?}\n");
}
}
_ => (),
}
});
}

View File

@@ -1,21 +0,0 @@
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new()
.build(&events_loop)
.unwrap();
window.set_min_dimensions(Some((400, 200)));
window.set_max_dimensions(Some((800, 400)));
events_loop.run_forever(|event| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
}
});
}

58
examples/monitor_list.rs Normal file
View File

@@ -0,0 +1,58 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::dpi::{PhysicalPosition, PhysicalSize};
use winit::monitor::MonitorHandle;
use winit::{event_loop::EventLoop, window::WindowBuilder};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
if let Some(mon) = window.primary_monitor() {
print_info("Primary output", mon);
}
for mon in window.available_monitors() {
if Some(&mon) == window.primary_monitor().as_ref() {
continue;
}
println!();
print_info("Output", mon);
}
}
fn print_info(intro: &str, monitor: MonitorHandle) {
if let Some(name) = monitor.name() {
println!("{intro}: {name}");
} else {
println!("{intro}: [no name]");
}
let PhysicalSize { width, height } = monitor.size();
print!(" Current mode: {width}x{height}");
if let Some(m_hz) = monitor.refresh_rate_millihertz() {
println!(" @ {}.{} Hz", m_hz / 1000, m_hz % 1000);
} else {
println!();
}
let PhysicalPosition { x, y } = monitor.position();
println!(" Position: {x},{y}");
println!(" Scale factor: {}", monitor.scale_factor());
println!(" Available modes (width x height x bit-depth):");
for mode in monitor.video_modes() {
let PhysicalSize { width, height } = mode.size();
let bits = mode.bit_depth();
let m_hz = mode.refresh_rate_millihertz();
println!(
" {width}x{height}x{bits} @ {}.{} Hz",
m_hz / 1000,
m_hz % 1000
);
}
}

62
examples/mouse_wheel.rs Normal file
View File

@@ -0,0 +1,62 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("Mouse Wheel events")
.build(&event_loop)
.unwrap();
println!(
r"
When using so called 'natural scrolling' (scrolling that acts like on a touch screen), this is what to expect:
Moving your finger downwards on a scroll wheel should make the window move down, and you should see a positive Y scroll value.
When moving fingers on a trackpad down and to the right, you should see positive X and Y deltas, and the window should move down and to the right.
With reverse scrolling, you should see the inverse behavior.
In both cases the example window should move like the content of a scroll area in any other application.
In other words, the deltas indicate the direction in which to move the content (in this case the window)."
);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::MouseWheel { delta, .. } => match delta {
winit::event::MouseScrollDelta::LineDelta(x, y) => {
println!("mouse wheel Line Delta: ({x},{y})");
let pixels_per_line = 120.0;
let mut pos = window.outer_position().unwrap();
pos.x += (x * pixels_per_line) as i32;
pos.y += (y * pixels_per_line) as i32;
window.set_outer_position(pos)
}
winit::event::MouseScrollDelta::PixelDelta(p) => {
println!("mouse wheel Pixel Delta: ({},{})", p.x, p.y);
let mut pos = window.outer_position().unwrap();
pos.x += p.x as i32;
pos.y += p.y as i32;
window.set_outer_position(pos)
}
},
_ => (),
},
_ => (),
}
});
}

199
examples/multithreaded.rs Normal file
View File

@@ -0,0 +1,199 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
use simple_logger::SimpleLogger;
use winit::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::EventLoop,
window::{CursorGrabMode, CursorIcon, Fullscreen, WindowBuilder, WindowLevel},
};
const WINDOW_COUNT: usize = 3;
const WINDOW_SIZE: PhysicalSize<u32> = PhysicalSize::new(600, 400);
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let mut window_senders = HashMap::with_capacity(WINDOW_COUNT);
for _ in 0..WINDOW_COUNT {
let window = WindowBuilder::new()
.with_inner_size(WINDOW_SIZE)
.build(&event_loop)
.unwrap();
let mut video_modes: Vec<_> = window.current_monitor().unwrap().video_modes().collect();
let mut video_mode_id = 0usize;
let (tx, rx) = mpsc::channel();
window_senders.insert(window.id(), tx);
thread::spawn(move || {
while let Ok(event) = rx.recv() {
match event {
WindowEvent::Moved { .. } => {
// We need to update our chosen video mode if the window
// was moved to an another monitor, so that the window
// appears on this monitor instead when we go fullscreen
let previous_video_mode = video_modes.get(video_mode_id).cloned();
video_modes = window.current_monitor().unwrap().video_modes().collect();
video_mode_id = video_mode_id.min(video_modes.len());
let video_mode = video_modes.get(video_mode_id);
// Different monitors may support different video modes,
// and the index we chose previously may now point to a
// completely different video mode, so notify the user
if video_mode != previous_video_mode.as_ref() {
println!(
"Window moved to another monitor, picked video mode: {}",
video_modes.get(video_mode_id).unwrap()
);
}
}
#[allow(deprecated)]
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(key),
modifiers,
..
},
..
} => {
window.set_title(&format!("{key:?}"));
let state = !modifiers.shift();
use VirtualKeyCode::*;
match key {
Key1 => window.set_window_level(WindowLevel::AlwaysOnTop),
Key2 => window.set_window_level(WindowLevel::AlwaysOnBottom),
Key3 => window.set_window_level(WindowLevel::Normal),
C => window.set_cursor_icon(match state {
true => CursorIcon::Progress,
false => CursorIcon::Default,
}),
D => window.set_decorations(!state),
// Cycle through video modes
Right | Left => {
video_mode_id = match key {
Left => video_mode_id.saturating_sub(1),
Right => (video_modes.len() - 1).min(video_mode_id + 1),
_ => unreachable!(),
};
println!("Picking video mode: {}", video_modes[video_mode_id]);
}
F => window.set_fullscreen(match (state, modifiers.alt()) {
(true, false) => Some(Fullscreen::Borderless(None)),
(true, true) => {
Some(Fullscreen::Exclusive(video_modes[video_mode_id].clone()))
}
(false, _) => None,
}),
L if state => {
if let Err(err) = window.set_cursor_grab(CursorGrabMode::Locked) {
println!("error: {err}");
}
}
G if state => {
if let Err(err) = window.set_cursor_grab(CursorGrabMode::Confined) {
println!("error: {err}");
}
}
G | L if !state => {
if let Err(err) = window.set_cursor_grab(CursorGrabMode::None) {
println!("error: {err}");
}
}
H => window.set_cursor_visible(!state),
I => {
println!("Info:");
println!("-> outer_position : {:?}", window.outer_position());
println!("-> inner_position : {:?}", window.inner_position());
println!("-> outer_size : {:?}", window.outer_size());
println!("-> inner_size : {:?}", window.inner_size());
println!("-> fullscreen : {:?}", window.fullscreen());
}
L => window.set_min_inner_size(match state {
true => Some(WINDOW_SIZE),
false => None,
}),
M => window.set_maximized(state),
P => window.set_outer_position({
let mut position = window.outer_position().unwrap();
let sign = if state { 1 } else { -1 };
position.x += 10 * sign;
position.y += 10 * sign;
position
}),
Q => window.request_redraw(),
R => window.set_resizable(state),
S => window.set_inner_size(match state {
true => PhysicalSize::new(
WINDOW_SIZE.width + 100,
WINDOW_SIZE.height + 100,
),
false => WINDOW_SIZE,
}),
W => {
if let Size::Physical(size) = WINDOW_SIZE.into() {
window
.set_cursor_position(Position::Physical(
PhysicalPosition::new(
size.width as i32 / 2,
size.height as i32 / 2,
),
))
.unwrap()
}
}
Z => {
window.set_visible(false);
thread::sleep(Duration::from_secs(1));
window.set_visible(true);
}
_ => (),
}
}
_ => (),
}
}
});
}
event_loop.run(move |event, _event_loop, control_flow| {
match !window_senders.is_empty() {
true => control_flow.set_wait(),
false => control_flow.set_exit(),
};
match event {
Event::WindowEvent { event, window_id } => match event {
WindowEvent::CloseRequested
| WindowEvent::Destroyed
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
} => {
window_senders.remove(&window_id);
}
_ => {
if let Some(tx) = window_senders.get(&window_id) {
if let Some(event) = event.to_static() {
tx.send(event).unwrap();
}
}
}
},
_ => {}
}
})
}
#[cfg(wasm_platform)]
fn main() {
panic!("Example not supported on Wasm");
}

View File

@@ -1,33 +1,61 @@
extern crate winit;
#![allow(clippy::single_match)]
use std::collections::HashMap;
use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::EventLoop,
window::Window,
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let mut windows = HashMap::new();
for _ in 0..3 {
let window = winit::Window::new(&events_loop).unwrap();
let window = Window::new(&event_loop).unwrap();
println!("Opened a new window: {:?}", window.id());
windows.insert(window.id(), window);
}
events_loop.run_forever(|event| {
println!("Press N to open a new window.");
event_loop.run(move |event, event_loop, control_flow| {
control_flow.set_wait();
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,
window_id,
} => {
println!("Window {:?} has received the signal to close", window_id);
Event::WindowEvent { event, window_id } => {
match event {
WindowEvent::CloseRequested => {
println!("Window {window_id:?} has received the signal to close");
// This drops the window, causing it to close.
windows.remove(&window_id);
// This drops the window, causing it to close.
windows.remove(&window_id);
if windows.is_empty() {
return winit::ControlFlow::Break;
if windows.is_empty() {
control_flow.set_exit();
}
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::N),
..
},
is_synthetic: false,
..
} => {
let window = Window::new(event_loop).unwrap();
println!("Opened a new window: {:?}", window.id());
windows.insert(window.id(), window);
}
_ => (),
}
}
_ => (),
}
winit::ControlFlow::Continue
})
}

View File

@@ -1,29 +0,0 @@
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::new();
let _window = winit::WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.unwrap();
let proxy = events_loop.create_proxy();
std::thread::spawn(move || {
// Wake up the `events_loop` once every second.
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
proxy.wakeup().unwrap();
}
});
events_loop.run_forever(|event| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } =>
winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
}
});
}

View File

@@ -0,0 +1,41 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
event_loop.run(move |event, _, control_flow| {
println!("{event:?}");
control_flow.set_wait();
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::MouseInput {
state: ElementState::Released,
..
} => {
window.request_redraw();
}
_ => (),
},
Event::RedrawRequested(_) => {
println!("\nredrawing!\n");
}
_ => (),
}
});
}

View File

@@ -0,0 +1,48 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
use std::{thread, time};
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
thread::spawn(move || loop {
thread::sleep(time::Duration::from_secs(1));
window.request_redraw();
});
event_loop.run(move |event, _, control_flow| {
println!("{event:?}");
control_flow.set_wait();
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => control_flow.set_exit(),
Event::RedrawRequested(_) => {
println!("\nredrawing!\n");
}
_ => (),
}
});
}
#[cfg(wasm_platform)]
fn main() {
unimplemented!() // `Window` can't be sent between threads
}

50
examples/resizable.rs Normal file
View File

@@ -0,0 +1,50 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
dpi::LogicalSize,
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let mut resizable = false;
let window = WindowBuilder::new()
.with_title("Hit space to toggle resizability.")
.with_inner_size(LogicalSize::new(600.0, 300.0))
.with_min_inner_size(LogicalSize::new(400.0, 200.0))
.with_max_inner_size(LogicalSize::new(800.0, 400.0))
.with_resizable(resizable)
.build(&event_loop)
.unwrap();
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Space),
state: ElementState::Released,
..
},
..
} => {
resizable = !resizable;
println!("Resizable: {resizable}");
window.set_resizable(resizable);
}
_ => (),
},
_ => (),
};
});
}

71
examples/theme.rs Normal file
View File

@@ -0,0 +1,71 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Theme, WindowBuilder},
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_theme(Some(Theme::Dark))
.build(&event_loop)
.unwrap();
println!("Initial theme: {:?}", window.theme());
println!("debugging keys:");
println!(" (A) Automatic theme");
println!(" (L) Light theme");
println!(" (D) Dark theme");
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
Event::WindowEvent {
event: WindowEvent::ThemeChanged(theme),
window_id,
..
} if window_id == window.id() => {
println!("Theme is changed: {theme:?}")
}
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state: ElementState::Pressed,
..
},
..
},
..
} => match key {
VirtualKeyCode::A => {
println!("Theme was: {:?}", window.theme());
window.set_theme(None);
}
VirtualKeyCode::L => {
println!("Theme was: {:?}", window.theme());
window.set_theme(Some(Theme::Light));
}
VirtualKeyCode::D => {
println!("Theme was: {:?}", window.theme());
window.set_theme(Some(Theme::Dark));
}
_ => (),
},
_ => (),
}
});
}

42
examples/timer.rs Normal file
View File

@@ -0,0 +1,42 @@
#![allow(clippy::single_match)]
use instant::Instant;
use std::time::Duration;
use simple_logger::SimpleLogger;
use winit::{
event::{Event, StartCause, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
let timer_length = Duration::new(1, 0);
event_loop.run(move |event, _, control_flow| {
println!("{event:?}");
match event {
Event::NewEvents(StartCause::Init) => {
control_flow.set_wait_until(Instant::now() + timer_length);
}
Event::NewEvents(StartCause::ResumeTimeReached { .. }) => {
control_flow.set_wait_until(Instant::now() + timer_length);
println!("\nTimer\n");
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => control_flow.set_exit(),
_ => (),
}
});
}

View File

@@ -0,0 +1,46 @@
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.with_title("Touchpad gestures")
.build(&event_loop)
.unwrap();
println!("Only supported on macOS at the moment.");
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent { event, .. } = event {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::TouchpadMagnify { delta, .. } => {
if delta > 0.0 {
println!("Zoomed in {delta}");
} else {
println!("Zoomed out {delta}");
}
}
WindowEvent::SmartMagnify { .. } => {
println!("Smart zoom");
}
WindowEvent::TouchpadRotate { delta, .. } => {
if delta > 0.0 {
println!("Rotated counterclockwise {delta}");
} else {
println!("Rotated clockwise {delta}");
}
}
_ => (),
}
}
});
}

View File

@@ -1,20 +1,34 @@
extern crate winit;
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = winit::WindowBuilder::new().with_decorations(false)
.with_transparency(true)
.build(&events_loop).unwrap();
let window = WindowBuilder::new()
.with_decorations(false)
.with_transparent(true)
.build(&event_loop)
.unwrap();
window.set_title("A fantastic window!");
events_loop.run_forever(|event| {
println!("{:?}", event);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
println!("{event:?}");
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => control_flow.set_exit(),
_ => (),
}
});
}

22
examples/video_modes.rs Normal file
View File

@@ -0,0 +1,22 @@
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::event_loop::EventLoop;
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let monitor = match event_loop.primary_monitor() {
Some(monitor) => monitor,
None => {
println!("No primary monitor detected.");
return;
}
};
println!("Listing available video modes:");
for mode in monitor.video_modes() {
println!("{mode}");
}
}

90
examples/web.rs Normal file
View File

@@ -0,0 +1,90 @@
#![allow(clippy::single_match)]
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
pub fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
#[cfg(wasm_platform)]
let log_list = wasm::insert_canvas_and_create_log_list(&window);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
#[cfg(wasm_platform)]
wasm::log_event(&log_list, &event);
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
Event::MainEventsCleared => {
window.request_redraw();
}
_ => (),
}
});
}
#[cfg(wasm_platform)]
mod wasm {
use wasm_bindgen::prelude::*;
use winit::{event::Event, window::Window};
#[wasm_bindgen(start)]
pub fn run() {
console_log::init_with_level(log::Level::Debug).expect("error initializing logger");
#[allow(clippy::main_recursion)]
super::main();
}
pub fn insert_canvas_and_create_log_list(window: &Window) -> web_sys::Element {
use winit::platform::web::WindowExtWebSys;
let canvas = window.canvas();
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let body = document.body().unwrap();
// Set a background color for the canvas to make it easier to tell where the canvas is for debugging purposes.
canvas.style().set_css_text("background-color: crimson;");
body.append_child(&canvas).unwrap();
let log_header = document.create_element("h2").unwrap();
log_header.set_text_content(Some("Event Log"));
body.append_child(&log_header).unwrap();
let log_list = document.create_element("ul").unwrap();
body.append_child(&log_list).unwrap();
log_list
}
pub fn log_event(log_list: &web_sys::Element, event: &Event<()>) {
log::debug!("{:?}", event);
// Getting access to browser logs requires a lot of setup on mobile devices.
// So we implement this basic logging system into the page to give developers an easy alternative.
// As a bonus its also kind of handy on desktop.
if let Event::WindowEvent { event, .. } = &event {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let log = document.create_element("li").unwrap();
log.set_text_content(Some(&format!("{event:?}")));
log_list
.insert_before(&log, log_list.first_child().as_ref())
.unwrap();
}
}
}

View File

@@ -0,0 +1,103 @@
pub fn main() {
println!("This example must be run with cargo run-wasm --example web_aspect_ratio")
}
#[cfg(wasm_platform)]
mod wasm {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlCanvasElement;
use winit::{
dpi::PhysicalSize,
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Window, WindowBuilder},
};
const EXPLANATION: &str = "
This example draws a circle in the middle of a 4/1 aspect ratio canvas which acts as a useful demonstration of winit's resize handling on web.
Even when the browser window is resized or aspect-ratio of the canvas changed the circle should always:
* Fill the entire width or height of the canvas (whichever is smaller) without exceeding it.
* Be perfectly round
* Not be blurry or pixelated (there is no antialiasing so you may still see jagged edges depending on the DPI of your monitor)
Currently winit does not handle resizes on web so the circle is rendered incorrectly.
This example demonstrates the desired future functionality which will possibly be provided by https://github.com/rust-windowing/winit/pull/2074
";
#[wasm_bindgen(start)]
pub fn run() {
console_log::init_with_level(log::Level::Debug).expect("error initializing logger");
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
// When running in a non-wasm environment this would set the window size to 100x100.
// However in this example it just sets a default initial size of 100x100 that is immediately overwritten due to the layout + styling of the page.
.with_inner_size(PhysicalSize::new(100, 100))
.build(&event_loop)
.unwrap();
let canvas = create_canvas(&window);
// Render once with the size info we currently have
render_circle(&canvas, window.inner_size());
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::Resized(resize),
window_id,
} if window_id == window.id() => {
render_circle(&canvas, resize);
}
_ => (),
}
});
}
pub fn create_canvas(window: &Window) -> HtmlCanvasElement {
use winit::platform::web::WindowExtWebSys;
let web_window = web_sys::window().unwrap();
let document = web_window.document().unwrap();
let body = document.body().unwrap();
// Set a background color for the canvas to make it easier to tell the where the canvas is for debugging purposes.
let canvas = window.canvas();
canvas
.style()
.set_css_text("display: block; background-color: crimson; margin: auto; width: 50%; aspect-ratio: 4 / 1;");
body.append_child(&canvas).unwrap();
let explanation = document.create_element("pre").unwrap();
explanation.set_text_content(Some(EXPLANATION));
body.append_child(&explanation).unwrap();
canvas
}
pub fn render_circle(canvas: &HtmlCanvasElement, size: PhysicalSize<u32>) {
log::info!("rendering circle with canvas size: {:?}", size);
let context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
context.begin_path();
context
.arc(
size.width as f64 / 2.0,
size.height as f64 / 2.0,
size.width.min(size.height) as f64 / 2.0,
0.0,
std::f64::consts::PI * 2.0,
)
.unwrap();
context.fill();
}
}

View File

@@ -1,22 +1,35 @@
extern crate winit;
#![allow(clippy::single_match)]
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
let mut events_loop = winit::EventsLoop::new();
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let _window = winit::WindowBuilder::new()
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
println!("{:?}", event);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
println!("{event:?}");
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,
..
} => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
Event::MainEventsCleared => {
window.request_redraw();
}
_ => (),
}
});
}

View File

@@ -0,0 +1,68 @@
#![allow(clippy::single_match)]
// This example is used by developers to test various window functions.
use simple_logger::SimpleLogger;
use winit::{
dpi::LogicalSize,
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{DeviceEventFilter, EventLoop},
window::{WindowBuilder, WindowButtons},
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_inner_size(LogicalSize::new(300.0, 300.0))
.build(&event_loop)
.unwrap();
eprintln!("Window Button keys:");
eprintln!(" (F) Toggle close button");
eprintln!(" (G) Toggle maximize button");
eprintln!(" (H) Toggle minimize button");
event_loop.set_device_event_filter(DeviceEventFilter::Never);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state: ElementState::Pressed,
..
},
..
},
..
} => match key {
VirtualKeyCode::F => {
let buttons = window.enabled_buttons();
window.set_enabled_buttons(buttons ^ WindowButtons::CLOSE);
}
VirtualKeyCode::G => {
let buttons = window.enabled_buttons();
window.set_enabled_buttons(buttons ^ WindowButtons::MAXIMIZE);
}
VirtualKeyCode::H => {
let buttons = window.enabled_buttons();
window.set_enabled_buttons(buttons ^ WindowButtons::MINIMIZE);
}
_ => (),
},
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
_ => (),
}
});
}

132
examples/window_debug.rs Normal file
View File

@@ -0,0 +1,132 @@
#![allow(clippy::single_match)]
// This example is used by developers to test various window functions.
use simple_logger::SimpleLogger;
use winit::{
dpi::{LogicalSize, PhysicalSize},
event::{DeviceEvent, ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{DeviceEventFilter, EventLoop},
window::{Fullscreen, WindowBuilder},
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_inner_size(LogicalSize::new(100.0, 100.0))
.build(&event_loop)
.unwrap();
eprintln!("debugging keys:");
eprintln!(" (E) Enter exclusive fullscreen");
eprintln!(" (F) Toggle borderless fullscreen");
eprintln!(" (P) Toggle borderless fullscreen on system's preffered monitor");
eprintln!(" (M) Toggle minimized");
eprintln!(" (Q) Quit event loop");
eprintln!(" (V) Toggle visibility");
eprintln!(" (X) Toggle maximized");
let mut minimized = false;
let mut visible = true;
event_loop.set_device_event_filter(DeviceEventFilter::Never);
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::DeviceEvent {
event:
DeviceEvent::Key(KeyboardInput {
virtual_keycode: Some(key),
state: ElementState::Pressed,
..
}),
..
} => match key {
VirtualKeyCode::M => {
if minimized {
minimized = !minimized;
window.set_minimized(minimized);
window.focus_window();
}
}
VirtualKeyCode::V => {
if !visible {
visible = !visible;
window.set_visible(visible);
}
}
_ => (),
},
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state: ElementState::Pressed,
..
},
..
},
..
} => match key {
VirtualKeyCode::E => {
fn area(size: PhysicalSize<u32>) -> u32 {
size.width * size.height
}
let monitor = window.current_monitor().unwrap();
if let Some(mode) = monitor
.video_modes()
.max_by(|a, b| area(a.size()).cmp(&area(b.size())))
{
window.set_fullscreen(Some(Fullscreen::Exclusive(mode)));
} else {
eprintln!("no video modes available");
}
}
VirtualKeyCode::F => {
if window.fullscreen().is_some() {
window.set_fullscreen(None);
} else {
let monitor = window.current_monitor();
window.set_fullscreen(Some(Fullscreen::Borderless(monitor)));
}
}
VirtualKeyCode::P => {
if window.fullscreen().is_some() {
window.set_fullscreen(None);
} else {
window.set_fullscreen(Some(Fullscreen::Borderless(None)));
}
}
VirtualKeyCode::M => {
minimized = !minimized;
window.set_minimized(minimized);
}
VirtualKeyCode::Q => {
control_flow.set_exit();
}
VirtualKeyCode::V => {
visible = !visible;
window.set_visible(visible);
}
VirtualKeyCode::X => {
let is_maximized = window.is_maximized();
window.set_maximized(!is_maximized);
}
_ => (),
},
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
_ => (),
}
});
}

View File

@@ -0,0 +1,141 @@
//! Demonstrates capability to create in-app draggable regions for client-side decoration support.
use simple_logger::SimpleLogger;
use winit::{
event::{
ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent,
},
event_loop::{ControlFlow, EventLoop},
window::{CursorIcon, ResizeDirection, WindowBuilder},
};
const BORDER: f64 = 8.0;
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0))
.with_min_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0))
.with_decorations(false)
.build(&event_loop)
.unwrap();
let mut border = false;
let mut cursor_location = None;
event_loop.run(move |event, _, control_flow| match event {
Event::NewEvents(StartCause::Init) => {
eprintln!("Press 'B' to toggle borderless")
}
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::CursorMoved { position, .. } => {
if !window.is_decorated() {
let new_location =
cursor_resize_direction(window.inner_size(), position, BORDER);
if new_location != cursor_location {
cursor_location = new_location;
window.set_cursor_icon(cursor_direction_icon(cursor_location))
}
}
}
WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
..
} => {
if let Some(dir) = cursor_location {
let _res = window.drag_resize_window(dir);
}
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(VirtualKeyCode::B),
..
},
..
} => {
border = !border;
window.set_decorations(border);
}
_ => (),
},
_ => (),
});
}
fn cursor_direction_icon(resize_direction: Option<ResizeDirection>) -> CursorIcon {
match resize_direction {
Some(resize_direction) => match resize_direction {
ResizeDirection::East => CursorIcon::EResize,
ResizeDirection::North => CursorIcon::NResize,
ResizeDirection::NorthEast => CursorIcon::NeResize,
ResizeDirection::NorthWest => CursorIcon::NwResize,
ResizeDirection::South => CursorIcon::SResize,
ResizeDirection::SouthEast => CursorIcon::SeResize,
ResizeDirection::SouthWest => CursorIcon::SwResize,
ResizeDirection::West => CursorIcon::WResize,
},
None => CursorIcon::Default,
}
}
fn cursor_resize_direction(
win_size: winit::dpi::PhysicalSize<u32>,
position: winit::dpi::PhysicalPosition<f64>,
border_size: f64,
) -> Option<ResizeDirection> {
enum XDirection {
West,
East,
Default,
}
enum YDirection {
North,
South,
Default,
}
let xdir = if position.x < border_size {
XDirection::West
} else if position.x > (win_size.width as f64 - border_size) {
XDirection::East
} else {
XDirection::Default
};
let ydir = if position.y < border_size {
YDirection::North
} else if position.y > (win_size.height as f64 - border_size) {
YDirection::South
} else {
YDirection::Default
};
Some(match xdir {
XDirection::West => match ydir {
YDirection::North => ResizeDirection::NorthWest,
YDirection::South => ResizeDirection::SouthWest,
YDirection::Default => ResizeDirection::West,
},
XDirection::East => match ydir {
YDirection::North => ResizeDirection::NorthEast,
YDirection::South => ResizeDirection::SouthEast,
YDirection::Default => ResizeDirection::East,
},
XDirection::Default => match ydir {
YDirection::North => ResizeDirection::North,
YDirection::South => ResizeDirection::South,
YDirection::Default => return None,
},
})
}

59
examples/window_icon.rs Normal file
View File

@@ -0,0 +1,59 @@
#![allow(clippy::single_match)]
use std::path::Path;
use simple_logger::SimpleLogger;
use winit::{
event::Event,
event_loop::EventLoop,
window::{Icon, WindowBuilder},
};
fn main() {
SimpleLogger::new().init().unwrap();
// You'll have to choose an icon size at your own discretion. On X11, the desired size varies
// by WM, and on Windows, you still have to account for screen scaling. Here we use 32px,
// since it seems to work well enough in most cases. Be careful about going too high, or
// you'll be bitten by the low-quality downscaling built into the WM.
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png");
let icon = load_icon(Path::new(path));
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("An iconic window!")
// At present, this only does anything on Windows and X11, so if you want to save load
// time, you can put icon loading behind a function that returns `None` on other platforms.
.with_window_icon(Some(icon))
.build(&event_loop)
.unwrap();
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
if let Event::WindowEvent { event, .. } = event {
use winit::event::WindowEvent::*;
match event {
CloseRequested => control_flow.set_exit(),
DroppedFile(path) => {
window.set_window_icon(Some(load_icon(&path)));
}
_ => (),
}
}
});
}
fn load_icon(path: &Path) -> Icon {
let (icon_rgba, icon_width, icon_height) = {
let image = image::open(path)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
}

View File

@@ -0,0 +1,67 @@
#![allow(clippy::single_match)]
#[cfg(target_os = "macos")]
use winit::platform::macos::{OptionAsAlt, WindowExtMacOS};
#[cfg(target_os = "macos")]
use winit::{
event::ElementState,
event::{Event, MouseButton, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
/// Prints the keyboard events characters received when option_is_alt is true versus false.
/// A left mouse click will toggle option_is_alt.
#[cfg(target_os = "macos")]
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.build(&event_loop)
.unwrap();
let mut option_as_alt = window.option_as_alt();
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
Event::WindowEvent { event, .. } => match event {
WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
..
} => {
option_as_alt = match option_as_alt {
OptionAsAlt::None => OptionAsAlt::OnlyLeft,
OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
OptionAsAlt::OnlyRight => OptionAsAlt::Both,
OptionAsAlt::Both => OptionAsAlt::None,
};
println!("Received Mouse click, toggling option_as_alt to: {option_as_alt:?}");
window.set_option_as_alt(option_as_alt);
}
WindowEvent::ReceivedCharacter(c) => println!("ReceivedCharacter: {c:?}"),
WindowEvent::KeyboardInput { .. } => println!("KeyboardInput: {event:?}"),
_ => (),
},
Event::MainEventsCleared => {
window.request_redraw();
}
_ => (),
}
});
}
#[cfg(not(target_os = "macos"))]
fn main() {
println!("This example is only supported on MacOS");
}

View File

@@ -0,0 +1,57 @@
use log::debug;
use simple_logger::SimpleLogger;
use winit::{
dpi::LogicalSize,
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_inner_size(LogicalSize::new(128.0, 128.0))
.with_resize_increments(LogicalSize::new(25.0, 25.0))
.build(&event_loop)
.unwrap();
let mut has_increments = true;
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(),
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Space),
state: ElementState::Released,
..
},
..
},
window_id,
} if window_id == window.id() => {
has_increments = !has_increments;
let new_increments = match window.resize_increments() {
Some(_) => None,
None => Some(LogicalSize::new(25.0, 25.0)),
};
debug!("Had increments: {}", new_increments.is_none());
window.set_resize_increments(new_increments);
}
Event::MainEventsCleared => window.request_redraw(),
_ => (),
}
});
}

View File

@@ -0,0 +1,64 @@
#![allow(clippy::single_match)]
// Limit this example to only compatible platforms.
#[cfg(any(
windows_platform,
macos_platform,
x11_platform,
wayland_platform,
android_platform,
orbital_platform,
))]
fn main() {
use std::{thread::sleep, time::Duration};
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
platform::run_return::EventLoopExtRunReturn,
window::WindowBuilder,
};
let mut event_loop = EventLoop::new();
SimpleLogger::new().init().unwrap();
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
let mut quit = false;
while !quit {
event_loop.run_return(|event, _, control_flow| {
control_flow.set_wait();
if let Event::WindowEvent { event, .. } = &event {
// Print only Window events to reduce noise
println!("{event:?}");
}
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
quit = true;
}
Event::MainEventsCleared => {
control_flow.set_exit();
}
_ => (),
}
});
// Sleep for 1/60 second to simulate rendering
println!("rendering");
sleep(Duration::from_millis(16));
}
}
#[cfg(any(ios_platform, wasm_platform))]
fn main() {
println!("This platform doesn't support run_return.");
}

9
run-wasm/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "run-wasm"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cargo-run-wasm = "0.2.0"

3
run-wasm/src/main.rs Normal file
View File

@@ -0,0 +1,3 @@
fn main() {
cargo_run_wasm::run_wasm_with_css("body { margin: 0px; }");
}

3
rustfmt.toml Normal file
View File

@@ -0,0 +1,3 @@
force_explicit_abi=true
use_field_init_shorthand=true
# merge_imports=true

583
src/dpi.rs Normal file
View File

@@ -0,0 +1,583 @@
//! UI scaling is important, so read the docs for this module if you don't want to be confused.
//!
//! ## Why should I care about UI scaling?
//!
//! Modern computer screens don't have a consistent relationship between resolution and size.
//! 1920x1080 is a common resolution for both desktop and mobile screens, despite mobile screens
//! normally being less than a quarter the size of their desktop counterparts. What's more, neither
//! desktop nor mobile screens are consistent resolutions within their own size classes - common
//! mobile screens range from below 720p to above 1440p, and desktop screens range from 720p to 5K
//! and beyond.
//!
//! Given that, it's a mistake to assume that 2D content will only be displayed on screens with
//! a consistent pixel density. If you were to render a 96-pixel-square image on a 1080p screen,
//! then render the same image on a similarly-sized 4K screen, the 4K rendition would only take up
//! about a quarter of the physical space as it did on the 1080p screen. That issue is especially
//! problematic with text rendering, where quarter-sized text becomes a significant legibility
//! problem.
//!
//! Failure to account for the scale factor can create a significantly degraded user experience.
//! Most notably, it can make users feel like they have bad eyesight, which will potentially cause
//! them to think about growing elderly, resulting in them having an existential crisis. Once users
//! enter that state, they will no longer be focused on your application.
//!
//! ## How should I handle it?
//!
//! The solution to this problem is to account for the device's *scale factor*. The scale factor is
//! the factor UI elements should be scaled by to be consistent with the rest of the user's system -
//! for example, a button that's normally 50 pixels across would be 100 pixels across on a device
//! with a scale factor of `2.0`, or 75 pixels across with a scale factor of `1.5`.
//!
//! Many UI systems, such as CSS, expose DPI-dependent units like [points] or [picas]. That's
//! usually a mistake, since there's no consistent mapping between the scale factor and the screen's
//! actual DPI. Unless you're printing to a physical medium, you should work in scaled pixels rather
//! than any DPI-dependent units.
//!
//! ### Position and Size types
//!
//! Winit's [`PhysicalPosition`] / [`PhysicalSize`] types correspond with the actual pixels on the
//! device, and the [`LogicalPosition`] / [`LogicalSize`] types correspond to the physical pixels
//! divided by the scale factor.
//! All of Winit's functions return physical types, but can take either logical or physical
//! coordinates as input, allowing you to use the most convenient coordinate system for your
//! particular application.
//!
//! Winit's position and size types types are generic over their exact pixel type, `P`, to allow the
//! API to have integer precision where appropriate (e.g. most window manipulation functions) and
//! floating precision when necessary (e.g. logical sizes for fractional scale factors and touch
//! input). If `P` is a floating-point type, please do not cast the values with `as {int}`. Doing so
//! will truncate the fractional part of the float, rather than properly round to the nearest
//! integer. Use the provided `cast` function or [`From`]/[`Into`] conversions, which handle the
//! rounding properly. Note that precision loss will still occur when rounding from a float to an
//! int, although rounding lessens the problem.
//!
//! ### Events
//!
//! Winit will dispatch a [`ScaleFactorChanged`] event whenever a window's scale factor has changed.
//! This can happen if the user drags their window from a standard-resolution monitor to a high-DPI
//! monitor, or if the user changes their DPI settings. This gives you a chance to rescale your
//! application's UI elements and adjust how the platform changes the window's size to reflect the new
//! scale factor. If a window hasn't received a [`ScaleFactorChanged`] event, then its scale factor
//! can be found by calling [`window.scale_factor()`].
//!
//! ## How is the scale factor calculated?
//!
//! Scale factor is calculated differently on different platforms:
//!
//! - **Windows:** On Windows 8 and 10, per-monitor scaling is readily configured by users from the
//! display settings. While users are free to select any option they want, they're only given a
//! selection of "nice" scale factors, i.e. 1.0, 1.25, 1.5... on Windows 7, the scale factor is
//! global and changing it requires logging out. See [this article][windows_1] for technical
//! details.
//! - **macOS:** Recent versions of macOS allow the user to change the scaling factor for certain
//! displays. When this is available, the user may pick a per-monitor scaling factor from a set
//! of pre-defined settings. All "retina displays" have a scaling factor above 1.0 by default but
//! the specific value varies across devices.
//! - **X11:** Many man-hours have been spent trying to figure out how to handle DPI in X11. Winit
//! currently uses a three-pronged approach:
//! + Use the value in the `WINIT_X11_SCALE_FACTOR` environment variable, if present.
//! + If not present, use the value set in `Xft.dpi` in Xresources.
//! + Otherwise, calculate the scale factor based on the millimeter monitor dimensions provided by XRandR.
//!
//! If `WINIT_X11_SCALE_FACTOR` is set to `randr`, it'll ignore the `Xft.dpi` field and use the
//! XRandR scaling method. Generally speaking, you should try to configure the standard system
//! variables to do what you want before resorting to `WINIT_X11_SCALE_FACTOR`.
//! - **Wayland:** On Wayland, scale factors are set per-screen by the server, and are always
//! integers (most often 1 or 2).
//! - **iOS:** Scale factors are set by Apple to the value that best suits the device, and range
//! from `1.0` to `3.0`. See [this article][apple_1] and [this article][apple_2] for more
//! information.
//! - **Android:** Scale factors are set by the manufacturer to the value that best suits the
//! device, and range from `1.0` to `4.0`. See [this article][android_1] for more information.
//! - **Web:** The scale factor is the ratio between CSS pixels and the physical device pixels.
//! In other words, it is the value of [`window.devicePixelRatio`][web_1]. It is affected by
//! both the screen scaling and the browser zoom level and can go below `1.0`.
//!
//!
//! [points]: https://en.wikipedia.org/wiki/Point_(typography)
//! [picas]: https://en.wikipedia.org/wiki/Pica_(typography)
//! [`ScaleFactorChanged`]: crate::event::WindowEvent::ScaleFactorChanged
//! [`window.scale_factor()`]: crate::window::Window::scale_factor
//! [windows_1]: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
//! [apple_1]: https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html
//! [apple_2]: https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/image-size-and-resolution/
//! [android_1]: https://developer.android.com/training/multiscreen/screendensities
//! [web_1]: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
pub trait Pixel: Copy + Into<f64> {
fn from_f64(f: f64) -> Self;
fn cast<P: Pixel>(self) -> P {
P::from_f64(self.into())
}
}
impl Pixel for u8 {
fn from_f64(f: f64) -> Self {
f.round() as u8
}
}
impl Pixel for u16 {
fn from_f64(f: f64) -> Self {
f.round() as u16
}
}
impl Pixel for u32 {
fn from_f64(f: f64) -> Self {
f.round() as u32
}
}
impl Pixel for i8 {
fn from_f64(f: f64) -> Self {
f.round() as i8
}
}
impl Pixel for i16 {
fn from_f64(f: f64) -> Self {
f.round() as i16
}
}
impl Pixel for i32 {
fn from_f64(f: f64) -> Self {
f.round() as i32
}
}
impl Pixel for f32 {
fn from_f64(f: f64) -> Self {
f as f32
}
}
impl Pixel for f64 {
fn from_f64(f: f64) -> Self {
f
}
}
/// Checks that the scale factor is a normal positive `f64`.
///
/// All functions that take a scale factor assert that this will return `true`. If you're sourcing scale factors from
/// anywhere other than winit, it's recommended to validate them using this function before passing them to winit;
/// otherwise, you risk panics.
#[inline]
pub fn validate_scale_factor(scale_factor: f64) -> bool {
scale_factor.is_sign_positive() && scale_factor.is_normal()
}
/// A position represented in logical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the
/// fractional part, which can cause noticable issues. To help with that, an `Into<(i32, i32)>`
/// implementation is provided which does the rounding for you.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalPosition<P> {
pub x: P,
pub y: P,
}
impl<P> LogicalPosition<P> {
#[inline]
pub const fn new(x: P, y: P) -> Self {
LogicalPosition { x, y }
}
}
impl<P: Pixel> LogicalPosition<P> {
#[inline]
pub fn from_physical<T: Into<PhysicalPosition<X>>, X: Pixel>(
physical: T,
scale_factor: f64,
) -> Self {
physical.into().to_logical(scale_factor)
}
#[inline]
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<X> {
assert!(validate_scale_factor(scale_factor));
let x = self.x.into() * scale_factor;
let y = self.y.into() * scale_factor;
PhysicalPosition::new(x, y).cast()
}
#[inline]
pub fn cast<X: Pixel>(&self) -> LogicalPosition<X> {
LogicalPosition {
x: self.x.cast(),
y: self.y.cast(),
}
}
}
impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalPosition<P> {
fn from((x, y): (X, X)) -> LogicalPosition<P> {
LogicalPosition::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for (X, X) {
fn from(p: LogicalPosition<P>) -> (X, X) {
(p.x.cast(), p.y.cast())
}
}
impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalPosition<P> {
fn from([x, y]: [X; 2]) -> LogicalPosition<P> {
LogicalPosition::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for [X; 2] {
fn from(p: LogicalPosition<P>) -> [X; 2] {
[p.x.cast(), p.y.cast()]
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<mint::Point2<P>> for LogicalPosition<P> {
fn from(p: mint::Point2<P>) -> Self {
Self::new(p.x, p.y)
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<LogicalPosition<P>> for mint::Point2<P> {
fn from(p: LogicalPosition<P>) -> Self {
mint::Point2 { x: p.x, y: p.y }
}
}
/// A position represented in physical pixels.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalPosition<P> {
pub x: P,
pub y: P,
}
impl<P> PhysicalPosition<P> {
#[inline]
pub const fn new(x: P, y: P) -> Self {
PhysicalPosition { x, y }
}
}
impl<P: Pixel> PhysicalPosition<P> {
#[inline]
pub fn from_logical<T: Into<LogicalPosition<X>>, X: Pixel>(
logical: T,
scale_factor: f64,
) -> Self {
logical.into().to_physical(scale_factor)
}
#[inline]
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalPosition<X> {
assert!(validate_scale_factor(scale_factor));
let x = self.x.into() / scale_factor;
let y = self.y.into() / scale_factor;
LogicalPosition::new(x, y).cast()
}
#[inline]
pub fn cast<X: Pixel>(&self) -> PhysicalPosition<X> {
PhysicalPosition {
x: self.x.cast(),
y: self.y.cast(),
}
}
}
impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalPosition<P> {
fn from((x, y): (X, X)) -> PhysicalPosition<P> {
PhysicalPosition::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for (X, X) {
fn from(p: PhysicalPosition<P>) -> (X, X) {
(p.x.cast(), p.y.cast())
}
}
impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalPosition<P> {
fn from([x, y]: [X; 2]) -> PhysicalPosition<P> {
PhysicalPosition::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for [X; 2] {
fn from(p: PhysicalPosition<P>) -> [X; 2] {
[p.x.cast(), p.y.cast()]
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<mint::Point2<P>> for PhysicalPosition<P> {
fn from(p: mint::Point2<P>) -> Self {
Self::new(p.x, p.y)
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<PhysicalPosition<P>> for mint::Point2<P> {
fn from(p: PhysicalPosition<P>) -> Self {
mint::Point2 { x: p.x, y: p.y }
}
}
/// A size represented in logical pixels.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalSize<P> {
pub width: P,
pub height: P,
}
impl<P> LogicalSize<P> {
#[inline]
pub const fn new(width: P, height: P) -> Self {
LogicalSize { width, height }
}
}
impl<P: Pixel> LogicalSize<P> {
#[inline]
pub fn from_physical<T: Into<PhysicalSize<X>>, X: Pixel>(
physical: T,
scale_factor: f64,
) -> Self {
physical.into().to_logical(scale_factor)
}
#[inline]
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalSize<X> {
assert!(validate_scale_factor(scale_factor));
let width = self.width.into() * scale_factor;
let height = self.height.into() * scale_factor;
PhysicalSize::new(width, height).cast()
}
#[inline]
pub fn cast<X: Pixel>(&self) -> LogicalSize<X> {
LogicalSize {
width: self.width.cast(),
height: self.height.cast(),
}
}
}
impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalSize<P> {
fn from((x, y): (X, X)) -> LogicalSize<P> {
LogicalSize::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for (X, X) {
fn from(s: LogicalSize<P>) -> (X, X) {
(s.width.cast(), s.height.cast())
}
}
impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalSize<P> {
fn from([x, y]: [X; 2]) -> LogicalSize<P> {
LogicalSize::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for [X; 2] {
fn from(s: LogicalSize<P>) -> [X; 2] {
[s.width.cast(), s.height.cast()]
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<mint::Vector2<P>> for LogicalSize<P> {
fn from(v: mint::Vector2<P>) -> Self {
Self::new(v.x, v.y)
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<LogicalSize<P>> for mint::Vector2<P> {
fn from(s: LogicalSize<P>) -> Self {
mint::Vector2 {
x: s.width,
y: s.height,
}
}
}
/// A size represented in physical pixels.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalSize<P> {
pub width: P,
pub height: P,
}
impl<P> PhysicalSize<P> {
#[inline]
pub const fn new(width: P, height: P) -> Self {
PhysicalSize { width, height }
}
}
impl<P: Pixel> PhysicalSize<P> {
#[inline]
pub fn from_logical<T: Into<LogicalSize<X>>, X: Pixel>(logical: T, scale_factor: f64) -> Self {
logical.into().to_physical(scale_factor)
}
#[inline]
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalSize<X> {
assert!(validate_scale_factor(scale_factor));
let width = self.width.into() / scale_factor;
let height = self.height.into() / scale_factor;
LogicalSize::new(width, height).cast()
}
#[inline]
pub fn cast<X: Pixel>(&self) -> PhysicalSize<X> {
PhysicalSize {
width: self.width.cast(),
height: self.height.cast(),
}
}
}
impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalSize<P> {
fn from((x, y): (X, X)) -> PhysicalSize<P> {
PhysicalSize::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for (X, X) {
fn from(s: PhysicalSize<P>) -> (X, X) {
(s.width.cast(), s.height.cast())
}
}
impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalSize<P> {
fn from([x, y]: [X; 2]) -> PhysicalSize<P> {
PhysicalSize::new(x.cast(), y.cast())
}
}
impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for [X; 2] {
fn from(s: PhysicalSize<P>) -> [X; 2] {
[s.width.cast(), s.height.cast()]
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<mint::Vector2<P>> for PhysicalSize<P> {
fn from(v: mint::Vector2<P>) -> Self {
Self::new(v.x, v.y)
}
}
#[cfg(feature = "mint")]
impl<P: Pixel> From<PhysicalSize<P>> for mint::Vector2<P> {
fn from(s: PhysicalSize<P>) -> Self {
mint::Vector2 {
x: s.width,
y: s.height,
}
}
}
/// A size that's either physical or logical.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Size {
Physical(PhysicalSize<u32>),
Logical(LogicalSize<f64>),
}
impl Size {
pub fn new<S: Into<Size>>(size: S) -> Size {
size.into()
}
pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalSize<P> {
match *self {
Size::Physical(size) => size.to_logical(scale_factor),
Size::Logical(size) => size.cast(),
}
}
pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalSize<P> {
match *self {
Size::Physical(size) => size.cast(),
Size::Logical(size) => size.to_physical(scale_factor),
}
}
pub fn clamp<S: Into<Size>>(input: S, min: S, max: S, scale_factor: f64) -> Size {
let (input, min, max) = (
input.into().to_physical::<f64>(scale_factor),
min.into().to_physical::<f64>(scale_factor),
max.into().to_physical::<f64>(scale_factor),
);
let width = input.width.clamp(min.width, max.width);
let height = input.height.clamp(min.height, max.height);
PhysicalSize::new(width, height).into()
}
}
impl<P: Pixel> From<PhysicalSize<P>> for Size {
#[inline]
fn from(size: PhysicalSize<P>) -> Size {
Size::Physical(size.cast())
}
}
impl<P: Pixel> From<LogicalSize<P>> for Size {
#[inline]
fn from(size: LogicalSize<P>) -> Size {
Size::Logical(size.cast())
}
}
/// A position that's either physical or logical.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Position {
Physical(PhysicalPosition<i32>),
Logical(LogicalPosition<f64>),
}
impl Position {
pub fn new<S: Into<Position>>(position: S) -> Position {
position.into()
}
pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalPosition<P> {
match *self {
Position::Physical(position) => position.to_logical(scale_factor),
Position::Logical(position) => position.cast(),
}
}
pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<P> {
match *self {
Position::Physical(position) => position.cast(),
Position::Logical(position) => position.to_physical(scale_factor),
}
}
}
impl<P: Pixel> From<PhysicalPosition<P>> for Position {
#[inline]
fn from(position: PhysicalPosition<P>) -> Position {
Position::Physical(position.cast())
}
}
impl<P: Pixel> From<LogicalPosition<P>> for Position {
#[inline]
fn from(position: LogicalPosition<P>) -> Position {
Position::Logical(position.cast())
}
}

82
src/error.rs Normal file
View File

@@ -0,0 +1,82 @@
use std::{error, fmt};
use crate::platform_impl;
/// An error whose cause it outside Winit's control.
#[derive(Debug)]
pub enum ExternalError {
/// The operation is not supported by the backend.
NotSupported(NotSupportedError),
/// The OS cannot perform the operation.
Os(OsError),
}
/// The error type for when the requested operation is not supported by the backend.
#[derive(Clone)]
pub struct NotSupportedError {
_marker: (),
}
/// The error type for when the OS cannot perform the requested operation.
#[derive(Debug)]
pub struct OsError {
line: u32,
file: &'static str,
error: platform_impl::OsError,
}
impl NotSupportedError {
#[inline]
#[allow(dead_code)]
pub(crate) fn new() -> NotSupportedError {
NotSupportedError { _marker: () }
}
}
impl OsError {
#[allow(dead_code)]
pub(crate) fn new(line: u32, file: &'static str, error: platform_impl::OsError) -> OsError {
OsError { line, file, error }
}
}
#[allow(unused_macros)]
macro_rules! os_error {
($error:expr) => {{
crate::error::OsError::new(line!(), file!(), $error)
}};
}
impl fmt::Display for OsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.pad(&format!(
"os error at {}:{}: {}",
self.file, self.line, self.error
))
}
}
impl fmt::Display for ExternalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match self {
ExternalError::NotSupported(e) => e.fmt(f),
ExternalError::Os(e) => e.fmt(f),
}
}
}
impl fmt::Debug for NotSupportedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("NotSupportedError").finish()
}
}
impl fmt::Display for NotSupportedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.pad("the requested operation is not supported by Winit")
}
}
impl error::Error for OsError {}
impl error::Error for ExternalError {}
impl error::Error for NotSupportedError {}

1392
src/event.rs Normal file

File diff suppressed because it is too large Load Diff

440
src/event_loop.rs Normal file
View File

@@ -0,0 +1,440 @@
//! The [`EventLoop`] struct and assorted supporting types, including
//! [`ControlFlow`].
//!
//! If you want to send custom events to the event loop, use
//! [`EventLoop::create_proxy`] to acquire an [`EventLoopProxy`] and call its
//! [`send_event`](`EventLoopProxy::send_event`) method.
//!
//! See the root-level documentation for information on how to create and use an event loop to
//! handle events.
use std::marker::PhantomData;
use std::ops::Deref;
use std::{error, fmt};
use instant::{Duration, Instant};
use once_cell::sync::OnceCell;
use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle};
use crate::{event::Event, monitor::MonitorHandle, platform_impl};
/// Provides a way to retrieve events from the system and from the windows that were registered to
/// the events loop.
///
/// An `EventLoop` can be seen more or less as a "context". Calling [`EventLoop::new`]
/// initializes everything that will be required to create windows. For example on Linux creating
/// an event loop opens a connection to the X or Wayland server.
///
/// To wake up an `EventLoop` from a another thread, see the [`EventLoopProxy`] docs.
///
/// Note that this cannot be shared across threads (due to platform-dependant logic
/// forbidding it), as such it is neither [`Send`] nor [`Sync`]. If you need cross-thread access, the
/// [`Window`] created from this _can_ be sent to an other thread, and the
/// [`EventLoopProxy`] allows you to wake up an `EventLoop` from another thread.
///
/// [`Window`]: crate::window::Window
pub struct EventLoop<T: 'static> {
pub(crate) event_loop: platform_impl::EventLoop<T>,
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
}
/// Target that associates windows with an [`EventLoop`].
///
/// This type exists to allow you to create new windows while Winit executes
/// your callback. [`EventLoop`] will coerce into this type (`impl<T> Deref for
/// EventLoop<T>`), so functions that take this as a parameter can also take
/// `&EventLoop`.
pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
}
/// Object that allows building the event loop.
///
/// This is used to make specifying options that affect the whole application
/// easier. But note that constructing multiple event loops is not supported.
#[derive(Default)]
pub struct EventLoopBuilder<T: 'static> {
pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes,
_p: PhantomData<T>,
}
impl EventLoopBuilder<()> {
/// Start building a new event loop.
#[inline]
pub fn new() -> Self {
Self::with_user_event()
}
}
impl<T> EventLoopBuilder<T> {
/// Start building a new event loop, with the given type as the user event
/// type.
#[inline]
pub fn with_user_event() -> Self {
Self {
platform_specific: Default::default(),
_p: PhantomData,
}
}
/// Builds a new event loop.
///
/// ***For cross-platform compatibility, the [`EventLoop`] must be created on the main thread,
/// and only once per application.***
///
/// Attempting to create the event loop on a different thread, or multiple event loops in
/// the same application, will panic. This restriction isn't
/// strictly necessary on all platforms, but is imposed to eliminate any nasty surprises when
/// porting to platforms that require it. `EventLoopBuilderExt::any_thread` functions are exposed
/// in the relevant [`platform`] module if the target platform supports creating an event loop on
/// any thread.
///
/// Calling this function will result in display backend initialisation.
///
/// ## Platform-specific
///
/// - **Linux:** Backend type can be controlled using an environment variable
/// `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`.
/// If it is not set, winit will try to connect to a Wayland connection, and if that fails,
/// will fall back on X11. If this variable is set with any other value, winit will panic.
/// - **Android:** Must be configured with an `AndroidApp` from `android_main()` by calling
/// [`.with_android_app(app)`] before calling `.build()`.
///
/// [`platform`]: crate::platform
#[cfg_attr(
android,
doc = "[`.with_android_app(app)`]: crate::platform::android::EventLoopBuilderExtAndroid::with_android_app"
)]
#[cfg_attr(
not(android),
doc = "[`.with_android_app(app)`]: #only-available-on-android"
)]
#[inline]
pub fn build(&mut self) -> EventLoop<T> {
static EVENT_LOOP_CREATED: OnceCell<()> = OnceCell::new();
if EVENT_LOOP_CREATED.set(()).is_err() {
panic!("Creating EventLoop multiple times is not supported.");
}
// Certain platforms accept a mutable reference in their API.
#[allow(clippy::unnecessary_mut_passed)]
EventLoop {
event_loop: platform_impl::EventLoop::new(&mut self.platform_specific),
_marker: PhantomData,
}
}
}
impl<T> fmt::Debug for EventLoop<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("EventLoop { .. }")
}
}
impl<T> fmt::Debug for EventLoopWindowTarget<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("EventLoopWindowTarget { .. }")
}
}
/// Set by the user callback given to the [`EventLoop::run`] method.
///
/// Indicates the desired behavior of the event loop after [`Event::RedrawEventsCleared`] is emitted.
///
/// Defaults to [`Poll`].
///
/// ## Persistency
///
/// Almost every change is persistent between multiple calls to the event loop closure within a
/// given run loop. The only exception to this is [`ExitWithCode`] which, once set, cannot be unset.
/// Changes are **not** persistent between multiple calls to `run_return` - issuing a new call will
/// reset the control flow to [`Poll`].
///
/// [`ExitWithCode`]: Self::ExitWithCode
/// [`Poll`]: Self::Poll
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControlFlow {
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
/// whether or not new events are available to process.
///
/// ## Platform-specific
///
/// - **Web:** Events are queued and usually sent when `requestAnimationFrame` fires but sometimes
/// the events in the queue may be sent before the next `requestAnimationFrame` callback, for
/// example when the scaling of the page has changed. This should be treated as an implementation
/// detail which should not be relied on.
Poll,
/// When the current loop iteration finishes, suspend the thread until another event arrives.
Wait,
/// When the current loop iteration finishes, suspend the thread until either another event
/// arrives or the given time is reached.
///
/// Useful for implementing efficient timers. Applications which want to render at the display's
/// native refresh rate should instead use [`Poll`] and the VSync functionality of a graphics API
/// to reduce odds of missed frames.
///
/// [`Poll`]: Self::Poll
WaitUntil(Instant),
/// Send a [`LoopDestroyed`] event and stop the event loop. This variant is *sticky* - once set,
/// `control_flow` cannot be changed from `ExitWithCode`, and any future attempts to do so will
/// result in the `control_flow` parameter being reset to `ExitWithCode`.
///
/// The contained number will be used as exit code. The [`Exit`] constant is a shortcut for this
/// with exit code 0.
///
/// ## Platform-specific
///
/// - **Android / iOS / WASM:** The supplied exit code is unused.
/// - **Unix:** On most Unix-like platforms, only the 8 least significant bits will be used,
/// which can cause surprises with negative exit values (`-42` would end up as `214`). See
/// [`std::process::exit`].
///
/// [`LoopDestroyed`]: Event::LoopDestroyed
/// [`Exit`]: ControlFlow::Exit
ExitWithCode(i32),
}
impl ControlFlow {
/// Alias for [`ExitWithCode`]`(0)`.
///
/// [`ExitWithCode`]: Self::ExitWithCode
#[allow(non_upper_case_globals)]
pub const Exit: Self = Self::ExitWithCode(0);
/// Sets this to [`Poll`].
///
/// [`Poll`]: Self::Poll
pub fn set_poll(&mut self) {
*self = Self::Poll;
}
/// Sets this to [`Wait`].
///
/// [`Wait`]: Self::Wait
pub fn set_wait(&mut self) {
*self = Self::Wait;
}
/// Sets this to [`WaitUntil`]`(instant)`.
///
/// [`WaitUntil`]: Self::WaitUntil
pub fn set_wait_until(&mut self, instant: Instant) {
*self = Self::WaitUntil(instant);
}
/// Sets this to wait until a timeout has expired.
///
/// In most cases, this is set to [`WaitUntil`]. However, if the timeout overflows, it is
/// instead set to [`Wait`].
///
/// [`WaitUntil`]: Self::WaitUntil
/// [`Wait`]: Self::Wait
pub fn set_wait_timeout(&mut self, timeout: Duration) {
match Instant::now().checked_add(timeout) {
Some(instant) => self.set_wait_until(instant),
None => self.set_wait(),
}
}
/// Sets this to [`ExitWithCode`]`(code)`.
///
/// [`ExitWithCode`]: Self::ExitWithCode
pub fn set_exit_with_code(&mut self, code: i32) {
*self = Self::ExitWithCode(code);
}
/// Sets this to [`Exit`].
///
/// [`Exit`]: Self::Exit
pub fn set_exit(&mut self) {
*self = Self::Exit;
}
}
impl Default for ControlFlow {
#[inline(always)]
fn default() -> Self {
Self::Poll
}
}
impl EventLoop<()> {
/// Alias for [`EventLoopBuilder::new().build()`].
///
/// [`EventLoopBuilder::new().build()`]: EventLoopBuilder::build
#[inline]
pub fn new() -> EventLoop<()> {
EventLoopBuilder::new().build()
}
}
impl Default for EventLoop<()> {
fn default() -> Self {
Self::new()
}
}
impl<T> EventLoop<T> {
#[deprecated = "Use `EventLoopBuilder::<T>::with_user_event().build()` instead."]
pub fn with_user_event() -> EventLoop<T> {
EventLoopBuilder::<T>::with_user_event().build()
}
/// Hijacks the calling thread and initializes the winit event loop with the provided
/// closure. Since the closure is `'static`, it must be a `move` closure if it needs to
/// access any data from the calling context.
///
/// See the [`ControlFlow`] docs for information on how changes to `&mut ControlFlow` impact the
/// event loop's behavior.
///
/// Any values not passed to this function will *not* be dropped.
///
/// ## Platform-specific
///
/// - **X11 / Wayland:** The program terminates with exit code 1 if the display server
/// disconnects.
///
/// [`ControlFlow`]: crate::event_loop::ControlFlow
#[inline]
pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
{
self.event_loop.run(event_handler)
}
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events to the main event loop.
pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy {
event_loop_proxy: self.event_loop.create_proxy(),
}
}
}
unsafe impl<T> HasRawDisplayHandle for EventLoop<T> {
/// Returns a [`raw_window_handle::RawDisplayHandle`] for the event loop.
fn raw_display_handle(&self) -> RawDisplayHandle {
self.event_loop.window_target().p.raw_display_handle()
}
}
impl<T> Deref for EventLoop<T> {
type Target = EventLoopWindowTarget<T>;
fn deref(&self) -> &EventLoopWindowTarget<T> {
self.event_loop.window_target()
}
}
impl<T> EventLoopWindowTarget<T> {
/// Returns the list of all the monitors available on the system.
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
self.p
.available_monitors()
.into_iter()
.map(|inner| MonitorHandle { inner })
}
/// Returns the primary monitor of the system.
///
/// Returns `None` if it can't identify any monitor as a primary one.
///
/// ## Platform-specific
///
/// **Wayland:** Always returns `None`.
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.p
.primary_monitor()
.map(|inner| MonitorHandle { inner })
}
/// Change [`DeviceEvent`] filter mode.
///
/// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit
/// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing
/// this filter at runtime to explicitly capture them again.
///
/// ## Platform-specific
///
/// - **Wayland / macOS / iOS / Android / Web / Orbital:** Unsupported.
///
/// [`DeviceEvent`]: crate::event::DeviceEvent
pub fn set_device_event_filter(&self, _filter: DeviceEventFilter) {
#[cfg(any(x11_platform, wayland_platform, windows))]
self.p.set_device_event_filter(_filter);
}
}
unsafe impl<T> HasRawDisplayHandle for EventLoopWindowTarget<T> {
/// Returns a [`raw_window_handle::RawDisplayHandle`] for the event loop.
fn raw_display_handle(&self) -> RawDisplayHandle {
self.p.raw_display_handle()
}
}
/// Used to send custom events to [`EventLoop`].
pub struct EventLoopProxy<T: 'static> {
event_loop_proxy: platform_impl::EventLoopProxy<T>,
}
impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self {
Self {
event_loop_proxy: self.event_loop_proxy.clone(),
}
}
}
impl<T: 'static> EventLoopProxy<T> {
/// Send an event to the [`EventLoop`] from which this proxy was created. This emits a
/// `UserEvent(event)` event in the event loop, where `event` is the value passed to this
/// function.
///
/// Returns an `Err` if the associated [`EventLoop`] no longer exists.
///
/// [`UserEvent(event)`]: Event::UserEvent
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
self.event_loop_proxy.send_event(event)
}
}
impl<T: 'static> fmt::Debug for EventLoopProxy<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("EventLoopProxy { .. }")
}
}
/// The error that is returned when an [`EventLoopProxy`] attempts to wake up an [`EventLoop`] that
/// no longer exists.
///
/// Contains the original event given to [`EventLoopProxy::send_event`].
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventLoopClosed<T>(pub T);
impl<T> fmt::Display for EventLoopClosed<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Tried to wake up a closed `EventLoop`")
}
}
impl<T: fmt::Debug> error::Error for EventLoopClosed<T> {}
/// Filter controlling the propagation of device events.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum DeviceEventFilter {
/// Always filter out device events.
Always,
/// Filter out device events while the window is not focused.
Unfocused,
/// Report all device events regardless of window focus.
Never,
}
impl Default for DeviceEventFilter {
fn default() -> Self {
Self::Unfocused
}
}

View File

@@ -1,451 +0,0 @@
use std::path::PathBuf;
use {WindowId, DeviceId};
/// Describes a generic event.
#[derive(Clone, Debug)]
pub enum Event {
WindowEvent {
window_id: WindowId,
event: WindowEvent,
},
DeviceEvent {
device_id: DeviceId,
event: DeviceEvent,
},
Awakened,
/// The application has been suspended or resumed.
///
/// The parameter is true if app was suspended, and false if it has been resumed.
Suspended(bool),
}
/// Describes an event from a `Window`.
#[derive(Clone, Debug)]
pub enum WindowEvent {
/// The size of the window has changed.
Resized(u32, u32),
/// The position of the window has changed.
Moved(i32, i32),
/// The window has been requested to close.
CloseRequested,
/// The window has been destroyed.
Destroyed,
/// A file has been dropped into the window.
DroppedFile(PathBuf),
/// A file is being hovered over the window.
HoveredFile(PathBuf),
/// A file was hovered, but has exited the window.
HoveredFileCancelled,
/// The window received a unicode character.
ReceivedCharacter(char),
/// The window gained or lost focus.
///
/// The parameter is true if the window has gained focus, and false if it has lost focus.
Focused(bool),
/// An event from the keyboard has been received.
KeyboardInput { device_id: DeviceId, input: KeyboardInput },
/// The cursor has moved on the window.
CursorMoved {
device_id: DeviceId,
/// (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this data is
/// limited by the display area and it may have been transformed by the OS to implement effects such as cursor
/// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
position: (f64, f64),
modifiers: ModifiersState
},
/// The cursor has entered the window.
CursorEntered { device_id: DeviceId },
/// The cursor has left the window.
CursorLeft { device_id: DeviceId },
/// A mouse wheel movement or touchpad scroll occurred.
MouseWheel { device_id: DeviceId, delta: MouseScrollDelta, phase: TouchPhase, modifiers: ModifiersState },
/// An mouse button press has been received.
MouseInput { device_id: DeviceId, state: ElementState, button: MouseButton, modifiers: ModifiersState },
/// Touchpad pressure event.
///
/// At the moment, only supported on Apple forcetouch-capable macbooks.
/// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad
/// is being pressed) and stage (integer representing the click level).
TouchpadPressure { device_id: DeviceId, pressure: f32, stage: i64 },
/// Motion on some analog axis. May report data redundant to other, more specific events.
AxisMotion { device_id: DeviceId, axis: AxisId, value: f64 },
/// The window needs to be redrawn.
Refresh,
/// Touch event has been received
Touch(Touch),
/// DPI scaling factor of the window has changed.
///
/// The following actions cause DPI changes:
///
/// * A user changes the resolution.
/// * A user changes the desktop scaling value (e.g. in Control Panel on Windows).
/// * A user moves the application window to a display with a different DPI.
HiDPIFactorChanged(f32),
}
/// Represents raw hardware events that are not associated with any particular window.
///
/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because
/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs
/// may not match.
///
/// Note that these events are delivered regardless of input focus.
#[derive(Clone, Debug)]
pub enum DeviceEvent {
Added,
Removed,
/// Change in physical position of a pointing device.
///
/// This represents raw, unfiltered physical motion. Not to be confused with `WindowEvent::CursorMoved`.
MouseMotion {
/// (x, y) change in position in unspecified units.
///
/// Different devices may use different units.
delta: (f64, f64),
},
/// Physical scroll event
MouseWheel {
delta: MouseScrollDelta,
},
/// Motion on some analog axis. This event will be reported for all arbitrary input devices
/// that winit supports on this platform, including mouse devices. If the device is a mouse
/// device then this will be reported alongside the MouseMotion event.
Motion { axis: AxisId, value: f64 },
Button { button: ButtonId, state: ElementState },
Key(KeyboardInput),
Text { codepoint: char },
}
/// Describes a keyboard input event.
#[derive(Debug, Clone, Copy)]
pub struct KeyboardInput {
/// Identifies the physical key pressed
///
/// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the
/// key is more important than the key's host GUI semantics, such as for movement controls in a first-person
/// game.
pub scancode: ScanCode,
pub state: ElementState,
/// Identifies the semantic meaning of the key
///
/// Use when the semantics of the key are more important than the physical location of the key, such as when
/// implementing appropriate behavior for "page up."
pub virtual_keycode: Option<VirtualKeyCode>,
/// Modifier keys active at the time of this input.
///
/// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
/// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
pub modifiers: ModifiersState
}
/// Describes touch-screen input state.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum TouchPhase {
Started,
Moved,
Ended,
Cancelled
}
/// Represents touch event
///
/// Every time user touches screen new Start event with some finger id is generated.
/// When the finger is removed from the screen End event with same id is generated.
///
/// For every id there will be at least 2 events with phases Start and End (or Cancelled).
/// There may be 0 or more Move events.
///
///
/// Depending on platform implementation id may or may not be reused by system after End event.
///
/// Gesture regonizer using this event should assume that Start event received with same id
/// as previously received End event is a new finger and has nothing to do with an old one.
///
/// Touch may be cancelled if for example window lost focus.
#[derive(Debug, Clone, Copy)]
pub struct Touch {
pub device_id: DeviceId,
pub phase: TouchPhase,
pub location: (f64,f64),
/// unique identifier of a finger.
pub id: u64
}
/// Hardware-dependent keyboard scan code.
pub type ScanCode = u32;
/// Identifier for a specific analog axis on some device.
pub type AxisId = u32;
/// Identifier for a specific button on some device.
pub type ButtonId = u32;
/// Describes the input state of a key.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum ElementState {
Pressed,
Released,
}
/// Describes a button of a mouse controller.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum MouseButton {
Left,
Right,
Middle,
Other(u8),
}
/// Describes a difference in the mouse scroll wheel state.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MouseScrollDelta {
/// Amount in lines or rows to scroll in the horizontal
/// and vertical directions.
///
/// Positive values indicate movement forward
/// (away from the user) or rightwards.
LineDelta(f32, f32),
/// Amount in pixels to scroll in the horizontal and
/// vertical direction.
///
/// Scroll events are expressed as a PixelDelta if
/// supported by the device (eg. a touchpad) and
/// platform.
PixelDelta(f32, f32)
}
/// Symbolic name for a keyboard key.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum VirtualKeyCode {
/// The '1' key over the letters.
Key1,
/// The '2' key over the letters.
Key2,
/// The '3' key over the letters.
Key3,
/// The '4' key over the letters.
Key4,
/// The '5' key over the letters.
Key5,
/// The '6' key over the letters.
Key6,
/// The '7' key over the letters.
Key7,
/// The '8' key over the letters.
Key8,
/// The '9' key over the letters.
Key9,
/// The '0' key over the 'O' and 'P' keys.
Key0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
/// The Escape key, next to F1.
Escape,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
/// Print Screen/SysRq.
Snapshot,
/// Scroll Lock.
Scroll,
/// Pause/Break key, next to Scroll lock.
Pause,
/// `Insert`, next to Backspace.
Insert,
Home,
Delete,
End,
PageDown,
PageUp,
Left,
Up,
Right,
Down,
/// The Backspace key, right over Enter.
// TODO: rename
Back,
/// The Enter key.
Return,
/// The space bar.
Space,
/// The "Compose" key on Linux.
Compose,
Caret,
Numlock,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
AbntC1,
AbntC2,
Add,
Apostrophe,
Apps,
At,
Ax,
Backslash,
Calculator,
Capital,
Colon,
Comma,
Convert,
Decimal,
Divide,
Equals,
Grave,
Kana,
Kanji,
LAlt,
LBracket,
LControl,
LMenu,
LShift,
LWin,
Mail,
MediaSelect,
MediaStop,
Minus,
Multiply,
Mute,
MyComputer,
NavigateForward, // also called "Prior"
NavigateBackward, // also called "Next"
NextTrack,
NoConvert,
NumpadComma,
NumpadEnter,
NumpadEquals,
OEM102,
Period,
PlayPause,
Power,
PrevTrack,
RAlt,
RBracket,
RControl,
RMenu,
RShift,
RWin,
Semicolon,
Slash,
Sleep,
Stop,
Subtract,
Sysrq,
Tab,
Underline,
Unlabeled,
VolumeDown,
VolumeUp,
Wake,
WebBack,
WebFavorites,
WebForward,
WebHome,
WebRefresh,
WebSearch,
WebStop,
Yen,
}
/// Represents the current state of the keyboard modifiers
///
/// Each field of this struct represents a modifier and is `true` if this modifier is active.
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub struct ModifiersState {
/// The "shift" key
pub shift: bool,
/// The "control" key
pub ctrl: bool,
/// The "alt" key
pub alt: bool,
/// The "logo" key
///
/// This is the "windows" key on PC and "command" key on Mac.
pub logo: bool
}

129
src/icon.rs Normal file
View File

@@ -0,0 +1,129 @@
use crate::platform_impl::PlatformIcon;
use std::{error::Error, fmt, io, mem};
#[repr(C)]
#[derive(Debug)]
pub(crate) struct Pixel {
pub(crate) r: u8,
pub(crate) g: u8,
pub(crate) b: u8,
pub(crate) a: u8,
}
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
#[derive(Debug)]
/// An error produced when using [`Icon::from_rgba`] with invalid arguments.
pub enum BadIcon {
/// Produced when the length of the `rgba` argument isn't divisible by 4, thus `rgba` can't be
/// safely interpreted as 32bpp RGBA pixels.
ByteCountNotDivisibleBy4 { byte_count: usize },
/// Produced when the number of pixels (`rgba.len() / 4`) isn't equal to `width * height`.
/// At least one of your arguments is incorrect.
DimensionsVsPixelCount {
width: u32,
height: u32,
width_x_height: usize,
pixel_count: usize,
},
/// Produced when underlying OS functionality failed to create the icon
OsError(io::Error),
}
impl fmt::Display for BadIcon {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BadIcon::ByteCountNotDivisibleBy4 { byte_count } => write!(f,
"The length of the `rgba` argument ({byte_count:?}) isn't divisible by 4, making it impossible to interpret as 32bpp RGBA pixels.",
),
BadIcon::DimensionsVsPixelCount {
width,
height,
width_x_height,
pixel_count,
} => write!(f,
"The specified dimensions ({width:?}x{height:?}) don't match the number of pixels supplied by the `rgba` argument ({pixel_count:?}). For those dimensions, the expected pixel count is {width_x_height:?}.",
),
BadIcon::OsError(e) => write!(f, "OS error when instantiating the icon: {e:?}"),
}
}
}
impl Error for BadIcon {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct RgbaIcon {
pub(crate) rgba: Vec<u8>,
pub(crate) width: u32,
pub(crate) height: u32,
}
/// For platforms which don't have window icons (e.g. web)
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct NoIcon;
#[allow(dead_code)] // These are not used on every platform
mod constructors {
use super::*;
impl RgbaIcon {
pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
if rgba.len() % PIXEL_SIZE != 0 {
return Err(BadIcon::ByteCountNotDivisibleBy4 {
byte_count: rgba.len(),
});
}
let pixel_count = rgba.len() / PIXEL_SIZE;
if pixel_count != (width * height) as usize {
Err(BadIcon::DimensionsVsPixelCount {
width,
height,
width_x_height: (width * height) as usize,
pixel_count,
})
} else {
Ok(RgbaIcon {
rgba,
width,
height,
})
}
}
}
impl NoIcon {
pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
// Create the rgba icon anyway to validate the input
let _ = RgbaIcon::from_rgba(rgba, width, height)?;
Ok(NoIcon)
}
}
}
/// An icon used for the window titlebar, taskbar, etc.
#[derive(Clone)]
pub struct Icon {
pub(crate) inner: PlatformIcon,
}
impl fmt::Debug for Icon {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt::Debug::fmt(&self.inner, formatter)
}
}
impl Icon {
/// Creates an icon from 32bpp RGBA data.
///
/// The length of `rgba` must be divisible by 4, and `width * height` must equal
/// `rgba.len() / 4`. Otherwise, this will return a `BadIcon` error.
pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
Ok(Icon {
inner: PlatformIcon::from_rgba(rgba, width, height)?,
})
}
}

View File

@@ -1,462 +1,161 @@
//! Winit allows you to build a window on as many platforms as possible.
//! Winit is a cross-platform window creation and event loop management library.
//!
//! # Building a window
//! # Building windows
//!
//! Before you can build a window, you first need to build an `EventsLoop`. This is done with the
//! `EventsLoop::new()` function. Example:
//! Before you can build a [`Window`], you first need to build an [`EventLoop`]. This is done with the
//! [`EventLoop::new()`] function.
//!
//! ```no_run
//! use winit::EventsLoop;
//! let events_loop = EventsLoop::new();
//! use winit::event_loop::EventLoop;
//! let event_loop = EventLoop::new();
//! ```
//!
//! Once this is done there are two ways to create a window:
//! Once this is done there are two ways to create a [`Window`]:
//!
//! - Calling `Window::new(&events_loop)`.
//! - Calling `let builder = WindowBuilder::new()` then `builder.build(&events_loop)`.
//! - Calling [`Window::new(&event_loop)`][window_new].
//! - Calling [`let builder = WindowBuilder::new()`][window_builder_new] then [`builder.build(&event_loop)`][window_builder_build].
//!
//! The first way is the simpliest way and will give you default values for everything.
//! The first method is the simplest, and will give you default values for everything. The second
//! method allows you to customize the way your [`Window`] will look and behave by modifying the
//! fields of the [`WindowBuilder`] object before you create the [`Window`].
//!
//! The second way allows you to customize the way your window will look and behave by modifying
//! the fields of the `WindowBuilder` object before you create the window.
//! # Event handling
//!
//! # Events handling
//! Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can
//! generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the
//! window or a key getting pressed while the window is focused. Devices can generate
//! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window.
//! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a
//! [`DeviceEvent`]. You can also create and handle your own custom [`UserEvent`]s, if desired.
//!
//! Once a window has been created, it will *generate events*. For example whenever the user moves
//! the window, resizes the window, moves the mouse, etc. an event is generated.
//! You can retrieve events by calling [`EventLoop::run`][event_loop_run]. This function will
//! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and
//! will run until the `control_flow` argument given to the closure is set to
//! [`ControlFlow`]`::`[`ExitWithCode`] (which [`ControlFlow`]`::`[`Exit`] aliases to), at which
//! point [`Event`]`::`[`LoopDestroyed`] is emitted and the entire program terminates.
//!
//! The events generated by a window can be retreived from the `EventsLoop` the window was created
//! with.
//! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop
//! model, since that can't be implemented properly on some platforms (e.g web, iOS) and works poorly on
//! most other platforms. However, this model can be re-implemented to an extent with
//! [`EventLoopExtRunReturn::run_return`]. See that method's documentation for more reasons about why
//! it's discouraged, beyond compatibility reasons.
//!
//! There are two ways to do so. The first is to call `events_loop.poll_events(...)`, which will
//! retreive all the events pending on the windows and immediately return after no new event is
//! available. You usually want to use this method in application that render continuously on the
//! screen, such as video games.
//!
//! ```no_run
//! use winit::{Event, WindowEvent};
//! # use winit::EventsLoop;
//! # let mut events_loop = EventsLoop::new();
//! use winit::{
//! event::{Event, WindowEvent},
//! event_loop::EventLoop,
//! window::WindowBuilder,
//! };
//!
//! loop {
//! events_loop.poll_events(|event| {
//! match event {
//! Event::WindowEvent { event: WindowEvent::Resized(w, h), .. } => {
//! println!("The window was resized to {}x{}", w, h);
//! },
//! _ => ()
//! }
//! });
//! }
//! ```
//! let event_loop = EventLoop::new();
//! let window = WindowBuilder::new().build(&event_loop).unwrap();
//!
//! The second way is to call `events_loop.run_forever(...)`. As its name tells, it will run
//! forever unless it is stopped by returning `ControlFlow::Break`.
//! event_loop.run(move |event, _, control_flow| {
//! // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't
//! // dispatched any events. This is ideal for games and similar applications.
//! control_flow.set_poll();
//!
//! ```no_run
//! use winit::{ControlFlow, Event, WindowEvent};
//! # use winit::EventsLoop;
//! # let mut events_loop = EventsLoop::new();
//! // ControlFlow::Wait pauses the event loop if no events are available to process.
//! // This is ideal for non-game applications that only update in response to user
//! // input, and uses significantly less power/CPU time than ControlFlow::Poll.
//! control_flow.set_wait();
//!
//! events_loop.run_forever(|event| {
//! match event {
//! Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
//! Event::WindowEvent {
//! event: WindowEvent::CloseRequested,
//! ..
//! } => {
//! println!("The close button was pressed; stopping");
//! ControlFlow::Break
//! control_flow.set_exit();
//! },
//! _ => ControlFlow::Continue,
//! Event::MainEventsCleared => {
//! // Application update code.
//!
//! // Queue a RedrawRequested event.
//! //
//! // You only need to call this if you've determined that you need to redraw, in
//! // applications which do not always need to. Applications that redraw continuously
//! // can just render here instead.
//! window.request_redraw();
//! },
//! Event::RedrawRequested(_) => {
//! // Redraw the application.
//! //
//! // It's preferable for applications that do not render continuously to render in
//! // this event rather than in MainEventsCleared, since rendering in here allows
//! // the program to gracefully handle redraws requested by the OS.
//! },
//! _ => ()
//! }
//! });
//! ```
//!
//! If you use multiple windows, the `WindowEvent` event has a member named `window_id`. You can
//! compare it with the value returned by the `id()` method of `Window` in order to know which
//! window has received the event.
//! [`Event`]`::`[`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be
//! compared to the value returned by [`Window::id()`][window_id_fn] to determine which [`Window`]
//! dispatched the event.
//!
//! # Drawing on the window
//!
//! Winit doesn't provide any function that allows drawing on a window. However it allows you to
//! retreive the raw handle of the window (see the `os` module for that), which in turn allows you
//! to create an OpenGL/Vulkan/DirectX/Metal/etc. context that will draw on the window.
//! Winit doesn't directly provide any methods for drawing on a [`Window`]. However it allows you to
//! retrieve the raw handle of the window and display (see the [`platform`] module and/or the
//! [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows
//! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics.
//!
//! Note that many platforms will display garbage data in the window's client area if the
//! application doesn't render anything to the window by the time the desktop compositor is ready to
//! display the window to the user. If you notice this happening, you should create the window with
//! [`visible` set to `false`](crate::window::WindowBuilder::with_visible) and explicitly make the
//! window visible only once you're ready to render into it.
//!
//! [`EventLoop`]: event_loop::EventLoop
//! [`EventLoopExtRunReturn::run_return`]: ./platform/run_return/trait.EventLoopExtRunReturn.html#tymethod.run_return
//! [`EventLoop::new()`]: event_loop::EventLoop::new
//! [event_loop_run]: event_loop::EventLoop::run
//! [`ControlFlow`]: event_loop::ControlFlow
//! [`Exit`]: event_loop::ControlFlow::Exit
//! [`ExitWithCode`]: event_loop::ControlFlow::ExitWithCode
//! [`Window`]: window::Window
//! [`WindowId`]: window::WindowId
//! [`WindowBuilder`]: window::WindowBuilder
//! [window_new]: window::Window::new
//! [window_builder_new]: window::WindowBuilder::new
//! [window_builder_build]: window::WindowBuilder::build
//! [window_id_fn]: window::Window::id
//! [`Event`]: event::Event
//! [`WindowEvent`]: event::WindowEvent
//! [`DeviceEvent`]: event::DeviceEvent
//! [`UserEvent`]: event::Event::UserEvent
//! [`LoopDestroyed`]: event::Event::LoopDestroyed
//! [`platform`]: platform
//! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle
//! [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "windows"))]
#![deny(rust_2018_idioms)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all)]
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![allow(clippy::missing_safety_doc)]
#[allow(unused_imports)]
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[cfg(target_os = "windows")]
extern crate log;
#[cfg(feature = "serde")]
#[macro_use]
extern crate winapi;
#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate serde;
#[macro_use]
extern crate objc;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate core_foundation;
#[cfg(target_os = "macos")]
extern crate core_graphics;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
extern crate x11_dl;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
extern crate percent_encoding;
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
extern crate bitflags;
pub mod dpi;
#[macro_use]
extern crate wayland_client;
pub mod error;
pub mod event;
pub mod event_loop;
mod icon;
pub mod monitor;
mod platform_impl;
pub mod window;
pub use events::*;
pub use window::{AvailableMonitorsIter, MonitorId};
mod platform;
mod events;
mod window;
pub mod os;
/// Represents a window.
///
/// # Example
///
/// ```no_run
/// use winit::{Event, EventsLoop, Window, WindowEvent, ControlFlow};
///
/// let mut events_loop = EventsLoop::new();
/// let window = Window::new(&events_loop).unwrap();
///
/// events_loop.run_forever(|event| {
/// match event {
/// Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
/// ControlFlow::Break
/// },
/// _ => ControlFlow::Continue,
/// }
/// });
/// ```
pub struct Window {
window: platform::Window,
}
/// Identifier of a window. Unique for each window.
///
/// Can be obtained with `window.id()`.
///
/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you
/// can then compare to the ids of your windows.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(platform::WindowId);
/// Identifier of an input device.
///
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or
/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(platform::DeviceId);
/// Provides a way to retreive events from the system and from the windows that were registered to
/// the events loop.
///
/// An `EventsLoop` can be seen more or less as a "context". Calling `EventsLoop::new()`
/// initializes everything that will be required to create windows. For example on Linux creating
/// an events loop opens a connection to the X or Wayland server.
///
/// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs.
///
/// Note that the `EventsLoop` cannot be shared accross threads (due to platform-dependant logic
/// forbiding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the
/// `Window` created from this `EventsLoop` _can_ be sent to an other thread, and the
/// `EventsLoopProxy` allows you to wakeup an `EventsLoop` from an other thread.
pub struct EventsLoop {
events_loop: platform::EventsLoop,
_marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
/// Returned by the user callback given to the `EventsLoop::run_forever` method.
///
/// Indicates whether the `run_forever` method should continue or complete.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControlFlow {
/// Continue looping and waiting for events.
Continue,
/// Break from the event loop.
Break,
}
impl EventsLoop {
/// Builds a new events loop.
///
/// Usage will result in display backend initialisation, this can be controlled on linux
/// using an environment variable `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`.
/// If it is not set, winit will try to connect to a wayland connection, and if it fails will
/// fallback on x11. If this variable is set with any other value, winit will panic.
pub fn new() -> EventsLoop {
EventsLoop {
events_loop: platform::EventsLoop::new(),
_marker: ::std::marker::PhantomData,
}
}
/// Returns the list of all the monitors available on the system.
///
// Note: should be replaced with `-> impl Iterator` once stable.
#[inline]
pub fn get_available_monitors(&self) -> AvailableMonitorsIter {
let data = self.events_loop.get_available_monitors();
AvailableMonitorsIter{ data: data.into_iter() }
}
/// Returns the primary monitor of the system.
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId { inner: self.events_loop.get_primary_monitor() }
}
/// Fetches all the events that are pending, calls the callback function for each of them,
/// and returns.
#[inline]
pub fn poll_events<F>(&mut self, callback: F)
where F: FnMut(Event)
{
self.events_loop.poll_events(callback)
}
/// Calls `callback` every time an event is received. If no event is available, sleeps the
/// current thread and waits for an event. If the callback returns `ControlFlow::Break` then
/// `run_forever` will immediately return.
#[inline]
pub fn run_forever<F>(&mut self, callback: F)
where F: FnMut(Event) -> ControlFlow
{
self.events_loop.run_forever(callback)
}
/// Creates an `EventsLoopProxy` that can be used to wake up the `EventsLoop` from another
/// thread.
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
events_loop_proxy: self.events_loop.create_proxy(),
}
}
}
/// Used to wake up the `EventsLoop` from another thread.
#[derive(Clone)]
pub struct EventsLoopProxy {
events_loop_proxy: platform::EventsLoopProxy,
}
impl EventsLoopProxy {
/// Wake up the `EventsLoop` from which this proxy was created.
///
/// This causes the `EventsLoop` to emit an `Awakened` event.
///
/// Returns an `Err` if the associated `EventsLoop` no longer exists.
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
self.events_loop_proxy.wakeup()
}
}
/// The error that is returned when an `EventsLoopProxy` attempts to wake up an `EventsLoop` that
/// no longer exists.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EventsLoopClosed;
impl std::fmt::Display for EventsLoopClosed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", std::error::Error::description(self))
}
}
impl std::error::Error for EventsLoopClosed {
fn description(&self) -> &str {
"Tried to wake up a closed `EventsLoop`"
}
}
/// Object that allows you to build windows.
#[derive(Clone)]
pub struct WindowBuilder {
/// The attributes to use to create the window.
pub window: WindowAttributes,
// Platform-specific configuration. Private.
platform_specific: platform::PlatformSpecificWindowBuilderAttributes,
}
/// Error that can happen while creating a window or a headless renderer.
#[derive(Debug, Clone)]
pub enum CreationError {
OsError(String),
/// TODO: remove this error
NotSupported,
}
impl CreationError {
fn to_string(&self) -> &str {
match *self {
CreationError::OsError(ref text) => &text,
CreationError::NotSupported => "Some of the requested attributes are not supported",
}
}
}
impl std::fmt::Display for CreationError {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
formatter.write_str(self.to_string())
}
}
impl std::error::Error for CreationError {
fn description(&self) -> &str {
self.to_string()
}
}
/// Describes the appearance of the mouse cursor.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum MouseCursor {
/// The platform-dependent default cursor.
Default,
/// A simple crosshair.
Crosshair,
/// A hand (often used to indicate links in web browsers).
Hand,
/// Self explanatory.
Arrow,
/// Indicates something is to be moved.
Move,
/// Indicates text that may be selected or edited.
Text,
/// Program busy indicator.
Wait,
/// Help indicator (often rendered as a "?")
Help,
/// Progress indicator. Shows that processing is being done. But in contrast
/// with "Wait" the user may still interact with the program. Often rendered
/// as a spinning beach ball, or an arrow with a watch or hourglass.
Progress,
/// Cursor showing that something cannot be done.
NotAllowed,
ContextMenu,
NoneCursor,
Cell,
VerticalText,
Alias,
Copy,
NoDrop,
Grab,
Grabbing,
AllScroll,
ZoomIn,
ZoomOut,
/// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
/// is used when the movement starts from the south-east corner of the box.
EResize,
NResize,
NeResize,
NwResize,
SResize,
SeResize,
SwResize,
WResize,
EwResize,
NsResize,
NeswResize,
NwseResize,
ColResize,
RowResize,
}
/// Describes how winit handles the cursor.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum CursorState {
/// Normal cursor behavior.
Normal,
/// The cursor will be invisible when over the window.
Hide,
/// Grabs the mouse cursor. The cursor's motion will be confined to this
/// window and the window has exclusive access to further events regarding
/// the cursor.
///
/// This is useful for first-person cameras for example.
Grab,
}
/// Attributes to use when creating a window.
#[derive(Clone)]
pub struct WindowAttributes {
/// The dimensions of the window. If this is `None`, some platform-specific dimensions will be
/// used.
///
/// The default is `None`.
pub dimensions: Option<(u32, u32)>,
/// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved).
///
/// The default is `None`.
pub min_dimensions: Option<(u32, u32)>,
/// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform.
///
/// The default is `None`.
pub max_dimensions: Option<(u32, u32)>,
/// Whether the window should be set as fullscreen upon creation.
///
/// The default is `None`.
pub fullscreen: Option<MonitorId>,
/// The title of the window in the title bar.
///
/// The default is `"winit window"`.
pub title: String,
/// Whether the window should be maximized upon creation.
///
/// The default is `false`.
pub maximized: bool,
/// Whether the window should be immediately visible upon creation.
///
/// The default is `true`.
pub visible: bool,
/// Whether the the window should be transparent. If this is true, writing colors
/// with alpha values different than `1.0` will produce a transparent window.
///
/// The default is `false`.
pub transparent: bool,
/// Whether the window should have borders and bars.
///
/// The default is `true`.
pub decorations: bool,
/// [iOS only] Enable multitouch,
/// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled)
pub multitouch: bool,
}
impl Default for WindowAttributes {
#[inline]
fn default() -> WindowAttributes {
WindowAttributes {
dimensions: None,
min_dimensions: None,
max_dimensions: None,
title: "winit window".to_owned(),
maximized: false,
fullscreen: None,
visible: true,
transparent: false,
decorations: true,
multitouch: false,
}
}
}
pub mod platform;

181
src/monitor.rs Normal file
View File

@@ -0,0 +1,181 @@
//! Types useful for interacting with a user's monitors.
//!
//! If you want to get basic information about a monitor, you can use the
//! [`MonitorHandle`] type. This is retrieved from one of the following
//! methods, which return an iterator of [`MonitorHandle`]:
//! - [`EventLoopWindowTarget::available_monitors`](crate::event_loop::EventLoopWindowTarget::available_monitors).
//! - [`Window::available_monitors`](crate::window::Window::available_monitors).
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
platform_impl,
};
/// Describes a fullscreen video mode of a monitor.
///
/// Can be acquired with [`MonitorHandle::video_modes`].
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct VideoMode {
pub(crate) video_mode: platform_impl::VideoMode,
}
impl std::fmt::Debug for VideoMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.video_mode.fmt(f)
}
}
impl PartialOrd for VideoMode {
fn partial_cmp(&self, other: &VideoMode) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for VideoMode {
fn cmp(&self, other: &VideoMode) -> std::cmp::Ordering {
// TODO: we can impl `Ord` for `PhysicalSize` once we switch from `f32`
// to `u32` there
let size: (u32, u32) = self.size().into();
let other_size: (u32, u32) = other.size().into();
self.monitor().cmp(&other.monitor()).then(
size.cmp(&other_size)
.then(
self.refresh_rate_millihertz()
.cmp(&other.refresh_rate_millihertz())
.then(self.bit_depth().cmp(&other.bit_depth())),
)
.reverse(),
)
}
}
impl VideoMode {
/// Returns the resolution of this video mode.
#[inline]
pub fn size(&self) -> PhysicalSize<u32> {
self.video_mode.size()
}
/// Returns the bit depth of this video mode, as in how many bits you have
/// available per color. This is generally 24 bits or 32 bits on modern
/// systems, depending on whether the alpha channel is counted or not.
///
/// ## Platform-specific
///
/// - **Wayland / Orbital:** Always returns 32.
/// - **iOS:** Always returns 32.
#[inline]
pub fn bit_depth(&self) -> u16 {
self.video_mode.bit_depth()
}
/// Returns the refresh rate of this video mode in mHz.
#[inline]
pub fn refresh_rate_millihertz(&self) -> u32 {
self.video_mode.refresh_rate_millihertz()
}
/// Returns the monitor that this video mode is valid for. Each monitor has
/// a separate set of valid video modes.
#[inline]
pub fn monitor(&self) -> MonitorHandle {
MonitorHandle {
inner: self.video_mode.monitor(),
}
}
}
impl std::fmt::Display for VideoMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}x{} @ {} mHz ({} bpp)",
self.size().width,
self.size().height,
self.refresh_rate_millihertz(),
self.bit_depth()
)
}
}
/// Handle to a monitor.
///
/// Allows you to retrieve information about a given monitor and can be used in [`Window`] creation.
///
/// [`Window`]: crate::window::Window
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct MonitorHandle {
pub(crate) inner: platform_impl::MonitorHandle,
}
impl MonitorHandle {
/// Returns a human-readable name of the monitor.
///
/// Returns `None` if the monitor doesn't exist anymore.
///
/// ## Platform-specific
///
/// - **Web:** Always returns None
#[inline]
pub fn name(&self) -> Option<String> {
self.inner.name()
}
/// Returns the monitor's resolution.
///
/// ## Platform-specific
///
/// - **Web:** Always returns (0,0)
#[inline]
pub fn size(&self) -> PhysicalSize<u32> {
self.inner.size()
}
/// Returns the top-left corner position of the monitor relative to the larger full
/// screen area.
///
/// ## Platform-specific
///
/// - **Web:** Always returns (0,0)
#[inline]
pub fn position(&self) -> PhysicalPosition<i32> {
self.inner.position()
}
/// The monitor refresh rate used by the system.
///
/// Return `Some` if succeed, or `None` if failed, which usually happens when the monitor
/// the window is on is removed.
///
/// When using exclusive fullscreen, the refresh rate of the [`VideoMode`] that was used to
/// enter fullscreen should be used instead.
#[inline]
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
self.inner.refresh_rate_millihertz()
}
/// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
///
/// See the [`dpi`](crate::dpi) module for more information.
///
/// ## Platform-specific
///
/// - **X11:** Can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
/// - **Android:** Always returns 1.0.
/// - **Web:** Always returns 1.0
#[inline]
pub fn scale_factor(&self) -> f64 {
self.inner.scale_factor()
}
/// Returns all fullscreen video modes supported by this monitor.
///
/// ## Platform-specific
///
/// - **Web:** Always returns an empty iterator
#[inline]
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
self.inner
.video_modes()
.map(|video_mode| VideoMode { video_mode })
}
}

View File

@@ -1,38 +0,0 @@
#![cfg(any(target_os = "android"))]
use std::os::raw::c_void;
use EventsLoop;
use Window;
use WindowBuilder;
/// Additional methods on `EventsLoop` that are specific to Android.
pub trait EventsLoopExt {
/// Makes it possible for glutin to register a callback when a suspend event happens on Android
fn set_suspend_callback(&self, cb: Option<Box<Fn(bool) -> ()>>);
}
impl EventsLoopExt for EventsLoop {
fn set_suspend_callback(&self, cb: Option<Box<Fn(bool) -> ()>>) {
self.events_loop.set_suspend_callback(cb);
}
}
/// Additional methods on `Window` that are specific to Android.
pub trait WindowExt {
fn get_native_window(&self) -> *const c_void;
}
impl WindowExt for Window {
#[inline]
fn get_native_window(&self) -> *const c_void {
self.window.get_native_window()
}
}
/// Additional methods on `WindowBuilder` that are specific to Android.
pub trait WindowBuilderExt {
}
impl WindowBuilderExt for WindowBuilder {
}

View File

@@ -1,151 +0,0 @@
#![cfg(target_os = "macos")]
use std::convert::From;
use std::os::raw::c_void;
use cocoa::appkit::NSApplicationActivationPolicy;
use {MonitorId, Window, WindowBuilder};
/// Additional methods on `Window` that are specific to MacOS.
pub trait WindowExt {
/// Returns a pointer to the cocoa `NSWindow` that is used by this window.
///
/// The pointer will become invalid when the `Window` is destroyed.
fn get_nswindow(&self) -> *mut c_void;
/// Returns a pointer to the cocoa `NSView` that is used by this window.
///
/// The pointer will become invalid when the `Window` is destroyed.
fn get_nsview(&self) -> *mut c_void;
}
impl WindowExt for Window {
#[inline]
fn get_nswindow(&self) -> *mut c_void {
self.window.get_nswindow()
}
#[inline]
fn get_nsview(&self) -> *mut c_void {
self.window.get_nsview()
}
}
/// Corresponds to `NSApplicationActivationPolicy`.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ActivationPolicy {
/// Corresponds to `NSApplicationActivationPolicyRegular`.
Regular,
/// Corresponds to `NSApplicationActivationPolicyAccessory`.
Accessory,
/// Corresponds to `NSApplicationActivationPolicyProhibited`.
Prohibited,
}
impl Default for ActivationPolicy {
fn default() -> Self {
ActivationPolicy::Regular
}
}
impl From<ActivationPolicy> for NSApplicationActivationPolicy {
fn from(activation_policy: ActivationPolicy) -> Self {
match activation_policy {
ActivationPolicy::Regular =>
NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
ActivationPolicy::Accessory =>
NSApplicationActivationPolicy::NSApplicationActivationPolicyAccessory,
ActivationPolicy::Prohibited =>
NSApplicationActivationPolicy::NSApplicationActivationPolicyProhibited,
}
}
}
/// Additional methods on `WindowBuilder` that are specific to MacOS.
///
/// **Note:** Properties dealing with the titlebar will be overwritten by the `with_decorations` method
/// on the base `WindowBuilder`:
///
/// - `with_titlebar_transparent`
/// - `with_title_hidden`
/// - `with_titlebar_hidden`
/// - `with_titlebar_buttons_hidden`
/// - `with_fullsize_content_view`
pub trait WindowBuilderExt {
fn with_activation_policy(self, activation_policy: ActivationPolicy) -> WindowBuilder;
fn with_movable_by_window_background(self, movable_by_window_background: bool) -> WindowBuilder;
fn with_titlebar_transparent(self, titlebar_transparent: bool) -> WindowBuilder;
fn with_title_hidden(self, title_hidden: bool) -> WindowBuilder;
fn with_titlebar_hidden(self, titlebar_hidden: bool) -> WindowBuilder;
fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> WindowBuilder;
fn with_fullsize_content_view(self, fullsize_content_view: bool) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
/// Sets the activation policy for the window being built
#[inline]
fn with_activation_policy(mut self, activation_policy: ActivationPolicy) -> WindowBuilder {
self.platform_specific.activation_policy = activation_policy;
self
}
/// Enables click-and-drag behavior for the entire window, not just the titlebar
#[inline]
fn with_movable_by_window_background(mut self, movable_by_window_background: bool) -> WindowBuilder {
self.platform_specific.movable_by_window_background = movable_by_window_background;
self
}
/// Makes the titlebar transparent and allows the content to appear behind it
#[inline]
fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> WindowBuilder {
self.platform_specific.titlebar_transparent = titlebar_transparent;
self
}
/// Hides the window titlebar
#[inline]
fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> WindowBuilder {
self.platform_specific.titlebar_hidden = titlebar_hidden;
self
}
/// Hides the window titlebar buttons
#[inline]
fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> WindowBuilder {
self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
self
}
/// Hides the window title
#[inline]
fn with_title_hidden(mut self, title_hidden: bool) -> WindowBuilder {
self.platform_specific.title_hidden = title_hidden;
self
}
/// Makes the window content appear behind the titlebar
#[inline]
fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> WindowBuilder {
self.platform_specific.fullsize_content_view = fullsize_content_view;
self
}
}
/// Additional methods on `MonitorId` that are specific to MacOS.
pub trait MonitorIdExt {
/// Returns the identifier of the monitor for Cocoa.
fn native_id(&self) -> u32;
/// Returns a pointer to the NSScreen representing this monitor.
fn get_nsscreen(&self) -> Option<*mut c_void>;
}
impl MonitorIdExt for MonitorId {
#[inline]
fn native_id(&self) -> u32 {
self.inner.get_native_identifier()
}
fn get_nsscreen(&self) -> Option<*mut c_void> {
self.inner.get_nsscreen().map(|s| s as *mut c_void)
}
}

View File

@@ -1,15 +0,0 @@
//! Contains traits with platform-specific methods in them.
//!
//! Contains the follow modules:
//!
//! - `android`
//! - `macos`
//! - `unix`
//! - `windows`
//!
//! However only the module corresponding to the platform you're compiling to will be available.
//!
pub mod android;
pub mod macos;
pub mod unix;
pub mod windows;

View File

@@ -1,231 +0,0 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
use std::os::raw;
use std::sync::Arc;
use std::ptr;
use EventsLoop;
use MonitorId;
use Window;
use platform::EventsLoop as LinuxEventsLoop;
use platform::Window as LinuxWindow;
use WindowBuilder;
use platform::x11::XConnection;
use platform::x11::ffi::XVisualInfo;
// TODO: stupid hack so that glutin can do its work
#[doc(hidden)]
pub use platform::x11;
pub use platform::XNotSupported;
/// Additional methods on `EventsLoop` that are specific to Linux.
pub trait EventsLoopExt {
/// Builds a new `EventsLoop` that is forced to use X11.
fn new_x11() -> Result<Self, XNotSupported>
where Self: Sized;
/// Builds a new `EventsLoop` that is forced to use Wayland.
fn new_wayland() -> Self
where Self: Sized;
/// True if the `EventsLoop` uses Wayland.
fn is_wayland(&self) -> bool;
/// True if the `EventsLoop` uses X11.
fn is_x11(&self) -> bool;
#[doc(hidden)]
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>>;
}
impl EventsLoopExt for EventsLoop {
#[inline]
fn new_x11() -> Result<Self, XNotSupported> {
LinuxEventsLoop::new_x11().map(|ev|
EventsLoop {
events_loop: ev,
_marker: ::std::marker::PhantomData,
}
)
}
#[inline]
fn new_wayland() -> Self {
EventsLoop {
events_loop: match LinuxEventsLoop::new_wayland() {
Ok(e) => e,
Err(_) => panic!() // TODO: propagate
},
_marker: ::std::marker::PhantomData,
}
}
#[inline]
fn is_wayland(&self) -> bool {
self.events_loop.is_wayland()
}
#[inline]
fn is_x11(&self) -> bool {
!self.events_loop.is_wayland()
}
#[inline]
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>> {
self.events_loop.x_connection().cloned()
}
}
/// Additional methods on `Window` that are specific to Unix.
pub trait WindowExt {
/// Returns the ID of the `Window` xlib object that is used by this window.
///
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
fn get_xlib_window(&self) -> Option<raw::c_ulong>;
/// Returns a pointer to the `Display` object of xlib that is used by this window.
///
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
///
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_xlib_display(&self) -> Option<*mut raw::c_void>;
fn get_xlib_screen_id(&self) -> Option<raw::c_int>;
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>>;
fn send_xim_spot(&self, x: i16, y: i16);
/// This function returns the underlying `xcb_connection_t` of an xlib `Display`.
///
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
///
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_xcb_connection(&self) -> Option<*mut raw::c_void>;
/// Returns a pointer to the `wl_surface` object of wayland that is used by this window.
///
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_wayland_surface(&self) -> Option<*mut raw::c_void>;
/// Returns a pointer to the `wl_display` object of wayland that is used by this window.
///
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_wayland_display(&self) -> Option<*mut raw::c_void>;
/// Check if the window is ready for drawing
///
/// It is a remnant of a previous implementation detail for the
/// wayland backend, and is no longer relevant.
///
/// Always return true.
#[deprecated]
fn is_ready(&self) -> bool;
}
impl WindowExt for Window {
#[inline]
fn get_xlib_window(&self) -> Option<raw::c_ulong> {
match self.window {
LinuxWindow::X(ref w) => Some(w.get_xlib_window()),
_ => None
}
}
#[inline]
fn get_xlib_display(&self) -> Option<*mut raw::c_void> {
match self.window {
LinuxWindow::X(ref w) => Some(w.get_xlib_display()),
_ => None
}
}
fn get_xlib_screen_id(&self) -> Option<raw::c_int> {
match self.window {
LinuxWindow::X(ref w) => Some(w.get_xlib_screen_id()),
_ => None
}
}
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>> {
match self.window {
LinuxWindow::X(ref w) => Some(w.get_xlib_xconnection()),
_ => None
}
}
fn get_xcb_connection(&self) -> Option<*mut raw::c_void> {
match self.window {
LinuxWindow::X(ref w) => Some(w.get_xcb_connection()),
_ => None
}
}
fn send_xim_spot(&self, x: i16, y: i16) {
if let LinuxWindow::X(ref w) = self.window {
w.send_xim_spot(x, y);
}
}
#[inline]
fn get_wayland_surface(&self) -> Option<*mut raw::c_void> {
use wayland_client::Proxy;
match self.window {
LinuxWindow::Wayland(ref w) => Some(w.get_surface().ptr() as *mut _),
_ => None
}
}
#[inline]
fn get_wayland_display(&self) -> Option<*mut raw::c_void> {
use wayland_client::Proxy;
match self.window {
LinuxWindow::Wayland(ref w) => Some(w.get_display().ptr() as *mut _),
_ => None
}
}
#[inline]
fn is_ready(&self) -> bool {
true
}
}
/// Additional methods on `WindowBuilder` that are specific to Unix.
pub trait WindowBuilderExt {
fn with_x11_visual<T>(self, visual_infos: *const T) -> WindowBuilder;
fn with_x11_screen(self, screen_id: i32) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
#[inline]
fn with_x11_visual<T>(mut self, visual_infos: *const T) -> WindowBuilder {
self.platform_specific.visual_infos = Some(
unsafe { ptr::read(visual_infos as *const XVisualInfo) }
);
self
}
#[inline]
fn with_x11_screen(mut self, screen_id: i32) -> WindowBuilder {
self.platform_specific.screen_id = Some(screen_id);
self
}
}
/// Additional methods on `MonitorId` that are specific to Linux.
pub trait MonitorIdExt {
/// Returns the inner identifier of the monitor.
fn native_id(&self) -> u32;
}
impl MonitorIdExt for MonitorId {
#[inline]
fn native_id(&self) -> u32 {
self.inner.get_native_identifier()
}
}

View File

@@ -1,58 +0,0 @@
#![cfg(target_os = "windows")]
use std::os::raw::c_void;
use libc;
use MonitorId;
use Window;
use WindowBuilder;
use winapi::shared::windef::HWND;
/// Additional methods on `Window` that are specific to Windows.
pub trait WindowExt {
/// Returns the native handle that is used by this window.
///
/// The pointer will become invalid when the native window was destroyed.
fn get_hwnd(&self) -> *mut libc::c_void;
}
impl WindowExt for Window {
#[inline]
fn get_hwnd(&self) -> *mut libc::c_void {
self.window.hwnd() as *mut _
}
}
/// Additional methods on `WindowBuilder` that are specific to Windows.
pub trait WindowBuilderExt {
fn with_parent_window(self, parent: HWND) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
/// Sets a parent to the window to be created.
#[inline]
fn with_parent_window(mut self, parent: HWND) -> WindowBuilder {
self.platform_specific.parent = Some(parent);
self
}
}
/// Additional methods on `MonitorId` that are specific to Windows.
pub trait MonitorIdExt {
/// Returns the name of the monitor adapter specific to the Win32 API.
fn native_id(&self) -> String;
/// Returns the handle of the monitor - `HMONITOR`.
fn hmonitor(&self) -> *mut c_void;
}
impl MonitorIdExt for MonitorId {
#[inline]
fn native_id(&self) -> String {
self.inner.get_native_identifier()
}
#[inline]
fn hmonitor(&self) -> *mut c_void {
self.inner.get_hmonitor() as *mut _
}
}

78
src/platform/android.rs Normal file
View File

@@ -0,0 +1,78 @@
use crate::{
event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget},
window::{Window, WindowBuilder},
};
use android_activity::{AndroidApp, ConfigurationRef, Rect};
/// Additional methods on [`EventLoop`] that are specific to Android.
pub trait EventLoopExtAndroid {}
impl<T> EventLoopExtAndroid for EventLoop<T> {}
/// Additional methods on [`EventLoopWindowTarget`] that are specific to Android.
pub trait EventLoopWindowTargetExtAndroid {}
/// Additional methods on [`Window`] that are specific to Android.
pub trait WindowExtAndroid {
fn content_rect(&self) -> Rect;
fn config(&self) -> ConfigurationRef;
}
impl WindowExtAndroid for Window {
fn content_rect(&self) -> Rect {
self.window.content_rect()
}
fn config(&self) -> ConfigurationRef {
self.window.config()
}
}
impl<T> EventLoopWindowTargetExtAndroid for EventLoopWindowTarget<T> {}
/// Additional methods on [`WindowBuilder`] that are specific to Android.
pub trait WindowBuilderExtAndroid {}
impl WindowBuilderExtAndroid for WindowBuilder {}
pub trait EventLoopBuilderExtAndroid {
/// Associates the `AndroidApp` that was passed to `android_main()` with the event loop
///
/// This must be called on Android since the `AndroidApp` is not global state.
fn with_android_app(&mut self, app: AndroidApp) -> &mut Self;
}
impl<T> EventLoopBuilderExtAndroid for EventLoopBuilder<T> {
fn with_android_app(&mut self, app: AndroidApp) -> &mut Self {
self.platform_specific.android_app = Some(app);
self
}
}
/// Re-export of the `android_activity` API
///
/// Winit re-exports the `android_activity` API for convenience so that most
/// applications can rely on the Winit crate to resolve the required version of
/// `android_activity` and avoid any chance of a conflict between Winit and the
/// application crate.
///
/// Unlike most libraries there can only be a single implementation
/// of the `android_activity` glue crate linked with an application because
/// it is responsible for the application's `android_main()` entry point.
///
/// Since Winit depends on a specific version of `android_activity` the simplest
/// way to avoid creating a conflict is for applications to avoid explicitly
/// depending on the `android_activity` crate, and instead consume the API that
/// is re-exported by Winit.
///
/// For compatibility applications should then import the `AndroidApp` type for
/// their `android_main(app: AndroidApp)` function like:
/// ```rust
/// #[cfg(target_os="android")]
/// use winit::platform::android::activity::AndroidApp;
/// ```
pub mod activity {
pub use android_activity::*;
}

View File

@@ -1,108 +0,0 @@
#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
use libc;
use std::os::raw;
#[link(name = "android")]
#[link(name = "EGL")]
#[link(name = "GLESv2")]
extern {}
/**
* asset_manager.h
*/
pub type AAssetManager = raw::c_void;
/**
* native_window.h
*/
pub type ANativeWindow = raw::c_void;
extern {
pub fn ANativeWindow_getHeight(window: *const ANativeWindow) -> libc::int32_t;
pub fn ANativeWindow_getWidth(window: *const ANativeWindow) -> libc::int32_t;
}
/**
* native_activity.h
*/
pub type JavaVM = ();
pub type JNIEnv = ();
pub type jobject = *const libc::c_void;
pub type AInputQueue = (); // FIXME: wrong
pub type ARect = (); // FIXME: wrong
#[repr(C)]
pub struct ANativeActivity {
pub callbacks: *mut ANativeActivityCallbacks,
pub vm: *mut JavaVM,
pub env: *mut JNIEnv,
pub clazz: jobject,
pub internalDataPath: *const libc::c_char,
pub externalDataPath: *const libc::c_char,
pub sdkVersion: libc::int32_t,
pub instance: *mut libc::c_void,
pub assetManager: *mut AAssetManager,
pub obbPath: *const libc::c_char,
}
#[repr(C)]
pub struct ANativeActivityCallbacks {
pub onStart: extern fn(*mut ANativeActivity),
pub onResume: extern fn(*mut ANativeActivity),
pub onSaveInstanceState: extern fn(*mut ANativeActivity, *mut libc::size_t),
pub onPause: extern fn(*mut ANativeActivity),
pub onStop: extern fn(*mut ANativeActivity),
pub onDestroy: extern fn(*mut ANativeActivity),
pub onWindowFocusChanged: extern fn(*mut ANativeActivity, libc::c_int),
pub onNativeWindowCreated: extern fn(*mut ANativeActivity, *const ANativeWindow),
pub onNativeWindowResized: extern fn(*mut ANativeActivity, *const ANativeWindow),
pub onNativeWindowRedrawNeeded: extern fn(*mut ANativeActivity, *const ANativeWindow),
pub onNativeWindowDestroyed: extern fn(*mut ANativeActivity, *const ANativeWindow),
pub onInputQueueCreated: extern fn(*mut ANativeActivity, *mut AInputQueue),
pub onInputQueueDestroyed: extern fn(*mut ANativeActivity, *mut AInputQueue),
pub onContentRectChanged: extern fn(*mut ANativeActivity, *const ARect),
pub onConfigurationChanged: extern fn(*mut ANativeActivity),
pub onLowMemory: extern fn(*mut ANativeActivity),
}
/**
* looper.h
*/
pub type ALooper = ();
#[link(name = "android")]
extern {
pub fn ALooper_forThread() -> *const ALooper;
pub fn ALooper_acquire(looper: *const ALooper);
pub fn ALooper_release(looper: *const ALooper);
pub fn ALooper_prepare(opts: libc::c_int) -> *const ALooper;
pub fn ALooper_pollOnce(timeoutMillis: libc::c_int, outFd: *mut libc::c_int,
outEvents: *mut libc::c_int, outData: *mut *mut libc::c_void) -> libc::c_int;
pub fn ALooper_pollAll(timeoutMillis: libc::c_int, outFd: *mut libc::c_int,
outEvents: *mut libc::c_int, outData: *mut *mut libc::c_void) -> libc::c_int;
pub fn ALooper_wake(looper: *const ALooper);
pub fn ALooper_addFd(looper: *const ALooper, fd: libc::c_int, ident: libc::c_int,
events: libc::c_int, callback: ALooper_callbackFunc, data: *mut libc::c_void)
-> libc::c_int;
pub fn ALooper_removeFd(looper: *const ALooper, fd: libc::c_int) -> libc::c_int;
}
pub const ALOOPER_PREPARE_ALLOW_NON_CALLBACKS: libc::c_int = 1 << 0;
pub const ALOOPER_POLL_WAKE: libc::c_int = -1;
pub const ALOOPER_POLL_CALLBACK: libc::c_int = -2;
pub const ALOOPER_POLL_TIMEOUT: libc::c_int = -3;
pub const ALOOPER_POLL_ERROR: libc::c_int = -4;
pub const ALOOPER_EVENT_INPUT: libc::c_int = 1 << 0;
pub const ALOOPER_EVENT_OUTPUT: libc::c_int = 1 << 1;
pub const ALOOPER_EVENT_ERROR: libc::c_int = 1 << 2;
pub const ALOOPER_EVENT_HANGUP: libc::c_int = 1 << 3;
pub const ALOOPER_EVENT_INVALID: libc::c_int = 1 << 4;
pub type ALooper_callbackFunc = extern fn(libc::c_int, libc::c_int, *mut libc::c_void) -> libc::c_int;

View File

@@ -1,340 +0,0 @@
#![cfg(target_os = "android")]
extern crate android_glue;
use libc;
use std::sync::mpsc::{Receiver, channel};
use std::os::raw::c_void;
use {CreationError, Event, WindowEvent, MouseCursor};
use CreationError::OsError;
use WindowId as RootWindowId;
use events::{Touch, TouchPhase};
use window::MonitorId as RootMonitorId;
use std::collections::VecDeque;
use std::cell::RefCell;
use CursorState;
use WindowAttributes;
pub struct EventsLoop {
event_rx: Receiver<android_glue::Event>,
suspend_callback: RefCell<Option<Box<Fn(bool) -> ()>>>
}
#[derive(Clone)]
pub struct EventsLoopProxy;
impl EventsLoop {
pub fn new() -> EventsLoop {
let (tx, rx) = channel();
android_glue::add_sender(tx);
EventsLoop {
event_rx: rx,
suspend_callback: RefCell::new(None),
}
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
let mut rb = VecDeque::new();
rb.push_back(MonitorId);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event)
{
while let Ok(event) = self.event_rx.try_recv() {
let e = match event{
android_glue::Event::EventMotion(motion) => {
Some(Event::WindowEvent {
window_id: RootWindowId(WindowId),
event: WindowEvent::Touch(Touch {
phase: match motion.action {
android_glue::MotionAction::Down => TouchPhase::Started,
android_glue::MotionAction::Move => TouchPhase::Moved,
android_glue::MotionAction::Up => TouchPhase::Ended,
android_glue::MotionAction::Cancel => TouchPhase::Cancelled,
},
location: (motion.x as f64, motion.y as f64),
id: motion.pointer_id as u64,
device_id: DEVICE_ID,
}),
})
},
android_glue::Event::InitWindow => {
// The activity went to foreground.
if let Some(cb) = self.suspend_callback.borrow().as_ref() {
(*cb)(false);
}
Some(Event::Suspended(false))
},
android_glue::Event::TermWindow => {
// The activity went to background.
if let Some(cb) = self.suspend_callback.borrow().as_ref() {
(*cb)(true);
}
Some(Event::Suspended(true))
},
android_glue::Event::WindowResized |
android_glue::Event::ConfigChanged => {
// Activity Orientation changed or resized.
let native_window = unsafe { android_glue::get_native_window() };
if native_window.is_null() {
None
} else {
let w = unsafe { ffi::ANativeWindow_getWidth(native_window as *const _) } as u32;
let h = unsafe { ffi::ANativeWindow_getHeight(native_window as *const _) } as u32;
Some(Event::WindowEvent {
window_id: RootWindowId(WindowId),
event: WindowEvent::Resized(w, h),
})
}
},
android_glue::Event::WindowRedrawNeeded => {
// The activity needs to be redrawn.
Some(Event::WindowEvent {
window_id: RootWindowId(WindowId),
event: WindowEvent::Refresh,
})
}
android_glue::Event::Wake => {
Some(Event::Awakened)
}
_ => {
None
}
};
if let Some(event) = e {
callback(event);
}
};
}
pub fn set_suspend_callback(&self, cb: Option<Box<Fn(bool) -> ()>>) {
*self.suspend_callback.borrow_mut() = cb;
}
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(::Event) -> ::ControlFlow,
{
// Yeah that's a very bad implementation.
loop {
let mut control_flow = ::ControlFlow::Continue;
self.poll_events(|e| {
if let ::ControlFlow::Break = callback(e) {
control_flow = ::ControlFlow::Break;
}
});
if let ::ControlFlow::Break = control_flow {
break;
}
::std::thread::sleep(::std::time::Duration::from_millis(5));
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
android_glue::wake_event_loop();
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
pub struct Window {
native_window: *const c_void,
}
#[derive(Clone)]
pub struct MonitorId;
mod ffi;
impl MonitorId {
#[inline]
pub fn get_name(&self) -> Option<String> {
Some("Primary".to_string())
}
#[inline]
pub fn get_dimensions(&self) -> (u32, u32) {
unsafe {
let window = android_glue::get_native_window();
(ffi::ANativeWindow_getWidth(window) as u32, ffi::ANativeWindow_getHeight(window) as u32)
}
}
#[inline]
pub fn get_position(&self) -> (i32, i32) {
// Android assumes single screen
(0, 0)
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
1.0
}
}
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;
impl Window {
pub fn new(_: &EventsLoop, win_attribs: &WindowAttributes,
_: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError>
{
// not implemented
assert!(win_attribs.min_dimensions.is_none());
assert!(win_attribs.max_dimensions.is_none());
let native_window = unsafe { android_glue::get_native_window() };
if native_window.is_null() {
return Err(OsError(format!("Android's native window is null")));
}
android_glue::set_multitouch(win_attribs.multitouch);
Ok(Window {
native_window: native_window as *const _,
})
}
#[inline]
pub fn get_native_window(&self) -> *const c_void {
self.native_window
}
#[inline]
pub fn set_title(&self, _: &str) {
}
#[inline]
pub fn show(&self) {
}
#[inline]
pub fn hide(&self) {
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn set_position(&self, _x: i32, _y: i32) {
}
#[inline]
pub fn set_min_dimensions(&self, _dimensions: Option<(u32, u32)>) { }
#[inline]
pub fn set_max_dimensions(&self, _dimensions: Option<(u32, u32)>) { }
#[inline]
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
if self.native_window.is_null() {
None
} else {
Some((
unsafe { ffi::ANativeWindow_getWidth(self.native_window as *const _) } as u32,
unsafe { ffi::ANativeWindow_getHeight(self.native_window as *const _) } as u32
))
}
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.get_inner_size()
}
#[inline]
pub fn set_inner_size(&self, _x: u32, _y: u32) {
}
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
unimplemented!();
}
#[inline]
pub fn platform_window(&self) -> *mut libc::c_void {
unimplemented!()
}
#[inline]
pub fn set_cursor(&self, _: MouseCursor) {
}
#[inline]
pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> {
Ok(())
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
1.0
}
#[inline]
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
Ok(())
}
#[inline]
pub fn set_maximized(&self, _maximized: bool) {
// Android has single screen maximized apps so nothing to do
}
#[inline]
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
// Android has single screen maximized apps so nothing to do
}
#[inline]
pub fn set_decorations(&self, _decorations: bool) {
// N/A
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId{inner: MonitorId}
}
pub fn id(&self) -> WindowId {
WindowId
}
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);

View File

@@ -1,316 +0,0 @@
#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
use std::os::raw::{c_int, c_char, c_void, c_ulong, c_double, c_long, c_ushort};
#[cfg(test)]
use std::mem;
pub type EM_BOOL = c_int;
pub type EM_UTF8 = c_char;
pub type EMSCRIPTEN_RESULT = c_int;
pub const EM_TRUE: EM_BOOL = 1;
pub const EM_FALSE: EM_BOOL = 0;
// values for EMSCRIPTEN_RESULT
pub const EMSCRIPTEN_RESULT_SUCCESS: c_int = 0;
pub const EMSCRIPTEN_RESULT_DEFERRED: c_int = 1;
pub const EMSCRIPTEN_RESULT_NOT_SUPPORTED: c_int = -1;
pub const EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED: c_int = -2;
pub const EMSCRIPTEN_RESULT_INVALID_TARGET: c_int = -3;
pub const EMSCRIPTEN_RESULT_UNKNOWN_TARGET: c_int = -4;
pub const EMSCRIPTEN_RESULT_INVALID_PARAM: c_int = -5;
pub const EMSCRIPTEN_RESULT_FAILED: c_int = -6;
pub const EMSCRIPTEN_RESULT_NO_DATA: c_int = -7;
// values for EMSCRIPTEN EVENT
pub const EMSCRIPTEN_EVENT_KEYPRESS: c_int = 1;
pub const EMSCRIPTEN_EVENT_KEYDOWN: c_int = 2;
pub const EMSCRIPTEN_EVENT_KEYUP: c_int = 3;
pub const EMSCRIPTEN_EVENT_CLICK: c_int = 4;
pub const EMSCRIPTEN_EVENT_MOUSEDOWN: c_int = 5;
pub const EMSCRIPTEN_EVENT_MOUSEUP: c_int = 6;
pub const EMSCRIPTEN_EVENT_DBLCLICK: c_int = 7;
pub const EMSCRIPTEN_EVENT_MOUSEMOVE: c_int = 8;
pub const EMSCRIPTEN_EVENT_WHEEL: c_int = 9;
pub const EMSCRIPTEN_EVENT_RESIZE: c_int = 10;
pub const EMSCRIPTEN_EVENT_SCROLL: c_int = 11;
pub const EMSCRIPTEN_EVENT_BLUR: c_int = 12;
pub const EMSCRIPTEN_EVENT_FOCUS: c_int = 13;
pub const EMSCRIPTEN_EVENT_FOCUSIN: c_int = 14;
pub const EMSCRIPTEN_EVENT_FOCUSOUT: c_int = 15;
pub const EMSCRIPTEN_EVENT_DEVICEORIENTATION: c_int = 16;
pub const EMSCRIPTEN_EVENT_DEVICEMOTION: c_int = 17;
pub const EMSCRIPTEN_EVENT_ORIENTATIONCHANGE: c_int = 18;
pub const EMSCRIPTEN_EVENT_FULLSCREENCHANGE: c_int = 19;
pub const EMSCRIPTEN_EVENT_POINTERLOCKCHANGE: c_int = 20;
pub const EMSCRIPTEN_EVENT_VISIBILITYCHANGE: c_int = 21;
pub const EMSCRIPTEN_EVENT_TOUCHSTART: c_int = 22;
pub const EMSCRIPTEN_EVENT_TOUCHEND: c_int = 23;
pub const EMSCRIPTEN_EVENT_TOUCHMOVE: c_int = 24;
pub const EMSCRIPTEN_EVENT_TOUCHCANCEL: c_int = 25;
pub const EMSCRIPTEN_EVENT_GAMEPADCONNECTED: c_int = 26;
pub const EMSCRIPTEN_EVENT_GAMEPADDISCONNECTED: c_int = 27;
pub const EMSCRIPTEN_EVENT_BEFOREUNLOAD: c_int = 28;
pub const EMSCRIPTEN_EVENT_BATTERYCHARGINGCHANGE: c_int = 29;
pub const EMSCRIPTEN_EVENT_BATTERYLEVELCHANGE: c_int = 30;
pub const EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST: c_int = 31;
pub const EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED: c_int = 32;
pub const EMSCRIPTEN_EVENT_MOUSEENTER: c_int = 33;
pub const EMSCRIPTEN_EVENT_MOUSELEAVE: c_int = 34;
pub const EMSCRIPTEN_EVENT_MOUSEOVER: c_int = 35;
pub const EMSCRIPTEN_EVENT_MOUSEOUT: c_int = 36;
pub const EMSCRIPTEN_EVENT_CANVASRESIZED: c_int = 37;
pub const EMSCRIPTEN_EVENT_POINTERLOCKERROR: c_int = 38;
pub const EM_HTML5_SHORT_STRING_LEN_BYTES: usize = 32;
pub const DOM_KEY_LOCATION_STANDARD: c_ulong = 0x00;
pub const DOM_KEY_LOCATION_LEFT: c_ulong = 0x01;
pub const DOM_KEY_LOCATION_RIGHT: c_ulong = 0x02;
pub const DOM_KEY_LOCATION_NUMPAD: c_ulong = 0x03;
pub type em_callback_func = Option<unsafe extern "C" fn()>;
pub type em_key_callback_func = Option<unsafe extern "C" fn(
eventType: c_int,
keyEvent: *const EmscriptenKeyboardEvent,
userData: *mut c_void) -> EM_BOOL>;
pub type em_mouse_callback_func = Option<unsafe extern "C" fn(
eventType: c_int,
mouseEvent: *const EmscriptenMouseEvent,
userData: *mut c_void) -> EM_BOOL>;
pub type em_pointerlockchange_callback_func = Option<unsafe extern "C" fn(
eventType: c_int,
pointerlockChangeEvent: *const EmscriptenPointerlockChangeEvent,
userData: *mut c_void) -> EM_BOOL>;
pub type em_fullscreenchange_callback_func = Option<unsafe extern "C" fn(
eventType: c_int,
fullscreenChangeEvent: *const EmscriptenFullscreenChangeEvent,
userData: *mut c_void) -> EM_BOOL>;
pub type em_touch_callback_func = Option<unsafe extern "C" fn(
eventType: c_int,
touchEvent: *const EmscriptenTouchEvent,
userData: *mut c_void) -> EM_BOOL>;
#[repr(C)]
pub struct EmscriptenFullscreenChangeEvent {
pub isFullscreen: c_int,
pub fullscreenEnabled: c_int,
pub nodeName: [c_char; 128usize],
pub id: [c_char; 128usize],
pub elementWidth: c_int,
pub elementHeight: c_int,
pub screenWidth: c_int,
pub screenHeight: c_int,
}
#[test]
fn bindgen_test_layout_EmscriptenFullscreenChangeEvent() {
assert_eq!(mem::size_of::<EmscriptenFullscreenChangeEvent>(), 280usize);
assert_eq!(mem::align_of::<EmscriptenFullscreenChangeEvent>(), 4usize);
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct EmscriptenKeyboardEvent {
pub key: [c_char; 32usize],
pub code: [c_char; 32usize],
pub location: c_ulong,
pub ctrlKey: c_int,
pub shiftKey: c_int,
pub altKey: c_int,
pub metaKey: c_int,
pub repeat: c_int,
pub locale: [c_char; 32usize],
pub charValue: [c_char; 32usize],
pub charCode: c_ulong,
pub keyCode: c_ulong,
pub which: c_ulong,
}
#[test]
fn bindgen_test_layout_EmscriptenKeyboardEvent() {
assert_eq!(mem::size_of::<EmscriptenKeyboardEvent>(), 184usize);
assert_eq!(mem::align_of::<EmscriptenKeyboardEvent>(), 8usize);
}
impl Clone for EmscriptenKeyboardEvent {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmscriptenMouseEvent {
pub timestamp: f64,
pub screenX: c_long,
pub screenY: c_long,
pub clientX: c_long,
pub clientY: c_long,
pub ctrlKey: c_int,
pub shiftKey: c_int,
pub altKey: c_int,
pub metaKey: c_int,
pub button: c_ushort,
pub buttons: c_ushort,
pub movementX: c_long,
pub movementY: c_long,
pub targetX: c_long,
pub targetY: c_long,
pub canvasX: c_long,
pub canvasY: c_long,
pub padding: c_long,
}
#[test]
fn bindgen_test_layout_EmscriptenMouseEvent() {
assert_eq!(mem::size_of::<EmscriptenMouseEvent>(), 120usize);
assert_eq!(mem::align_of::<EmscriptenMouseEvent>(), 8usize);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmscriptenTouchPoint {
pub identifier: c_long,
pub screenX: c_long,
pub screenY: c_long,
pub clientX: c_long,
pub clientY: c_long,
pub pageX: c_long,
pub pageY: c_long,
pub isChanged: c_int,
pub onTarget: c_int,
pub targetX: c_long,
pub targetY: c_long,
pub canvasX: c_long,
pub canvasY: c_long,
}
#[test]
fn bindgen_test_layout_EmscriptenTouchPoint() {
assert_eq!(mem::size_of::<EmscriptenTouchPoint>(), 96usize);
assert_eq!(mem::align_of::<EmscriptenTouchPoint>(), 8usize);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmscriptenTouchEvent {
pub numTouches: c_int,
pub ctrlKey: c_int,
pub shiftKey: c_int,
pub altKey: c_int,
pub metaKey: c_int,
pub touches: [EmscriptenTouchPoint; 32usize],
}
#[test]
fn bindgen_test_layout_EmscriptenTouchEvent() {
assert_eq!(mem::size_of::<EmscriptenTouchEvent>(), 3096usize);
assert_eq!(mem::align_of::<EmscriptenTouchEvent>(), 8usize);
}
#[repr(C)]
pub struct EmscriptenPointerlockChangeEvent {
pub isActive: c_int,
pub nodeName: [c_char; 128usize],
pub id: [c_char; 128usize],
}
#[test]
fn bindgen_test_layout_EmscriptenPointerlockChangeEvent() {
assert_eq!(mem::size_of::<EmscriptenPointerlockChangeEvent>(), 260usize);
assert_eq!(mem::align_of::<EmscriptenPointerlockChangeEvent>(), 4usize);
}
extern "C" {
pub fn emscripten_set_canvas_size(
width: c_int, height: c_int)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_get_canvas_size(
width: *mut c_int, height: *mut c_int,
is_fullscreen: *mut c_int)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_element_css_size(
target: *const c_char, width: c_double,
height: c_double) -> EMSCRIPTEN_RESULT;
pub fn emscripten_get_element_css_size(
target: *const c_char, width: *mut c_double,
height: *mut c_double) -> EMSCRIPTEN_RESULT;
pub fn emscripten_request_pointerlock(
target: *const c_char, deferUntilInEventHandler: EM_BOOL)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_exit_pointerlock() -> EMSCRIPTEN_RESULT;
pub fn emscripten_request_fullscreen(
target: *const c_char, deferUntilInEventHandler: EM_BOOL)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_exit_fullscreen() -> EMSCRIPTEN_RESULT;
pub fn emscripten_set_keydown_callback(
target: *const c_char, userData: *mut c_void,
useCapture: EM_BOOL, callback: em_key_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_keyup_callback(
target: *const c_char, userData: *mut c_void,
useCapture: EM_BOOL, callback: em_key_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_mousemove_callback(
target: *const c_char, user_data: *mut c_void,
use_capture: EM_BOOL, callback: em_mouse_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_mousedown_callback(
target: *const c_char, user_data: *mut c_void,
use_capture: EM_BOOL, callback: em_mouse_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_mouseup_callback(
target: *const c_char, user_data: *mut c_void,
use_capture: EM_BOOL, callback: em_mouse_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_hide_mouse();
pub fn emscripten_get_device_pixel_ratio() -> f64;
pub fn emscripten_set_pointerlockchange_callback(
target: *const c_char, userData: *mut c_void, useCapture: EM_BOOL,
callback: em_pointerlockchange_callback_func) -> EMSCRIPTEN_RESULT;
pub fn emscripten_set_fullscreenchange_callback(
target: *const c_char, userData: *mut c_void, useCapture: EM_BOOL,
callback: em_fullscreenchange_callback_func) -> EMSCRIPTEN_RESULT;
pub fn emscripten_asm_const(code: *const c_char);
pub fn emscripten_set_main_loop(
func: em_callback_func, fps: c_int, simulate_infinite_loop: EM_BOOL);
pub fn emscripten_cancel_main_loop();
pub fn emscripten_set_touchstart_callback(
target: *const c_char, userData: *mut c_void,
useCapture: c_int, callback: em_touch_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_touchend_callback(
target: *const c_char, userData: *mut c_void,
useCapture: c_int, callback: em_touch_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_touchmove_callback(
target: *const c_char, userData: *mut c_void,
useCapture: c_int, callback: em_touch_callback_func)
-> EMSCRIPTEN_RESULT;
pub fn emscripten_set_touchcancel_callback(
target: *const c_char, userData: *mut c_void,
useCapture: c_int, callback: em_touch_callback_func)
-> EMSCRIPTEN_RESULT;
}

File diff suppressed because it is too large Load Diff

306
src/platform/ios.rs Normal file
View File

@@ -0,0 +1,306 @@
use std::os::raw::c_void;
use objc2::rc::Id;
use crate::{
event_loop::EventLoop,
monitor::{MonitorHandle, VideoMode},
window::{Window, WindowBuilder},
};
/// Additional methods on [`EventLoop`] that are specific to iOS.
pub trait EventLoopExtIOS {
/// Returns the [`Idiom`] (phone/tablet/tv/etc) for the current device.
fn idiom(&self) -> Idiom;
}
impl<T: 'static> EventLoopExtIOS for EventLoop<T> {
fn idiom(&self) -> Idiom {
self.event_loop.idiom()
}
}
/// Additional methods on [`Window`] that are specific to iOS.
pub trait WindowExtIOS {
/// Returns a pointer to the [`UIWindow`] that is used by this window.
///
/// The pointer will become invalid when the [`Window`] is destroyed.
///
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
fn ui_window(&self) -> *mut c_void;
/// Returns a pointer to the [`UIViewController`] that is used by this window.
///
/// The pointer will become invalid when the [`Window`] is destroyed.
///
/// [`UIViewController`]: https://developer.apple.com/documentation/uikit/uiviewcontroller?language=objc
fn ui_view_controller(&self) -> *mut c_void;
/// Returns a pointer to the [`UIView`] that is used by this window.
///
/// The pointer will become invalid when the [`Window`] is destroyed.
///
/// [`UIView`]: https://developer.apple.com/documentation/uikit/uiview?language=objc
fn ui_view(&self) -> *mut c_void;
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `scale_factor`.
///
/// The default value is device dependent, and it's recommended GLES or Metal applications set
/// this to [`MonitorHandle::scale_factor()`].
///
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
fn set_scale_factor(&self, scale_factor: f64);
/// Sets the valid orientations for the [`Window`].
///
/// The default value is [`ValidOrientations::LandscapeAndPortrait`].
///
/// This changes the value returned by
/// [`-[UIViewController supportedInterfaceOrientations]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621435-supportedinterfaceorientations?language=objc),
/// and then calls
/// [`-[UIViewController attemptRotationToDeviceOrientation]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621400-attemptrotationtodeviceorientati?language=objc).
fn set_valid_orientations(&self, valid_orientations: ValidOrientations);
/// Sets whether the [`Window`] prefers the home indicator hidden.
///
/// The default is to prefer showing the home indicator.
///
/// This changes the value returned by
/// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc),
/// and then calls
/// [`-[UIViewController setNeedsUpdateOfHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887509-setneedsupdateofhomeindicatoraut?language=objc).
///
/// This only has an effect on iOS 11.0+.
fn set_prefers_home_indicator_hidden(&self, hidden: bool);
/// Sets the screen edges for which the system gestures will take a lower priority than the
/// application's touch handling.
///
/// This changes the value returned by
/// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc),
/// and then calls
/// [`-[UIViewController setNeedsUpdateOfScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887507-setneedsupdateofscreenedgesdefer?language=objc).
///
/// This only has an effect on iOS 11.0+.
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge);
/// Sets whether the [`Window`] prefers the status bar hidden.
///
/// The default is to prefer showing the status bar.
///
/// This changes the value returned by
/// [`-[UIViewController prefersStatusBarHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc),
/// and then calls
/// [`-[UIViewController setNeedsStatusBarAppearanceUpdate]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621354-setneedsstatusbarappearanceupdat?language=objc).
fn set_prefers_status_bar_hidden(&self, hidden: bool);
}
impl WindowExtIOS for Window {
#[inline]
fn ui_window(&self) -> *mut c_void {
self.window.ui_window()
}
#[inline]
fn ui_view_controller(&self) -> *mut c_void {
self.window.ui_view_controller()
}
#[inline]
fn ui_view(&self) -> *mut c_void {
self.window.ui_view()
}
#[inline]
fn set_scale_factor(&self, scale_factor: f64) {
self.window.set_scale_factor(scale_factor)
}
#[inline]
fn set_valid_orientations(&self, valid_orientations: ValidOrientations) {
self.window.set_valid_orientations(valid_orientations)
}
#[inline]
fn set_prefers_home_indicator_hidden(&self, hidden: bool) {
self.window.set_prefers_home_indicator_hidden(hidden)
}
#[inline]
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge) {
self.window
.set_preferred_screen_edges_deferring_system_gestures(edges)
}
#[inline]
fn set_prefers_status_bar_hidden(&self, hidden: bool) {
self.window.set_prefers_status_bar_hidden(hidden)
}
}
/// Additional methods on [`WindowBuilder`] that are specific to iOS.
pub trait WindowBuilderExtIOS {
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `scale_factor`.
///
/// The default value is device dependent, and it's recommended GLES or Metal applications set
/// this to [`MonitorHandle::scale_factor()`].
///
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
fn with_scale_factor(self, scale_factor: f64) -> WindowBuilder;
/// Sets the valid orientations for the [`Window`].
///
/// The default value is [`ValidOrientations::LandscapeAndPortrait`].
///
/// This sets the initial value returned by
/// [`-[UIViewController supportedInterfaceOrientations]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621435-supportedinterfaceorientations?language=objc).
fn with_valid_orientations(self, valid_orientations: ValidOrientations) -> WindowBuilder;
/// Sets whether the [`Window`] prefers the home indicator hidden.
///
/// The default is to prefer showing the home indicator.
///
/// This sets the initial value returned by
/// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc).
///
/// This only has an effect on iOS 11.0+.
fn with_prefers_home_indicator_hidden(self, hidden: bool) -> WindowBuilder;
/// Sets the screen edges for which the system gestures will take a lower priority than the
/// application's touch handling.
///
/// This sets the initial value returned by
/// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc).
///
/// This only has an effect on iOS 11.0+.
fn with_preferred_screen_edges_deferring_system_gestures(
self,
edges: ScreenEdge,
) -> WindowBuilder;
/// Sets whether the [`Window`] prefers the status bar hidden.
///
/// The default is to prefer showing the status bar.
///
/// This sets the initial value returned by
/// [`-[UIViewController prefersStatusBarHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc).
fn with_prefers_status_bar_hidden(self, hidden: bool) -> WindowBuilder;
}
impl WindowBuilderExtIOS for WindowBuilder {
#[inline]
fn with_scale_factor(mut self, scale_factor: f64) -> WindowBuilder {
self.platform_specific.scale_factor = Some(scale_factor);
self
}
#[inline]
fn with_valid_orientations(mut self, valid_orientations: ValidOrientations) -> WindowBuilder {
self.platform_specific.valid_orientations = valid_orientations;
self
}
#[inline]
fn with_prefers_home_indicator_hidden(mut self, hidden: bool) -> WindowBuilder {
self.platform_specific.prefers_home_indicator_hidden = hidden;
self
}
#[inline]
fn with_preferred_screen_edges_deferring_system_gestures(
mut self,
edges: ScreenEdge,
) -> WindowBuilder {
self.platform_specific
.preferred_screen_edges_deferring_system_gestures = edges;
self
}
#[inline]
fn with_prefers_status_bar_hidden(mut self, hidden: bool) -> WindowBuilder {
self.platform_specific.prefers_status_bar_hidden = hidden;
self
}
}
/// Additional methods on [`MonitorHandle`] that are specific to iOS.
pub trait MonitorHandleExtIOS {
/// Returns a pointer to the [`UIScreen`] that is used by this monitor.
///
/// [`UIScreen`]: https://developer.apple.com/documentation/uikit/uiscreen?language=objc
fn ui_screen(&self) -> *mut c_void;
/// Returns the preferred [`VideoMode`] for this monitor.
///
/// This translates to a call to [`-[UIScreen preferredMode]`](https://developer.apple.com/documentation/uikit/uiscreen/1617823-preferredmode?language=objc).
fn preferred_video_mode(&self) -> VideoMode;
}
impl MonitorHandleExtIOS for MonitorHandle {
#[inline]
fn ui_screen(&self) -> *mut c_void {
Id::as_ptr(self.inner.ui_screen()) as *mut c_void
}
#[inline]
fn preferred_video_mode(&self) -> VideoMode {
VideoMode {
video_mode: self.inner.preferred_video_mode(),
}
}
}
/// Valid orientations for a particular [`Window`].
#[derive(Clone, Copy, Debug)]
pub enum ValidOrientations {
/// Excludes `PortraitUpsideDown` on iphone
LandscapeAndPortrait,
Landscape,
/// Excludes `PortraitUpsideDown` on iphone
Portrait,
}
impl Default for ValidOrientations {
#[inline]
fn default() -> ValidOrientations {
ValidOrientations::LandscapeAndPortrait
}
}
/// The device [idiom].
///
/// [idiom]: https://developer.apple.com/documentation/uikit/uidevice/1620037-userinterfaceidiom?language=objc
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Idiom {
Unspecified,
/// iPhone and iPod touch.
Phone,
/// iPad.
Pad,
/// tvOS and Apple TV.
TV,
CarPlay,
}
bitflags! {
/// The [edges] of a screen.
///
/// [edges]: https://developer.apple.com/documentation/uikit/uirectedge?language=objc
#[derive(Default)]
pub struct ScreenEdge: u8 {
const NONE = 0;
const TOP = 1 << 0;
const LEFT = 1 << 1;
const BOTTOM = 1 << 2;
const RIGHT = 1 << 3;
const ALL = ScreenEdge::TOP.bits | ScreenEdge::LEFT.bits
| ScreenEdge::BOTTOM.bits | ScreenEdge::RIGHT.bits;
}
}

View File

@@ -1,107 +0,0 @@
use std::ffi::CString;
use libc;
use objc::runtime::{ Object, Class };
#[allow(non_camel_case_types)]
pub type id = *mut Object;
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
pub const nil: id = 0 as id;
pub type CFStringRef = *const libc::c_void;
pub type CFTimeInterval = f64;
pub type Boolean = u32;
#[allow(non_upper_case_globals)]
pub const kCFRunLoopRunHandledSource: i32 = 4;
#[cfg(target_pointer_width = "32")]
pub type CGFloat = f32;
#[cfg(target_pointer_width = "64")]
pub type CGFloat = f64;
#[cfg(target_pointer_width = "32")]
pub type NSUInteger = u32;
#[cfg(target_pointer_width = "64")]
pub type NSUInteger = u64;
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CGPoint {
pub x: CGFloat,
pub y: CGFloat,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CGRect {
pub origin: CGPoint,
pub size: CGSize
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CGSize {
pub width: CGFloat,
pub height: CGFloat
}
#[link(name = "UIKit", kind = "framework")]
#[link(name = "CoreFoundation", kind = "framework")]
#[link(name = "GlKit", kind = "framework")]
extern {
pub static kCFRunLoopDefaultMode: CFStringRef;
// int UIApplicationMain ( int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName );
pub fn UIApplicationMain(argc: libc::c_int, argv: *const libc::c_char, principalClassName: id, delegateClassName: id) -> libc::c_int;
// SInt32 CFRunLoopRunInMode ( CFStringRef mode, CFTimeInterval seconds, Boolean returnAfterSourceHandled );
pub fn CFRunLoopRunInMode(mode: CFStringRef, seconds: CFTimeInterval, returnAfterSourceHandled: Boolean) -> i32;
}
extern {
pub fn setjmp(env: *mut libc::c_void) -> libc::c_int;
pub fn longjmp(env: *mut libc::c_void, val: libc::c_int);
}
pub trait NSString: Sized {
unsafe fn alloc(_: Self) -> id {
msg_send![class("NSString"), alloc]
}
#[allow(non_snake_case)]
unsafe fn initWithUTF8String_(self, c_string: *const i8) -> id;
#[allow(non_snake_case)]
unsafe fn stringByAppendingString_(self, other: id) -> id;
unsafe fn init_str(self, string: &str) -> Self;
#[allow(non_snake_case)]
unsafe fn UTF8String(self) -> *const libc::c_char;
}
impl NSString for id {
unsafe fn initWithUTF8String_(self, c_string: *const i8) -> id {
msg_send![self, initWithUTF8String:c_string as id]
}
unsafe fn stringByAppendingString_(self, other: id) -> id {
msg_send![self, stringByAppendingString:other]
}
unsafe fn init_str(self, string: &str) -> id {
let cstring = CString::new(string).unwrap();
self.initWithUTF8String_(cstring.as_ptr())
}
unsafe fn UTF8String(self) -> *const libc::c_char {
msg_send![self, UTF8String]
}
}
#[inline]
pub fn class(name: &str) -> *mut Class {
unsafe {
::std::mem::transmute(Class::get(name))
}
}

View File

@@ -1,564 +0,0 @@
//! iOS support
//!
//! # Building app
//! To build ios app you will need rustc built for this targets:
//!
//! - armv7-apple-ios
//! - armv7s-apple-ios
//! - i386-apple-ios
//! - aarch64-apple-ios
//! - x86_64-apple-ios
//!
//! Then
//!
//! ```
//! cargo build --target=...
//! ```
//! The simplest way to integrate your app into xcode environment is to build it
//! as a static library. Wrap your main function and export it.
//!
//! ```rust, ignore
//! #[no_mangle]
//! pub extern fn start_glutin_app() {
//! start_inner()
//! }
//!
//! fn start_inner() {
//! ...
//! }
//!
//! ```
//!
//! Compile project and then drag resulting .a into Xcode project. Add glutin.h to xcode.
//!
//! ```ignore
//! void start_glutin_app();
//! ```
//!
//! Use start_glutin_app inside your xcode's main function.
//!
//!
//! # App lifecycle and events
//!
//! iOS environment is very different from other platforms and you must be very
//! careful with it's events. Familiarize yourself with
//! [app lifecycle](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/).
//!
//!
//! This is how those event are represented in glutin:
//!
//! - applicationDidBecomeActive is Focused(true)
//! - applicationWillResignActive is Focused(false)
//! - applicationDidEnterBackground is Suspended(true)
//! - applicationWillEnterForeground is Suspended(false)
//! - applicationWillTerminate is Destroyed
//!
//! Keep in mind that after Destroyed event is received every attempt to draw with
//! opengl will result in segfault.
//!
//! Also note that app will not receive Destroyed event if suspended, it will be SIGKILL'ed
#![cfg(target_os = "ios")]
use std::collections::VecDeque;
use std::ptr;
use std::mem;
use std::os::raw::c_void;
use libc;
use libc::c_int;
use objc::runtime::{Class, Object, Sel, BOOL, YES };
use objc::declare::{ ClassDecl };
use { CreationError, CursorState, MouseCursor, WindowAttributes };
use WindowId as RootEventId;
use WindowEvent;
use Event;
use events::{ Touch, TouchPhase };
use window::MonitorId as RootMonitorId;
mod ffi;
use self::ffi::{
setjmp,
UIApplicationMain,
CFTimeInterval,
CFRunLoopRunInMode,
kCFRunLoopDefaultMode,
kCFRunLoopRunHandledSource,
id,
nil,
NSString,
CGFloat,
longjmp,
CGRect,
CGPoint
};
static mut jmpbuf: [c_int;27] = [0;27];
#[derive(Clone)]
pub struct MonitorId;
pub struct Window {
delegate_state: *mut DelegateState
}
#[derive(Clone)]
pub struct WindowProxy;
#[derive(Debug)]
struct DelegateState {
events_queue: VecDeque<Event>,
window: id,
controller: id,
size: (u32,u32),
scale: f32
}
impl DelegateState {
#[inline]
fn new(window: id, controller:id, size: (u32,u32), scale: f32) -> DelegateState {
DelegateState {
events_queue: VecDeque::new(),
window: window,
controller: controller,
size: size,
scale: scale
}
}
}
impl MonitorId {
#[inline]
pub fn get_name(&self) -> Option<String> {
Some("Primary".to_string())
}
#[inline]
pub fn get_dimensions(&self) -> (u32, u32) {
unimplemented!()
}
#[inline]
pub fn get_position(&self) -> (i32, i32) {
// iOS assumes single screen
(0, 0)
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
1.0
}
}
pub struct EventsLoop {
delegate_state: *mut DelegateState
}
#[derive(Clone)]
pub struct EventsLoopProxy;
impl EventsLoop {
pub fn new() -> EventsLoop {
unsafe {
if setjmp(mem::transmute(&mut jmpbuf)) != 0 {
let app: id = msg_send![Class::get("UIApplication").unwrap(), sharedApplication];
let delegate: id = msg_send![app, delegate];
let state: *mut c_void = *(&*delegate).get_ivar("glutinState");
let state = state as *mut DelegateState;
let events_loop = EventsLoop {
delegate_state: state
};
return events_loop;
}
}
create_delegate_class();
create_view_class();
start_app();
panic!("Couldn't create UIApplication")
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
let mut rb = VecDeque::new();
rb.push_back(MonitorId);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event)
{
unsafe {
let state = &mut *self.delegate_state;
if let Some(event) = state.events_queue.pop_front() {
callback(event);
return;
}
// jump hack, so we won't quit on willTerminate event before processing it
if setjmp(mem::transmute(&mut jmpbuf)) != 0 {
if let Some(event) = state.events_queue.pop_front() {
callback(event);
return;
}
}
// run runloop
let seconds: CFTimeInterval = 0.000002;
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, 1) == kCFRunLoopRunHandledSource {}
if let Some(event) = state.events_queue.pop_front() {
callback(event)
}
}
}
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(::Event) -> ::ControlFlow,
{
// Yeah that's a very bad implementation.
loop {
let mut control_flow = ::ControlFlow::Continue;
self.poll_events(|e| {
if let ::ControlFlow::Break = callback(e) {
control_flow = ::ControlFlow::Break;
}
});
if let ::ControlFlow::Break = control_flow {
break;
}
::std::thread::sleep(::std::time::Duration::from_millis(5));
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
unimplemented!()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
impl Window {
pub fn new(ev: &EventsLoop, _: &WindowAttributes, _: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError>
{
Ok(Window {
delegate_state: ev.delegate_state,
})
}
#[inline]
pub fn set_title(&self, _: &str) {
}
#[inline]
pub fn show(&self) {
}
#[inline]
pub fn hide(&self) {
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn set_position(&self, _x: i32, _y: i32) {
}
#[inline]
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
unsafe { Some((&*self.delegate_state).size) }
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.get_inner_size()
}
#[inline]
pub fn set_inner_size(&self, _x: u32, _y: u32) {
}
#[inline]
pub fn set_min_dimensions(&self, _dimensions: Option<(u32, u32)>) { }
#[inline]
pub fn set_max_dimensions(&self, _dimensions: Option<(u32, u32)>) { }
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
unimplemented!();
}
#[inline]
pub fn platform_window(&self) -> *mut libc::c_void {
unimplemented!()
}
#[inline]
pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
#[inline]
pub fn set_cursor(&self, _: MouseCursor) {
}
#[inline]
pub fn set_cursor_state(&self, _: CursorState) -> Result<(), String> {
Ok(())
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
unsafe { (&*self.delegate_state) }.scale
}
#[inline]
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
unimplemented!();
}
#[inline]
pub fn create_window_proxy(&self) -> WindowProxy {
WindowProxy
}
#[inline]
pub fn set_maximized(&self, _maximized: bool) {
// iOS has single screen maximized apps so nothing to do
}
#[inline]
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
// iOS has single screen maximized apps so nothing to do
}
#[inline]
pub fn set_decorations(&self, _decorations: bool) {
// N/A
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId{inner: MonitorId}
}
#[inline]
pub fn id(&self) -> WindowId {
WindowId
}
}
fn create_delegate_class() {
extern fn did_finish_launching(this: &mut Object, _: Sel, _: id, _: id) -> BOOL {
unsafe {
let main_screen: id = msg_send![Class::get("UIScreen").unwrap(), mainScreen];
let bounds: CGRect = msg_send![main_screen, bounds];
let scale: CGFloat = msg_send![main_screen, nativeScale];
let window: id = msg_send![Class::get("UIWindow").unwrap(), alloc];
let window: id = msg_send![window, initWithFrame:bounds.clone()];
let size = (bounds.size.width as u32, bounds.size.height as u32);
let view_controller: id = msg_send![Class::get("MainViewController").unwrap(), alloc];
let view_controller: id = msg_send![view_controller, init];
let _: () = msg_send![window, setRootViewController:view_controller];
let _: () = msg_send![window, makeKeyAndVisible];
let state = Box::new(DelegateState::new(window, view_controller, size, scale as f32));
let state_ptr: *mut DelegateState = mem::transmute(state);
this.set_ivar("glutinState", state_ptr as *mut c_void);
let _: () = msg_send![this, performSelector:sel!(postLaunch:) withObject:nil afterDelay:0.0];
}
YES
}
extern fn post_launch(_: &Object, _: Sel, _: id) {
unsafe { longjmp(mem::transmute(&mut jmpbuf),1); }
}
extern fn did_become_active(this: &Object, _: Sel, _: id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: WindowEvent::Focused(true),
});
}
}
extern fn will_resign_active(this: &Object, _: Sel, _: id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: WindowEvent::Focused(false),
});
}
}
extern fn will_enter_foreground(this: &Object, _: Sel, _: id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Suspended(false));
}
}
extern fn did_enter_background(this: &Object, _: Sel, _: id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Suspended(true));
}
}
extern fn will_terminate(this: &Object, _: Sel, _: id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
// push event to the front to garantee that we'll process it
// immidiatly after jump
state.events_queue.push_front(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: WindowEvent::Destroyed,
});
longjmp(mem::transmute(&mut jmpbuf),1);
}
}
extern fn handle_touches(this: &Object, _: Sel, touches: id, _:id) {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState);
let touches_enum: id = msg_send![touches, objectEnumerator];
loop {
let touch: id = msg_send![touches_enum, nextObject];
if touch == nil {
break
}
let location: CGPoint = msg_send![touch, locationInView:nil];
let touch_id = touch as u64;
let phase: i32 = msg_send![touch, phase];
state.events_queue.push_back(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: WindowEvent::Touch(Touch {
device_id: DEVICE_ID,
id: touch_id,
location: (location.x as f64, location.y as f64),
phase: match phase {
0 => TouchPhase::Started,
1 => TouchPhase::Moved,
// 2 is UITouchPhaseStationary and is not expected here
3 => TouchPhase::Ended,
4 => TouchPhase::Cancelled,
_ => panic!("unexpected touch phase: {:?}", phase)
}
}),
});
}
}
}
let ui_responder = Class::get("UIResponder").unwrap();
let mut decl = ClassDecl::new("AppDelegate", ui_responder).unwrap();
unsafe {
decl.add_method(sel!(application:didFinishLaunchingWithOptions:),
did_finish_launching as extern fn(&mut Object, Sel, id, id) -> BOOL);
decl.add_method(sel!(applicationDidBecomeActive:),
did_become_active as extern fn(&Object, Sel, id));
decl.add_method(sel!(applicationWillResignActive:),
will_resign_active as extern fn(&Object, Sel, id));
decl.add_method(sel!(applicationWillEnterForeground:),
will_enter_foreground as extern fn(&Object, Sel, id));
decl.add_method(sel!(applicationDidEnterBackground:),
did_enter_background as extern fn(&Object, Sel, id));
decl.add_method(sel!(applicationWillTerminate:),
will_terminate as extern fn(&Object, Sel, id));
decl.add_method(sel!(touchesBegan:withEvent:),
handle_touches as extern fn(this: &Object, _: Sel, _: id, _:id));
decl.add_method(sel!(touchesMoved:withEvent:),
handle_touches as extern fn(this: &Object, _: Sel, _: id, _:id));
decl.add_method(sel!(touchesEnded:withEvent:),
handle_touches as extern fn(this: &Object, _: Sel, _: id, _:id));
decl.add_method(sel!(touchesCancelled:withEvent:),
handle_touches as extern fn(this: &Object, _: Sel, _: id, _:id));
decl.add_method(sel!(postLaunch:),
post_launch as extern fn(&Object, Sel, id));
decl.add_ivar::<*mut c_void>("glutinState");
decl.register();
}
}
fn create_view_class() {
let ui_view_controller = Class::get("UIViewController").unwrap();
let decl = ClassDecl::new("MainViewController", ui_view_controller).unwrap();
decl.register();
}
#[inline]
fn start_app() {
unsafe {
UIApplicationMain(0, ptr::null(), nil, NSString::alloc(nil).init_str("AppDelegate"));
}
}
// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);

View File

@@ -1,15 +0,0 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
#![allow(dead_code)]
use std::os::raw::{c_void, c_char, c_int};
pub const RTLD_LAZY: c_int = 0x001;
pub const RTLD_NOW: c_int = 0x002;
#[link="dl"]
extern {
pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void;
pub fn dlerror() -> *mut c_char;
pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
pub fn dlclose(handle: *mut c_void) -> c_int;
}

View File

@@ -1,451 +0,0 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
use std::collections::VecDeque;
use std::sync::Arc;
use std::env;
use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow};
use libc;
use self::x11::XConnection;
use self::x11::XError;
use self::x11::ffi::XVisualInfo;
pub use self::x11::XNotSupported;
use window::MonitorId as RootMonitorId;
mod dlopen;
pub mod wayland;
pub mod x11;
/// Environment variable specifying which backend should be used on unix platform.
///
/// Legal values are x11 and wayland. If this variable is set only the named backend
/// will be tried by winit. If it is not set, winit will try to connect to a wayland connection,
/// and if it fails will fallback on x11.
///
/// If this variable is set with any other value, winit will panic.
const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND";
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub visual_infos: Option<XVisualInfo>,
pub screen_id: Option<i32>,
}
lazy_static!(
pub static ref X11_BACKEND: Result<Arc<XConnection>, XNotSupported> = {
XConnection::new(Some(x_error_callback)).map(Arc::new)
};
);
pub enum Window {
X(x11::Window),
Wayland(wayland::Window)
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum WindowId {
X(x11::WindowId),
Wayland(wayland::WindowId)
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DeviceId {
X(x11::DeviceId),
Wayland(wayland::DeviceId)
}
#[derive(Clone)]
pub enum MonitorId {
X(x11::MonitorId),
Wayland(wayland::MonitorId),
}
impl MonitorId {
#[inline]
pub fn get_name(&self) -> Option<String> {
match self {
&MonitorId::X(ref m) => m.get_name(),
&MonitorId::Wayland(ref m) => m.get_name(),
}
}
#[inline]
pub fn get_native_identifier(&self) -> u32 {
match self {
&MonitorId::X(ref m) => m.get_native_identifier(),
&MonitorId::Wayland(ref m) => m.get_native_identifier(),
}
}
#[inline]
pub fn get_dimensions(&self) -> (u32, u32) {
match self {
&MonitorId::X(ref m) => m.get_dimensions(),
&MonitorId::Wayland(ref m) => m.get_dimensions(),
}
}
#[inline]
pub fn get_position(&self) -> (i32, i32) {
match self {
&MonitorId::X(ref m) => m.get_position(),
&MonitorId::Wayland(ref m) => m.get_position(),
}
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
match self {
&MonitorId::X(ref m) => m.get_hidpi_factor(),
&MonitorId::Wayland(ref m) => m.get_hidpi_factor(),
}
}
}
impl Window {
#[inline]
pub fn new(events_loop: &EventsLoop,
window: &::WindowAttributes,
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
-> Result<Self, CreationError>
{
match *events_loop {
EventsLoop::Wayland(ref evlp) => {
wayland::Window::new(evlp, window).map(Window::Wayland)
},
EventsLoop::X(ref el) => {
x11::Window::new(el, window, pl_attribs).map(Window::X)
},
}
}
#[inline]
pub fn id(&self) -> WindowId {
match self {
&Window::X(ref w) => WindowId::X(w.id()),
&Window::Wayland(ref w) => WindowId::Wayland(w.id())
}
}
#[inline]
pub fn set_title(&self, title: &str) {
match self {
&Window::X(ref w) => w.set_title(title),
&Window::Wayland(ref w) => w.set_title(title)
}
}
#[inline]
pub fn show(&self) {
match self {
&Window::X(ref w) => w.show(),
&Window::Wayland(ref w) => w.show()
}
}
#[inline]
pub fn hide(&self) {
match self {
&Window::X(ref w) => w.hide(),
&Window::Wayland(ref w) => w.hide()
}
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
match self {
&Window::X(ref w) => w.get_position(),
&Window::Wayland(ref w) => w.get_position()
}
}
#[inline]
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
match self {
&Window::X(ref m) => m.get_inner_position(),
&Window::Wayland(ref m) => m.get_inner_position(),
}
}
#[inline]
pub fn set_position(&self, x: i32, y: i32) {
match self {
&Window::X(ref w) => w.set_position(x, y),
&Window::Wayland(ref w) => w.set_position(x, y)
}
}
#[inline]
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
match self {
&Window::X(ref w) => w.get_inner_size(),
&Window::Wayland(ref w) => w.get_inner_size()
}
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
match self {
&Window::X(ref w) => w.get_outer_size(),
&Window::Wayland(ref w) => w.get_outer_size()
}
}
#[inline]
pub fn set_inner_size(&self, x: u32, y: u32) {
match self {
&Window::X(ref w) => w.set_inner_size(x, y),
&Window::Wayland(ref w) => w.set_inner_size(x, y)
}
}
#[inline]
pub fn set_min_dimensions(&self, dimensions: Option<(u32, u32)>) {
match self {
&Window::X(ref w) => w.set_min_dimensions(dimensions),
&Window::Wayland(ref w) => w.set_min_dimensions(dimensions)
}
}
#[inline]
pub fn set_max_dimensions(&self, dimensions: Option<(u32, u32)>) {
match self {
&Window::X(ref w) => w.set_max_dimensions(dimensions),
&Window::Wayland(ref w) => w.set_max_dimensions(dimensions)
}
}
#[inline]
pub fn set_cursor(&self, cursor: MouseCursor) {
match self {
&Window::X(ref w) => w.set_cursor(cursor),
&Window::Wayland(ref w) => w.set_cursor(cursor)
}
}
#[inline]
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
match self {
&Window::X(ref w) => w.set_cursor_state(state),
&Window::Wayland(ref w) => w.set_cursor_state(state)
}
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
match self {
&Window::X(ref w) => w.hidpi_factor(),
&Window::Wayland(ref w) => w.hidpi_factor()
}
}
#[inline]
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
match self {
&Window::X(ref w) => w.set_cursor_position(x, y),
&Window::Wayland(ref w) => w.set_cursor_position(x, y)
}
}
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
use wayland_client::Proxy;
match self {
&Window::X(ref w) => w.platform_display(),
&Window::Wayland(ref w) => w.get_display().ptr() as *mut _
}
}
#[inline]
pub fn platform_window(&self) -> *mut libc::c_void {
use wayland_client::Proxy;
match self {
&Window::X(ref w) => w.platform_window(),
&Window::Wayland(ref w) => w.get_surface().ptr() as *mut _
}
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
match self {
&Window::X(ref w) => w.set_maximized(maximized),
&Window::Wayland(ref w) => w.set_maximized(maximized),
}
}
#[inline]
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
match self {
&Window::X(ref w) => w.set_fullscreen(monitor),
&Window::Wayland(ref w) => w.set_fullscreen(monitor)
}
}
#[inline]
pub fn set_decorations(&self, decorations: bool) {
match self {
&Window::X(ref w) => w.set_decorations(decorations),
&Window::Wayland(ref w) => w.set_decorations(decorations)
}
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
match self {
&Window::X(ref w) => RootMonitorId{inner: MonitorId::X(w.get_current_monitor())},
&Window::Wayland(ref w) => RootMonitorId{inner: MonitorId::Wayland(w.get_current_monitor())},
}
}
}
unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
-> libc::c_int
{
use std::ffi::CStr;
if let Ok(ref x) = *X11_BACKEND {
let mut buff: Vec<u8> = Vec::with_capacity(1024);
(x.xlib.XGetErrorText)(dpy, (*event).error_code as i32, buff.as_mut_ptr() as *mut libc::c_char, buff.capacity() as i32);
let description = CStr::from_ptr(buff.as_mut_ptr() as *const libc::c_char).to_string_lossy();
let error = XError {
description: description.into_owned(),
error_code: (*event).error_code,
request_code: (*event).request_code,
minor_code: (*event).minor_code,
};
*x.latest_error.lock().unwrap() = Some(error);
}
0
}
pub enum EventsLoop {
Wayland(wayland::EventsLoop),
X(x11::EventsLoop)
}
#[derive(Clone)]
pub enum EventsLoopProxy {
X(x11::EventsLoopProxy),
Wayland(wayland::EventsLoopProxy),
}
impl EventsLoop {
pub fn new() -> EventsLoop {
if let Ok(env_var) = env::var(BACKEND_PREFERENCE_ENV_VAR) {
match env_var.as_str() {
"x11" => {
return EventsLoop::new_x11().unwrap(); // TODO: propagate
},
"wayland" => {
match EventsLoop::new_wayland() {
Ok(e) => return e,
Err(_) => panic!() // TODO: propagate
}
},
_ => panic!("Unknown environment variable value for {}, try one of `x11`,`wayland`",
BACKEND_PREFERENCE_ENV_VAR),
}
}
if let Ok(el) = EventsLoop::new_wayland() {
return el;
}
if let Ok(el) = EventsLoop::new_x11() {
return el;
}
panic!("No backend is available")
}
pub fn new_wayland() -> Result<EventsLoop, ()> {
wayland::EventsLoop::new()
.map(EventsLoop::Wayland)
.ok_or(())
}
pub fn new_x11() -> Result<EventsLoop, XNotSupported> {
match *X11_BACKEND {
Ok(ref x) => Ok(EventsLoop::X(x11::EventsLoop::new(x.clone()))),
Err(ref err) => Err(err.clone()),
}
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
match *self {
EventsLoop::Wayland(ref evlp) => evlp.get_available_monitors()
.into_iter()
.map(MonitorId::Wayland)
.collect(),
EventsLoop::X(ref evlp) => x11::get_available_monitors(evlp.x_connection())
.into_iter()
.map(MonitorId::X)
.collect(),
}
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
match *self {
EventsLoop::Wayland(ref evlp) => MonitorId::Wayland(evlp.get_primary_monitor()),
EventsLoop::X(ref evlp) => MonitorId::X(x11::get_primary_monitor(evlp.x_connection())),
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
match *self {
EventsLoop::Wayland(ref evlp) => EventsLoopProxy::Wayland(evlp.create_proxy()),
EventsLoop::X(ref evlp) => EventsLoopProxy::X(evlp.create_proxy()),
}
}
pub fn poll_events<F>(&mut self, callback: F)
where F: FnMut(::Event)
{
match *self {
EventsLoop::Wayland(ref mut evlp) => evlp.poll_events(callback),
EventsLoop::X(ref mut evlp) => evlp.poll_events(callback)
}
}
pub fn run_forever<F>(&mut self, callback: F)
where F: FnMut(::Event) -> ControlFlow
{
match *self {
EventsLoop::Wayland(ref mut evlp) => evlp.run_forever(callback),
EventsLoop::X(ref mut evlp) => evlp.run_forever(callback)
}
}
#[inline]
pub fn is_wayland(&self) -> bool {
match *self {
EventsLoop::Wayland(_) => true,
EventsLoop::X(_) => false,
}
}
#[inline]
pub fn x_connection(&self) -> Option<&Arc<XConnection>> {
match *self {
EventsLoop::Wayland(_) => None,
EventsLoop::X(ref ev) => Some(ev.x_connection()),
}
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
match *self {
EventsLoopProxy::Wayland(ref proxy) => proxy.wakeup(),
EventsLoopProxy::X(ref proxy) => proxy.wakeup(),
}
}
}

View File

@@ -1,594 +0,0 @@
use std::cell::RefCell;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use {EventsLoopClosed, ControlFlow};
use super::WindowId;
use super::window::WindowStore;
use super::keyboard::init_keyboard;
use wayland_client::{EnvHandler, EnvNotify, default_connect, EventQueue, EventQueueHandle, Proxy, StateToken};
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
wl_display, wl_registry, wl_output, wl_surface,
wl_pointer, wl_keyboard, wl_touch};
use super::wayland_window::{Frame, Shell, create_frame, FrameImplementation};
use super::wayland_protocols::unstable::xdg_shell::v6::client::zxdg_shell_v6;
pub struct EventsLoopSink {
buffer: VecDeque<::Event>
}
unsafe impl Send for EventsLoopSink { }
impl EventsLoopSink {
pub fn new() -> EventsLoopSink{
EventsLoopSink {
buffer: VecDeque::new()
}
}
pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
let evt = ::Event::WindowEvent {
event: evt,
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
};
self.buffer.push_back(evt);
}
pub fn send_raw_event(&mut self, evt: ::Event) {
self.buffer.push_back(evt);
}
fn empty_with<F>(&mut self, callback: &mut F) where F: FnMut(::Event) {
for evt in self.buffer.drain(..) {
callback(evt)
}
}
}
pub struct EventsLoop {
// The Event Queue
pub evq: RefCell<EventQueue>,
// our sink, shared with some handlers, buffering the events
sink: Arc<Mutex<EventsLoopSink>>,
// Whether or not there is a pending `Awakened` event to be emitted.
pending_wakeup: Arc<AtomicBool>,
// The window store
pub store: StateToken<WindowStore>,
// the env
env_token: StateToken<EnvHandler<InnerEnv>>,
// the ctxt
pub ctxt_token: StateToken<StateContext>,
// a cleanup switch to prune dead windows
pub cleanup_needed: Arc<Mutex<bool>>,
// The wayland display
pub display: Arc<wl_display::WlDisplay>,
}
// A handle that can be sent across threads and used to wake up the `EventsLoop`.
//
// We should only try and wake up the `EventsLoop` if it still exists, so we hold Weak ptrs.
#[derive(Clone)]
pub struct EventsLoopProxy {
display: Weak<wl_display::WlDisplay>,
pending_wakeup: Weak<AtomicBool>,
}
impl EventsLoopProxy {
// Causes the `EventsLoop` to stop blocking on `run_forever` and emit an `Awakened` event.
//
// Returns `Err` if the associated `EventsLoop` no longer exists.
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
let display = self.display.upgrade();
let wakeup = self.pending_wakeup.upgrade();
match (display, wakeup) {
(Some(display), Some(wakeup)) => {
// Update the `EventsLoop`'s `pending_wakeup` flag.
wakeup.store(true, Ordering::Relaxed);
// Cause the `EventsLoop` to break from `dispatch` if it is currently blocked.
display.sync();
display.flush().map_err(|_| EventsLoopClosed)?;
Ok(())
},
_ => Err(EventsLoopClosed),
}
}
}
impl EventsLoop {
pub fn new() -> Option<EventsLoop> {
let (display, mut event_queue) = match default_connect() {
Ok(ret) => ret,
Err(_) => return None
};
let registry = display.get_registry();
let ctxt_token = event_queue.state().insert(
StateContext::new(registry.clone().unwrap())
);
let env_token = EnvHandler::init_with_notify(
&mut event_queue,
&registry,
env_notify(),
ctxt_token.clone()
);
// two round trips to fully initialize
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
event_queue.state().with_value(&ctxt_token, |proxy, ctxt| {
ctxt.ensure_shell(proxy.get_mut(&env_token))
});
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
let store = event_queue.state().insert(WindowStore::new());
let seat_idata = SeatIData {
sink: sink.clone(),
keyboard: None,
pointer: None,
touch: None,
windows_token: store.clone()
};
let mut me = EventsLoop {
display: Arc::new(display),
evq: RefCell::new(event_queue),
sink: sink,
pending_wakeup: Arc::new(AtomicBool::new(false)),
store: store,
ctxt_token: ctxt_token,
env_token: env_token,
cleanup_needed: Arc::new(Mutex::new(false))
};
me.init_seat(|evqh, seat| {
evqh.register(seat, seat_implementation(), seat_idata);
});
Some(me)
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
display: Arc::downgrade(&self.display),
pending_wakeup: Arc::downgrade(&self.pending_wakeup),
}
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event)
{
// send pending events to the server
self.display.flush().expect("Wayland connection lost.");
// dispatch any pre-buffered events
self.sink.lock().unwrap().empty_with(&mut callback);
// try to read pending events
if let Some(h) = self.evq.get_mut().prepare_read() {
h.read_events().expect("Wayland connection lost.");
}
// dispatch wayland events
self.evq.get_mut().dispatch_pending().expect("Wayland connection lost.");
self.post_dispatch_triggers();
// dispatch buffered events to client
self.sink.lock().unwrap().empty_with(&mut callback);
}
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(::Event) -> ControlFlow,
{
// send pending events to the server
self.display.flush().expect("Wayland connection lost.");
// Check for control flow by wrapping the callback.
let control_flow = ::std::cell::Cell::new(ControlFlow::Continue);
let mut callback = |event| if let ControlFlow::Break = callback(event) {
control_flow.set(ControlFlow::Break);
};
// dispatch any pre-buffered events
self.post_dispatch_triggers();
self.sink.lock().unwrap().empty_with(&mut callback);
loop {
// dispatch events blocking if needed
self.evq.get_mut().dispatch().expect("Wayland connection lost.");
self.post_dispatch_triggers();
// empty buffer of events
self.sink.lock().unwrap().empty_with(&mut callback);
if let ControlFlow::Break = control_flow.get() {
break;
}
}
}
pub fn get_primary_monitor(&self) -> MonitorId {
let mut guard = self.evq.borrow_mut();
let state = guard.state();
let state_ctxt = state.get(&self.ctxt_token);
if let Some(info) = state_ctxt.monitors.iter().next() {
MonitorId {
info: info.clone()
}
} else {
panic!("No monitor is available.")
}
}
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
let mut guard = self.evq.borrow_mut();
let state = guard.state();
let state_ctxt = state.get(&self.ctxt_token);
state_ctxt.monitors.iter()
.map(|m| MonitorId { info: m.clone() })
.collect()
}
}
/*
* Private EventsLoop Internals
*/
wayland_env!(InnerEnv,
compositor: wl_compositor::WlCompositor,
shm: wl_shm::WlShm,
subcompositor: wl_subcompositor::WlSubcompositor
);
pub struct StateContext {
registry: wl_registry::WlRegistry,
seat: Option<wl_seat::WlSeat>,
shell: Option<Shell>,
monitors: Vec<Arc<Mutex<OutputInfo>>>
}
impl StateContext {
fn new(registry: wl_registry::WlRegistry) -> StateContext {
StateContext {
registry: registry,
seat: None,
shell: None,
monitors: Vec::new()
}
}
/// Ensures a shell is available
///
/// If a shell is already bound, do nothing. Otherwise,
/// try to bind wl_shell as a fallback. If this fails,
/// panic, as this is a bug from the compositor.
fn ensure_shell(&mut self, env: &mut EnvHandler<InnerEnv>) {
if self.shell.is_some() {
return;
}
// xdg_shell is not available, so initialize wl_shell
for &(name, ref interface, _) in env.globals() {
if interface == "wl_shell" {
self.shell = Some(Shell::Wl(self.registry.bind::<wl_shell::WlShell>(1, name)));
return;
}
}
// This is a compositor bug, it _must_ at least support wl_shell
panic!("Compositor didi not advertize xdg_shell not wl_shell.");
}
pub fn monitor_id_for(&self, output: &wl_output::WlOutput) -> MonitorId {
for info in &self.monitors {
let guard = info.lock().unwrap();
if guard.output.equals(output) {
return MonitorId {
info: info.clone()
};
}
}
panic!("Received an inexistent wl_output?!");
}
}
impl EventsLoop {
pub fn init_seat<F>(&mut self, f: F)
where F: FnOnce(&mut EventQueueHandle, &wl_seat::WlSeat)
{
let mut guard = self.evq.borrow_mut();
if guard.state().get(&self.ctxt_token).seat.is_some() {
// seat has already been init
return;
}
// clone the token to make borrow checker happy
let ctxt_token = self.ctxt_token.clone();
let seat = guard.state().with_value(&self.env_token, |proxy, env| {
let ctxt = proxy.get(&ctxt_token);
for &(name, ref interface, _) in env.globals() {
if interface == wl_seat::WlSeat::interface_name() {
return Some(ctxt.registry.bind::<wl_seat::WlSeat>(5, name));
}
}
None
});
if let Some(seat) = seat {
f(&mut *guard, &seat);
guard.state().get_mut(&self.ctxt_token).seat = Some(seat)
}
}
fn post_dispatch_triggers(&mut self) {
let mut sink = self.sink.lock().unwrap();
let evq = self.evq.get_mut();
// process a possible pending wakeup call
if self.pending_wakeup.load(Ordering::Relaxed) {
sink.send_raw_event(::Event::Awakened);
self.pending_wakeup.store(false, Ordering::Relaxed);
}
// prune possible dead windows
{
let mut cleanup_needed = self.cleanup_needed.lock().unwrap();
if *cleanup_needed {
let pruned = evq.state().get_mut(&self.store).cleanup();
*cleanup_needed = false;
for wid in pruned {
sink.send_event(::WindowEvent::Destroyed, wid);
}
}
}
// process pending resize/refresh
evq.state().get_mut(&self.store).for_each(
|newsize, refresh, frame_refresh, closed, wid, frame| {
if let Some(frame) = frame {
if let Some((w, h)) = newsize {
frame.resize(w as i32, h as i32);
frame.refresh();
sink.send_event(::WindowEvent::Resized(w as u32, h as u32), wid);
} else if frame_refresh {
frame.refresh();
}
}
if refresh {
sink.send_event(::WindowEvent::Refresh, wid);
}
if closed {
sink.send_event(::WindowEvent::CloseRequested, wid);
}
}
)
}
/// Create a new window with given dimensions
///
/// Grabs a lock on the event queue in the process
pub fn create_window<ID: 'static, F>(&self, width: u32, height: u32, implem: FrameImplementation<ID>, idata: F)
-> (wl_surface::WlSurface, Frame)
where F: FnOnce(&wl_surface::WlSurface) -> ID
{
let (surface, frame) = {
let mut guard = self.evq.borrow_mut();
let env = guard.state().get(&self.env_token).clone_inner().unwrap();
let shell = match guard.state().get(&self.ctxt_token).shell {
Some(Shell::Wl(ref wl_shell)) => Shell::Wl(wl_shell.clone().unwrap()),
Some(Shell::Xdg(ref xdg_shell)) => Shell::Xdg(xdg_shell.clone().unwrap()),
None => unreachable!()
};
let seat = guard.state().get(&self.ctxt_token).seat.as_ref().and_then(|s| s.clone());
let surface = env.compositor.create_surface();
let frame = create_frame(
&mut guard,
implem,
idata(&surface),
&surface, width as i32, height as i32,
&env.compositor,
&env.subcompositor,
&env.shm,
&shell,
seat
).expect("Failed to create a tmpfile buffer.");
(surface, frame)
};
(surface, frame)
}
}
/*
* Wayland protocol implementations
*/
fn env_notify() -> EnvNotify<StateToken<StateContext>> {
EnvNotify {
new_global: |evqh, token, registry, id, interface, version| {
use std::cmp::min;
if interface == wl_output::WlOutput::interface_name() {
// a new output is available
let output = registry.bind::<wl_output::WlOutput>(min(version, 3), id);
evqh.register(&output, output_impl(), token.clone());
evqh.state().get_mut(&token).monitors.push(
Arc::new(Mutex::new(OutputInfo::new(output, id)))
);
} else if interface == zxdg_shell_v6::ZxdgShellV6::interface_name() {
// We have an xdg_shell, bind it
let xdg_shell = registry.bind::<zxdg_shell_v6::ZxdgShellV6>(1, id);
evqh.register(&xdg_shell, xdg_ping_implementation(), ());
evqh.state().get_mut(&token).shell = Some(Shell::Xdg(xdg_shell));
}
},
del_global: |evqh, token, _, id| {
// maybe this was a monitor, cleanup
evqh.state().get_mut(&token).monitors.retain(
|m| m.lock().unwrap().id != id
);
},
ready: |_, _, _| {}
}
}
fn xdg_ping_implementation() -> zxdg_shell_v6::Implementation<()> {
zxdg_shell_v6::Implementation {
ping: |_, _, shell, serial| {
shell.pong(serial);
}
}
}
struct SeatIData {
sink: Arc<Mutex<EventsLoopSink>>,
pointer: Option<wl_pointer::WlPointer>,
keyboard: Option<wl_keyboard::WlKeyboard>,
touch: Option<wl_touch::WlTouch>,
windows_token: StateToken<WindowStore>
}
fn seat_implementation() -> wl_seat::Implementation<SeatIData> {
wl_seat::Implementation {
name: |_, _, _, _| {},
capabilities: |evqh, idata, seat, capabilities| {
// create pointer if applicable
if capabilities.contains(wl_seat::Capability::Pointer) && idata.pointer.is_none() {
let pointer = seat.get_pointer().expect("Seat is not dead");
let p_idata = super::pointer::PointerIData::new(
&idata.sink,
idata.windows_token.clone()
);
evqh.register(&pointer, super::pointer::pointer_implementation(), p_idata);
idata.pointer = Some(pointer);
}
// destroy pointer if applicable
if !capabilities.contains(wl_seat::Capability::Pointer) {
if let Some(pointer) = idata.pointer.take() {
pointer.release();
}
}
// create keyboard if applicable
if capabilities.contains(wl_seat::Capability::Keyboard) && idata.keyboard.is_none() {
let kbd = seat.get_keyboard().expect("Seat is not dead");
init_keyboard(evqh, &kbd, &idata.sink);
idata.keyboard = Some(kbd);
}
// destroy keyboard if applicable
if !capabilities.contains(wl_seat::Capability::Keyboard) {
if let Some(kbd) = idata.keyboard.take() {
kbd.release();
}
}
// create touch if applicable
if capabilities.contains(wl_seat::Capability::Touch) && idata.touch.is_none() {
let touch = seat.get_touch().expect("Seat is not dead");
let t_idata = super::touch::TouchIData::new(
&idata.sink,
idata.windows_token.clone()
);
evqh.register(&touch, super::touch::touch_implementation(), t_idata);
idata.touch = Some(touch);
}
// destroy touch if applicable
if !capabilities.contains(wl_seat::Capability::Touch) {
if let Some(touch) = idata.touch.take() {
touch.release();
}
}
}
}
}
/*
* Monitor stuff
*/
fn output_impl() -> wl_output::Implementation<StateToken<StateContext>> {
wl_output::Implementation {
geometry: |evqh, token, output, x, y, _, _, _, make, model, _| {
let ctxt = evqh.state().get_mut(token);
for info in &ctxt.monitors {
let mut guard = info.lock().unwrap();
if guard.output.equals(output) {
guard.pix_pos = (x, y);
guard.name = format!("{} - {}", make, model);
return;
}
}
},
mode: |evqh, token, output, flags, w, h, _refresh| {
if flags.contains(wl_output::Mode::Current) {
let ctxt = evqh.state().get_mut(token);
for info in &ctxt.monitors {
let mut guard = info.lock().unwrap();
if guard.output.equals(output) {
guard.pix_size = (w as u32, h as u32);
return;
}
}
}
},
done: |_, _, _| {},
scale: |evqh, token, output, scale| {
let ctxt = evqh.state().get_mut(token);
for info in &ctxt.monitors {
let mut guard = info.lock().unwrap();
if guard.output.equals(output) {
guard.scale = scale as f32;
return;
}
}
}
}
}
pub struct OutputInfo {
pub output: wl_output::WlOutput,
pub id: u32,
pub scale: f32,
pub pix_size: (u32, u32),
pub pix_pos: (i32, i32),
pub name: String
}
impl OutputInfo {
fn new(output: wl_output::WlOutput, id: u32) -> OutputInfo {
OutputInfo {
output: output,
id: id,
scale: 1.0,
pix_size: (0, 0),
pix_pos: (0, 0),
name: "".into()
}
}
}
#[derive(Clone)]
pub struct MonitorId {
pub info: Arc<Mutex<OutputInfo>>
}
impl MonitorId {
pub fn get_name(&self) -> Option<String> {
Some(self.info.lock().unwrap().name.clone())
}
#[inline]
pub fn get_native_identifier(&self) -> u32 {
self.info.lock().unwrap().id
}
pub fn get_dimensions(&self) -> (u32, u32) {
self.info.lock().unwrap().pix_size
}
pub fn get_position(&self) -> (i32, i32) {
self.info.lock().unwrap().pix_pos
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
self.info.lock().unwrap().scale
}
}

View File

@@ -1,296 +0,0 @@
use std::sync::{Arc, Mutex};
use {VirtualKeyCode, ElementState, WindowEvent as Event, KeyboardInput, ModifiersState};
use super::{EventsLoopSink, WindowId, make_wid, DeviceId};
use super::wayland_kbd::{MappedKeyboardImplementation, register_kbd};
use wayland_client::protocol::wl_keyboard;
use wayland_client::EventQueueHandle;
pub fn init_keyboard(evq: &mut EventQueueHandle, keyboard: &wl_keyboard::WlKeyboard, sink: &Arc<Mutex<EventsLoopSink>>) {
let idata = KeyboardIData {
sink: sink.clone(),
target: None
};
if register_kbd(evq, keyboard, mapped_keyboard_impl(), idata).is_err() {
// initializing libxkbcommon failed :(
// fallback implementation
let idata = KeyboardIData {
sink: sink.clone(),
target: None
};
evq.register(keyboard, raw_keyboard_impl(), idata);
}
}
struct KeyboardIData {
sink: Arc<Mutex<EventsLoopSink>>,
target: Option<WindowId>
}
fn mapped_keyboard_impl() -> MappedKeyboardImplementation<KeyboardIData> {
MappedKeyboardImplementation {
enter: |_, idata, _, _, surface, _, _, _| {
let wid = make_wid(surface);
idata.sink.lock().unwrap().send_event(Event::Focused(true), wid);
idata.target = Some(wid);
},
leave: |_, idata, _, _, surface| {
let wid = make_wid(surface);
idata.sink.lock().unwrap().send_event(Event::Focused(false), wid);
idata.target = None;
},
key: |_, idata, _, _, _, mods, rawkey, keysym, state, utf8| {
if let Some(wid) = idata.target {
let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released,
};
let vkcode = key_to_vkey(rawkey, keysym);
let mut guard = idata.sink.lock().unwrap();
guard.send_event(
Event::KeyboardInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
input: KeyboardInput {
state: state,
scancode: rawkey,
virtual_keycode: vkcode,
modifiers: ModifiersState {
shift: mods.shift,
ctrl: mods.ctrl,
alt: mods.alt,
logo: mods.logo
},
},
},
wid
);
// send char event only on key press, not release
if let ElementState::Released = state { return }
if let Some(txt) = utf8 {
for chr in txt.chars() {
guard.send_event(Event::ReceivedCharacter(chr), wid);
}
}
}
},
repeat_info: |_, _idata, _, _rate, _delay| {
// TODO: handle repeat info
}
}
}
// This is fallback impl if libxkbcommon was not available
// This case should probably never happen, as most wayland
// compositors _need_ libxkbcommon anyway...
//
// In this case, we don't have the keymap information (it is
// supposed to be serialized by the compositor using libxkbcommon)
fn raw_keyboard_impl() -> wl_keyboard::Implementation<KeyboardIData> {
wl_keyboard::Implementation {
enter: |_, idata, _, _, surface, _| {
let wid = make_wid(surface);
idata.sink.lock().unwrap().send_event(Event::Focused(true), wid);
idata.target = Some(wid);
},
leave: |_, idata, _, _, surface| {
let wid = make_wid(surface);
idata.sink.lock().unwrap().send_event(Event::Focused(false), wid);
idata.target = None;
},
key: |_, idata, _, _, _, key, state| {
if let Some(wid) = idata.target {
let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released,
};
idata.sink.lock().unwrap().send_event(
Event::KeyboardInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
input: KeyboardInput {
state: state,
scancode: key,
virtual_keycode: None,
modifiers: ModifiersState::default(),
},
},
wid
);
}
},
repeat_info: |_, _idata, _, _rate, _delay| {},
keymap: |_, _, _, _, _, _| {},
modifiers: |_, _, _, _, _, _, _, _| {}
}
}
fn key_to_vkey(rawkey: u32, keysym: u32) -> Option<VirtualKeyCode> {
match rawkey {
1 => Some(VirtualKeyCode::Escape),
2 => Some(VirtualKeyCode::Key1),
3 => Some(VirtualKeyCode::Key2),
4 => Some(VirtualKeyCode::Key3),
5 => Some(VirtualKeyCode::Key4),
6 => Some(VirtualKeyCode::Key5),
7 => Some(VirtualKeyCode::Key6),
8 => Some(VirtualKeyCode::Key7),
9 => Some(VirtualKeyCode::Key8),
10 => Some(VirtualKeyCode::Key9),
11 => Some(VirtualKeyCode::Key0),
_ => keysym_to_vkey(keysym)
}
}
fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
use super::wayland_kbd::keysyms;
match keysym {
// letters
keysyms::XKB_KEY_A | keysyms::XKB_KEY_a => Some(VirtualKeyCode::A),
keysyms::XKB_KEY_B | keysyms::XKB_KEY_b => Some(VirtualKeyCode::B),
keysyms::XKB_KEY_C | keysyms::XKB_KEY_c => Some(VirtualKeyCode::C),
keysyms::XKB_KEY_D | keysyms::XKB_KEY_d => Some(VirtualKeyCode::D),
keysyms::XKB_KEY_E | keysyms::XKB_KEY_e => Some(VirtualKeyCode::E),
keysyms::XKB_KEY_F | keysyms::XKB_KEY_f => Some(VirtualKeyCode::F),
keysyms::XKB_KEY_G | keysyms::XKB_KEY_g => Some(VirtualKeyCode::G),
keysyms::XKB_KEY_H | keysyms::XKB_KEY_h => Some(VirtualKeyCode::H),
keysyms::XKB_KEY_I | keysyms::XKB_KEY_i => Some(VirtualKeyCode::I),
keysyms::XKB_KEY_J | keysyms::XKB_KEY_j => Some(VirtualKeyCode::J),
keysyms::XKB_KEY_K | keysyms::XKB_KEY_k => Some(VirtualKeyCode::K),
keysyms::XKB_KEY_L | keysyms::XKB_KEY_l => Some(VirtualKeyCode::L),
keysyms::XKB_KEY_M | keysyms::XKB_KEY_m => Some(VirtualKeyCode::M),
keysyms::XKB_KEY_N | keysyms::XKB_KEY_n => Some(VirtualKeyCode::N),
keysyms::XKB_KEY_O | keysyms::XKB_KEY_o => Some(VirtualKeyCode::O),
keysyms::XKB_KEY_P | keysyms::XKB_KEY_p => Some(VirtualKeyCode::P),
keysyms::XKB_KEY_Q | keysyms::XKB_KEY_q => Some(VirtualKeyCode::Q),
keysyms::XKB_KEY_R | keysyms::XKB_KEY_r => Some(VirtualKeyCode::R),
keysyms::XKB_KEY_S | keysyms::XKB_KEY_s => Some(VirtualKeyCode::S),
keysyms::XKB_KEY_T | keysyms::XKB_KEY_t => Some(VirtualKeyCode::T),
keysyms::XKB_KEY_U | keysyms::XKB_KEY_u => Some(VirtualKeyCode::U),
keysyms::XKB_KEY_V | keysyms::XKB_KEY_v => Some(VirtualKeyCode::V),
keysyms::XKB_KEY_W | keysyms::XKB_KEY_w => Some(VirtualKeyCode::W),
keysyms::XKB_KEY_X | keysyms::XKB_KEY_x => Some(VirtualKeyCode::X),
keysyms::XKB_KEY_Y | keysyms::XKB_KEY_y => Some(VirtualKeyCode::Y),
keysyms::XKB_KEY_Z | keysyms::XKB_KEY_z => Some(VirtualKeyCode::Z),
// F--
keysyms::XKB_KEY_F1 => Some(VirtualKeyCode::F1),
keysyms::XKB_KEY_F2 => Some(VirtualKeyCode::F2),
keysyms::XKB_KEY_F3 => Some(VirtualKeyCode::F3),
keysyms::XKB_KEY_F4 => Some(VirtualKeyCode::F4),
keysyms::XKB_KEY_F5 => Some(VirtualKeyCode::F5),
keysyms::XKB_KEY_F6 => Some(VirtualKeyCode::F6),
keysyms::XKB_KEY_F7 => Some(VirtualKeyCode::F7),
keysyms::XKB_KEY_F8 => Some(VirtualKeyCode::F8),
keysyms::XKB_KEY_F9 => Some(VirtualKeyCode::F9),
keysyms::XKB_KEY_F10 => Some(VirtualKeyCode::F10),
keysyms::XKB_KEY_F11 => Some(VirtualKeyCode::F11),
keysyms::XKB_KEY_F12 => Some(VirtualKeyCode::F12),
keysyms::XKB_KEY_F13 => Some(VirtualKeyCode::F13),
keysyms::XKB_KEY_F14 => Some(VirtualKeyCode::F14),
keysyms::XKB_KEY_F15 => Some(VirtualKeyCode::F15),
// flow control
keysyms::XKB_KEY_Print => Some(VirtualKeyCode::Snapshot),
keysyms::XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll),
keysyms::XKB_KEY_Pause => Some(VirtualKeyCode::Pause),
keysyms::XKB_KEY_Insert => Some(VirtualKeyCode::Insert),
keysyms::XKB_KEY_Home => Some(VirtualKeyCode::Home),
keysyms::XKB_KEY_Delete => Some(VirtualKeyCode::Delete),
keysyms::XKB_KEY_End => Some(VirtualKeyCode::End),
keysyms::XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown),
keysyms::XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp),
// arrows
keysyms::XKB_KEY_Left => Some(VirtualKeyCode::Left),
keysyms::XKB_KEY_Up => Some(VirtualKeyCode::Up),
keysyms::XKB_KEY_Right => Some(VirtualKeyCode::Right),
keysyms::XKB_KEY_Down => Some(VirtualKeyCode::Down),
//
keysyms::XKB_KEY_BackSpace => Some(VirtualKeyCode::Back),
keysyms::XKB_KEY_Return => Some(VirtualKeyCode::Return),
keysyms::XKB_KEY_space => Some(VirtualKeyCode::Space),
// keypad
keysyms::XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock),
keysyms::XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0),
keysyms::XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1),
keysyms::XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2),
keysyms::XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3),
keysyms::XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4),
keysyms::XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5),
keysyms::XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6),
keysyms::XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7),
keysyms::XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8),
keysyms::XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9),
// misc
// => Some(VirtualKeyCode::AbntC1),
// => Some(VirtualKeyCode::AbntC2),
keysyms::XKB_KEY_plus => Some(VirtualKeyCode::Add),
keysyms::XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe),
// => Some(VirtualKeyCode::Apps),
// => Some(VirtualKeyCode::At),
// => Some(VirtualKeyCode::Ax),
keysyms::XKB_KEY_backslash => Some(VirtualKeyCode::Backslash),
// => Some(VirtualKeyCode::Calculator),
// => Some(VirtualKeyCode::Capital),
keysyms::XKB_KEY_colon => Some(VirtualKeyCode::Colon),
keysyms::XKB_KEY_comma => Some(VirtualKeyCode::Comma),
// => Some(VirtualKeyCode::Convert),
// => Some(VirtualKeyCode::Decimal),
// => Some(VirtualKeyCode::Divide),
keysyms::XKB_KEY_equal => Some(VirtualKeyCode::Equals),
// => Some(VirtualKeyCode::Grave),
// => Some(VirtualKeyCode::Kana),
// => Some(VirtualKeyCode::Kanji),
keysyms::XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt),
// => Some(VirtualKeyCode::LBracket),
keysyms::XKB_KEY_Control_L => Some(VirtualKeyCode::LControl),
// => Some(VirtualKeyCode::LMenu),
keysyms::XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift),
// => Some(VirtualKeyCode::LWin),
// => Some(VirtualKeyCode::Mail),
// => Some(VirtualKeyCode::MediaSelect),
// => Some(VirtualKeyCode::MediaStop),
keysyms::XKB_KEY_minus => Some(VirtualKeyCode::Minus),
keysyms::XKB_KEY_asterisk => Some(VirtualKeyCode::Multiply),
// => Some(VirtualKeyCode::Mute),
// => Some(VirtualKeyCode::MyComputer),
// => Some(VirtualKeyCode::NextTrack),
// => Some(VirtualKeyCode::NoConvert),
keysyms::XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma),
keysyms::XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter),
keysyms::XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals),
// => Some(VirtualKeyCode::OEM102),
// => Some(VirtualKeyCode::Period),
// => Some(VirtualKeyCode::Playpause),
// => Some(VirtualKeyCode::Power),
// => Some(VirtualKeyCode::Prevtrack),
keysyms::XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt),
// => Some(VirtualKeyCode::RBracket),
keysyms::XKB_KEY_Control_R => Some(VirtualKeyCode::RControl),
// => Some(VirtualKeyCode::RMenu),
keysyms::XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift),
// => Some(VirtualKeyCode::RWin),
keysyms::XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon),
keysyms::XKB_KEY_slash => Some(VirtualKeyCode::Slash),
// => Some(VirtualKeyCode::Sleep),
// => Some(VirtualKeyCode::Stop),
// => Some(VirtualKeyCode::Subtract),
// => Some(VirtualKeyCode::Sysrq),
keysyms::XKB_KEY_Tab => Some(VirtualKeyCode::Tab),
keysyms::XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab),
// => Some(VirtualKeyCode::Underline),
// => Some(VirtualKeyCode::Unlabeled),
keysyms::XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown),
keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp),
// => Some(VirtualKeyCode::Wake),
// => Some(VirtualKeyCode::Webback),
// => Some(VirtualKeyCode::WebFavorites),
// => Some(VirtualKeyCode::WebForward),
// => Some(VirtualKeyCode::WebHome),
// => Some(VirtualKeyCode::WebRefresh),
// => Some(VirtualKeyCode::WebSearch),
// => Some(VirtualKeyCode::WebStop),
// => Some(VirtualKeyCode::Yen),
// fallback
_ => None
}
}

View File

@@ -1,28 +0,0 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
pub use self::window::Window;
pub use self::event_loop::{EventsLoop, EventsLoopProxy, EventsLoopSink, MonitorId};
extern crate wayland_kbd;
extern crate wayland_window;
extern crate wayland_protocols;
use wayland_client::protocol::wl_surface;
use wayland_client::Proxy;
mod event_loop;
mod pointer;
mod touch;
mod keyboard;
mod window;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(usize);
#[inline]
fn make_wid(s: &wl_surface::WlSurface) -> WindowId {
WindowId(s.ptr() as usize)
}

View File

@@ -1,194 +0,0 @@
use std::sync::{Arc, Mutex};
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase};
use events::ModifiersState;
use super::{WindowId, DeviceId};
use super::event_loop::EventsLoopSink;
use super::window::WindowStore;
use wayland_client::{Proxy, StateToken};
use wayland_client::protocol::wl_pointer;
pub struct PointerIData {
sink: Arc<Mutex<EventsLoopSink>>,
windows_token: StateToken<WindowStore>,
mouse_focus: Option<WindowId>,
axis_buffer: Option<(f32, f32)>,
axis_discrete_buffer: Option<(i32, i32)>,
axis_state: TouchPhase,
}
impl PointerIData {
pub fn new(sink: &Arc<Mutex<EventsLoopSink>>, token: StateToken<WindowStore>)
-> PointerIData
{
PointerIData {
sink: sink.clone(),
windows_token: token,
mouse_focus: None,
axis_buffer: None,
axis_discrete_buffer: None,
axis_state: TouchPhase::Cancelled
}
}
}
pub fn pointer_implementation() -> wl_pointer::Implementation<PointerIData> {
wl_pointer::Implementation {
enter: |evqh, idata, _, _, surface, x, y| {
let wid = evqh.state().get(&idata.windows_token).find_wid(surface);
if let Some(wid) = wid {
idata.mouse_focus = Some(wid);
let mut guard = idata.sink.lock().unwrap();
guard.send_event(
Event::CursorEntered {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
},
wid,
);
guard.send_event(
Event::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
position: (x, y),
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
},
leave: |evqh, idata, _, _, surface| {
idata.mouse_focus = None;
let wid = evqh.state().get(&idata.windows_token).find_wid(surface);
if let Some(wid) = wid {
let mut guard = idata.sink.lock().unwrap();
guard.send_event(
Event::CursorLeft {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
},
wid,
);
}
},
motion: |_, idata, _, _, x, y| {
if let Some(wid) = idata.mouse_focus {
idata.sink.lock().unwrap().send_event(
Event::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
position: (x, y),
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid
);
}
},
button: |_, idata, _, _, _, button, state| {
if let Some(wid) = idata.mouse_focus {
let state = match state {
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
wl_pointer::ButtonState::Released => ElementState::Released
};
let button = match button {
0x110 => MouseButton::Left,
0x111 => MouseButton::Right,
0x112 => MouseButton::Middle,
// TODO figure out the translation ?
_ => return
};
idata.sink.lock().unwrap().send_event(
Event::MouseInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
state: state,
button: button,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid
);
}
},
axis: |_, idata, pointer, _, axis, value| {
if let Some(wid) = idata.mouse_focus {
if pointer.version() < 5 {
let (mut x, mut y) = (0.0, 0.0);
// old seat compatibility
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32
}
idata.sink.lock().unwrap().send_event(
Event::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta(x as f32, y as f32),
phase: TouchPhase::Moved,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid
);
} else {
let (mut x, mut y) = idata.axis_buffer.unwrap_or((0.0, 0.0));
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32
}
idata.axis_buffer = Some((x,y));
idata.axis_state = match idata.axis_state {
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
_ => TouchPhase::Started
}
}
}
},
frame: |_, idata, _| {
let axis_buffer = idata.axis_buffer.take();
let axis_discrete_buffer = idata.axis_discrete_buffer.take();
if let Some(wid) = idata.mouse_focus {
if let Some((x, y)) = axis_discrete_buffer {
idata.sink.lock().unwrap().send_event(
Event::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::LineDelta(x as f32, y as f32),
phase: idata.axis_state,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid
);
} else if let Some((x, y)) = axis_buffer {
idata.sink.lock().unwrap().send_event(
Event::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta(x as f32, y as f32),
phase: idata.axis_state,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid
);
}
}
},
axis_source: |_, _, _, _| {},
axis_stop: |_, idata, _, _, _| {
idata.axis_state = TouchPhase::Ended;
},
axis_discrete: |_, idata, _, axis, discrete| {
let (mut x, mut y) = idata.axis_discrete_buffer.unwrap_or((0,0));
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= discrete,
wl_pointer::Axis::HorizontalScroll => x += discrete
}
idata.axis_discrete_buffer = Some((x,y));
idata.axis_state = match idata.axis_state {
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
_ => TouchPhase::Started
}
},
}
}

View File

@@ -1,106 +0,0 @@
use std::sync::{Arc, Mutex};
use {WindowEvent as Event, TouchPhase};
use super::{WindowId, DeviceId};
use super::event_loop::EventsLoopSink;
use super::window::WindowStore;
use wayland_client::StateToken;
use wayland_client::protocol::wl_touch;
pub struct TouchIData {
sink: Arc<Mutex<EventsLoopSink>>,
windows_token: StateToken<WindowStore>,
pending_ids: Vec<TouchPoint>,
}
struct TouchPoint {
wid: WindowId,
location: (f64, f64),
id: i32
}
impl TouchIData {
pub fn new(sink: &Arc<Mutex<EventsLoopSink>>, token: StateToken<WindowStore>)
-> TouchIData
{
TouchIData {
sink: sink.clone(),
windows_token: token,
pending_ids: Vec::new(),
}
}
}
pub fn touch_implementation() -> wl_touch::Implementation<TouchIData> {
wl_touch::Implementation {
down: |evqh, idata, _, _serial, _time, surface, touch_id, x, y| {
let wid = evqh.state().get(&idata.windows_token).find_wid(surface);
if let Some(wid) = wid {
let mut guard = idata.sink.lock().unwrap();
guard.send_event(
Event::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Started,
location: (x, y),
id: touch_id as u64
}),
wid,
);
idata.pending_ids.push(TouchPoint {
wid: wid,
location: (x, y),
id: touch_id
});
}
},
up: |_, idata, _, _serial, _time, touch_id| {
let idx = idata.pending_ids.iter().position(|p| p.id == touch_id);
if let Some(idx) = idx {
let pt = idata.pending_ids.remove(idx);
let mut guard = idata.sink.lock().unwrap();
guard.send_event(
Event::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Ended,
location: pt.location,
id: touch_id as u64
}),
pt.wid,
);
}
},
motion: |_, idata, _, _time, touch_id, x, y| {
let pt = idata.pending_ids.iter_mut().find(|p| p.id == touch_id);
if let Some(pt) = pt {
let mut guard = idata.sink.lock().unwrap();
pt.location = (x, y);
guard.send_event(
Event::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Moved,
location: (x, y),
id: touch_id as u64
}),
pt.wid,
);
}
},
frame: |_, _, _| {},
cancel: |_, idata, _| {
let mut guard = idata.sink.lock().unwrap();
for pt in idata.pending_ids.drain(..) {
guard.send_event(
Event::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Cancelled,
location: pt.location,
id: pt.id as u64
}),
pt.wid,
);
}
}
}
}

View File

@@ -1,364 +0,0 @@
use std::sync::{Arc, Mutex, Weak};
use wayland_client::protocol::{wl_display,wl_surface};
use wayland_client::{Proxy, StateToken};
use {CreationError, MouseCursor, CursorState, WindowAttributes};
use platform::MonitorId as PlatformMonitorId;
use window::MonitorId as RootMonitorId;
use super::{EventsLoop, WindowId, make_wid, MonitorId};
use super::wayland_window::{Frame, FrameImplementation, State as FrameState};
use super::event_loop::StateContext;
pub struct Window {
surface: wl_surface::WlSurface,
frame: Arc<Mutex<Frame>>,
monitors: Arc<Mutex<MonitorList>>,
size: Arc<Mutex<(u32, u32)>>,
kill_switch: (Arc<Mutex<bool>>, Arc<Mutex<bool>>),
display: Arc<wl_display::WlDisplay>,
need_frame_refresh: Arc<Mutex<bool>>
}
impl Window {
pub fn new(evlp: &EventsLoop, attributes: &WindowAttributes) -> Result<Window, CreationError>
{
let (width, height) = attributes.dimensions.unwrap_or((800,600));
// Create the decorated surface
let size = Arc::new(Mutex::new((width, height)));
let store_token = evlp.store.clone();
let (surface, mut frame) = evlp.create_window(
width, height, decorated_impl(),
|surface| FrameIData {
surface: surface.clone().unwrap(),
store_token: store_token.clone()
}
);
// Check for fullscreen requirements
if let Some(RootMonitorId { inner: PlatformMonitorId::Wayland(ref monitor_id) }) = attributes.fullscreen {
let info = monitor_id.info.lock().unwrap();
frame.set_state(FrameState::Fullscreen(Some(&info.output)));
} else if attributes.maximized {
frame.set_state(FrameState::Maximized);
}
// set decorations
frame.set_decorate(attributes.decorations);
// min-max dimensions
frame.set_min_size(attributes.min_dimensions.map(|(w, h)| (w as i32, h as i32)));
frame.set_max_size(attributes.max_dimensions.map(|(w, h)| (w as i32, h as i32)));
// setup the monitor tracking
let monitor_list = Arc::new(Mutex::new(MonitorList::default()));
{
let mut evq = evlp.evq.borrow_mut();
let idata = (evlp.ctxt_token.clone(), monitor_list.clone());
evq.register(&surface, surface_impl(), idata);
}
let kill_switch = Arc::new(Mutex::new(false));
let need_frame_refresh = Arc::new(Mutex::new(true));
let frame = Arc::new(Mutex::new(frame));
{
let mut evq = evlp.evq.borrow_mut();
evq.state().get_mut(&store_token).windows.push(InternalWindow {
closed: false,
newsize: None,
need_refresh: false,
need_frame_refresh: need_frame_refresh.clone(),
surface: surface.clone().unwrap(),
kill_switch: kill_switch.clone(),
frame: Arc::downgrade(&frame)
});
evq.sync_roundtrip().unwrap();
}
Ok(Window {
display: evlp.display.clone(),
surface: surface,
frame: frame,
monitors: monitor_list,
size: size,
kill_switch: (kill_switch, evlp.cleanup_needed.clone()),
need_frame_refresh: need_frame_refresh
})
}
#[inline]
pub fn id(&self) -> WindowId {
make_wid(&self.surface)
}
pub fn set_title(&self, title: &str) {
self.frame.lock().unwrap().set_title(title.into());
}
#[inline]
pub fn show(&self) {
// TODO
}
#[inline]
pub fn hide(&self) {
// TODO
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
// Not possible with wayland
None
}
#[inline]
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
// Not possible with wayland
None
}
#[inline]
pub fn set_position(&self, _x: i32, _y: i32) {
// Not possible with wayland
}
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
Some(self.size.lock().unwrap().clone())
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
let (w, h) = self.size.lock().unwrap().clone();
let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
Some((w as u32, h as u32))
}
#[inline]
// NOTE: This will only resize the borders, the contents must be updated by the user
pub fn set_inner_size(&self, x: u32, y: u32) {
self.frame.lock().unwrap().resize(x as i32, y as i32);
*(self.size.lock().unwrap()) = (x, y);
}
#[inline]
pub fn set_min_dimensions(&self, dimensions: Option<(u32, u32)>) {
self.frame.lock().unwrap().set_min_size(dimensions.map(|(w, h)| (w as i32, h as i32)));
}
#[inline]
pub fn set_max_dimensions(&self, dimensions: Option<(u32, u32)>) {
self.frame.lock().unwrap().set_max_size(dimensions.map(|(w, h)| (w as i32, h as i32)));
}
#[inline]
pub fn set_cursor(&self, _cursor: MouseCursor) {
// TODO
}
#[inline]
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
use CursorState::{Grab, Normal, Hide};
// TODO : not yet possible on wayland to grab cursor
match state {
Grab => Err("Cursor cannot be grabbed on wayland yet.".to_string()),
Hide => Err("Cursor cannot be hidden on wayland yet.".to_string()),
Normal => Ok(())
}
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
let mut factor = 1.0;
let guard = self.monitors.lock().unwrap();
for monitor_id in &guard.monitors {
let info = monitor_id.info.lock().unwrap();
if info.scale > factor { factor = info.scale; }
}
factor
}
pub fn set_decorations(&self, decorate: bool) {
self.frame.lock().unwrap().set_decorate(decorate);
*(self.need_frame_refresh.lock().unwrap()) = true;
}
pub fn set_maximized(&self, maximized: bool) {
if maximized {
self.frame.lock().unwrap().set_state(FrameState::Maximized);
} else {
self.frame.lock().unwrap().set_state(FrameState::Regular);
}
}
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
if let Some(RootMonitorId { inner: PlatformMonitorId::Wayland(ref monitor_id) }) = monitor {
let info = monitor_id.info.lock().unwrap();
self.frame.lock().unwrap().set_state(FrameState::Fullscreen(Some(&info.output)));
} else {
self.frame.lock().unwrap().set_state(FrameState::Regular);
}
}
#[inline]
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
// TODO: not yet possible on wayland
Err(())
}
pub fn get_display(&self) -> &wl_display::WlDisplay {
&*self.display
}
pub fn get_surface(&self) -> &wl_surface::WlSurface {
&self.surface
}
pub fn get_current_monitor(&self) -> MonitorId {
// we don't know how much each monitor sees us so...
// just return the most recent one ?
let guard = self.monitors.lock().unwrap();
guard.monitors.last().unwrap().clone()
}
}
impl Drop for Window {
fn drop(&mut self) {
*(self.kill_switch.0.lock().unwrap()) = true;
*(self.kill_switch.1.lock().unwrap()) = true;
}
}
/*
* Internal store for windows
*/
struct InternalWindow {
surface: wl_surface::WlSurface,
newsize: Option<(i32, i32)>,
need_refresh: bool,
need_frame_refresh: Arc<Mutex<bool>>,
closed: bool,
kill_switch: Arc<Mutex<bool>>,
frame: Weak<Mutex<Frame>>
}
pub struct WindowStore {
windows: Vec<InternalWindow>
}
impl WindowStore {
pub fn new() -> WindowStore {
WindowStore { windows: Vec::new() }
}
pub fn find_wid(&self, surface: &wl_surface::WlSurface) -> Option<WindowId> {
for window in &self.windows {
if surface.equals(&window.surface) {
return Some(make_wid(surface));
}
}
None
}
pub fn cleanup(&mut self) -> Vec<WindowId> {
let mut pruned = Vec::new();
self.windows.retain(|w| {
if *w.kill_switch.lock().unwrap() {
// window is dead, cleanup
pruned.push(make_wid(&w.surface));
w.surface.destroy();
false
} else {
true
}
});
pruned
}
pub fn for_each<F>(&mut self, mut f: F)
where F: FnMut(Option<(i32, i32)>, bool, bool, bool, WindowId, Option<&mut Frame>)
{
for window in &mut self.windows {
let opt_arc = window.frame.upgrade();
let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
f(
window.newsize.take(),
window.need_refresh,
::std::mem::replace(&mut *window.need_frame_refresh.lock().unwrap(), false),
window.closed,
make_wid(&window.surface),
opt_mutex_lock.as_mut().map(|m| &mut **m)
);
window.need_refresh = false;
// avoid re-spamming the event
window.closed = false;
}
}
}
/*
* Protocol implementation
*/
struct FrameIData {
store_token: StateToken<WindowStore>,
surface: wl_surface::WlSurface
}
fn decorated_impl() -> FrameImplementation<FrameIData> {
FrameImplementation {
configure: |evqh, idata, _, newsize| {
let store = evqh.state().get_mut(&idata.store_token);
for window in &mut store.windows {
if window.surface.equals(&idata.surface) {
window.newsize = newsize;
window.need_refresh = true;
*(window.need_frame_refresh.lock().unwrap()) = true;
return;
}
}
},
close: |evqh, idata| {
let store = evqh.state().get_mut(&idata.store_token);
for window in &mut store.windows {
if window.surface.equals(&idata.surface) {
window.closed = true;
return;
}
}
},
refresh: |evqh, idata| {
let store = evqh.state().get_mut(&idata.store_token);
for window in &mut store.windows {
if window.surface.equals(&idata.surface) {
*(window.need_frame_refresh.lock().unwrap()) = true;
return;
}
}
}
}
}
#[derive(Default)]
struct MonitorList {
monitors: Vec<MonitorId>
}
fn surface_impl() -> wl_surface::Implementation<(StateToken<StateContext>, Arc<Mutex<MonitorList>>)> {
wl_surface::Implementation {
enter: |evqh, &mut (ref token, ref list), _, output| {
let mut guard = list.lock().unwrap();
let ctxt = evqh.state().get(token);
let monitor = ctxt.monitor_id_for(output);
guard.monitors.push(monitor);
},
leave: |evqh, &mut (ref token, ref list), _, output| {
let mut guard = list.lock().unwrap();
let ctxt = evqh.state().get(token);
let monitor = ctxt.monitor_id_for(output);
guard.monitors.retain(|m| !Arc::ptr_eq(&m.info, &monitor.info));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
pub use x11_dl::keysym::*;
pub use x11_dl::xcursor::*;
pub use x11_dl::xlib::*;
pub use x11_dl::xinput::*;
pub use x11_dl::xinput2::*;
pub use x11_dl::xlib_xcb::*;
pub use x11_dl::error::OpenError;
pub use x11_dl::xrandr::*;

View File

@@ -1,134 +0,0 @@
use std::ptr;
use std::sync::Arc;
use std::os::raw::{c_short, c_void};
use super::{ffi, util, XConnection, XError};
#[derive(Debug)]
pub enum ImeContextCreationError {
XError(XError),
Null,
}
unsafe fn create_pre_edit_attr<'a>(
xconn: &'a Arc<XConnection>,
ic_spot: &'a ffi::XPoint,
) -> util::XSmartPointer<'a, c_void> {
util::XSmartPointer::new(
xconn,
(xconn.xlib.XVaCreateNestedList)(
0,
ffi::XNSpotLocation_0.as_ptr() as *const _,
ic_spot,
ptr::null_mut::<()>(),
),
).expect("XVaCreateNestedList returned NULL")
}
// WARNING: this struct doesn't destroy its XIC resource when dropped.
// This is intentional, as it doesn't have enough information to know whether or not the context
// still exists on the server. Since `ImeInner` has that awareness, destruction must be handled
// through `ImeInner`.
#[derive(Debug)]
pub struct ImeContext {
pub ic: ffi::XIC,
pub ic_spot: ffi::XPoint,
}
impl ImeContext {
pub unsafe fn new(
xconn: &Arc<XConnection>,
im: ffi::XIM,
window: ffi::Window,
ic_spot: Option<ffi::XPoint>,
) -> Result<Self, ImeContextCreationError> {
let ic = if let Some(ic_spot) = ic_spot {
ImeContext::create_ic_with_spot(xconn, im, window, ic_spot)
} else {
ImeContext::create_ic(xconn, im, window)
};
let ic = ic.ok_or(ImeContextCreationError::Null)?;
xconn.check_errors().map_err(ImeContextCreationError::XError)?;
Ok(ImeContext {
ic,
ic_spot: ic_spot.unwrap_or_else(|| ffi::XPoint { x: 0, y: 0 }),
})
}
unsafe fn create_ic(
xconn: &Arc<XConnection>,
im: ffi::XIM,
window: ffi::Window,
) -> Option<ffi::XIC> {
let ic = (xconn.xlib.XCreateIC)(
im,
ffi::XNInputStyle_0.as_ptr() as *const _,
ffi::XIMPreeditNothing | ffi::XIMStatusNothing,
ffi::XNClientWindow_0.as_ptr() as *const _,
window,
ptr::null_mut::<()>(),
);
if ic.is_null() {
None
} else {
Some(ic)
}
}
unsafe fn create_ic_with_spot(
xconn: &Arc<XConnection>,
im: ffi::XIM,
window: ffi::Window,
ic_spot: ffi::XPoint,
) -> Option<ffi::XIC> {
let pre_edit_attr = create_pre_edit_attr(xconn, &ic_spot);
let ic = (xconn.xlib.XCreateIC)(
im,
ffi::XNInputStyle_0.as_ptr() as *const _,
ffi::XIMPreeditNothing | ffi::XIMStatusNothing,
ffi::XNClientWindow_0.as_ptr() as *const _,
window,
ffi::XNPreeditAttributes_0.as_ptr() as *const _,
pre_edit_attr.ptr,
ptr::null_mut::<()>(),
);
if ic.is_null() {
None
} else {
Some(ic)
}
}
pub fn focus(&self, xconn: &Arc<XConnection>) -> Result<(), XError> {
unsafe {
(xconn.xlib.XSetICFocus)(self.ic);
}
xconn.check_errors()
}
pub fn unfocus(&self, xconn: &Arc<XConnection>) -> Result<(), XError> {
unsafe {
(xconn.xlib.XUnsetICFocus)(self.ic);
}
xconn.check_errors()
}
pub fn set_spot(&mut self, xconn: &Arc<XConnection>, x: c_short, y: c_short) {
if self.ic_spot.x == x && self.ic_spot.y == y {
return;
}
self.ic_spot = ffi::XPoint { x, y };
unsafe {
let pre_edit_attr = create_pre_edit_attr(xconn, &self.ic_spot);
(xconn.xlib.XSetICValues)(
self.ic,
ffi::XNPreeditAttributes_0.as_ptr() as *const _,
pre_edit_attr.ptr,
ptr::null_mut::<()>(),
);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,129 +0,0 @@
use std::sync::Arc;
use std::slice;
use super::XConnection;
#[derive(Clone)]
pub struct MonitorId {
/// The actual id
id: u32,
/// The name of the monitor
name: String,
/// The size of the monitor
dimensions: (u32, u32),
/// The position of the monitor in the X screen
position: (i32, i32),
/// If the monitor is the primary one
primary: bool,
/// The DPI scaling factor
hidpi_factor: f32,
}
pub fn get_available_monitors(x: &Arc<XConnection>) -> Vec<MonitorId> {
let mut available = Vec::new();
unsafe {
let root = (x.xlib.XDefaultRootWindow)(x.display);
let resources = (x.xrandr.XRRGetScreenResources)(x.display, root);
if let Some(ref xrandr_1_5) = x.xrandr_1_5 {
// We're in XRandR >= 1.5, enumerate Monitors to handle things like MST and videowalls
let mut nmonitors = 0;
let monitors = (xrandr_1_5.XRRGetMonitors)(x.display, root, 1, &mut nmonitors);
for i in 0..nmonitors {
let monitor = *(monitors.offset(i as isize));
let output = (xrandr_1_5.XRRGetOutputInfo)(x.display, resources, *(monitor.outputs.offset(0)));
let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
let name = String::from_utf8_lossy(nameslice).into_owned();
let hidpi_factor = {
let x_mm = (*output).mm_width as f32;
let y_mm = (*output).mm_height as f32;
let x_px = monitor.width as f32;
let y_px = monitor.height as f32;
let ppmm = ((x_px * y_px) / (x_mm * y_mm)).sqrt();
// Quantize 1/12 step size
((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0)
};
(xrandr_1_5.XRRFreeOutputInfo)(output);
available.push(MonitorId{
id: i as u32,
name,
hidpi_factor,
dimensions: (monitor.width as u32, monitor.height as u32),
position: (monitor.x as i32, monitor.y as i32),
primary: (monitor.primary != 0),
});
}
(xrandr_1_5.XRRFreeMonitors)(monitors);
} else {
// We're in XRandR < 1.5, enumerate CRTCs. Everything will work but MST and
// videowall setups will show more monitors than the logical groups the user
// cares about
for i in 0..(*resources).ncrtc {
let crtcid = *((*resources).crtcs.offset(i as isize));
let crtc = (x.xrandr.XRRGetCrtcInfo)(x.display, resources, crtcid);
if (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0 {
let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *((*crtc).outputs.offset(0)));
let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
let name = String::from_utf8_lossy(nameslice).into_owned();
let hidpi_factor = {
let x_mm = (*output).mm_width as f32;
let y_mm = (*output).mm_height as f32;
let x_px = (*crtc).width as f32;
let y_px = (*crtc).height as f32;
let ppmm = ((x_px * y_px) / (x_mm * y_mm)).sqrt();
// Quantize 1/12 step size
((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0)
};
(x.xrandr.XRRFreeOutputInfo)(output);
available.push(MonitorId{
id: crtcid as u32,
name,
hidpi_factor,
dimensions: ((*crtc).width as u32, (*crtc).height as u32),
position: ((*crtc).x as i32, (*crtc).y as i32),
primary: true,
});
}
(x.xrandr.XRRFreeCrtcInfo)(crtc);
}
}
(x.xrandr.XRRFreeScreenResources)(resources);
}
available
}
#[inline]
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId {
get_available_monitors(x).into_iter().find(|m| m.primary)
// 'no primary' case is better handled picking some existing monitor
.or_else(|| get_available_monitors(x).into_iter().next())
.expect("[winit] Failed to find any x11 monitor")
}
impl MonitorId {
pub fn get_name(&self) -> Option<String> {
Some(self.name.clone())
}
#[inline]
pub fn get_native_identifier(&self) -> u32 {
self.id as u32
}
pub fn get_dimensions(&self) -> (u32, u32) {
self.dimensions
}
pub fn get_position(&self) -> (i32, i32) {
self.position
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
self.hidpi_factor
}
}

View File

@@ -1,365 +0,0 @@
use std::mem;
use std::ptr;
use std::str;
use std::sync::Arc;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_char, c_double, c_int, c_long, c_short, c_uchar, c_uint, c_ulong};
use super::{ffi, XConnection, XError};
use events::ModifiersState;
pub struct XSmartPointer<'a, T> {
xconn: &'a Arc<XConnection>,
pub ptr: *mut T,
}
impl<'a, T> XSmartPointer<'a, T> {
// You're responsible for only passing things to this that should be XFree'd.
// Returns None if ptr is null.
pub fn new(xconn: &'a Arc<XConnection>, ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
Some(XSmartPointer {
xconn,
ptr,
})
} else {
None
}
}
}
impl<'a, T> Deref for XSmartPointer<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.ptr }
}
}
impl<'a, T> DerefMut for XSmartPointer<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.ptr }
}
}
impl<'a, T> Drop for XSmartPointer<'a, T> {
fn drop(&mut self) {
unsafe {
(self.xconn.xlib.XFree)(self.ptr as *mut _);
}
}
}
pub unsafe fn get_atom(xconn: &Arc<XConnection>, name: &[u8]) -> Result<ffi::Atom, XError> {
let atom_name: *const c_char = name.as_ptr() as _;
let atom = (xconn.xlib.XInternAtom)(xconn.display, atom_name, ffi::False);
xconn.check_errors().map(|_| atom)
}
pub unsafe fn send_client_msg(
xconn: &Arc<XConnection>,
window: c_ulong, // the window this is "about"; not necessarily this window
target_window: c_ulong, // the window we're sending to
message_type: ffi::Atom,
event_mask: Option<c_long>,
data: (c_long, c_long, c_long, c_long, c_long),
) -> Result<(), XError> {
let mut event: ffi::XClientMessageEvent = mem::uninitialized();
event.type_ = ffi::ClientMessage;
event.display = xconn.display;
event.window = window;
event.message_type = message_type;
event.format = 32;
event.data = ffi::ClientMessageData::new();
event.data.set_long(0, data.0);
event.data.set_long(1, data.1);
event.data.set_long(2, data.2);
event.data.set_long(3, data.3);
event.data.set_long(4, data.4);
let event_mask = event_mask.unwrap_or(ffi::NoEventMask);
(xconn.xlib.XSendEvent)(
xconn.display,
target_window,
ffi::False,
event_mask,
&mut event.into(),
);
xconn.check_errors().map(|_| ())
}
#[derive(Debug, Clone)]
pub enum GetPropertyError {
XError(XError),
TypeMismatch(ffi::Atom),
FormatMismatch(c_int),
NothingAllocated,
}
impl GetPropertyError {
pub fn is_actual_property_type(&self, t: ffi::Atom) -> bool {
if let GetPropertyError::TypeMismatch(actual_type) = *self {
actual_type == t
} else {
false
}
}
}
pub unsafe fn get_property<T>(
xconn: &Arc<XConnection>,
window: c_ulong,
property: ffi::Atom,
property_type: ffi::Atom,
) -> Result<Vec<T>, GetPropertyError> {
let mut data = Vec::new();
let mut done = false;
while !done {
let mut actual_type: ffi::Atom = mem::uninitialized();
let mut actual_format: c_int = mem::uninitialized();
let mut byte_count: c_ulong = mem::uninitialized();
let mut bytes_after: c_ulong = mem::uninitialized();
let mut buf: *mut c_uchar = ptr::null_mut();
(xconn.xlib.XGetWindowProperty)(
xconn.display,
window,
property,
(data.len() / 4) as c_long,
1024,
ffi::False,
property_type,
&mut actual_type,
&mut actual_format,
&mut byte_count,
&mut bytes_after,
&mut buf,
);
if let Err(e) = xconn.check_errors() {
return Err(GetPropertyError::XError(e));
}
if actual_type != property_type {
return Err(GetPropertyError::TypeMismatch(actual_type));
}
// Fun fact: actual_format ISN'T the size of the type; it's more like a really bad enum
let format_mismatch = match actual_format as usize {
8 => mem::size_of::<T>() != mem::size_of::<c_char>(),
16 => mem::size_of::<T>() != mem::size_of::<c_short>(),
32 => mem::size_of::<T>() != mem::size_of::<c_long>(),
_ => true, // this won't actually be reached; the XError condition above is triggered
};
if format_mismatch {
return Err(GetPropertyError::FormatMismatch(actual_format));
}
if !buf.is_null() {
let mut buf =
Vec::from_raw_parts(buf as *mut T, byte_count as usize, byte_count as usize);
data.append(&mut buf);
} else {
return Err(GetPropertyError::NothingAllocated);
}
done = bytes_after == 0;
}
Ok(data)
}
impl From<ffi::XIModifierState> for ModifiersState {
fn from(mods: ffi::XIModifierState) -> Self {
let state = mods.effective as c_uint;
ModifiersState {
alt: state & ffi::Mod1Mask != 0,
shift: state & ffi::ShiftMask != 0,
ctrl: state & ffi::ControlMask != 0,
logo: state & ffi::Mod4Mask != 0,
}
}
}
#[derive(Debug)]
pub struct PointerState {
#[allow(dead_code)]
root: ffi::Window,
#[allow(dead_code)]
child: ffi::Window,
#[allow(dead_code)]
root_x: c_double,
#[allow(dead_code)]
root_y: c_double,
#[allow(dead_code)]
win_x: c_double,
#[allow(dead_code)]
win_y: c_double,
#[allow(dead_code)]
buttons: ffi::XIButtonState,
modifiers: ffi::XIModifierState,
#[allow(dead_code)]
group: ffi::XIGroupState,
#[allow(dead_code)]
relative_to_window: bool,
}
impl PointerState {
pub fn get_modifier_state(&self) -> ModifiersState {
self.modifiers.into()
}
}
pub unsafe fn query_pointer(
xconn: &Arc<XConnection>,
window: ffi::Window,
device_id: c_int,
) -> Result<PointerState, XError> {
let mut root_return = mem::uninitialized();
let mut child_return = mem::uninitialized();
let mut root_x_return = mem::uninitialized();
let mut root_y_return = mem::uninitialized();
let mut win_x_return = mem::uninitialized();
let mut win_y_return = mem::uninitialized();
let mut buttons_return = mem::uninitialized();
let mut modifiers_return = mem::uninitialized();
let mut group_return = mem::uninitialized();
let relative_to_window = (xconn.xinput2.XIQueryPointer)(
xconn.display,
device_id,
window,
&mut root_return,
&mut child_return,
&mut root_x_return,
&mut root_y_return,
&mut win_x_return,
&mut win_y_return,
&mut buttons_return,
&mut modifiers_return,
&mut group_return,
) == ffi::True;
xconn.check_errors()?;
Ok(PointerState {
root: root_return,
child: child_return,
root_x: root_x_return,
root_y: root_y_return,
win_x: win_x_return,
win_y: win_y_return,
buttons: buttons_return,
modifiers: modifiers_return,
group: group_return,
relative_to_window,
})
}
unsafe fn lookup_utf8_inner(
xconn: &Arc<XConnection>,
ic: ffi::XIC,
key_event: &mut ffi::XKeyEvent,
buffer: &mut [u8],
) -> (ffi::KeySym, ffi::Status, c_int) {
let mut keysym: ffi::KeySym = 0;
let mut status: ffi::Status = 0;
let count = (xconn.xlib.Xutf8LookupString)(
ic,
key_event,
buffer.as_mut_ptr() as *mut c_char,
buffer.len() as c_int,
&mut keysym,
&mut status,
);
(keysym, status, count)
}
pub unsafe fn lookup_utf8(
xconn: &Arc<XConnection>,
ic: ffi::XIC,
key_event: &mut ffi::XKeyEvent,
) -> String {
const INIT_BUFF_SIZE: usize = 16;
// Buffer allocated on heap instead of stack, due to the possible reallocation
let mut buffer: Vec<u8> = vec![mem::uninitialized(); INIT_BUFF_SIZE];
let (_, status, mut count) = lookup_utf8_inner(
xconn,
ic,
key_event,
&mut buffer,
);
// Buffer overflowed, dynamically reallocate
if status == ffi::XBufferOverflow {
buffer = vec![mem::uninitialized(); count as usize];
let (_, _, new_count) = lookup_utf8_inner(
xconn,
ic,
key_event,
&mut buffer,
);
count = new_count;
}
str::from_utf8(&buffer[..count as usize]).unwrap_or("").to_string()
}
#[derive(Debug)]
pub struct FrameExtents {
pub left: c_ulong,
pub right: c_ulong,
pub top: c_ulong,
pub bottom: c_ulong,
}
impl FrameExtents {
pub fn new(left: c_ulong, right: c_ulong, top: c_ulong, bottom: c_ulong) -> Self {
FrameExtents { left, right, top, bottom }
}
pub fn from_border(border: c_ulong) -> Self {
Self::new(border, border, border, border)
}
}
#[derive(Debug)]
pub struct WindowGeometry {
pub x: c_int,
pub y: c_int,
pub width: c_uint,
pub height: c_uint,
pub frame: FrameExtents,
}
impl WindowGeometry {
pub fn get_position(&self) -> (i32, i32) {
(self.x as _, self.y as _)
}
pub fn get_inner_position(&self) -> (i32, i32) {
(
self.x.saturating_add(self.frame.left as c_int) as _,
self.y.saturating_add(self.frame.top as c_int) as _,
)
}
pub fn get_inner_size(&self) -> (u32, u32) {
(self.width as _, self.height as _)
}
pub fn get_outer_size(&self) -> (u32, u32) {
(
self.width.saturating_add(
self.frame.left.saturating_add(self.frame.right) as c_uint
) as _,
self.height.saturating_add(
self.frame.top.saturating_add(self.frame.bottom) as c_uint
) as _,
)
}
}

File diff suppressed because it is too large Load Diff

371
src/platform/macos.rs Normal file
View File

@@ -0,0 +1,371 @@
use std::os::raw::c_void;
use objc2::rc::Id;
use crate::{
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
monitor::MonitorHandle,
window::{Window, WindowBuilder},
};
/// Additional methods on [`Window`] that are specific to MacOS.
pub trait WindowExtMacOS {
/// Returns a pointer to the cocoa `NSWindow` that is used by this window.
///
/// The pointer will become invalid when the [`Window`] is destroyed.
fn ns_window(&self) -> *mut c_void;
/// Returns a pointer to the cocoa `NSView` that is used by this window.
///
/// The pointer will become invalid when the [`Window`] is destroyed.
fn ns_view(&self) -> *mut c_void;
/// Returns whether or not the window is in simple fullscreen mode.
fn simple_fullscreen(&self) -> bool;
/// Toggles a fullscreen mode that doesn't require a new macOS space.
/// Returns a boolean indicating whether the transition was successful (this
/// won't work if the window was already in the native fullscreen).
///
/// This is how fullscreen used to work on macOS in versions before Lion.
/// And allows the user to have a fullscreen window without using another
/// space or taking control over the entire monitor.
fn set_simple_fullscreen(&self, fullscreen: bool) -> bool;
/// Returns whether or not the window has shadow.
fn has_shadow(&self) -> bool;
/// Sets whether or not the window has shadow.
fn set_has_shadow(&self, has_shadow: bool);
/// Get the window's edit state.
///
/// # Examples
///
/// ```ignore
/// WindowEvent::CloseRequested => {
/// if window.is_document_edited() {
/// // Show the user a save pop-up or similar
/// } else {
/// // Close the window
/// drop(window);
/// }
/// }
/// ```
fn is_document_edited(&self) -> bool;
/// Put the window in a state which indicates a file save is required.
fn set_document_edited(&self, edited: bool);
/// Set option as alt behavior as described in [`OptionAsAlt`].
///
/// This will ignore diacritical marks and accent characters from
/// being processed as received characters. Instead, the input
/// device's raw character will be placed in event queues with the
/// Alt modifier set.
fn set_option_as_alt(&self, option_as_alt: OptionAsAlt);
/// Getter for the [`WindowExtMacOS::set_option_as_alt`].
fn option_as_alt(&self) -> OptionAsAlt;
}
impl WindowExtMacOS for Window {
#[inline]
fn ns_window(&self) -> *mut c_void {
self.window.ns_window()
}
#[inline]
fn ns_view(&self) -> *mut c_void {
self.window.ns_view()
}
#[inline]
fn simple_fullscreen(&self) -> bool {
self.window.simple_fullscreen()
}
#[inline]
fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
self.window.set_simple_fullscreen(fullscreen)
}
#[inline]
fn has_shadow(&self) -> bool {
self.window.has_shadow()
}
#[inline]
fn set_has_shadow(&self, has_shadow: bool) {
self.window.set_has_shadow(has_shadow)
}
#[inline]
fn is_document_edited(&self) -> bool {
self.window.is_document_edited()
}
#[inline]
fn set_document_edited(&self, edited: bool) {
self.window.set_document_edited(edited)
}
#[inline]
fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
self.window.set_option_as_alt(option_as_alt)
}
#[inline]
fn option_as_alt(&self) -> OptionAsAlt {
self.window.option_as_alt()
}
}
/// Corresponds to `NSApplicationActivationPolicy`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ActivationPolicy {
/// Corresponds to `NSApplicationActivationPolicyRegular`.
Regular,
/// Corresponds to `NSApplicationActivationPolicyAccessory`.
Accessory,
/// Corresponds to `NSApplicationActivationPolicyProhibited`.
Prohibited,
}
impl Default for ActivationPolicy {
fn default() -> Self {
ActivationPolicy::Regular
}
}
/// Additional methods on [`WindowBuilder`] that are specific to MacOS.
///
/// **Note:** Properties dealing with the titlebar will be overwritten by the [`WindowBuilder::with_decorations`] method:
/// - `with_titlebar_transparent`
/// - `with_title_hidden`
/// - `with_titlebar_hidden`
/// - `with_titlebar_buttons_hidden`
/// - `with_fullsize_content_view`
pub trait WindowBuilderExtMacOS {
/// Enables click-and-drag behavior for the entire window, not just the titlebar.
fn with_movable_by_window_background(self, movable_by_window_background: bool)
-> WindowBuilder;
/// Makes the titlebar transparent and allows the content to appear behind it.
fn with_titlebar_transparent(self, titlebar_transparent: bool) -> WindowBuilder;
/// Hides the window title.
fn with_title_hidden(self, title_hidden: bool) -> WindowBuilder;
/// Hides the window titlebar.
fn with_titlebar_hidden(self, titlebar_hidden: bool) -> WindowBuilder;
/// Hides the window titlebar buttons.
fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> WindowBuilder;
/// Makes the window content appear behind the titlebar.
fn with_fullsize_content_view(self, fullsize_content_view: bool) -> WindowBuilder;
fn with_disallow_hidpi(self, disallow_hidpi: bool) -> WindowBuilder;
fn with_has_shadow(self, has_shadow: bool) -> WindowBuilder;
/// Window accepts click-through mouse events.
fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> WindowBuilder;
/// Set whether the `OptionAsAlt` key is interpreted as the `Alt` modifier.
///
/// See [`WindowExtMacOS::set_option_as_alt`] for details on what this means if set.
fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> WindowBuilder;
}
impl WindowBuilderExtMacOS for WindowBuilder {
#[inline]
fn with_movable_by_window_background(
mut self,
movable_by_window_background: bool,
) -> WindowBuilder {
self.platform_specific.movable_by_window_background = movable_by_window_background;
self
}
#[inline]
fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> WindowBuilder {
self.platform_specific.titlebar_transparent = titlebar_transparent;
self
}
#[inline]
fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> WindowBuilder {
self.platform_specific.titlebar_hidden = titlebar_hidden;
self
}
#[inline]
fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> WindowBuilder {
self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
self
}
#[inline]
fn with_title_hidden(mut self, title_hidden: bool) -> WindowBuilder {
self.platform_specific.title_hidden = title_hidden;
self
}
#[inline]
fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> WindowBuilder {
self.platform_specific.fullsize_content_view = fullsize_content_view;
self
}
#[inline]
fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> WindowBuilder {
self.platform_specific.disallow_hidpi = disallow_hidpi;
self
}
#[inline]
fn with_has_shadow(mut self, has_shadow: bool) -> WindowBuilder {
self.platform_specific.has_shadow = has_shadow;
self
}
#[inline]
fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> WindowBuilder {
self.platform_specific.accepts_first_mouse = accepts_first_mouse;
self
}
#[inline]
fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> WindowBuilder {
self.platform_specific.option_as_alt = option_as_alt;
self
}
}
pub trait EventLoopBuilderExtMacOS {
/// Sets the activation policy for the application.
///
/// It is set to [`ActivationPolicy::Regular`] by default.
///
/// # Example
///
/// Set the activation policy to "accessory".
///
/// ```
/// use winit::event_loop::EventLoopBuilder;
/// #[cfg(target_os = "macos")]
/// use winit::platform::macos::{EventLoopBuilderExtMacOS, ActivationPolicy};
///
/// let mut builder = EventLoopBuilder::new();
/// #[cfg(target_os = "macos")]
/// builder.with_activation_policy(ActivationPolicy::Accessory);
/// # if false { // We can't test this part
/// let event_loop = builder.build();
/// # }
/// ```
fn with_activation_policy(&mut self, activation_policy: ActivationPolicy) -> &mut Self;
/// Used to control whether a default menubar menu is created.
///
/// Menu creation is enabled by default.
///
/// # Example
///
/// Disable creating a default menubar.
///
/// ```
/// use winit::event_loop::EventLoopBuilder;
/// #[cfg(target_os = "macos")]
/// use winit::platform::macos::EventLoopBuilderExtMacOS;
///
/// let mut builder = EventLoopBuilder::new();
/// #[cfg(target_os = "macos")]
/// builder.with_default_menu(false);
/// # if false { // We can't test this part
/// let event_loop = builder.build();
/// # }
/// ```
fn with_default_menu(&mut self, enable: bool) -> &mut Self;
/// Used to prevent the application from automatically activating when launched if
/// another application is already active.
///
/// The default behavior is to ignore other applications and activate when launched.
fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
}
impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
#[inline]
fn with_activation_policy(&mut self, activation_policy: ActivationPolicy) -> &mut Self {
self.platform_specific.activation_policy = activation_policy;
self
}
#[inline]
fn with_default_menu(&mut self, enable: bool) -> &mut Self {
self.platform_specific.default_menu = enable;
self
}
#[inline]
fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
self.platform_specific.activate_ignoring_other_apps = ignore;
self
}
}
/// Additional methods on [`MonitorHandle`] that are specific to MacOS.
pub trait MonitorHandleExtMacOS {
/// Returns the identifier of the monitor for Cocoa.
fn native_id(&self) -> u32;
/// Returns a pointer to the NSScreen representing this monitor.
fn ns_screen(&self) -> Option<*mut c_void>;
}
impl MonitorHandleExtMacOS for MonitorHandle {
#[inline]
fn native_id(&self) -> u32 {
self.inner.native_identifier()
}
fn ns_screen(&self) -> Option<*mut c_void> {
self.inner.ns_screen().map(|s| Id::as_ptr(&s) as _)
}
}
/// Additional methods on [`EventLoopWindowTarget`] that are specific to macOS.
pub trait EventLoopWindowTargetExtMacOS {
/// Hide the entire application. In most applications this is typically triggered with Command-H.
fn hide_application(&self);
/// Hide the other applications. In most applications this is typically triggered with Command+Option-H.
fn hide_other_applications(&self);
}
impl<T> EventLoopWindowTargetExtMacOS for EventLoopWindowTarget<T> {
fn hide_application(&self) {
self.p.hide_application()
}
fn hide_other_applications(&self) {
self.p.hide_other_applications()
}
}
/// Option as alt behavior.
///
/// The default is `None`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum OptionAsAlt {
/// The left `Option` key is treated as `Alt`.
OnlyLeft,
/// The right `Option` key is treated as `Alt`.
OnlyRight,
/// Both `Option` keys are treated as `Alt`.
Both,
/// No special handling is applied for `Option` key.
None,
}
impl Default for OptionAsAlt {
fn default() -> Self {
OptionAsAlt::None
}
}

View File

@@ -1,774 +0,0 @@
use {ControlFlow, EventsLoopClosed};
use cocoa::{self, appkit, foundation};
use cocoa::appkit::{NSApplication, NSEvent, NSEventMask, NSEventModifierFlags, NSEventPhase, NSView, NSWindow};
use events::{self, ElementState, Event, MouseButton, TouchPhase, WindowEvent, DeviceEvent, ModifiersState, KeyboardInput};
use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};
use super::window::Window2;
use std;
use super::DeviceId;
pub struct EventsLoop {
modifiers: Modifiers,
pub shared: Arc<Shared>,
}
// State shared between the `EventsLoop` and its registered windows.
pub struct Shared {
pub windows: Mutex<Vec<Weak<Window2>>>,
pub pending_events: Mutex<VecDeque<Event>>,
// The user event callback given via either of the `poll_events` or `run_forever` methods.
//
// We store the user's callback here so that it may be accessed by each of the window delegate
// callbacks (e.g. resize, close, etc) for the duration of a call to either of the
// `poll_events` or `run_forever` methods.
//
// This is *only* `Some` for the duration of a call to either of these methods and will be
// `None` otherwise.
user_callback: UserCallback,
}
#[derive(Clone)]
pub struct Proxy {}
struct Modifiers {
shift_pressed: bool,
ctrl_pressed: bool,
win_pressed: bool,
alt_pressed: bool,
}
// Wrapping the user callback in a type allows us to:
//
// - ensure the callback pointer is never accidentally cloned
// - ensure that only the `EventsLoop` can `store` and `drop` the callback pointer
// - Share access to the user callback with the NSWindow callbacks.
pub struct UserCallback {
mutex: Mutex<Option<*mut FnMut(Event)>>,
}
impl Shared {
pub fn new() -> Self {
Shared {
windows: Mutex::new(Vec::new()),
pending_events: Mutex::new(VecDeque::new()),
user_callback: UserCallback { mutex: Mutex::new(None) },
}
}
fn call_user_callback_with_pending_events(&self) {
loop {
let event = match self.pending_events.lock().unwrap().pop_front() {
Some(event) => event,
None => return,
};
unsafe {
self.user_callback.call_with_event(event);
}
}
}
// Calls the user callback if one exists.
//
// Otherwise, stores the event in the `pending_events` queue.
//
// This is necessary for the case when `WindowDelegate` callbacks are triggered during a call
// to the user's callback.
pub fn call_user_callback_with_event_or_store_in_pending(&self, event: Event) {
if self.user_callback.mutex.lock().unwrap().is_some() {
unsafe {
self.user_callback.call_with_event(event);
}
} else {
self.pending_events.lock().unwrap().push_back(event);
}
}
// Removes the window with the given `Id` from the `windows` list.
//
// This is called in response to `windowWillClose`.
pub fn find_and_remove_window(&self, id: super::window::Id) {
if let Ok(mut windows) = self.windows.lock() {
windows.retain(|w| match w.upgrade() {
Some(w) => w.id() != id,
None => true,
});
}
}
}
impl Modifiers {
pub fn new() -> Self {
Modifiers {
shift_pressed: false,
ctrl_pressed: false,
win_pressed: false,
alt_pressed: false,
}
}
}
impl UserCallback {
// Here we store user's `callback` behind the mutex so that they may be safely shared between
// each of the window delegates.
//
// In order to make sure that the pointer is always valid, we must manually guarantee that it
// is dropped before the callback itself is dropped. Thus, this should *only* be called at the
// beginning of a call to `poll_events` and `run_forever`, both of which *must* drop the
// callback at the end of their scope using the `drop` method.
fn store<F>(&self, callback: &mut F)
where F: FnMut(Event)
{
let trait_object = callback as &mut FnMut(Event);
let trait_object_ptr = trait_object as *const FnMut(Event) as *mut FnMut(Event);
*self.mutex.lock().unwrap() = Some(trait_object_ptr);
}
// Emits the given event via the user-given callback.
//
// This is unsafe as it requires dereferencing the pointer to the user-given callback. We
// guarantee this is safe by ensuring the `UserCallback` never lives longer than the user-given
// callback.
//
// Note that the callback may not always be `Some`. This is because some `NSWindowDelegate`
// callbacks can be triggered by means other than `NSApp().sendEvent`. For example, if a window
// is destroyed or created during a call to the user's callback, the `WindowDelegate` methods
// may be called with `windowShouldClose` or `windowDidResignKey`.
unsafe fn call_with_event(&self, event: Event) {
let callback = match self.mutex.lock().unwrap().take() {
Some(callback) => callback,
None => return,
};
(*callback)(event);
*self.mutex.lock().unwrap() = Some(callback);
}
// Used to drop the user callback pointer at the end of the `poll_events` and `run_forever`
// methods. This is done to enforce our guarantee that the top callback will never live longer
// than the call to either `poll_events` or `run_forever` to which it was given.
fn drop(&self) {
self.mutex.lock().unwrap().take();
}
}
impl EventsLoop {
pub fn new() -> Self {
// Mark this thread as the main thread of the Cocoa event system.
//
// This must be done before any worker threads get a chance to call it
// (e.g., via `EventsLoopProxy::wakeup()`), causing a wrong thread to be
// marked as the main thread.
unsafe { appkit::NSApp(); }
EventsLoop {
shared: Arc::new(Shared::new()),
modifiers: Modifiers::new(),
}
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(Event),
{
unsafe {
if !msg_send![cocoa::base::class("NSThread"), isMainThread] {
panic!("Events can only be polled from the main thread on macOS");
}
}
self.shared.user_callback.store(&mut callback);
// Loop as long as we have pending events to return.
loop {
unsafe {
// First, yield all pending events.
self.shared.call_user_callback_with_pending_events();
let pool = foundation::NSAutoreleasePool::new(cocoa::base::nil);
// Poll for the next event, returning `nil` if there are none.
let ns_event = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
NSEventMask::NSAnyEventMask.bits() | NSEventMask::NSEventMaskPressure.bits(),
foundation::NSDate::distantPast(cocoa::base::nil),
foundation::NSDefaultRunLoopMode,
cocoa::base::YES);
let event = self.ns_event_to_event(ns_event);
let _: () = msg_send![pool, release];
match event {
// Call the user's callback.
Some(event) => self.shared.user_callback.call_with_event(event),
None => break,
}
}
}
self.shared.user_callback.drop();
}
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(Event) -> ControlFlow
{
unsafe {
if !msg_send![cocoa::base::class("NSThread"), isMainThread] {
panic!("Events can only be polled from the main thread on macOS");
}
}
// Track whether or not control flow has changed.
let control_flow = std::cell::Cell::new(ControlFlow::Continue);
let mut callback = |event| {
if let ControlFlow::Break = callback(event) {
control_flow.set(ControlFlow::Break);
}
};
self.shared.user_callback.store(&mut callback);
loop {
unsafe {
// First, yield all pending events.
self.shared.call_user_callback_with_pending_events();
if let ControlFlow::Break = control_flow.get() {
break;
}
let pool = foundation::NSAutoreleasePool::new(cocoa::base::nil);
// Wait for the next event. Note that this function blocks during resize.
let ns_event = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
NSEventMask::NSAnyEventMask.bits() | NSEventMask::NSEventMaskPressure.bits(),
foundation::NSDate::distantFuture(cocoa::base::nil),
foundation::NSDefaultRunLoopMode,
cocoa::base::YES);
let maybe_event = self.ns_event_to_event(ns_event);
// Release the pool before calling the top callback in case the user calls either
// `run_forever` or `poll_events` within the callback.
let _: () = msg_send![pool, release];
if let Some(event) = maybe_event {
self.shared.user_callback.call_with_event(event);
if let ControlFlow::Break = control_flow.get() {
break;
}
}
}
}
self.shared.user_callback.drop();
}
// Convert some given `NSEvent` into a winit `Event`.
unsafe fn ns_event_to_event(&mut self, ns_event: cocoa::base::id) -> Option<Event> {
if ns_event == cocoa::base::nil {
return None;
}
// FIXME: Despite not being documented anywhere, an `NSEvent` is produced when a user opens
// Spotlight while the NSApplication is in focus. This `NSEvent` produces a `NSEventType`
// with value `21`. This causes a SEGFAULT as soon as we try to match on the `NSEventType`
// enum as there is no variant associated with the value. Thus, we return early if this
// sneaky event occurs. If someone does find some documentation on this, please fix this by
// adding an appropriate variant to the `NSEventType` enum in the cocoa-rs crate.
if ns_event.eventType() as u64 == 21 {
return None;
}
let event_type = ns_event.eventType();
let ns_window = ns_event.window();
let window_id = super::window::get_window_id(ns_window);
// FIXME: Document this. Why do we do this? Seems like it passes on events to window/app.
// If we don't do this, window does not become main for some reason.
match event_type {
appkit::NSKeyDown => (),
_ => appkit::NSApp().sendEvent_(ns_event),
}
let windows = self.shared.windows.lock().unwrap();
let maybe_window = windows.iter()
.filter_map(Weak::upgrade)
.find(|window| window_id == window.id());
let into_event = |window_event| Event::WindowEvent {
window_id: ::WindowId(window_id),
event: window_event,
};
// Returns `Some` window if one of our windows is the key window.
let maybe_key_window = || windows.iter()
.filter_map(Weak::upgrade)
.find(|window| {
let is_key_window: cocoa::base::BOOL = msg_send![*window.window, isKeyWindow];
is_key_window == cocoa::base::YES
});
match event_type {
appkit::NSKeyDown => {
let mut events = std::collections::VecDeque::new();
let received_c_str = foundation::NSString::UTF8String(ns_event.characters());
let received_str = std::ffi::CStr::from_ptr(received_c_str);
let vkey = to_virtual_key_code(NSEvent::keyCode(ns_event));
let state = ElementState::Pressed;
let code = NSEvent::keyCode(ns_event) as u32;
let window_event = WindowEvent::KeyboardInput {
device_id: DEVICE_ID,
input: KeyboardInput {
state: state,
scancode: code,
virtual_keycode: vkey,
modifiers: event_mods(ns_event),
},
};
for received_char in std::str::from_utf8(received_str.to_bytes()).unwrap().chars() {
let window_event = WindowEvent::ReceivedCharacter(received_char);
events.push_back(into_event(window_event));
}
self.shared.pending_events.lock().unwrap().extend(events.into_iter());
Some(into_event(window_event))
},
appkit::NSKeyUp => {
let vkey = to_virtual_key_code(NSEvent::keyCode(ns_event));
let state = ElementState::Released;
let code = NSEvent::keyCode(ns_event) as u32;
let window_event = WindowEvent::KeyboardInput {
device_id: DEVICE_ID,
input: KeyboardInput {
state: state,
scancode: code,
virtual_keycode: vkey,
modifiers: event_mods(ns_event),
},
};
Some(into_event(window_event))
},
appkit::NSFlagsChanged => {
unsafe fn modifier_event(event: cocoa::base::id,
keymask: NSEventModifierFlags,
key: events::VirtualKeyCode,
key_pressed: bool) -> Option<WindowEvent>
{
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
let state = ElementState::Pressed;
let code = NSEvent::keyCode(event) as u32;
let window_event = WindowEvent::KeyboardInput {
device_id: DEVICE_ID,
input: KeyboardInput {
state: state,
scancode: code,
virtual_keycode: Some(key),
modifiers: event_mods(event),
},
};
Some(window_event)
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
let state = ElementState::Released;
let code = NSEvent::keyCode(event) as u32;
let window_event = WindowEvent::KeyboardInput {
device_id: DEVICE_ID,
input: KeyboardInput {
state: state,
scancode: code,
virtual_keycode: Some(key),
modifiers: event_mods(event),
},
};
Some(window_event)
} else {
None
}
}
let mut events = std::collections::VecDeque::new();
if let Some(window_event) = modifier_event(ns_event,
NSEventModifierFlags::NSShiftKeyMask,
events::VirtualKeyCode::LShift,
self.modifiers.shift_pressed)
{
self.modifiers.shift_pressed = !self.modifiers.shift_pressed;
events.push_back(into_event(window_event));
}
if let Some(window_event) = modifier_event(ns_event,
NSEventModifierFlags::NSControlKeyMask,
events::VirtualKeyCode::LControl,
self.modifiers.ctrl_pressed)
{
self.modifiers.ctrl_pressed = !self.modifiers.ctrl_pressed;
events.push_back(into_event(window_event));
}
if let Some(window_event) = modifier_event(ns_event,
NSEventModifierFlags::NSCommandKeyMask,
events::VirtualKeyCode::LWin,
self.modifiers.win_pressed)
{
self.modifiers.win_pressed = !self.modifiers.win_pressed;
events.push_back(into_event(window_event));
}
if let Some(window_event) = modifier_event(ns_event,
NSEventModifierFlags::NSAlternateKeyMask,
events::VirtualKeyCode::LAlt,
self.modifiers.alt_pressed)
{
self.modifiers.alt_pressed = !self.modifiers.alt_pressed;
events.push_back(into_event(window_event));
}
let event = events.pop_front();
self.shared.pending_events.lock().unwrap().extend(events.into_iter());
event
},
appkit::NSLeftMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Left, modifiers: event_mods(ns_event) })) },
appkit::NSLeftMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Left, modifiers: event_mods(ns_event) })) },
appkit::NSRightMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Right, modifiers: event_mods(ns_event) })) },
appkit::NSRightMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Right, modifiers: event_mods(ns_event) })) },
appkit::NSOtherMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Middle, modifiers: event_mods(ns_event) })) },
appkit::NSOtherMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Middle, modifiers: event_mods(ns_event) })) },
appkit::NSMouseEntered => {
let window = match maybe_window.or_else(maybe_key_window) {
Some(window) => window,
None => return None,
};
let window_point = ns_event.locationInWindow();
let view_point = if ns_window == cocoa::base::nil {
let ns_size = foundation::NSSize::new(0.0, 0.0);
let ns_rect = foundation::NSRect::new(window_point, ns_size);
let window_rect = window.window.convertRectFromScreen_(ns_rect);
window.view.convertPoint_fromView_(window_rect.origin, cocoa::base::nil)
} else {
window.view.convertPoint_fromView_(window_point, cocoa::base::nil)
};
let view_rect = NSView::frame(*window.view);
let scale_factor = window.hidpi_factor();
let x = (scale_factor * view_point.x as f32) as f64;
let y = (scale_factor * (view_rect.size.height - view_point.y) as f32) as f64;
let window_event = WindowEvent::CursorMoved { device_id: DEVICE_ID, position: (x, y), modifiers: event_mods(ns_event) };
let event = Event::WindowEvent { window_id: ::WindowId(window.id()), event: window_event };
self.shared.pending_events.lock().unwrap().push_back(event);
Some(into_event(WindowEvent::CursorEntered { device_id: DEVICE_ID }))
},
appkit::NSMouseExited => { Some(into_event(WindowEvent::CursorLeft { device_id: DEVICE_ID })) },
appkit::NSMouseMoved |
appkit::NSLeftMouseDragged |
appkit::NSOtherMouseDragged |
appkit::NSRightMouseDragged => {
// If the mouse movement was on one of our windows, use it.
// Otherwise, if one of our windows is the key window (receiving input), use it.
// Otherwise, return `None`.
let window = match maybe_window.or_else(maybe_key_window) {
Some(window) => window,
None => return None,
};
let window_point = ns_event.locationInWindow();
let view_point = if ns_window == cocoa::base::nil {
let ns_size = foundation::NSSize::new(0.0, 0.0);
let ns_rect = foundation::NSRect::new(window_point, ns_size);
let window_rect = window.window.convertRectFromScreen_(ns_rect);
window.view.convertPoint_fromView_(window_rect.origin, cocoa::base::nil)
} else {
window.view.convertPoint_fromView_(window_point, cocoa::base::nil)
};
let view_rect = NSView::frame(*window.view);
let scale_factor = window.hidpi_factor();
let mut events = std::collections::VecDeque::new();
{
let x = (scale_factor * view_point.x as f32) as f64;
let y = (scale_factor * (view_rect.size.height - view_point.y) as f32) as f64;
let window_event = WindowEvent::CursorMoved { device_id: DEVICE_ID, position: (x, y), modifiers: event_mods(ns_event) };
let event = Event::WindowEvent { window_id: ::WindowId(window.id()), event: window_event };
events.push_back(event);
}
let delta_x = (scale_factor * ns_event.deltaX() as f32) as f64;
if delta_x != 0.0 {
let motion_event = DeviceEvent::Motion { axis: 0, value: delta_x };
let event = Event::DeviceEvent{ device_id: DEVICE_ID, event: motion_event };
events.push_back(event);
}
let delta_y = (scale_factor * ns_event.deltaY() as f32) as f64;
if delta_y != 0.0 {
let motion_event = DeviceEvent::Motion { axis: 1, value: delta_y };
let event = Event::DeviceEvent{ device_id: DEVICE_ID, event: motion_event };
events.push_back(event);
}
if delta_x != 0.0 || delta_y != 0.0 {
let motion_event = DeviceEvent::MouseMotion { delta: (delta_x, delta_y) };
let event = Event::DeviceEvent{ device_id: DEVICE_ID, event: motion_event };
events.push_back(event);
}
let event = events.pop_front();
self.shared.pending_events.lock().unwrap().extend(events.into_iter());
event
},
appkit::NSScrollWheel => {
// If none of the windows received the scroll, return `None`.
let window = match maybe_window {
Some(window) => window,
None => return None,
};
use events::MouseScrollDelta::{LineDelta, PixelDelta};
let scale_factor = window.hidpi_factor();
let delta = if ns_event.hasPreciseScrollingDeltas() == cocoa::base::YES {
PixelDelta(scale_factor * ns_event.scrollingDeltaX() as f32,
scale_factor * ns_event.scrollingDeltaY() as f32)
} else {
LineDelta(scale_factor * ns_event.scrollingDeltaX() as f32,
scale_factor * ns_event.scrollingDeltaY() as f32)
};
let phase = match ns_event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => TouchPhase::Started,
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
self.shared.pending_events.lock().unwrap().push_back(Event::DeviceEvent {
device_id: DEVICE_ID,
event: DeviceEvent::MouseWheel {
delta: if ns_event.hasPreciseScrollingDeltas() == cocoa::base::YES {
PixelDelta(ns_event.scrollingDeltaX() as f32,
ns_event.scrollingDeltaY() as f32)
} else {
LineDelta(ns_event.scrollingDeltaX() as f32,
ns_event.scrollingDeltaY() as f32)
},
}
});
let window_event = WindowEvent::MouseWheel { device_id: DEVICE_ID, delta: delta, phase: phase, modifiers: event_mods(ns_event) };
Some(into_event(window_event))
},
appkit::NSEventTypePressure => {
let pressure = ns_event.pressure();
let stage = ns_event.stage();
let window_event = WindowEvent::TouchpadPressure { device_id: DEVICE_ID, pressure: pressure, stage: stage };
Some(into_event(window_event))
},
appkit::NSApplicationDefined => match ns_event.subtype() {
appkit::NSEventSubtype::NSApplicationActivatedEventType => {
Some(Event::Awakened)
},
_ => None,
},
_ => None,
}
}
pub fn create_proxy(&self) -> Proxy {
Proxy {}
}
}
impl Proxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
// Awaken the event loop by triggering `NSApplicationActivatedEventType`.
unsafe {
let pool = foundation::NSAutoreleasePool::new(cocoa::base::nil);
let event =
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
cocoa::base::nil,
appkit::NSApplicationDefined,
foundation::NSPoint::new(0.0, 0.0),
appkit::NSEventModifierFlags::empty(),
0.0,
0,
cocoa::base::nil,
appkit::NSEventSubtype::NSApplicationActivatedEventType,
0,
0);
appkit::NSApp().postEvent_atStart_(event, cocoa::base::NO);
foundation::NSAutoreleasePool::drain(pool);
}
Ok(())
}
}
fn to_virtual_key_code(code: u16) -> Option<events::VirtualKeyCode> {
Some(match code {
0x00 => events::VirtualKeyCode::A,
0x01 => events::VirtualKeyCode::S,
0x02 => events::VirtualKeyCode::D,
0x03 => events::VirtualKeyCode::F,
0x04 => events::VirtualKeyCode::H,
0x05 => events::VirtualKeyCode::G,
0x06 => events::VirtualKeyCode::Z,
0x07 => events::VirtualKeyCode::X,
0x08 => events::VirtualKeyCode::C,
0x09 => events::VirtualKeyCode::V,
//0x0a => World 1,
0x0b => events::VirtualKeyCode::B,
0x0c => events::VirtualKeyCode::Q,
0x0d => events::VirtualKeyCode::W,
0x0e => events::VirtualKeyCode::E,
0x0f => events::VirtualKeyCode::R,
0x10 => events::VirtualKeyCode::Y,
0x11 => events::VirtualKeyCode::T,
0x12 => events::VirtualKeyCode::Key1,
0x13 => events::VirtualKeyCode::Key2,
0x14 => events::VirtualKeyCode::Key3,
0x15 => events::VirtualKeyCode::Key4,
0x16 => events::VirtualKeyCode::Key6,
0x17 => events::VirtualKeyCode::Key5,
0x18 => events::VirtualKeyCode::Equals,
0x19 => events::VirtualKeyCode::Key9,
0x1a => events::VirtualKeyCode::Key7,
0x1b => events::VirtualKeyCode::Minus,
0x1c => events::VirtualKeyCode::Key8,
0x1d => events::VirtualKeyCode::Key0,
0x1e => events::VirtualKeyCode::RBracket,
0x1f => events::VirtualKeyCode::O,
0x20 => events::VirtualKeyCode::U,
0x21 => events::VirtualKeyCode::LBracket,
0x22 => events::VirtualKeyCode::I,
0x23 => events::VirtualKeyCode::P,
0x24 => events::VirtualKeyCode::Return,
0x25 => events::VirtualKeyCode::L,
0x26 => events::VirtualKeyCode::J,
0x27 => events::VirtualKeyCode::Apostrophe,
0x28 => events::VirtualKeyCode::K,
0x29 => events::VirtualKeyCode::Semicolon,
0x2a => events::VirtualKeyCode::Backslash,
0x2b => events::VirtualKeyCode::Comma,
0x2c => events::VirtualKeyCode::Slash,
0x2d => events::VirtualKeyCode::N,
0x2e => events::VirtualKeyCode::M,
0x2f => events::VirtualKeyCode::Period,
0x30 => events::VirtualKeyCode::Tab,
0x31 => events::VirtualKeyCode::Space,
0x32 => events::VirtualKeyCode::Grave,
0x33 => events::VirtualKeyCode::Back,
//0x34 => unkown,
0x35 => events::VirtualKeyCode::Escape,
0x36 => events::VirtualKeyCode::RWin,
0x37 => events::VirtualKeyCode::LWin,
0x38 => events::VirtualKeyCode::LShift,
//0x39 => Caps lock,
//0x3a => Left alt,
0x3b => events::VirtualKeyCode::LControl,
0x3c => events::VirtualKeyCode::RShift,
//0x3d => Right alt,
0x3e => events::VirtualKeyCode::RControl,
//0x3f => Fn key,
//0x40 => F17 Key,
0x41 => events::VirtualKeyCode::Decimal,
//0x42 -> unkown,
0x43 => events::VirtualKeyCode::Multiply,
//0x44 => unkown,
0x45 => events::VirtualKeyCode::Add,
//0x46 => unkown,
0x47 => events::VirtualKeyCode::Numlock,
//0x48 => KeypadClear,
0x49 => events::VirtualKeyCode::VolumeUp,
0x4a => events::VirtualKeyCode::VolumeDown,
0x4b => events::VirtualKeyCode::Divide,
0x4c => events::VirtualKeyCode::NumpadEnter,
//0x4d => unkown,
0x4e => events::VirtualKeyCode::Subtract,
//0x4f => F18 key,
//0x50 => F19 Key,
0x51 => events::VirtualKeyCode::NumpadEquals,
0x52 => events::VirtualKeyCode::Numpad0,
0x53 => events::VirtualKeyCode::Numpad1,
0x54 => events::VirtualKeyCode::Numpad2,
0x55 => events::VirtualKeyCode::Numpad3,
0x56 => events::VirtualKeyCode::Numpad4,
0x57 => events::VirtualKeyCode::Numpad5,
0x58 => events::VirtualKeyCode::Numpad6,
0x59 => events::VirtualKeyCode::Numpad7,
//0x5a => F20 Key,
0x5b => events::VirtualKeyCode::Numpad8,
0x5c => events::VirtualKeyCode::Numpad9,
//0x5d => unkown,
//0x5e => unkown,
//0x5f => unkown,
0x60 => events::VirtualKeyCode::F5,
0x61 => events::VirtualKeyCode::F6,
0x62 => events::VirtualKeyCode::F7,
0x63 => events::VirtualKeyCode::F3,
0x64 => events::VirtualKeyCode::F8,
0x65 => events::VirtualKeyCode::F9,
//0x66 => unkown,
0x67 => events::VirtualKeyCode::F11,
//0x68 => unkown,
0x69 => events::VirtualKeyCode::F13,
//0x6a => F16 Key,
0x6b => events::VirtualKeyCode::F14,
//0x6c => unkown,
0x6d => events::VirtualKeyCode::F10,
//0x6e => unkown,
0x6f => events::VirtualKeyCode::F12,
//0x70 => unkown,
0x71 => events::VirtualKeyCode::F15,
0x72 => events::VirtualKeyCode::Insert,
0x73 => events::VirtualKeyCode::Home,
0x74 => events::VirtualKeyCode::PageUp,
0x75 => events::VirtualKeyCode::Delete,
0x76 => events::VirtualKeyCode::F4,
0x77 => events::VirtualKeyCode::End,
0x78 => events::VirtualKeyCode::F2,
0x79 => events::VirtualKeyCode::PageDown,
0x7a => events::VirtualKeyCode::F1,
0x7b => events::VirtualKeyCode::Left,
0x7c => events::VirtualKeyCode::Right,
0x7d => events::VirtualKeyCode::Down,
0x7e => events::VirtualKeyCode::Up,
//0x7f => unkown,
0xa => events::VirtualKeyCode::Caret,
_ => return None,
})
}
fn event_mods(event: cocoa::base::id) -> ModifiersState {
let flags = unsafe {
NSEvent::modifierFlags(event)
};
ModifiersState {
shift: flags.contains(NSEventModifierFlags::NSShiftKeyMask),
ctrl: flags.contains(NSEventModifierFlags::NSControlKeyMask),
alt: flags.contains(NSEventModifierFlags::NSAlternateKeyMask),
logo: flags.contains(NSEventModifierFlags::NSCommandKeyMask),
}
}
// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);

View File

@@ -1,42 +0,0 @@
#![cfg(target_os = "macos")]
pub use self::events_loop::{EventsLoop, Proxy as EventsLoopProxy};
pub use self::monitor::MonitorId;
pub use self::window::{Id as WindowId, PlatformSpecificWindowBuilderAttributes, Window2};
use std::sync::Arc;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
use {CreationError};
pub struct Window {
pub window: Arc<Window2>,
}
impl ::std::ops::Deref for Window {
type Target = Window2;
#[inline]
fn deref(&self) -> &Window2 {
&*self.window
}
}
impl Window {
pub fn new(events_loop: &EventsLoop,
attributes: &::WindowAttributes,
pl_attribs: &PlatformSpecificWindowBuilderAttributes) -> Result<Self, CreationError>
{
let weak_shared = Arc::downgrade(&events_loop.shared);
let window = Arc::new(try!(Window2::new(weak_shared, attributes, pl_attribs)));
let weak_window = Arc::downgrade(&window);
events_loop.shared.windows.lock().unwrap().push(weak_window);
Ok(Window { window: window })
}
}
mod events_loop;
mod monitor;
mod window;

View File

@@ -1,94 +0,0 @@
use cocoa::appkit::NSScreen;
use cocoa::base::{id, nil};
use cocoa::foundation::{NSString, NSUInteger};
use core_graphics::display::{CGDirectDisplayID, CGDisplay};
use std::collections::VecDeque;
use super::EventsLoop;
use super::window::IdRef;
#[derive(Clone, PartialEq)]
pub struct MonitorId(CGDirectDisplayID);
impl EventsLoop {
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
let mut monitors = VecDeque::new();
if let Ok(displays) = CGDisplay::active_displays() {
for d in displays {
monitors.push_back(MonitorId(d));
}
}
monitors
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
let id = MonitorId(CGDisplay::main().id);
id
}
pub fn make_monitor_from_display(id: CGDirectDisplayID) -> MonitorId {
let id = MonitorId(id);
id
}
}
impl MonitorId {
pub fn get_name(&self) -> Option<String> {
let MonitorId(display_id) = *self;
let screen_num = CGDisplay::new(display_id).model_number();
Some(format!("Monitor #{}", screen_num))
}
#[inline]
pub fn get_native_identifier(&self) -> u32 {
self.0
}
pub fn get_dimensions(&self) -> (u32, u32) {
let MonitorId(display_id) = *self;
let display = CGDisplay::new(display_id);
let dimension = {
let height = display.pixels_high();
let width = display.pixels_wide();
(width as u32, height as u32)
};
dimension
}
#[inline]
pub fn get_position(&self) -> (i32, i32) {
unimplemented!()
}
pub fn get_hidpi_factor(&self) -> f32 {
let screen = match self.get_nsscreen() {
Some(screen) => screen,
None => return 1.0, // default to 1.0 when we can't find the screen
};
unsafe { NSScreen::backingScaleFactor(screen) as f32 }
}
pub(crate) fn get_nsscreen(&self) -> Option<id> {
unsafe {
let native_id = self.get_native_identifier();
let screens = NSScreen::screens(nil);
let count: NSUInteger = msg_send![screens, count];
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
let mut matching_screen: Option<id> = None;
for i in 0..count {
let screen = msg_send![screens, objectAtIndex: i as NSUInteger];
let device_description = NSScreen::deviceDescription(screen);
let value: id = msg_send![device_description, objectForKey:*key];
if value != nil {
let screen_number: NSUInteger = msg_send![value, unsignedIntegerValue];
if screen_number as u32 == native_id {
matching_screen = Some(screen);
break;
}
}
}
matching_screen
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,43 @@
pub use self::platform::*;
//! Contains traits with platform-specific methods in them.
//!
//! Contains the follow OS-specific modules:
//!
//! - `android`
//! - `ios`
//! - `macos`
//! - `unix`
//! - `windows`
//! - `web`
//!
//! And the following platform-specific module:
//!
//! - `run_return` (available on `windows`, `unix`, `macos`, and `android`)
//!
//! However only the module corresponding to the platform you're compiling to will be available.
#[cfg(target_os = "windows")]
#[path="windows/mod.rs"]
mod platform;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
#[path="linux/mod.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path="macos/mod.rs"]
mod platform;
#[cfg(target_os = "android")]
#[path="android/mod.rs"]
mod platform;
#[cfg(target_os = "ios")]
#[path="ios/mod.rs"]
mod platform;
#[cfg(target_os = "emscripten")]
#[path="emscripten/mod.rs"]
mod platform;
#[cfg(android_platform)]
pub mod android;
#[cfg(ios_platform)]
pub mod ios;
#[cfg(macos_platform)]
pub mod macos;
#[cfg(orbital_platform)]
pub mod orbital;
#[cfg(wayland_platform)]
pub mod wayland;
#[cfg(wasm_platform)]
pub mod web;
#[cfg(windows_platform)]
pub mod windows;
#[cfg(x11_platform)]
pub mod x11;
#[cfg(all(not(target_os = "ios"), not(target_os = "windows"), not(target_os = "linux"),
not(target_os = "macos"), not(target_os = "android"), not(target_os = "dragonfly"),
not(target_os = "freebsd"), not(target_os = "openbsd"), not(target_os = "emscripten")))]
compile_error!("The platform you're compiling for is not supported by winit");
#[cfg(any(
windows_platform,
macos_platform,
android_platform,
x11_platform,
wayland_platform,
orbital_platform
))]
pub mod run_return;

1
src/platform/orbital.rs Normal file
View File

@@ -0,0 +1 @@
// There are no Orbital specific traits yet.

View File

@@ -0,0 +1,53 @@
use crate::{
event::Event,
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
};
/// Additional methods on [`EventLoop`] to return control flow to the caller.
pub trait EventLoopExtRunReturn {
/// A type provided by the user that can be passed through [`Event::UserEvent`].
type UserEvent;
/// Initializes the `winit` event loop.
///
/// Unlike [`EventLoop::run`], this function accepts non-`'static` (i.e. non-`move`) closures
/// and returns control flow to the caller when `control_flow` is set to [`ControlFlow::Exit`].
///
/// # Caveats
///
/// Despite its appearance at first glance, this is *not* a perfect replacement for
/// `poll_events`. For example, this function will not return on Windows or macOS while a
/// window is getting resized, resulting in all application logic outside of the
/// `event_handler` closure not running until the resize operation ends. Other OS operations
/// may also result in such freezes. This behavior is caused by fundamental limitations in the
/// underlying OS APIs, which cannot be hidden by `winit` without severe stability repercussions.
///
/// You are strongly encouraged to use `run`, unless the use of this is absolutely necessary.
///
/// ## Platform-specific
///
/// - **X11 / Wayland:** This function returns `1` upon disconnection from
/// the display server.
fn run_return<F>(&mut self, event_handler: F) -> i32
where
F: FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
);
}
impl<T> EventLoopExtRunReturn for EventLoop<T> {
type UserEvent = T;
fn run_return<F>(&mut self, event_handler: F) -> i32
where
F: FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
),
{
self.event_loop.run_return(event_handler)
}
}

144
src/platform/wayland.rs Normal file
View File

@@ -0,0 +1,144 @@
use std::os::raw;
use crate::{
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
monitor::MonitorHandle,
window::{Window, WindowBuilder},
};
use crate::platform_impl::{
ApplicationName, Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget,
Window as LinuxWindow,
};
pub use crate::window::Theme;
/// Additional methods on [`EventLoopWindowTarget`] that are specific to Wayland.
pub trait EventLoopWindowTargetExtWayland {
/// True if the [`EventLoopWindowTarget`] uses Wayland.
fn is_wayland(&self) -> bool;
/// Returns a pointer to the `wl_display` object of wayland that is used by this
/// [`EventLoopWindowTarget`].
///
/// Returns `None` if the [`EventLoop`] doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the winit [`EventLoop`] is destroyed.
///
/// [`EventLoop`]: crate::event_loop::EventLoop
fn wayland_display(&self) -> Option<*mut raw::c_void>;
}
impl<T> EventLoopWindowTargetExtWayland for EventLoopWindowTarget<T> {
#[inline]
fn is_wayland(&self) -> bool {
self.p.is_wayland()
}
#[inline]
fn wayland_display(&self) -> Option<*mut raw::c_void> {
match self.p {
LinuxEventLoopWindowTarget::Wayland(ref p) => {
Some(p.display().get_display_ptr() as *mut _)
}
#[cfg(x11_platform)]
_ => None,
}
}
}
/// Additional methods on [`EventLoopBuilder`] that are specific to Wayland.
pub trait EventLoopBuilderExtWayland {
/// Force using Wayland.
fn with_wayland(&mut self) -> &mut Self;
/// Whether to allow the event loop to be created off of the main thread.
///
/// By default, the window is only allowed to be created on the main
/// thread, to make platform compatibility easier.
fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
}
impl<T> EventLoopBuilderExtWayland for EventLoopBuilder<T> {
#[inline]
fn with_wayland(&mut self) -> &mut Self {
self.platform_specific.forced_backend = Some(Backend::Wayland);
self
}
#[inline]
fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
self.platform_specific.any_thread = any_thread;
self
}
}
/// Additional methods on [`Window`] that are specific to Wayland.
pub trait WindowExtWayland {
/// Returns a pointer to the `wl_surface` object of wayland that is used by this window.
///
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the [`Window`] is destroyed.
fn wayland_surface(&self) -> Option<*mut raw::c_void>;
/// Returns a pointer to the `wl_display` object of wayland that is used by this window.
///
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the [`Window`] is destroyed.
fn wayland_display(&self) -> Option<*mut raw::c_void>;
}
impl WindowExtWayland for Window {
#[inline]
fn wayland_surface(&self) -> Option<*mut raw::c_void> {
match self.window {
LinuxWindow::Wayland(ref w) => Some(w.surface().as_ref().c_ptr() as *mut _),
#[cfg(x11_platform)]
_ => None,
}
}
#[inline]
fn wayland_display(&self) -> Option<*mut raw::c_void> {
match self.window {
LinuxWindow::Wayland(ref w) => Some(w.display().get_display_ptr() as *mut _),
#[cfg(x11_platform)]
_ => None,
}
}
}
/// Additional methods on [`WindowBuilder`] that are specific to Wayland.
pub trait WindowBuilderExtWayland {
/// Build window with the given name.
///
/// The `general` name sets an application ID, which should match the `.desktop`
/// file destributed with your program. The `instance` is a `no-op`.
///
/// For details about application ID conventions, see the
/// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
fn with_name(self, general: impl Into<String>, instance: impl Into<String>) -> Self;
}
impl WindowBuilderExtWayland for WindowBuilder {
#[inline]
fn with_name(mut self, general: impl Into<String>, instance: impl Into<String>) -> Self {
self.platform_specific.name = Some(ApplicationName::new(general.into(), instance.into()));
self
}
}
/// Additional methods on `MonitorHandle` that are specific to Wayland.
pub trait MonitorHandleExtWayland {
/// Returns the inner identifier of the monitor.
fn native_id(&self) -> u32;
}
impl MonitorHandleExtWayland for MonitorHandle {
#[inline]
fn native_id(&self) -> u32 {
self.inner.native_identifier()
}
}

89
src/platform/web.rs Normal file
View File

@@ -0,0 +1,89 @@
//! The web target does not automatically insert the canvas element object into the web page, to
//! allow end users to determine how the page should be laid out. Use the [`WindowExtWebSys`] trait
//! to retrieve the canvas from the Window. Alternatively, use the [`WindowBuilderExtWebSys`] trait
//! to provide your own canvas.
use crate::event::Event;
use crate::event_loop::ControlFlow;
use crate::event_loop::EventLoop;
use crate::event_loop::EventLoopWindowTarget;
use crate::window::WindowBuilder;
use web_sys::HtmlCanvasElement;
pub trait WindowExtWebSys {
fn canvas(&self) -> HtmlCanvasElement;
/// Whether the browser reports the preferred color scheme to be "dark".
fn is_dark_mode(&self) -> bool;
}
pub trait WindowBuilderExtWebSys {
fn with_canvas(self, canvas: Option<HtmlCanvasElement>) -> Self;
/// Whether `event.preventDefault` should be automatically called to prevent event propagation
/// when appropriate.
///
/// For example, mouse wheel events are only handled by the canvas by default. This avoids
/// the default behavior of scrolling the page.
fn with_prevent_default(self, prevent_default: bool) -> Self;
/// Whether the canvas should be focusable using the tab key. This is necessary to capture
/// canvas keyboard events.
fn with_focusable(self, focusable: bool) -> Self;
}
impl WindowBuilderExtWebSys for WindowBuilder {
fn with_canvas(mut self, canvas: Option<HtmlCanvasElement>) -> Self {
self.platform_specific.canvas = canvas;
self
}
fn with_prevent_default(mut self, prevent_default: bool) -> Self {
self.platform_specific.prevent_default = prevent_default;
self
}
fn with_focusable(mut self, focusable: bool) -> Self {
self.platform_specific.focusable = focusable;
self
}
}
/// Additional methods on `EventLoop` that are specific to the web.
pub trait EventLoopExtWebSys {
/// A type provided by the user that can be passed through `Event::UserEvent`.
type UserEvent;
/// Initializes the winit event loop.
///
/// Unlike `run`, this returns immediately, and doesn't throw an exception in order to
/// satisfy its `!` return type.
fn spawn<F>(self, event_handler: F)
where
F: 'static
+ FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
);
}
impl<T> EventLoopExtWebSys for EventLoop<T> {
type UserEvent = T;
fn spawn<F>(self, event_handler: F)
where
F: 'static
+ FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
),
{
self.event_loop.spawn(event_handler)
}
}

Some files were not shown because too many files have changed in this diff Show More