Merge next back to dev branch (#305)

* refactor(windows): `begin_resize_drag` now similar to gtk's (#200)

* refactor(windows): `begin_resize_drag` now similart to gtk's

* fix

* feat(linux): skipping taskbar will now also skip pager (#198)

* refactor(linux): clean dummy device_id (#195)

* refactor(linux): clean dummy device_id

* fmt

* feat(linux): allow resizing undecorated window using touch (#199)

* refactor(windows): only skip taskbar if needed when `set_visible` is called (#196)

* fix: increase borderless resizing inset (#202)

* fix: increase borderless resizing inset

* update some comments

* Replace winapi with windows crate bindings shared with WRY (#206)

* fix(deps): update rust crate libayatana-appindicator to 0.1.6 (#190)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Add Windows crate and webview2-com-sys bindings

* Initial port to webview2-com-sys

* Finish conversion and remove winapi

* Fix renamed lint warning

* Fix all match arms referencing const variables

* Put back the assert instead of expect

* Point to the published version of webview2-com-sys

* Cleanup slightly weird BOOL handling

* Replace mem::zeroed with Default::default

* Add a summary in .changes

* Remove extra projects not in config.json

* Fix clippy warnings

* Update to 32-bit compatible webview2-com-sys

* Better fix for merge conflict

* Fix clippy errors on Windows

* Use path prefix to prevent variable shadowing

* Fix Windows clippy warnings with nightly toolchain

* Fix Linux nightly/stable clippy warnings

* Fix macOS nightly/stable clippy warnings

* Put back public *mut libc::c_void for consistency

* Re-run cargo fmt

* Move call_default_window_proc to util mod

* Remove unnecessary util::to_wstring calls

* Don't repeat LRESULT expression in match arms

* Replace bitwise operations with util functions

* Cleanup more bit mask & shift with util fns

* Prefer from conversions instead of as cast

* Implement get_xbutton_wparam

* Use *mut libc::c_void for return types

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Renovate Bot <bot@renovateapp.com>

* fix(keyboard): add mapping for space key on Windows (#209)

* fix(keyboard): add mapping for space key on Windows

* change file

* feat: impl Clone for EventLoopWindowTarget (#211)

* chore: add `on_issue_closed.yml` (#214)

* Update tray dependency version (#217)

* Delete on_issue_closed.yml (#221)

* refactor(linux): event loop (#233)

* Use crossbeam::channel

* Fix crossbeam channel import

* Add check on poll event

* Fix deadlock when unregistering shortcut on Linux (#230)

* Add fullscreen monitor selection support on Linux (#235)

* Add fullscreen monitor support on Linux

* Add change file

* Remove todo on videomode

* Fix clippy

* Update to 2021 edition (#236)

* Update to 2021 edition

* Fix clippy

* Add run_return on Linux (#237)

* Add run_return on Linux

* Add main context

* Add run_return trait on Linux (#238)

* Fix: #239 Update webview2-com and windows crates (#240)

* Replace webivew2-com-sys with prebuilt windows

* Use windows utility instead of direct GetLastError

* Bump windows version and add changelog

* Run cargo fmt

* Restore inverted matches macro

* Scope constants in match arms

* Fix inverted null check

* Update src/platform_impl/windows/util.rs

Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>

* Use env_logger instead of simple_logger (#241)

* Use env_logger instead of simple_logger

* Make clippy happy

* Cherry pick commits to next (#244)

* feat(macos): Add `unhide_application` method, closes #182 (#231)

* feat(macos): Add `unhide_application` method

* Update src/platform/macos.rs

Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>

* Reanme to `show_application()`

* Remove broken doc link

Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>

* feat: Allow more strings to parse to keycode (#229)

* feat: support accelerator key strings `,` `-` `.` `Space` `Tab` and `F13`-`F24` (#228)

* feat(macOS): support more accelerator key strings

* Move function keys together

* Add `,` `-` `.` `Space` `F20-F24` for Windows

* Remove support for accelerators not found in `winapi`

* Add `,` `-` `.` `Space` `F13-F24` for Linux

* Update .changes

* Add the rest for Windows

* Add the rest for Linux

* Add the rest on macOS

* Update accelerator-strings.md

* Fix git comments

Co-authored-by: Kasper <kasperkh.kh@gmail.com>
Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>

* Add redraw events on Linux (#245)

* Add redraw events on Linux

* Update doc of RequestRedraw Event

* Add change file

* Fix missing menu bar on borderless window (#247)

Credit goes to irh's work on winit commit f2de8475fc4703d03a2ecc2cda627b017202e623

* refactor: improve `set_skip_taskbar` impl on Windows (#250)

* fix: emit errors on parsing an invalid accelerator for string, closes #135 (#252)

* chore: update comment

* fix(linux): fix focus events not firing properly (#253)

* fix(linux): fix focus events not firing properly

* add changelog

* chore: update focus events error message

* chore: fmt

* fix: revert windows-rs 0.28 version bump

* fix(linux): fix native menu items (#256)

* chore: remove examples commited by accident

* Update `ReceivedImeText` (#251)

* Allow receiving text without Ime on Windows

* Avoid panic todo

* Receive text without ime on mac

* Fix CursorMoved event on Linux

* Add ReceivedImeText on Linux

This only add Simple IME from GTK for now. We should add the actual IME
from system in the future.

* Fix redraw event that causes inifinite loop (#260)

* Fix redraw event that causes inifinite loop

* Refactor event loop

* Remove unused function

* Add doc comment on linux's run_return

* Ignore doc test on run_return

* Add non blocking iteration on Linux (#261)

* Docs: SystemTrayExtWindows::remove() is gone (#262)

Fix docs following #153

* Fix busy loop on Linux (#265)

* Update windows crate to 0.29.0 (#266)

* Update to windows 0.29.0

* Add change description

* Remove clippy check (#267)

* refactor(windows): align util function with win32 names

* chore: update PR template

* fix(linux): fire resized & moved events on min/maximize, closes #219 (#254)

* feat(linux): implement `raw_window_handle()` (#269)

* chore(deps): update to raw-window-handle 0.4

* add linux raw-window-handle support

* update macos/ios/android

* fix ios

* Fix core-video-sys dependency (#274)

* 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. (#275)

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.

* Fix some invalid msg_send! usage (#276)

* Revert "Fix some invalid msg_send! usage (#276)" (#277)

This reverts commit a3a2e0cfc4.

* Revert "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. (#275)" (#279)

This reverts commit 6f9c468f26.

* 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. (#280)

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.

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

* Fix some invalid msg_send! usage (#278)

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

* Add exit code to ControlFlow::Exit (#281)

* Add exit code to ControlFlow::Exit

* Cargo fmt

* Add change files

Co-authored-by:  multisn8 <contact@multisamplednight.com>

* Add new_any_thread to Unix event loop (#282)

* Update windows crate to 0.30.0 (#283)

* Update windows crate to 0.30.0

* Simplify new-type usage

* Fix boxing in GWL_USERDATA

* Make sure everyone is using Get/SetWindowLongPtrW

* build the system_tray module when "ayatana" feature is enabled (#285)

Without those cfg feature checks, the "ayatana" feature does
actually not enable anything.

* Fix click events missing whe tray has menu (#291)

* Fix click events missing whe tray has menu

* Add change file

* Fix crash when tray has no menu (#294)

* chore: update pull request commit exmple

* fix(windows): send correct position for system tray events, closes #295 (#300)

* fix(windows): revert maximized state handling to winit impl, closes #193 (#299)

* fix(windows): revet maximized state handling to winit impl, closes #193

* add chanefile [skip ci]

* fix: `MenuItem::Quit` on Windows (#303)

* fix: `MenuItem::Close` on Windows

* use `PostQuitMessage` instead

Co-authored-by: amrbashir <amr.bashir2015@gmail.com>

* feat: v1 audit by Radically Open Security (#304)

* Update to gtk 0.15 (#288)

* Update to gtk 0.15

* Fix picky none on set_geometry_hint

* Fix CursorMoved position

Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>
Co-authored-by: Bill Avery <wravery@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Lucas Fernandes Nogueira <lucasfernandesnog@gmail.com>
Co-authored-by: Kasper <kasperkh.kh@gmail.com>
Co-authored-by: amrbashir <amr.bashir2015@gmail.com>
Co-authored-by: Jay Oster <jay@kodewerx.org>
Co-authored-by: madsmtm <mads@marquart.dk>
Co-authored-by: multisn8 <contact@multisamplednight.com>
Co-authored-by: Aurélien Jacobs <aurel@gnuage.org>
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>
This commit is contained in:
130 files changed
+4240 -3761

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"tao": minor
---
Update to gtk 0.15
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Emit errors when parsing an invalid accelerator from a string.
+5
View File
@@ -0,0 +1,5 @@
---
tao: minor
---
Add support for more accelerator keys: `,` `-` `.` `=` `;` `/` `\` `'` `` ` `` `[` `]` `Space` `Tab` and `F13`-`F24`
+4
View File
@@ -0,0 +1,4 @@
---
"tao": patch
---
Increased Borderless window resizing inset.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Update to 2021 edition and msrv to 1.56
+5
View File
@@ -0,0 +1,5 @@
---
"tao": minor
---
**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.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fixes the `MenuItem::Quit` behavior on Windows.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Add support for `SPACE` shortcut key on Windows.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
* Fix redrawn event that causing infinite lopp on Linux
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fix linux native menu items not working.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
* Fix resizing undecorated window on Linux.
* Undecorated window can be resized using touch on Linux.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fix focus events not firing on Linux
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Add monitor selection when fullscreen on Linux and close possible way to create VideoMode on Linux since gtk doesn't acutally have such feature.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
* Add `RedrawEventsCleared` and `RedrawRequested` on Linux
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Add run_return trait on Linux
@@ -0,0 +1,5 @@
---
"tao": patch
---
`window.set_skip_taskbar()` on Linux will now also skip the pager (Alt+Tab), this matches the behavior on Windows.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Update tray dependency version.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Fix deadlock when unregistering shortcut on Linux.
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fire `WindowEvent::Resized` and `WindowEvent::Moved` when window is min/maximized on Linux to align with Windows behavior.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Fix menubar missing on borderless window.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fix core-video-sys dependency.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions.
+5
View File
@@ -0,0 +1,5 @@
---
tao: minor
---
Allow more strings to parse to keycode, for example `,` is now parsed as a comma.
+6
View File
@@ -0,0 +1,6 @@
---
"tao": patch
---
* Update `raw-window-handle` to `0.4`
* Add `raw_window_handle()` implementation on linux.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Fix click events missing whe tray has menu.
+5
View File
@@ -0,0 +1,5 @@
---
tao: minor
---
Add macOS `show_application()` method
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Add new_any_thread to Unix event loop.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Replace all of the `winapi` crate references with the `windows` crate. The generated bindings are in the `webview2-com-sys` crate to share types with WRY later.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Implement `Clone` for `EventLoopWindowTarget`.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Update the `windows` crate to 0.25.0, which comes with pre-built libraries. Tao no longer depends on `webview2-com-sys` to generate bindings shared with WRY.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Update the `windows` crate to 0.29.0.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": patch
---
Update the `windows` crate to 0.30.0. This version re-introduced a lot of new-types for things like HWND, LRESULT, WPARAM, LPARAM, etc.
+5
View File
@@ -0,0 +1,5 @@
---
"tao": "patch"
---
Fix using `WindowBuilder::with_visible` and `WindowBuilder::with_maximized` not behaving correctly.
@@ -0,0 +1,5 @@
---
"tao": "patch"
---
On Windows, send correct position on system tray events.
+14 -20
View File
@@ -1,36 +1,30 @@
<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/tauri-apps/tauri/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
Update "[ ]" to "[x]" to check a box
Please make sure to read the Pull Request Guidelines: https://github.com/tauri-apps/tauri/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->
<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->
**What kind of change does this PR introduce?** (check at least one)
### What kind of change does this PR introduce?
<!-- Check at least one. If you are introducing a new binding, you must reference an issue where this binding has been proposed, discussed and approved by the maintainers. -->
- [ ] Bugfix
- [ ] Feature
- [ ] Docs
- [ ] New Binding issue #___
- [ ] Code style update
- [ ] Refactor
- [ ] Documentation
- [ ] Build-related changes
- [ ] Other, please describe:
**Does this PR introduce a breaking change?** (check one)
<!--
If yes, please describe the impact and migration path for existing applications in an attached issue. Filing a PR with breaking changes that has not been discussed and approved by the maintainers in an issue will be immediately closed.
-->
### Does this PR introduce a breaking change?
<!-- If yes, please describe the impact and migration path for existing applications in an attached issue. -->
- [ ] Yes. Issue #___
- [ ] Yes, and the changes were approved in issue #___
- [ ] No
**The PR fulfills these requirements:**
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix: #xxx[,#xxx]`, where "xxx" is the issue number)
### Checklist
- [ ] When resolving issues, they are referenced in the PR's title (e.g `fix: remove a typo, closes #___, #___`)
- [ ] A change file is added if any packages will require a version bump due to this PR per [the instructions in the readme](https://github.com/tauri-apps/tauri/blob/dev/.changes/readme.md).
- [ ] I have added a convincing reason for adding this feature, if necessary
If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)
**Other information:**
### Other information
+2 -7
View File
@@ -15,14 +15,9 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: stable
override: true
components: rustfmt, clippy
- name: clippy check
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-targets -- -D warnings
components: rustfmt
- name: fmt
uses: actions-rs/cargo@v1
with:
+48 -41
View File
@@ -6,7 +6,8 @@ authors = [
"Tauri Programme within The Commons Conservancy",
"The winit contributors"
]
edition = "2018"
edition = "2021"
rust-version = "1.56"
keywords = [ "windowing" ]
license = "Apache-2.0"
readme = "README.md"
@@ -27,7 +28,7 @@ targets = [
[features]
default = [ "tray" ]
tray = [ "tauri-libappindicator" ]
tray = [ "libappindicator" ]
ayatana = [ "libayatana-appindicator" ]
dox = [ "gtk/dox" ]
@@ -37,13 +38,13 @@ lazy_static = "1"
libc = "0.2"
log = "0.4"
serde = { version = "1", optional = true, features = [ "serde_derive" ] }
raw-window-handle = "0.3"
raw-window-handle = "0.4"
bitflags = "1"
crossbeam-channel = "0.5"
[dev-dependencies]
image = "0.23"
simple_logger = "1.13"
env_logger = "0.9"
[target."cfg(target_os = \"android\")".dependencies]
ndk = "0.4"
@@ -60,8 +61,8 @@ core-graphics = "0.22"
dispatch = "0.2"
scopeguard = "1.1"
[target."cfg(target_os = \"macos\")".dependencies.core-video-sys]
version = "0.1"
[target."cfg(target_os = \"macos\")".dependencies.tao-core-video-sys]
version = "0.2"
default_features = false
features = [ "display_link" ]
@@ -71,43 +72,49 @@ cc = "1"
[target."cfg(target_os = \"windows\")".dependencies]
parking_lot = "0.11"
unicode-segmentation = "1.8.0"
windows_macros = "0.30.0"
[target."cfg(target_os = \"windows\")".dependencies.winapi]
version = "0.3"
features = [
"combaseapi",
"commctrl",
"dwmapi",
"errhandlingapi",
"imm",
"hidusage",
"libloaderapi",
"objbase",
"ole2",
"processthreadsapi",
"shellapi",
"shellscalingapi",
"shobjidl_core",
"unknwnbase",
"winbase",
"windowsx",
"winerror",
"wingdi",
"winnt",
"winnls",
"winuser",
"impl-default"
[target."cfg(target_os = \"windows\")".dependencies.windows]
version = "0.30.0"
features = [
"alloc",
"Win32_Devices_HumanInterfaceDevice",
"Win32_Foundation",
"Win32_Globalization",
"Win32_Graphics_Dwm",
"Win32_Graphics_Gdi",
"Win32_System_Com",
"Win32_System_Com_StructuredStorage",
"Win32_System_DataExchange",
"Win32_System_Diagnostics_Debug",
"Win32_System_LibraryLoader",
"Win32_System_Memory",
"Win32_System_Ole",
"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\", target_os = \"netbsd\"))".dependencies]
cairo-rs = "0.14"
gio = "0.14"
glib = "0.14"
glib-sys = "0.14"
gtk = { version = "0.14", features = [ "v3_22" ] }
gdk = { version = "0.14", features = [ "v3_22" ] }
gdk-sys = "0.14"
gdk-pixbuf = { version = "0.14", features = [ "v2_36_8" ] }
libayatana-appindicator = { version = "0.1.6", optional = true }
tauri-libappindicator = { version = "0.1.2", optional = true }
cairo-rs = "0.15"
gio = "0.15"
glib = "0.15"
glib-sys = "0.15"
gtk = { version = "0.15", features = [ "v3_22" ] }
gdk = { version = "0.15", features = [ "v3_22" ] }
gdk-sys = "0.15"
gdkx11-sys = "0.15"
gdk-pixbuf = { version = "0.15", features = [ "v2_36_8" ] }
libayatana-appindicator = { version = "0.2", optional = true }
libappindicator = { version = "0.7", optional = true }
x11-dl = "2.18"
Binary file not shown.
+1 -2
View File
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
fn main() {
use simple_logger::SimpleLogger;
use tao::{
accelerator::{Accelerator, RawMods},
dpi::LogicalSize,
@@ -12,7 +11,7 @@ fn main() {
window::WindowBuilder,
};
SimpleLogger::new().init().unwrap();
env_logger::init();
// create a sample hotkey
let hotkey = Accelerator::new(RawMods::Shift, KeyCode::Digit1);
+1 -2
View File
@@ -3,7 +3,6 @@
use std::{thread, time};
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -23,7 +22,7 @@ const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100);
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
println!("Press '1' to switch to Wait mode.");
println!("Press '2' to switch to WaitUntil mode.");
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -9,7 +8,7 @@ use tao::{
};
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -11,7 +10,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -3,7 +3,7 @@
#[allow(clippy::single_match)]
fn main() {
use simple_logger::SimpleLogger;
env_logger::init();
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -15,7 +15,6 @@ fn main() {
Timer,
}
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::<CustomEvent>::with_user_event();
let _window = WindowBuilder::new()
+2 -5
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
#[cfg(target_os = "macos")]
use tao::platform::macos::{CustomMenuItemExtMacOS, NativeImage};
use tao::{
@@ -15,7 +14,7 @@ use tao::{
};
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
// create clipboard instance
@@ -48,6 +47,7 @@ fn main() {
// add `my_sub_menu` children of `first_menu` with `Sub menu` title
first_menu.add_submenu("Sub menu", true, my_sub_menu);
first_menu.add_native_item(MenuItem::CloseWindow);
first_menu.add_native_item(MenuItem::Quit);
// create custom item `Selected and disabled` children of `second_menu`
@@ -80,9 +80,6 @@ fn main() {
window_id,
..
} if window_id == window.id() => *control_flow = ControlFlow::Exit,
Event::MainEventsCleared => {
window.request_redraw();
}
Event::MenuEvent {
window_id,
menu_id,
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -11,7 +10,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window_1 = WindowBuilder::new().build(&event_loop).unwrap();
+1 -2
View File
@@ -3,7 +3,6 @@
use std::io::{stdin, stdout, Write};
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -14,7 +13,7 @@ use tao::{
#[allow(clippy::single_match)]
#[allow(clippy::ok_expect)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
print!("Please choose the fullscreen mode: (1) exclusive, (2) borderless: ");
+1 -2
View File
@@ -3,7 +3,6 @@
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn main() {
use simple_logger::SimpleLogger;
use std::str::FromStr;
use tao::{
accelerator::{Accelerator, AcceleratorId, RawMods, SysMods},
@@ -14,7 +13,7 @@ fn main() {
window::WindowBuilder,
};
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
// create new shortcut manager instance
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -11,7 +10,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
dpi::LogicalSize,
event::{Event, WindowEvent},
@@ -11,7 +10,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
+1 -2
View File
@@ -3,7 +3,6 @@
extern crate tao;
use simple_logger::SimpleLogger;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -13,7 +12,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -1,11 +1,10 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{event_loop::EventLoop, window::WindowBuilder};
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{DeviceEvent, Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -11,7 +10,7 @@ use tao::{
#[allow(clippy::collapsible_match)]
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -6,7 +6,6 @@
fn main() {
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
use simple_logger::SimpleLogger;
use tao::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
event::{ElementState, Event, KeyEvent, WindowEvent},
@@ -18,7 +17,7 @@ fn main() {
const WINDOW_COUNT: usize = 3;
const WINDOW_SIZE: PhysicalSize<u32> = PhysicalSize::new(600, 400);
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let mut window_senders = HashMap::with_capacity(WINDOW_COUNT);
for _ in 0..WINDOW_COUNT {
+1 -2
View File
@@ -3,7 +3,6 @@
use std::collections::HashMap;
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -11,7 +10,7 @@ use tao::{
};
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let mut windows = HashMap::new();
+3 -4
View File
@@ -3,7 +3,6 @@
#[cfg(any(target_os = "windows", target_os = "macos"))]
fn main() {
use simple_logger::SimpleLogger;
use std::collections::HashMap;
#[cfg(target_os = "macos")]
use tao::platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS};
@@ -16,8 +15,8 @@ fn main() {
window::WindowBuilder,
};
#[cfg(target_os = "windows")]
use winapi::shared::windef::HWND;
SimpleLogger::new().init().unwrap();
use windows::Win32::Foundation::HWND;
env_logger::init();
let event_loop = EventLoop::new();
let mut windows = HashMap::new();
let main_window = WindowBuilder::new().build(&event_loop).unwrap();
@@ -25,7 +24,7 @@ fn main() {
#[cfg(target_os = "macos")]
let parent_window = main_window.ns_window();
#[cfg(target_os = "windows")]
let parent_window = main_window.hwnd() as HWND;
let parent_window = HWND(main_window.hwnd() as _);
let child_window = WindowBuilder::new()
.with_parent_window(parent_window)
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{ElementState, Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -10,7 +9,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -3,7 +3,6 @@
use std::{thread, time};
use simple_logger::SimpleLogger;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -13,7 +12,7 @@ use tao::{
#[allow(clippy::single_match)]
#[allow(clippy::collapsible_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
dpi::LogicalSize,
event::{ElementState, Event, KeyEvent, WindowEvent},
@@ -12,7 +11,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let mut resizable = false;
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
dpi::PhysicalPosition,
event::{ElementState, Event, WindowEvent},
@@ -10,7 +9,7 @@ use tao::{
};
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
+1 -2
View File
@@ -6,7 +6,6 @@
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[cfg(feature = "tray")]
fn main() {
use simple_logger::SimpleLogger;
use std::collections::HashMap;
#[cfg(target_os = "linux")]
use std::path::Path;
@@ -20,7 +19,7 @@ fn main() {
window::{Window, WindowId},
};
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let mut windows: HashMap<WindowId, Window> = HashMap::new();
+1 -2
View File
@@ -6,7 +6,6 @@
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[cfg(feature = "tray")]
fn main() {
use simple_logger::SimpleLogger;
use std::collections::HashMap;
#[cfg(target_os = "linux")]
use std::path::Path;
@@ -27,7 +26,7 @@ fn main() {
window::WindowBuilder,
};
SimpleLogger::new().init().unwrap();
env_logger::init();
#[cfg(target_os = "macos")]
let mut event_loop = EventLoop::new();
+1 -2
View File
@@ -4,7 +4,6 @@
use instant::Instant;
use std::time::Duration;
use simple_logger::SimpleLogger;
use tao::{
event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -13,7 +12,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -10,7 +9,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -1,12 +1,11 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::event_loop::EventLoop;
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let monitor = match event_loop.primary_monitor() {
Some(monitor) => monitor,
+1 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use simple_logger::SimpleLogger;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -10,7 +9,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -3,7 +3,6 @@
// This example is used by developers to test various window functions.
use simple_logger::SimpleLogger;
use tao::{
dpi::{LogicalSize, PhysicalSize},
event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent},
@@ -15,7 +14,7 @@ use tao::{
#[allow(clippy::single_match)]
#[allow(clippy::collapsible_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
+1 -2
View File
@@ -4,7 +4,6 @@
extern crate image;
use std::path::Path;
use simple_logger::SimpleLogger;
use tao::{
event::Event,
event_loop::{ControlFlow, EventLoop},
@@ -13,7 +12,7 @@ use tao::{
#[allow(clippy::single_match)]
fn main() {
SimpleLogger::new().init().unwrap();
env_logger::init();
// You'll have to choose an icon size at your own discretion. On Linux, the icon should be
// provided in whatever size it was naturally drawn; that is, don’t scale the image before passing
+1 -2
View File
@@ -7,7 +7,6 @@
fn main() {
use std::{thread::sleep, time::Duration};
use simple_logger::SimpleLogger;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -16,7 +15,7 @@ fn main() {
};
let mut event_loop = EventLoop::new();
SimpleLogger::new().init().unwrap();
env_logger::init();
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
+58 -44
View File
@@ -1,9 +1,6 @@
//! The Accelerator struct and associated types.
use crate::{
error::OsError,
keyboard::{KeyCode, ModifiersState, NativeKeyCode},
};
use crate::keyboard::{KeyCode, ModifiersState, NativeKeyCode};
use std::{
borrow::Borrow,
collections::hash_map::DefaultHasher,
@@ -62,9 +59,9 @@ impl Accelerator {
// compatible with tauri and it also open the option
// to generate accelerator from string
impl FromStr for Accelerator {
type Err = OsError;
type Err = AcceleratorParseError;
fn from_str(accelerator_string: &str) -> Result<Self, Self::Err> {
Ok(parse_accelerator(accelerator_string))
parse_accelerator(accelerator_string)
}
}
@@ -256,14 +253,37 @@ impl AcceleratorId {
}
}
fn parse_accelerator(accelerator_string: &str) -> Accelerator {
#[derive(Debug, Clone)]
pub struct AcceleratorParseError(String);
impl std::fmt::Display for AcceleratorParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[AcceleratorParseError]: {}", self.0)
}
}
fn parse_accelerator(accelerator_string: &str) -> Result<Accelerator, AcceleratorParseError> {
let mut mods = ModifiersState::empty();
let mut key = KeyCode::Unidentified(NativeKeyCode::Unidentified);
for raw in accelerator_string.to_uppercase().split('+') {
let token = raw.trim().to_string();
if token.is_empty() {
continue;
return Err(AcceleratorParseError(
"Unexpected empty token while parsing accelerator".into(),
));
}
if key != KeyCode::Unidentified(NativeKeyCode::Unidentified) {
// at this point we already parsed the modifiers and found a main key but
// the function received more then one main key or it is not in the right order
// examples:
// 1. "Ctrl+Shift+C+A" => only one main key should be allowd.
// 2. "Ctrl+C+Shift" => wrong order
return Err(AcceleratorParseError(format!(
"Unexpected accelerator string format: \"{}\"",
accelerator_string
)));
}
match token.as_str() {
@@ -287,18 +307,26 @@ fn parse_accelerator(accelerator_string: &str) -> Accelerator {
}
_ => {
if let Ok(keycode) = KeyCode::from_str(token.to_uppercase().as_str()) {
key = keycode;
match keycode {
KeyCode::Unidentified(_) => {
return Err(AcceleratorParseError(format!(
"Couldn't identify \"{}\" as a valid `KeyCode`",
token
)))
}
_ => key = keycode,
}
}
}
}
}
Accelerator {
Ok(Accelerator {
// use the accelerator string as id
id: Some(AcceleratorId(hash_string_to_u16(accelerator_string))),
key,
mods,
}
})
}
fn hash_string_to_u16(title: &str) -> u16 {
@@ -319,7 +347,7 @@ fn hash_accelerator_to_u16(hotkey: Accelerator) -> u16 {
#[test]
fn test_parse_accelerator() {
assert_eq!(
parse_accelerator("CTRL+X"),
parse_accelerator("CTRL+X").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("CTRL+X")),
mods: ModifiersState::CONTROL,
@@ -327,7 +355,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("SHIFT+C"),
parse_accelerator("SHIFT+C").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("SHIFT+C")),
mods: ModifiersState::SHIFT,
@@ -335,7 +363,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("CTRL+Z"),
parse_accelerator("CTRL+Z").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("CTRL+Z")),
mods: ModifiersState::CONTROL,
@@ -343,7 +371,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("super+ctrl+SHIFT+alt+Up"),
parse_accelerator("super+ctrl+SHIFT+alt+Up").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("super+ctrl+SHIFT+alt+Up")),
mods: ModifiersState::SUPER
@@ -354,7 +382,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("5"),
parse_accelerator("5").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("5")),
mods: ModifiersState::empty(),
@@ -362,7 +390,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("G"),
parse_accelerator("G").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("G")),
mods: ModifiersState::empty(),
@@ -370,7 +398,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("G"),
parse_accelerator("G").unwrap(),
Accelerator {
// id not with same uppercase should work
id: Some(AcceleratorId::new("g")),
@@ -378,24 +406,15 @@ fn test_parse_accelerator() {
key: KeyCode::KeyG,
}
);
let acc = parse_accelerator("+G");
assert!(acc.is_err());
let acc = parse_accelerator("SHGSH+G");
assert!(acc.is_err());
assert_eq!(
parse_accelerator("+G"),
Accelerator {
id: Some(AcceleratorId::new("+G")),
mods: ModifiersState::empty(),
key: KeyCode::KeyG,
}
);
assert_eq!(
parse_accelerator("SHGSH+G"),
Accelerator {
id: Some(AcceleratorId::new("SHGSH+G")),
mods: ModifiersState::empty(),
key: KeyCode::KeyG,
}
);
assert_eq!(
parse_accelerator("SHiFT+F12"),
parse_accelerator("SHiFT+F12").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("SHIFT+F12")),
mods: ModifiersState::SHIFT,
@@ -403,7 +422,7 @@ fn test_parse_accelerator() {
}
);
assert_eq!(
parse_accelerator("CmdOrCtrl+Space"),
parse_accelerator("CmdOrCtrl+Space").unwrap(),
Accelerator {
id: Some(AcceleratorId::new("CmdOrCtrl+Space")),
#[cfg(target_os = "macos")]
@@ -413,12 +432,7 @@ fn test_parse_accelerator() {
key: KeyCode::Space,
}
);
assert_eq!(
parse_accelerator("CTRL+"),
Accelerator {
id: Some(AcceleratorId::new("CTRL+")),
mods: ModifiersState::CONTROL,
key: KeyCode::Unidentified(NativeKeyCode::Unidentified),
}
);
let acc = parse_accelerator("CTRL+");
assert!(acc.is_err());
}
+1
View File
@@ -54,6 +54,7 @@ pub(crate) type FormatId = &'static str;
/// Object that allows you to access the `ClipboardFormat`.
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub(crate) struct ClipboardFormat {
pub(crate) identifier: FormatId,
pub(crate) data: Vec<u8>,
+9
View File
@@ -138,6 +138,15 @@ pub enum Event<'a, T: 'static> {
///
/// Mainly of interest to applications with mostly-static graphics that avoid redrawing unless
/// something changes, like most non-game GUIs.
///
/// ## Platform-specific
///
/// - **Linux: This is triggered by `draw` signal of the gtk window. It can be used to detect if
/// the window is requested to redraw. But widgets it contains are usually not tied to its signal.
/// So if you really want to draw each component, please consider using `connect_draw` method
/// from [`WidgetExt`] directly.**
///
/// [`WidgetExt`]: https://gtk-rs.org/gtk3-rs/stable/latest/docs/gtk/prelude/trait.WidgetExt.html
RedrawRequested(WindowId),
/// Emitted after all `RedrawRequested` events have been processed and control flow is about to
+32 -6
View File
@@ -41,6 +41,7 @@ pub struct EventLoop<T: 'static> {
/// 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`.
#[derive(Clone)]
pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
pub(crate) _marker: ::std::marker::PhantomData<*mut ()>, // Not Send nor Sync
@@ -65,9 +66,9 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
///
/// ## 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 `Exit` 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`.
/// 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`.
///
/// [events_cleared]: crate::event::Event::RedrawEventsCleared
#[non_exhaustive]
@@ -82,9 +83,29 @@ pub enum ControlFlow {
/// arrives or the given time is reached.
WaitUntil(Instant),
/// Send a `LoopDestroyed` event and stop the event loop. This variant is *sticky* - once set,
/// `control_flow` cannot be changed from `Exit`, and any future attempts to do so will result
/// in the `control_flow` parameter being reset to `Exit`.
Exit,
/// `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`].
///
/// [`Exit`]: ControlFlow::Exit
ExitWithCode(i32),
}
impl ControlFlow {
/// Alias for [`ExitWithCode`]`(0)`.
///
/// [`ExitWithCode`]: ControlFlow::ExitWithCode
#[allow(non_upper_case_globals)]
pub const Exit: Self = Self::ExitWithCode(0);
}
impl Default for ControlFlow {
@@ -142,6 +163,11 @@ impl<T> EventLoop<T> {
///
/// Any values not passed to this function will *not* be dropped.
///
/// ## Platform-specific
///
/// - **Unix**: 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) -> !
+26 -27
View File
@@ -667,11 +667,11 @@ impl FromStr for KeyCode {
type Err = OsError;
fn from_str(accelerator_string: &str) -> Result<Self, Self::Err> {
let keycode = match accelerator_string.to_uppercase().as_str() {
"BACKQUOTE" => KeyCode::Backquote,
"`" | "BACKQUOTE" => KeyCode::Backquote,
"BACKSLASH" => KeyCode::Backslash,
"BRACKETLEFT" => KeyCode::BracketLeft,
"BRACKETRIGHT" => KeyCode::BracketRight,
"COMMA" => KeyCode::Comma,
"[" | "BRACKETLEFT" => KeyCode::BracketLeft,
"]" | "BRACKETRIGHT" => KeyCode::BracketRight,
"," | "COMMA" => KeyCode::Comma,
"0" => KeyCode::Digit0,
"1" => KeyCode::Digit1,
"2" => KeyCode::Digit2,
@@ -682,20 +682,20 @@ impl FromStr for KeyCode {
"7" => KeyCode::Digit7,
"8" => KeyCode::Digit8,
"9" => KeyCode::Digit9,
"NUMPAD0" => KeyCode::Numpad0,
"NUMPAD1" => KeyCode::Numpad1,
"NUMPAD2" => KeyCode::Numpad2,
"NUMPAD3" => KeyCode::Numpad3,
"NUMPAD4" => KeyCode::Numpad4,
"NUMPAD5" => KeyCode::Numpad5,
"NUMPAD6" => KeyCode::Numpad6,
"NUMPAD7" => KeyCode::Numpad7,
"NUMPAD8" => KeyCode::Numpad8,
"NUMPAD9" => KeyCode::Numpad9,
"NUM0" | "NUMPAD0" => KeyCode::Numpad0,
"NUM1" | "NUMPAD1" => KeyCode::Numpad1,
"NUM2" | "NUMPAD2" => KeyCode::Numpad2,
"NUM3" | "NUMPAD3" => KeyCode::Numpad3,
"NUM4" | "NUMPAD4" => KeyCode::Numpad4,
"NUM5" | "NUMPAD5" => KeyCode::Numpad5,
"NUM6" | "NUMPAD6" => KeyCode::Numpad6,
"NUM7" | "NUMPAD7" => KeyCode::Numpad7,
"NUM8" | "NUMPAD8" => KeyCode::Numpad8,
"NUM9" | "NUMPAD9" => KeyCode::Numpad9,
"=" => KeyCode::Equal,
"-" => KeyCode::Minus,
"PERIOD" => KeyCode::Period,
"QUOTE" => KeyCode::Quote,
"." | "PERIOD" => KeyCode::Period,
"'" | "QUOTE" => KeyCode::Quote,
"\\" => KeyCode::IntlBackslash,
"A" => KeyCode::KeyA,
"B" => KeyCode::KeyB,
@@ -724,8 +724,8 @@ impl FromStr for KeyCode {
"Y" => KeyCode::KeyY,
"Z" => KeyCode::KeyZ,
"SEMICOLON" => KeyCode::Semicolon,
"SLASH" => KeyCode::Slash,
";" | "SEMICOLON" => KeyCode::Semicolon,
"/" | "SLASH" => KeyCode::Slash,
"BACKSPACE" => KeyCode::Backspace,
"CAPSLOCK" => KeyCode::CapsLock,
"CONTEXTMENU" => KeyCode::ContextMenu,
@@ -747,16 +747,15 @@ impl FromStr for KeyCode {
"RIGHT" => KeyCode::ArrowRight,
"NUMLOCK" => KeyCode::NumLock,
"NUMPADADD" => KeyCode::NumpadAdd,
"NUMPADBACKSPACE" => KeyCode::NumpadBackspace,
"NUMPADCLEAR" => KeyCode::NumpadClear,
"NUMPADCOMMA" => KeyCode::NumpadComma,
"NUMPADDIVIDE" => KeyCode::NumpadDivide,
"NUMPADSUBSTRACT" => KeyCode::NumpadSubtract,
"NUMPADENTER" => KeyCode::NumpadEnter,
"NUMADD" | "NUMPADADD" => KeyCode::NumpadAdd,
"NUMBACKSPACE" | "NUMPADBACKSPACE" => KeyCode::NumpadBackspace,
"NUMCLEAR" | "NUMPADCLEAR" => KeyCode::NumpadClear,
"NUMCOMMA" | "NUMPADCOMMA" => KeyCode::NumpadComma,
"NUMDIVIDE" | "NUMPADDIVIDE" => KeyCode::NumpadDivide,
"NUMSUBSTRACT" | "NUMPADSUBSTRACT" => KeyCode::NumpadSubtract,
"NUMENTER" | "NUMPADENTER" => KeyCode::NumpadEnter,
"ESCAPE" => KeyCode::Escape,
"ESC" => KeyCode::Escape,
"ESC" | "ESCAPE" => KeyCode::Escape,
"FN" => KeyCode::Fn,
"FNLOCK" => KeyCode::FnLock,
"PRINTSCREEN" => KeyCode::PrintScreen,
+8 -5
View File
@@ -34,8 +34,8 @@
//! 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`]`::`[`Exit`], at which point [`Event`]`::`[`LoopDestroyed`] is emitted and the
//! entire program terminates.
//! [`ControlFlow`]`::`[`ExitWithCode`] (which [`ControlFlow`]`::`[`Exit`] aliases to), at which
//! point [`Event`]`::`[`LoopDestroyed`] is emitted and the entire program terminates.
//!
//! Tao 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
@@ -117,6 +117,7 @@
//! [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
@@ -132,16 +133,18 @@
//! [`platform`]: platform
//! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle
#![allow(
clippy::match_str_case_mismatch,
clippy::upper_case_acronyms,
clippy::from_over_into,
clippy::option_map_unit_fn,
clippy::needless_lifetimes,
clippy::type_complexity,
clippy::identity_op,
clippy::wrong_self_convention
clippy::wrong_self_convention,
clippy::non_send_fields_in_send_ty
)]
#![deny(rust_2018_idioms)]
#![deny(broken_intra_doc_links)]
#![deny(rustdoc::broken_intra_doc_links)]
#[allow(unused_imports)]
#[macro_use]
@@ -180,7 +183,7 @@ mod platform_impl;
target_os = "netbsd",
target_os = "openbsd"
))]
#[cfg(feature = "tray")]
#[cfg(any(feature = "tray", feature = "ayatana"))]
pub mod system_tray;
pub mod window;
+3
View File
@@ -152,6 +152,9 @@ impl MonitorHandle {
}
/// Returns all fullscreen video modes supported by this monitor.
///
/// ## Platform-specific
/// - **Linux:** Unsupported. This will always return empty iterator.
#[inline]
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
self.inner.video_modes()
+8
View File
@@ -445,6 +445,8 @@ impl MonitorHandleExtMacOS for MonitorHandle {
pub trait EventLoopWindowTargetExtMacOS {
/// Hide the entire application. In most applications this is typically triggered with Command-H.
fn hide_application(&self);
/// Show the entire application.
fn show_application(&self);
/// Hide the other applications. In most applications this is typically triggered with Command+Option-H.
fn hide_other_applications(&self);
}
@@ -456,6 +458,12 @@ impl<T> EventLoopWindowTargetExtMacOS for EventLoopWindowTarget<T> {
unsafe { msg_send![app, hide: 0] }
}
fn show_application(&self) {
let cls = objc::runtime::Class::get("NSApplication").unwrap();
let app: cocoa::base::id = unsafe { msg_send![cls, sharedApplication] };
unsafe { msg_send![app, unhide: 0] }
}
fn hide_other_applications(&self) {
let cls = objc::runtime::Class::get("NSApplication").unwrap();
let app: cocoa::base::id = unsafe { msg_send![cls, sharedApplication] };
+8 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
#![cfg(any(target_os = "windows", target_os = "macos", target_os = "android",))]
#![cfg(not(target_os = "ios"))]
use crate::{
event::Event,
@@ -27,7 +27,12 @@ pub trait EventLoopExtRunReturn {
/// underlying OS APIs, which cannot be hidden by `tao` without severe stability repercussions.
///
/// You are strongly encouraged to use `run`, unless the use of this is absolutely necessary.
fn run_return<F>(&mut self, event_handler: F)
///
/// ## Platform-specific
///
/// - **Unix-alikes** (**X11** or **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);
}
@@ -35,7 +40,7 @@ pub trait EventLoopExtRunReturn {
impl<T> EventLoopExtRunReturn for EventLoop<T> {
type UserEvent = T;
fn run_return<F>(&mut self, event_handler: F)
fn run_return<F>(&mut self, event_handler: F) -> i32
where
F: FnMut(Event<'_, Self::UserEvent>, &EventLoopWindowTarget<Self::UserEvent>, &mut ControlFlow),
{
+30 -2
View File
@@ -9,8 +9,11 @@
target_os = "openbsd"
))]
pub use crate::platform_impl::hit_test;
use crate::window::{Window, WindowBuilder};
pub use crate::platform_impl::{hit_test, EventLoop as UnixEventLoop};
use crate::{
event_loop::EventLoop,
window::{Window, WindowBuilder},
};
/// Additional methods on `Window` that are specific to Unix.
pub trait WindowExtUnix {
@@ -42,3 +45,28 @@ impl WindowBuilderExtUnix for WindowBuilder {
self
}
}
/// Additional methods on `EventLoop` that are specific to Unix.
pub trait EventLoopExtUnix {
/// Builds a new `EventLoop` on any thread.
///
/// This method bypasses the cross-platform compatibility requirement
/// that `EventLoop` be created on the main thread.
fn new_any_thread() -> Self
where
Self: Sized;
}
fn wrap_ev<T>(event_loop: UnixEventLoop<T>) -> EventLoop<T> {
EventLoop {
event_loop,
_marker: std::marker::PhantomData,
}
}
impl<T> EventLoopExtUnix for EventLoop<T> {
#[inline]
fn new_any_thread() -> Self {
wrap_ev(UnixEventLoop::new_any_thread())
}
}
+18 -34
View File
@@ -3,7 +3,7 @@
#![cfg(target_os = "windows")]
use std::{os::raw::c_void, path::Path};
use std::path::Path;
pub use crate::platform_impl::hit_test;
use crate::{
@@ -15,12 +15,9 @@ use crate::{
window::{BadIcon, Icon, Theme, Window, WindowBuilder},
};
use libc;
use winapi::{
shared::{
minwindef::{self, WORD},
windef::{HMENU, HWND},
},
um::winuser,
use windows::Win32::{
Foundation::HWND,
UI::{Input::KeyboardAndMouse::*, WindowsAndMessaging::*},
};
/// Additional methods on `EventLoop` that are specific to Windows.
@@ -114,7 +111,7 @@ pub trait WindowExtWindows {
fn reset_dead_keys(&self);
/// Starts the resizing drag from given edge
fn begin_resize_drag(&self, edge: isize);
fn begin_resize_drag(&self, edge: isize, button: u32, x: i32, y: i32);
/// Whether to show the window icon in the taskbar or not.
fn set_skip_taskbar(&self, skip: bool);
@@ -123,18 +120,18 @@ pub trait WindowExtWindows {
impl WindowExtWindows for Window {
#[inline]
fn hinstance(&self) -> *mut libc::c_void {
self.window.hinstance() as *mut _
self.window.hinstance().0 as _
}
#[inline]
fn hwnd(&self) -> *mut libc::c_void {
self.window.hwnd() as *mut _
self.window.hwnd().0 as _
}
#[inline]
fn set_enable(&self, enabled: bool) {
unsafe {
winapi::um::winuser::EnableWindow(self.hwnd() as _, enabled as _);
EnableWindow(self.window.hwnd(), enabled);
}
}
@@ -154,27 +151,13 @@ impl WindowExtWindows for Window {
}
#[inline]
fn begin_resize_drag(&self, edge: isize) {
unsafe {
let point = {
let mut pos = std::mem::zeroed();
winuser::GetCursorPos(&mut pos);
pos
};
winuser::ReleaseCapture();
winuser::PostMessageW(
self.hwnd() as _,
winuser::WM_NCLBUTTONDOWN,
edge as minwindef::WPARAM,
&point as *const _ as minwindef::LPARAM,
);
}
fn begin_resize_drag(&self, edge: isize, button: u32, x: i32, y: i32) {
self.window.begin_resize_drag(edge, button, x, y)
}
#[inline]
fn set_skip_taskbar(&self, skip: bool) {
self.window.set_skip_taskbar(skip, true);
self.window.set_skip_taskbar(skip);
}
}
@@ -203,7 +186,8 @@ pub trait WindowBuilderExtWindows {
///
/// Parent and menu are mutually exclusive; a child window cannot have a menu!
///
/// The menu must have been manually created beforehand with [`winapi::um::winuser::CreateMenu`] or similar.
/// The menu must have been manually created beforehand with [`windows::Win32::UI::WindowsAndMessaging::CreateMenu`]
/// or similar.
///
/// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how the menus look.
/// If you use this, it is recommended that you combine it with `with_theme(Some(Theme::Light))` to avoid a jarring effect.
@@ -286,7 +270,7 @@ pub trait MonitorHandleExtWindows {
fn native_id(&self) -> String;
/// Returns the handle of the monitor - `HMONITOR`.
fn hmonitor(&self) -> *mut c_void;
fn hmonitor(&self) -> *mut libc::c_void;
}
impl MonitorHandleExtWindows for MonitorHandle {
@@ -296,8 +280,8 @@ impl MonitorHandleExtWindows for MonitorHandle {
}
#[inline]
fn hmonitor(&self) -> *mut c_void {
self.inner.hmonitor() as *mut _
fn hmonitor(&self) -> *mut libc::c_void {
self.inner.hmonitor().0 as _
}
}
@@ -334,7 +318,7 @@ pub trait IconExtWindows: Sized {
///
/// In cases where the specified size does not exist in the file, Windows may perform scaling
/// to get an icon of the desired size.
fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
fn from_resource(ordinal: u16, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
}
impl IconExtWindows for Icon {
@@ -343,7 +327,7 @@ impl IconExtWindows for Icon {
Ok(Icon { inner: win_icon })
}
fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> {
fn from_resource(ordinal: u16, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> {
let win_icon = WinIcon::from_resource(ordinal, size)?;
Ok(Icon { inner: win_icon })
}
+15 -14
View File
@@ -18,6 +18,7 @@ use ndk::{
};
use ndk_glue::{Event, Rect};
use ndk_sys::AKeyEvent_getKeyCode;
use raw_window_handle::{AndroidNdkHandle, RawWindowHandle};
use std::{
collections::VecDeque,
convert::TryInto,
@@ -116,10 +117,10 @@ pub struct EventLoop<T: 'static> {
macro_rules! call_event_handler {
( $event_handler:expr, $window_target:expr, $cf:expr, $event:expr ) => {{
if $cf != ControlFlow::Exit {
$event_handler($event, $window_target, &mut $cf);
if let ControlFlow::ExitWithCode(code) = $cf {
$event_handler($event, $window_target, &mut ControlFlow::ExitWithCode(code));
} else {
$event_handler($event, $window_target, &mut ControlFlow::Exit);
$event_handler($event, $window_target, &mut $cf);
}
}};
}
@@ -146,11 +147,11 @@ impl<T: 'static> EventLoop<T> {
F:
'static + FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
self.run_return(event_handler);
::std::process::exit(0);
let exit_code = self.run_return(event_handler);
::std::process::exit(exit_code);
}
pub fn run_return<F>(&mut self, mut event_handler: F)
pub fn run_return<F>(&mut self, mut event_handler: F) -> i32
where
F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
@@ -376,7 +377,7 @@ impl<T: 'static> EventLoop<T> {
);
match control_flow {
ControlFlow::Exit => {
ControlFlow::ExitWithCode(code) => {
self.first_event = poll(
self
.looper
@@ -387,7 +388,7 @@ impl<T: 'static> EventLoop<T> {
start: Instant::now(),
requested_resume: None,
};
break 'event_loop;
break 'event_loop code;
}
ControlFlow::Poll => {
self.first_event = poll(
@@ -463,6 +464,7 @@ impl<T> Clone for EventLoopProxy<T> {
}
}
#[derive(Clone)]
pub struct EventLoopWindowTarget<T: 'static> {
_marker: std::marker::PhantomData<T>,
}
@@ -657,15 +659,14 @@ impl Window {
))
}
pub fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
let a_native_window = if let Some(native_window) = ndk_glue::native_window().as_ref() {
unsafe { native_window.ptr().as_mut() as *mut _ as *mut _ }
pub fn raw_window_handle(&self) -> RawWindowHandle {
let mut handle = AndroidNdkHandle::empty();
if let Some(native_window) = ndk_glue::native_window().as_ref() {
handle.a_native_window = unsafe { native_window.ptr().as_mut() as *mut _ as *mut _ }
} else {
panic!("Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events.");
};
let mut handle = raw_window_handle::android::AndroidHandle::empty();
handle.a_native_window = a_native_window;
raw_window_handle::RawWindowHandle::Android(handle)
RawWindowHandle::AndroidNdk(handle)
}
pub fn config(&self) -> Configuration {
+2 -2
View File
@@ -299,7 +299,7 @@ impl AppState {
};
(waiting_event_handler, event)
}
(ControlFlow::Exit, _) => bug!("unexpected `ControlFlow` `Exit`"),
(ControlFlow::ExitWithCode(_), _) => bug!("unexpected `ControlFlow` `Exit`"),
s => bug!("`EventHandler` unexpectedly woke up {:?}", s),
};
@@ -450,7 +450,7 @@ impl AppState {
});
self.waker.start()
}
(_, ControlFlow::Exit) => {
(_, ControlFlow::ExitWithCode(_)) => {
// https://developer.apple.com/library/archive/qa/qa1561/_index.html
// it is not possible to quit an iOS app gracefully and programatically
warn!("`ControlFlow::Exit` ignored on iOS");
+1
View File
@@ -49,6 +49,7 @@ pub enum EventProxy {
},
}
#[derive(Clone)]
pub struct EventLoopWindowTarget<T: 'static> {
receiver: Receiver<T>,
sender_to_clone: Sender<T>,
+2 -1
View File
@@ -65,7 +65,8 @@
// window size/position.
macro_rules! assert_main_thread {
($($t:tt)*) => {
if !msg_send![class!(NSThread), isMainThread] {
let is_main_thread: ::objc::runtime::BOOL = msg_send!(class!(NSThread), isMainThread);
if is_main_thread == ::objc::runtime::NO {
panic!($($t)*);
}
};
+7 -9
View File
@@ -1,7 +1,7 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
use raw_window_handle::{ios::IOSHandle, RawWindowHandle};
use raw_window_handle::{RawWindowHandle, UiKitHandle};
use std::{
collections::VecDeque,
ops::{Deref, DerefMut},
@@ -229,7 +229,7 @@ impl Inner {
let uiscreen = match monitor {
Some(Fullscreen::Exclusive(video_mode)) => {
let uiscreen = video_mode.video_mode.monitor.ui_screen() as id;
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode];
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode.0];
uiscreen
}
Some(Fullscreen::Borderless(monitor)) => monitor
@@ -341,13 +341,11 @@ impl Inner {
}
pub fn raw_window_handle(&self) -> RawWindowHandle {
let handle = IOSHandle {
ui_window: self.window as _,
ui_view: self.view as _,
ui_view_controller: self.view_controller as _,
..IOSHandle::empty()
};
RawWindowHandle::IOS(handle)
let mut handle = UiKitHandle::empty();
handle.ui_window = self.window as _;
handle.ui_view = self.view as _;
handle.ui_view_controller = self.view_controller as _;
RawWindowHandle::UiKit(handle)
}
}
File diff suppressed because it is too large. Load diff
@@ -94,11 +94,13 @@ impl ShortcutManager {
),
)))
{
#[cfg(debug_assertions)]
eprintln!("hotkey: thread_sender.send error {}", err);
}
} else if let Err(err) = thread_sender.send(HotkeyMessage::RegisterHotkeyResult(Ok(
(keycode, modifiers),
))) {
#[cfg(debug_assertions)]
eprintln!("hotkey: thread_sender.send error {}", err);
}
}
@@ -113,8 +115,14 @@ impl ShortcutManager {
),
)))
{
#[cfg(debug_assertions)]
eprintln!("hotkey: thread_sender.send error {}", err);
}
} else if let Err(err) =
thread_sender.send(HotkeyMessage::UnregisterHotkeyResult(Ok(())))
{
#[cfg(debug_assertions)]
eprintln!("hotkey: thread_sender.send error {}", err);
}
}
Ok(HotkeyMessage::DropThread) => {
@@ -123,6 +131,7 @@ impl ShortcutManager {
}
Err(err) => {
if let TryRecvError::Disconnected = err {
#[cfg(debug_assertions)]
eprintln!("hotkey: try_recv error {}", err);
}
}
@@ -245,6 +254,7 @@ impl ShortcutManager {
impl Drop for ShortcutManager {
fn drop(&mut self) {
if let Err(err) = self.method_sender.send(HotkeyMessage::DropThread) {
#[cfg(debug_assertions)]
eprintln!("cant send close thread message {}", err);
}
}
+13
View File
@@ -220,6 +220,7 @@ pub(crate) fn make_key_event(
},
});
} else {
#[cfg(debug_assertions)]
eprintln!("Couldn't get key from code: {:?}", physical_key);
}
None
@@ -299,6 +300,18 @@ pub fn key_to_raw_key(src: &KeyCode) -> Option<RawKey> {
KeyCode::F10 => F10,
KeyCode::F11 => F11,
KeyCode::F12 => F12,
KeyCode::F13 => F13,
KeyCode::F14 => F14,
KeyCode::F15 => F15,
KeyCode::F16 => F16,
KeyCode::F17 => F17,
KeyCode::F18 => F18,
KeyCode::F19 => F19,
KeyCode::F20 => F20,
KeyCode::F21 => F21,
KeyCode::F22 => F22,
KeyCode::F23 => F23,
KeyCode::F24 => F24,
KeyCode::PrintScreen => Print,
KeyCode::ScrollLock => Scroll_Lock,
+53 -5
View File
@@ -18,10 +18,15 @@ use crate::{
};
macro_rules! menuitem {
( $description:expr, $key:expr, $accel_group:ident ) => {{
( $description:expr, $key:expr, $accel_group:ident, $window_id:expr, $native_menu_item:expr, $tx:ident ) => {{
let item = GtkMenuItem::with_label($description);
let (key, mods) = gtk::accelerator_parse($key);
item.add_accelerator("activate", $accel_group, key, mods, AccelFlags::VISIBLE);
item.connect_activate(move |_| {
if let Err(e) = $tx.send(($window_id, WindowRequest::Menu(($native_menu_item, None)))) {
log::warn!("Fail to send native menu request: {}", e);
}
});
Some(item)
}};
}
@@ -57,6 +62,7 @@ unsafe impl Send for Menu {}
unsafe impl Sync for Menu {}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct MenuItemAttributes {
id: MenuId,
key: Option<Accelerator>,
@@ -113,7 +119,7 @@ impl Menu {
menu_type: MenuType,
) -> CustomMenuItem {
let gtk_item = if selected {
let item = CheckMenuItem::with_label(&title);
let item = CheckMenuItem::with_label(title);
item.set_active(true);
item.upcast::<GtkMenuItem>()
} else {
@@ -245,17 +251,47 @@ impl Menu {
menu_type: GtkMenuType::Native,
menu_item: Some(MenuItem::Hide),
..
} => menuitem!("Hide", "<Ctrl>H", accel_group),
} => {
let tx_clone = tx.clone();
menuitem!(
"Hide",
"<Ctrl>H",
accel_group,
window_id,
Some(MenuItem::Hide),
tx_clone
)
}
GtkMenuInfo {
menu_type: GtkMenuType::Native,
menu_item: Some(MenuItem::CloseWindow),
..
} => menuitem!("Close Window", "<Ctrl>W", accel_group),
} => {
let tx_clone = tx.clone();
menuitem!(
"Close Window",
"<Ctrl>W",
accel_group,
window_id,
Some(MenuItem::CloseWindow),
tx_clone
)
}
GtkMenuInfo {
menu_type: GtkMenuType::Native,
menu_item: Some(MenuItem::Quit),
..
} => menuitem!("Quit", "Q", accel_group),
} => {
let tx_clone = tx.clone();
menuitem!(
"Quit",
"<Ctrl>Q",
accel_group,
window_id,
Some(MenuItem::Quit),
tx_clone
)
}
// TODO add others
_ => None,
};
@@ -305,6 +341,18 @@ fn register_accelerator(item: &GtkMenuItem, accel_group: &AccelGroup, menu_key:
KeyCode::Digit7 => '7' as u32,
KeyCode::Digit8 => '8' as u32,
KeyCode::Digit9 => '9' as u32,
KeyCode::Comma => ',' as u32,
KeyCode::Minus => '-' as u32,
KeyCode::Period => '.' as u32,
KeyCode::Space => ' ' as u32,
KeyCode::Equal => '=' as u32,
KeyCode::Semicolon => ';' as u32,
KeyCode::Slash => '/' as u32,
KeyCode::Backslash => '\\' as u32,
KeyCode::Quote => '\'' as u32,
KeyCode::Backquote => '`' as u32,
KeyCode::BracketLeft => '[' as u32,
KeyCode::BracketRight => ']' as u32,
k => {
if let Some(gdk_key) = key_to_raw_key(k) {
*gdk_key
+7 -12
View File
@@ -16,11 +16,11 @@ mod keyboard;
mod keycode;
mod menu;
mod monitor;
#[cfg(feature = "tray")]
#[cfg(any(feature = "tray", feature = "ayatana"))]
mod system_tray;
mod window;
#[cfg(feature = "tray")]
#[cfg(any(feature = "tray", feature = "ayatana"))]
pub use self::system_tray::{SystemTray, SystemTrayBuilder};
pub use self::{
clipboard::Clipboard,
@@ -32,7 +32,7 @@ pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget};
pub use monitor::{MonitorHandle, VideoMode};
pub use window::{hit_test, PlatformIcon, Window, WindowId};
use crate::keyboard::Key;
use crate::{event::DeviceId as RootDeviceId, keyboard::Key};
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {
@@ -40,19 +40,11 @@ pub struct KeyEventExtra {
pub key_without_modifiers: Key<'static>,
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub skip_taskbar: bool,
}
impl Default for PlatformSpecificWindowBuilderAttributes {
fn default() -> Self {
Self {
skip_taskbar: false,
}
}
}
unsafe impl Send for PlatformSpecificWindowBuilderAttributes {}
unsafe impl Sync for PlatformSpecificWindowBuilderAttributes {}
@@ -73,3 +65,6 @@ impl DeviceId {
Self(0)
}
}
// FIXME: currently we use a dummy device id, find if we can get device id from gtk
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId(0));
+15 -13
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize},
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
};
@@ -12,7 +12,7 @@ pub struct MonitorHandle {
// We have to store the monitor number in GdkScreen despite
// it's deprecated. Otherwise, there's no way to set it in
// GtkWindow in Gtk3.
number: i32,
pub(crate) number: i32,
}
impl MonitorHandle {
@@ -29,19 +29,21 @@ impl MonitorHandle {
#[inline]
pub fn size(&self) -> PhysicalSize<u32> {
let rect = self.monitor.geometry();
PhysicalSize {
width: rect.width as u32,
height: rect.height as u32,
LogicalSize {
width: rect.width() as u32,
height: rect.height() as u32,
}
.to_physical(self.scale_factor())
}
#[inline]
pub fn position(&self) -> PhysicalPosition<i32> {
let rect = self.monitor.geometry();
PhysicalPosition {
x: rect.x,
y: rect.y,
LogicalPosition {
x: rect.x(),
y: rect.y(),
}
.to_physical(self.scale_factor())
}
#[inline]
@@ -51,7 +53,7 @@ impl MonitorHandle {
#[inline]
pub fn video_modes(&self) -> Box<dyn Iterator<Item = RootVideoMode>> {
todo!()
Box::new(Vec::new().into_iter())
}
}
@@ -64,21 +66,21 @@ pub struct VideoMode;
impl VideoMode {
#[inline]
pub fn size(&self) -> PhysicalSize<u32> {
todo!()
panic!("VideoMode is unsupported on Linux.")
}
#[inline]
pub fn bit_depth(&self) -> u16 {
todo!()
panic!("VideoMode is unsupported on Linux.")
}
#[inline]
pub fn refresh_rate(&self) -> u16 {
todo!()
panic!("VideoMode is unsupported on Linux.")
}
#[inline]
pub fn monitor(&self) -> RootMonitorHandle {
todo!()
panic!("VideoMode is unsupported on Linux.")
}
}
+50 -33
View File
@@ -10,10 +10,11 @@ use std::{
use gdk::{WindowEdge, WindowState};
use gdk_pixbuf::{Colorspace, Pixbuf};
use gtk::{prelude::*, AccelGroup, ApplicationWindow, Orientation};
use gtk::{prelude::*, AccelGroup, Orientation};
use raw_window_handle::{RawWindowHandle, XlibHandle};
use crate::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
icon::{BadIcon, Icon},
menu::{MenuId, MenuItem},
@@ -143,27 +144,28 @@ impl Window {
.max_inner_size
.map(|size| size.to_logical::<f64>(win_scale_factor as f64).into())
.unwrap_or_default();
window.set_geometry_hints::<ApplicationWindow>(
None,
Some(&gdk::Geometry {
let picky_none: Option<&gtk::Window> = None;
window.set_geometry_hints(
picky_none,
Some(&gdk::Geometry::new(
min_width,
min_height,
max_width,
max_height,
base_width: 0,
base_height: 0,
width_inc: 0,
height_inc: 0,
min_aspect: 0f64,
max_aspect: 0f64,
win_gravity: gdk::Gravity::Center,
}),
0,
0,
0,
0,
0f64,
0f64,
gdk::Gravity::Center,
)),
geom_mask,
);
// Set Position
if let Some(position) = attributes.position {
let (x, y): (i32, i32) = position.to_physical::<i32>(win_scale_factor as f64).into();
let (x, y): (i32, i32) = position.to_logical::<i32>(win_scale_factor as f64).into();
window.move_(x, y);
}
@@ -198,9 +200,10 @@ impl Window {
// Rest attributes
window.set_title(&attributes.title);
// TODO set it with Fullscreen enum
if attributes.fullscreen.is_some() {
window.fullscreen();
if let Some(Fullscreen::Borderless(Some(f))) = &attributes.fullscreen {
let number = f.inner.number;
let screen = window.display().default_screen();
window.fullscreen_on_monitor(&screen, number);
}
if attributes.maximized {
window.maximize();
@@ -245,7 +248,7 @@ impl Window {
let minimized = Rc::new(AtomicBool::new(false));
let min_clone = minimized.clone();
window.connect_window_state_event(move |_window, event| {
window.connect_window_state_event(move |_, event| {
let state = event.new_window_state();
max_clone.store(state.contains(WindowState::MAXIMIZED), Ordering::Release);
min_clone.store(state.contains(WindowState::ICONIFIED), Ordering::Release);
@@ -262,7 +265,9 @@ impl Window {
log::warn!("Fail to send wire up events request: {}", e);
}
window.queue_draw();
if let Err(e) = window_requests_tx.send((window_id, WindowRequest::Redraw)) {
log::warn!("Fail to send redraw request: {}", e);
}
let win = Self {
window_id,
@@ -302,24 +307,24 @@ impl Window {
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
let (x, y) = &*self.position;
Ok(PhysicalPosition::new(
x.load(Ordering::Acquire),
y.load(Ordering::Acquire),
))
Ok(
LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire))
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64),
)
}
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
let (x, y) = &*self.position;
Ok(PhysicalPosition::new(
x.load(Ordering::Acquire),
y.load(Ordering::Acquire),
))
Ok(
LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire))
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64),
)
}
pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
let (x, y): (i32, i32) = position
.into()
.to_physical::<i32>(self.scale_factor())
.to_logical::<i32>(self.scale_factor())
.into();
if let Err(e) = self
@@ -333,10 +338,11 @@ impl Window {
pub fn inner_size(&self) -> PhysicalSize<u32> {
let (width, height) = &*self.size;
PhysicalSize::new(
LogicalSize::new(
width.load(Ordering::Acquire) as u32,
height.load(Ordering::Acquire) as u32,
)
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64)
}
pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
@@ -353,10 +359,11 @@ impl Window {
pub fn outer_size(&self) -> PhysicalSize<u32> {
let (width, height) = &*self.size;
PhysicalSize::new(
LogicalSize::new(
width.load(Ordering::Acquire) as u32,
height.load(Ordering::Acquire) as u32,
)
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64)
}
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
@@ -518,7 +525,7 @@ impl Window {
}
pub fn set_ime_position<P: Into<Position>>(&self, _position: P) {
todo!()
//TODO
}
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
@@ -604,8 +611,18 @@ impl Window {
Some(RootMonitorHandle { inner: handle })
}
pub fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
todo!()
pub fn raw_window_handle(&self) -> RawWindowHandle {
// TODO: add wayland support
let mut handle = XlibHandle::empty();
unsafe {
if let Some(window) = self.window.window() {
handle.window = gdk_x11_sys::gdk_x11_window_get_xid(window.as_ptr() as *mut _);
}
if let Ok(xlib) = x11_dl::xlib::Xlib::open() {
handle.display = (xlib.XOpenDisplay)(std::ptr::null()) as _;
}
}
RawWindowHandle::Xlib(handle)
}
pub(crate) fn set_skip_taskbar(&self, skip: bool) {
+33 -26
View File
@@ -20,9 +20,7 @@ use cocoa::{
base::{id, nil},
foundation::{NSAutoreleasePool, NSSize},
};
use objc::runtime::YES;
use objc::runtime::Object;
use objc::runtime::{Object, BOOL, NO, YES};
use crate::{
dpi::LogicalSize,
@@ -64,7 +62,6 @@ pub trait EventHandler: Debug {
struct EventLoopHandler<T: 'static> {
callback: Weak<RefCell<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>>,
will_exit: bool,
window_target: Rc<RootWindowTarget<T>>,
}
@@ -100,25 +97,25 @@ impl<T> Debug for EventLoopHandler<T> {
impl<T> EventHandler for EventLoopHandler<T> {
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) {
self.with_callback(|this, mut callback| {
(callback)(event.userify(), &this.window_target, control_flow);
this.will_exit |= *control_flow == ControlFlow::Exit;
if this.will_exit {
*control_flow = ControlFlow::Exit;
if let ControlFlow::ExitWithCode(code) = *control_flow {
let dummy = &mut ControlFlow::ExitWithCode(code);
(callback)(event.userify(), &this.window_target, dummy);
} else {
(callback)(event.userify(), &this.window_target, control_flow);
}
});
}
fn handle_user_events(&mut self, control_flow: &mut ControlFlow) {
self.with_callback(|this, mut callback| {
let mut will_exit = this.will_exit;
for event in this.window_target.p.receiver.try_iter() {
(callback)(Event::UserEvent(event), &this.window_target, control_flow);
will_exit |= *control_flow == ControlFlow::Exit;
if will_exit {
*control_flow = ControlFlow::Exit;
if let ControlFlow::ExitWithCode(code) = *control_flow {
let dummy = &mut ControlFlow::ExitWithCode(code);
(callback)(Event::UserEvent(event), &this.window_target, dummy);
} else {
(callback)(Event::UserEvent(event), &this.window_target, control_flow);
}
}
this.will_exit = will_exit;
});
}
}
@@ -162,7 +159,10 @@ impl Handler {
}
fn should_exit(&self) -> bool {
*self.control_flow.lock().unwrap() == ControlFlow::Exit
matches!(
*self.control_flow.lock().unwrap(),
ControlFlow::ExitWithCode(_)
)
}
fn get_control_flow_and_update_prev(&self) -> ControlFlow {
@@ -267,16 +267,20 @@ impl AppState {
) {
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
callback,
will_exit: false,
window_target,
}));
}
pub fn exit() {
pub fn exit() -> i32 {
HANDLER.set_in_callback(true);
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::LoopDestroyed));
HANDLER.set_in_callback(false);
HANDLER.callback.lock().unwrap().take();
if let ControlFlow::ExitWithCode(code) = HANDLER.get_old_and_new_control_flow().1 {
code
} else {
0
}
}
pub fn launched(app_delegate: &Object) {
@@ -323,7 +327,7 @@ impl AppState {
}
}
}
ControlFlow::Exit => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
ControlFlow::ExitWithCode(_) => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
};
HANDLER.set_in_callback(true);
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(cause)));
@@ -347,14 +351,16 @@ impl AppState {
}
pub fn queue_event(wrapper: EventWrapper) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
let is_main_thread: BOOL = unsafe { msg_send!(class!(NSThread), isMainThread) };
if is_main_thread == NO {
panic!("Event queued from different thread: {:#?}", wrapper);
}
HANDLER.events().push_back(wrapper);
}
pub fn queue_events(mut wrappers: VecDeque<EventWrapper>) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
let is_main_thread: BOOL = unsafe { msg_send!(class!(NSThread), isMainThread) };
if is_main_thread == NO {
panic!("Events queued from different thread: {:#?}", wrappers);
}
HANDLER.events().append(&mut wrappers);
@@ -388,8 +394,9 @@ impl AppState {
let dialog_open = if window_count > 1 {
let dialog: id = msg_send![windows, lastObject];
let is_main_window: bool = msg_send![dialog, isMainWindow];
msg_send![dialog, isVisible] && !is_main_window
let is_main_window: BOOL = msg_send![dialog, isMainWindow];
let is_visible: BOOL = msg_send![dialog, isVisible];
is_visible != NO && is_main_window == NO
} else {
false
};
@@ -404,9 +411,9 @@ impl AppState {
pool.drain();
if window_count > 0 {
let window: id = msg_send![windows, objectAtIndex:0];
let window_has_focus = msg_send![window, isKeyWindow];
if !dialog_open && window_has_focus && dialog_is_closing {
let window: id = msg_send![windows, firstObject];
let window_has_focus: BOOL = msg_send![window, isKeyWindow];
if !dialog_open && window_has_focus != NO && dialog_is_closing {
HANDLER.dialog_is_closing.store(false, Ordering::SeqCst);
}
if dialog_open {
@@ -417,7 +424,7 @@ impl AppState {
}
HANDLER.update_start_time();
match HANDLER.get_old_and_new_control_flow() {
(ControlFlow::Exit, _) | (_, ControlFlow::Exit) => (),
(ControlFlow::ExitWithCode(_), _) | (_, ControlFlow::ExitWithCode(_)) => (),
(old, new) if old == new => (),
(_, ControlFlow::Wait) => HANDLER.waker().stop(),
(_, ControlFlow::WaitUntil(instant)) => HANDLER.waker().start_at(instant),
+1
View File
@@ -20,6 +20,7 @@ impl Clipboard {
let _: NSInteger = msg_send![pasteboard, clearContents];
let result: BOOL = msg_send![pasteboard, setString: nsstring forType: NSPasteboardTypeString];
if result != YES {
#[cfg(debug_assertions)]
println!("failed to set clipboard");
}
}
+1 -1
View File
@@ -163,7 +163,7 @@ pub fn create_key_event(
logical_key = key_from_code.clone();
key_without_modifiers = key_from_code;
} else {
//println!("Couldn't get key from code: {:?}", physical_key);
//#[cfg(debug_assertions)] println!("Couldn't get key from code: {:?}", physical_key);
key_without_modifiers = get_modifierless_char(scancode);
let modifiers = unsafe { NSEvent::modifierFlags(ns_event) };
+20 -16
View File
@@ -14,9 +14,9 @@ use std::{
};
use cocoa::{
appkit::{NSApp, NSEventType::NSApplicationDefined},
base::{id, nil, YES},
foundation::{NSAutoreleasePool, NSPoint},
appkit::{NSApp, NSEventModifierFlags, NSEventSubtype, NSEventType::NSApplicationDefined},
base::{id, nil, BOOL, NO, YES},
foundation::{NSAutoreleasePool, NSInteger, NSPoint, NSTimeInterval},
};
use crossbeam_channel::{self as channel, Receiver, Sender};
use scopeguard::defer;
@@ -63,6 +63,7 @@ impl PanicInfo {
}
}
#[derive(Clone)]
pub struct EventLoopWindowTarget<T: 'static> {
pub sender: Sender<T>, // this is only here to be cloned elsewhere
pub receiver: Receiver<T>,
@@ -106,7 +107,8 @@ pub struct EventLoop<T: 'static> {
impl<T> EventLoop<T> {
pub fn new() -> Self {
let delegate = unsafe {
if !msg_send![class!(NSThread), isMainThread] {
let is_main_thread: BOOL = msg_send!(class!(NSThread), isMainThread);
if is_main_thread == NO {
panic!("On macOS, `EventLoop` must be created on the main thread!");
}
@@ -143,11 +145,11 @@ impl<T> EventLoop<T> {
where
F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
{
self.run_return(callback);
process::exit(0);
let exit_code = self.run_return(callback);
process::exit(exit_code);
}
pub fn run_return<F>(&mut self, callback: F)
pub fn run_return<F>(&mut self, callback: F) -> i32
where
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
{
@@ -164,7 +166,7 @@ impl<T> EventLoop<T> {
self._callback = Some(Rc::clone(&callback));
unsafe {
let exit_code = unsafe {
let pool = NSAutoreleasePool::new(nil);
defer!(pool.drain());
let app = NSApp();
@@ -182,9 +184,11 @@ impl<T> EventLoop<T> {
drop(self._callback.take());
resume_unwind(panic);
}
AppState::exit();
}
AppState::exit()
};
drop(self._callback.take());
exit_code
}
pub fn create_proxy(&self) -> Proxy<T> {
@@ -199,13 +203,13 @@ pub unsafe fn post_dummy_event(target: id) {
event_class,
otherEventWithType: NSApplicationDefined
location: NSPoint::new(0.0, 0.0)
modifierFlags: 0
timestamp: 0
windowNumber: 0
modifierFlags: NSEventModifierFlags::empty()
timestamp: 0 as NSTimeInterval
windowNumber: 0 as NSInteger
context: nil
subtype: 0
data1: 0
data2: 0
subtype: NSEventSubtype::NSWindowExposedEventType
data1: 0 as NSInteger
data2: 0 as NSInteger
];
let () = msg_send![target, postEvent: dummy_event atStart: YES];
}
+11 -1
View File
@@ -112,6 +112,7 @@ pub const kCGCursorWindowLevelKey: NSInteger = 19;
pub const kCGNumberOfWindowLevelKeys: NSInteger = 20;
#[derive(Debug, Clone, Copy)]
#[repr(isize)]
pub enum NSWindowLevel {
NSNormalWindowLevel = kCGBaseWindowLevelKey as _,
NSFloatingWindowLevel = kCGFloatingWindowLevelKey as _,
@@ -168,9 +169,18 @@ pub const IO8BitOverlayPixels: &str = "O8";
pub type CGWindowLevel = i32;
pub type CGDisplayModeRef = *mut libc::c_void;
// `CGDisplayCreateUUIDFromDisplayID` comes from the `ColorSync` framework.
// However, that framework was only introduced "publicly" in macOS 10.13.
//
// Since we want to support older versions, we can't link to `ColorSync`
// directly. Fortunately, it has always been available as a subframework of
// `ApplicationServices`, see:
// https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html#//apple_ref/doc/uid/TP40001067-CH210-BBCFFIEG
//
// TODO: Remove the WINIT_LINK_COLORSYNC hack, it is probably not needed.
#[cfg_attr(
not(use_colorsync_cgdisplaycreateuuidfromdisplayid),
link(name = "CoreGraphics", kind = "framework")
link(name = "ApplicationServices", kind = "framework")
)]
#[cfg_attr(
use_colorsync_cgdisplaycreateuuidfromdisplayid,
@@ -63,6 +63,7 @@ impl ShortcutManager {
// we get only 1 keycode as we don't generate it for the modifier
// it's safe to use first()
if let Some(scan_code) = accelerator.key.to_scancode() {
#[cfg(debug_assertions)]
println!("register {:?}", accelerator);
// register hotkey
let handler_ref = register_hotkey(
+26 -3
View File
@@ -469,8 +469,6 @@ impl Accelerator {
/// Returns the empty string if no key equivalent is known.
fn key_equivalent(self) -> String {
match self.key {
KeyCode::Minus => "-".into(),
KeyCode::Equal => "=".into(),
KeyCode::KeyA => "a".into(),
KeyCode::KeyB => "b".into(),
KeyCode::KeyC => "c".into(),
@@ -507,8 +505,20 @@ impl Accelerator {
KeyCode::Digit7 => "7".into(),
KeyCode::Digit8 => "8".into(),
KeyCode::Digit9 => "9".into(),
KeyCode::Escape => "\u{1b}".into(),
KeyCode::Comma => ",".into(),
KeyCode::Minus => "-".into(),
KeyCode::Period => ".".into(),
KeyCode::Space => "\u{0020}".into(),
KeyCode::Equal => "=".into(),
KeyCode::Semicolon => ";".into(),
KeyCode::Slash => "/".into(),
KeyCode::Backslash => "\\".into(),
KeyCode::Quote => "\'".into(),
KeyCode::Backquote => "`".into(),
KeyCode::BracketLeft => "[".into(),
KeyCode::BracketRight => "]".into(),
KeyCode::Tab => "⇥".into(),
KeyCode::Escape => "\u{001b}".into(),
// from NSText.h
KeyCode::Enter => "\u{0003}".into(),
KeyCode::Backspace => "\u{0008}".into(),
@@ -537,7 +547,20 @@ impl Accelerator {
KeyCode::F10 => "\u{F70D}".into(),
KeyCode::F11 => "\u{F70E}".into(),
KeyCode::F12 => "\u{F70F}".into(),
KeyCode::F13 => "\u{F710}".into(),
KeyCode::F14 => "\u{F711}".into(),
KeyCode::F15 => "\u{F712}".into(),
KeyCode::F16 => "\u{F713}".into(),
KeyCode::F17 => "\u{F714}".into(),
KeyCode::F18 => "\u{F715}".into(),
KeyCode::F19 => "\u{F716}".into(),
KeyCode::F20 => "\u{F717}".into(),
KeyCode::F21 => "\u{F718}".into(),
KeyCode::F22 => "\u{F719}".into(),
KeyCode::F23 => "\u{F71A}".into(),
KeyCode::F24 => "\u{F71B}".into(),
_ => {
#[cfg(debug_assertions)]
eprintln!("no key equivalent for {:?}", self);
"".into()
}
+1
View File
@@ -165,6 +165,7 @@ impl fmt::Debug for MonitorHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// TODO: Do this using the proper fmt API
#[derive(Debug)]
#[allow(dead_code)] // none of the member reads in Debug::fmt are detected
struct MonitorHandle {
name: Option<String>,
native_identifier: u32,
+4 -1
View File
@@ -142,7 +142,10 @@ where
// However we want to keep that weak reference around after the function.
std::mem::forget(info_from_raw);
stop_app_on_panic(Weak::clone(&panic_info), move || f(panic_info.0));
stop_app_on_panic(Weak::clone(&panic_info), move || {
let _ = &panic_info;
f(panic_info.0)
});
}
// begin is queued with the highest priority to ensure it is processed before other observers
Loaded 100 of 130 files, more files were not shown because too many files have changed in this diff. Show more