mirror of
https://github.com/aphrody-labs/tao.git
synced 2026-10-17 12:36:18 +00:00
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 commita3a2e0cfc4. * 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 commit6f9c468f26. * 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
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": minor
|
||||
---
|
||||
|
||||
Update to gtk 0.15
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Emit errors when parsing an invalid accelerator from a string.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tao: minor
|
||||
---
|
||||
|
||||
Add support for more accelerator keys: `,` `-` `.` `=` `;` `/` `\` `'` `` ` `` `[` `]` `Space` `Tab` and `F13`-`F24`
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
Increased Borderless window resizing inset.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Update to 2021 edition and msrv to 1.56
|
||||
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fixes the `MenuItem::Quit` behavior on Windows.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Add support for `SPACE` shortcut key on Windows.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
* Fix redrawn event that causing infinite lopp on Linux
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix linux native menu items not working.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
* Fix resizing undecorated window on Linux.
|
||||
* Undecorated window can be resized using touch on Linux.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix focus events not firing on Linux
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
* Add `RedrawEventsCleared` and `RedrawRequested` on Linux
|
||||
@@ -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.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Update tray dependency version.
|
||||
|
||||
@@ -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.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix menubar missing on borderless window.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix core-video-sys dependency.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tao: minor
|
||||
---
|
||||
|
||||
Allow more strings to parse to keycode, for example `,` is now parsed as a comma.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
* Update `raw-window-handle` to `0.4`
|
||||
* Add `raw_window_handle()` implementation on linux.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Fix click events missing whe tray has menu.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tao: minor
|
||||
---
|
||||
|
||||
Add macOS `show_application()` method
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Add new_any_thread to Unix event loop.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Implement `Clone` for `EventLoopWindowTarget`.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tao": patch
|
||||
---
|
||||
|
||||
Update the `windows` crate to 0.29.0.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
@@ -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.
@@ -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);
|
||||
|
||||
@@ -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
@@ -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,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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -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,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,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();
|
||||
|
||||
@@ -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,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,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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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,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()
|
||||
|
||||
@@ -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,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,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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
@@ -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,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,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
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
@@ -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>,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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] };
|
||||
|
||||
@@ -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
@@ -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
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -49,6 +49,7 @@ pub enum EventProxy {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EventLoopWindowTarget<T: 'static> {
|
||||
receiver: Receiver<T>,
|
||||
sender_to_clone: Sender<T>,
|
||||
|
||||
@@ -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)*);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
@@ -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.")
|
||||
}
|
||||
}
|
||||
@@ -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<>k::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) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) };
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in new issue
Block a user