diff --git a/Cargo.lock b/Cargo.lock index 52134ebbd..97e16667c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1105,26 +1105,26 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 2.0.6", ] [[package]] name = "cargo_toml" -version = "0.17.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" dependencies = [ "serde", - "toml 0.8.2", + "toml 0.8.19", ] [[package]] @@ -2231,7 +2231,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 0.8.2", + "toml 0.8.19", "vswhom", "winreg", ] @@ -3499,15 +3499,6 @@ dependencies = [ "cfb", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "interpolate_name" version = "0.2.4" @@ -6854,15 +6845,15 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.2", + "toml 0.8.19", "version-compare", ] [[package]] name = "tao" -version = "0.30.8" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" +checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9" dependencies = [ "bitflags 2.6.0", "cocoa 0.26.0", @@ -6875,7 +6866,6 @@ dependencies = [ "gdkwayland-sys", "gdkx11-sys", "gtk", - "instant", "jni", "lazy_static", "libc", @@ -6939,9 +6929,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.1.1" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e545de0a2dfe296fa67db208266cd397c5a55ae782da77973ef4c4fac90e9f2c" +checksum = "78f6efc261c7905839b4914889a5b25df07f0ff89c63fb4afd6ff8c96af15e4d" dependencies = [ "anyhow", "bytes", @@ -6992,9 +6982,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.3" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd2a4bcfaf5fb9f4be72520eefcb61ae565038f8ccba2a497d8c28f463b8c01" +checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df" dependencies = [ "anyhow", "cargo_toml", @@ -7008,15 +6998,15 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.8.2", + "toml 0.8.19", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf79faeecf301d3e969b1fae977039edb77a4c1f25cc0a961be298b54bff97cf" +checksum = "f77894f9ddb5cb6c04fcfe8c8869ebe0aded4dabf19917118d48be4a95599ab5" dependencies = [ "base64 0.22.1", "brotli", @@ -7041,9 +7031,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52027c8c5afb83166dacddc092ee8fff50772f9646d461d8c33ee887e447a03" +checksum = "3240a5caed760a532e8f687be6f05b2c7d11a1d791fb53ccc08cfeb3e5308736" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -7082,7 +7072,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "toml 0.8.2", + "toml 0.8.19", "walkdir", ] @@ -7108,9 +7098,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.0.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4307310e1d2c09ab110235834722e7c2b85099b683e1eb7342ab351b0be5ada3" +checksum = "8b59fd750551b1066744ab956a1cd6b1ea3e1b3763b0b9153ac27a044d596426" dependencies = [ "log", "raw-window-handle", @@ -7120,7 +7110,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 1.0.63", + "thiserror 2.0.6", "url", ] @@ -7142,7 +7132,7 @@ dependencies = [ "tauri-plugin", "tauri-utils", "thiserror 2.0.6", - "toml 0.8.2", + "toml 0.8.19", "url", "uuid", ] @@ -7252,9 +7242,9 @@ dependencies = [ [[package]] name = "tauri-plugin-process" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae06a00087c148962a52814a2d7265b1a0505bced5ffb74f8c284a5f96a4d03d" +checksum = "40cc553ab29581c8c43dfa5fb0c9d5aee8ba962ad3b42908eea26c79610441b7" dependencies = [ "tauri", "tauri-plugin", @@ -7290,7 +7280,6 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-plugin-deep-link", "thiserror 2.0.6", "tracing", "windows-sys 0.59.0", @@ -7315,9 +7304,9 @@ dependencies = [ [[package]] name = "tauri-plugin-updater" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7351014c140906bcfff59d96e04b1170c8f602557f40eb37f7de356d4e7067b" +checksum = "ce2d39224390c41ba544f02b4f1721f42256320b3fb8c371e9425cbddeb4a68c" dependencies = [ "base64 0.22.1", "dirs", @@ -7360,9 +7349,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce18d43f80d4aba3aa8a0c953bbe835f3d0f2370aca75e8dbb14bd4bab27958" +checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7" dependencies = [ "dpi", "gtk", @@ -7379,9 +7368,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f442a38863e10129ffe2cec7bd09c2dcf8a098a3a27801a476a304d5bb991d2" +checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0" dependencies = [ "gtk", "http", @@ -7433,9 +7422,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54" +checksum = "96fb10e7cc97456b2d5b9c03e335b5de5da982039a303a20d10006885e4523a0" dependencies = [ "brotli", "cargo_metadata", @@ -7461,7 +7450,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.6", - "toml 0.8.2", + "toml 0.8.19", "url", "urlpattern", "uuid", @@ -7742,14 +7731,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.22", ] [[package]] @@ -7781,8 +7770,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap 2.5.0", - "serde", - "serde_spanned", "toml_datetime", "winnow 0.5.40", ] @@ -7794,6 +7781,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap 2.5.0", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.6.20", ] @@ -8457,9 +8446,9 @@ dependencies = [ [[package]] name = "webview2-com" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" +checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921" dependencies = [ "webview2-com-macros", "webview2-com-sys", @@ -8482,9 +8471,9 @@ dependencies = [ [[package]] name = "webview2-com-sys" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" +checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4" dependencies = [ "thiserror 1.0.63", "windows 0.58.0", @@ -9147,9 +9136,9 @@ dependencies = [ [[package]] name = "wry" -version = "0.47.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ce51277d65170f6379d8cda935c80e3c2d1f0ff712a123c8bddb11b31a4b73" +checksum = "1e644bf458e27b11b0ecafc9e5633d1304fdae82baca1d42185669752fe6ca4f" dependencies = [ "base64 0.22.1", "block2", @@ -9177,7 +9166,7 @@ dependencies = [ "sha2", "soup3", "tao-macros", - "thiserror 1.0.63", + "thiserror 2.0.6", "url", "webkit2gtk", "webkit2gtk-sys", diff --git a/Cargo.toml b/Cargo.toml index f17c601c6..6237f8a34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,9 @@ tokio = { version = "1.39.3", features = [ "rt-multi-thread", "time", ] } -tauri = { version = "2.1.1" } -specta = { version = "=2.0.0-rc.20" } +tauri = { version = "2.2.3", features = [ "specta" ] } +specta = { version = "=2.0.0-rc.20", features = [ "derive" ] } + scap = { git = "https://github.com/CapSoftware/scap", rev = "58d4410bf52f" } nokhwa = { git = "https://github.com/CapSoftware/nokhwa", rev = "d37141b1883d", features = [ "input-native", diff --git a/apps/desktop/scripts/prepare.js b/apps/desktop/scripts/prepare.js index 708291fa2..ac45f925d 100644 --- a/apps/desktop/scripts/prepare.js +++ b/apps/desktop/scripts/prepare.js @@ -156,8 +156,7 @@ async function main() { } main().catch((err) => { - console.error("--- Preparation Failed"); + console.error("\n--- Preparation Failed"); console.error(err); console.error("---"); - process.exit(1); }); diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 67de2c39d..222394100 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -25,18 +25,17 @@ tauri = { workspace = true, features = [ "image-png", ] } tauri-specta = { version = "=2.0.0-rc.20", features = ["derive", "typescript"] } -tauri-plugin-dialog = "2.0.0" +tauri-plugin-dialog = "2.2.0" tauri-plugin-fs = "2.2.0" -tauri-plugin-global-shortcut = "2.1.0" -tauri-plugin-http = "2.1.0" -tauri-plugin-notification = "2.1.0" -tauri-plugin-os = "2.1.0" -tauri-plugin-process = "2.0.1" -tauri-plugin-shell = "2.1.0" -[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies] -tauri-plugin-single-instance = { version = "2.2.1", features = ["deep-link"] } +tauri-plugin-global-shortcut = "2.2.0" +tauri-plugin-http = "2.2.0" +tauri-plugin-notification = "2.2.0" +tauri-plugin-os = "2.2.0" +tauri-plugin-process = "2.2.0" +tauri-plugin-shell = "2.2.0" +tauri-plugin-single-instance = "2.2.0" tauri-plugin-store = "2.2.0" -tauri-plugin-updater = "2.2.0" +tauri-plugin-updater = "2.3.1" tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "v2" } tauri-plugin-window-state = "2.2.0" tauri-plugin-positioner = "2.2.0" diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 6d2ece278..c6975daa7 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -2022,8 +2022,22 @@ pub async fn run() { #[cfg(target_os = "macos")] { - builder = builder.plugin(tauri_nspanel::init()).plugin( - // TODO(Ilya): Also enable for Windows when Tao is updated to `0.31.0` + builder = builder.plugin(tauri_nspanel::init()); + } + + builder + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_store::Builder::new().build()) + .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_process::init()) + .plugin(tauri_plugin_oauth::init()) + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_updater::Builder::new().build()) + .plugin(tauri_plugin_notification::init()) + .plugin(flags::plugin::init()) + .plugin(tauri_plugin_deep_link::init()) + .plugin( tauri_plugin_window_state::Builder::new() .with_state_flags({ use tauri_plugin_window_state::StateFlags; @@ -2043,21 +2057,7 @@ pub async fn run() { _ => label, }) .build(), - ); - } - - builder - .plugin(tauri_plugin_deep_link::init()) - .plugin(tauri_plugin_shell::init()) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_store::Builder::new().build()) - .plugin(tauri_plugin_os::init()) - .plugin(tauri_plugin_process::init()) - .plugin(tauri_plugin_oauth::init()) - .plugin(tauri_plugin_http::init()) - .plugin(tauri_plugin_updater::Builder::new().build()) - .plugin(tauri_plugin_notification::init()) - .plugin(flags::plugin::init()) + ) .invoke_handler({ let handler = specta_builder.invoke_handler(); diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 9ccebba92..45d4a618c 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -13,10 +13,6 @@ use tauri::{ #[cfg(target_os = "macos")] const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(12.0, 12.0); -#[cfg(target_os = "windows")] -const WIN_WSCAPTION_WSTHICKFRAME_LOGICAL_SIZE: tauri::LogicalSize = - tauri::LogicalSize::new(12.0, 35.0); - #[derive(Clone)] pub enum CapWindowId { // Contains onboarding + permissions @@ -270,12 +266,7 @@ impl ShowCapWindow { if FLAGS.pause_resume { width += 32.0; } - let mut height = 40.0; - #[cfg(target_os = "windows")] - { - width -= WIN_WSCAPTION_WSTHICKFRAME_LOGICAL_SIZE.width; - height -= WIN_WSCAPTION_WSTHICKFRAME_LOGICAL_SIZE.height; - } + let height = 40.0; self.window_builder(app, "/in-progress-recording") .maximized(false) @@ -351,44 +342,6 @@ impl ShowCapWindow { window.hide().ok(); - // TODO(Ilya): Remove once Tao is updated to `0.31.0` - #[cfg(target_os = "windows")] - { - use tauri_plugin_positioner::{Position, WindowExt}; - - if matches!( - self, - Self::Setup - | Self::Main - | Self::Editor { .. } - | Self::Settings { .. } - | Self::Upgrade - ) { - let _ = window.move_window(Position::Center); - } - - if matches!(self, Self::InProgressRecording { .. }) { - let _ = window.move_window(Position::BottomCenter); - - if let Ok(outer_size) = window.outer_size() { - let screen_position = monitor.position(); - let window_size = tauri::PhysicalSize:: { - width: outer_size.width as i32, - height: outer_size.height as i32, - }; - let screen_size = tauri::PhysicalSize:: { - width: monitor.size().width as i32, - height: monitor.size().height as i32, - }; - - let _ = window.set_position(tauri::PhysicalPosition { - x: screen_position.x + ((screen_size.width / 2) - (window_size.width / 2)), - y: screen_size.height - (window_size.height - screen_position.y) - 120, - }); - } - } - } - #[cfg(target_os = "macos")] if let Some(position) = id.traffic_lights_position() { add_traffic_lights(&window, position); @@ -411,32 +364,9 @@ impl ShowCapWindow { .shadow(true); if let Some(min) = id.min_size() { - // TODO(Ilya): Remove once Tao is updated to `0.31.0` - // currently, undecorated windows with shadows get the invisible bounds of the titlebar and window frame added to the inner size - #[cfg(target_os = "windows")] - let size = if matches!( - self, - Self::Setup - | Self::Main - | Self::Editor { .. } - | Self::Settings { .. } - | Self::InProgressRecording { .. } - | Self::Upgrade - ) { - ( - min.0 - WIN_WSCAPTION_WSTHICKFRAME_LOGICAL_SIZE.width, - min.1 - WIN_WSCAPTION_WSTHICKFRAME_LOGICAL_SIZE.height, - ) - } else { - min - }; - - #[cfg(not(target_os = "windows"))] - let size = min; - builder = builder - .inner_size(size.0, size.1) - .min_inner_size(size.0, size.1); + .inner_size(min.0, min.1) + .min_inner_size(min.0, min.1); } #[cfg(target_os = "macos")] diff --git a/crates/media/src/platform/macos.rs b/crates/media/src/platform/macos.rs index 36d3ac43d..544aacbbf 100644 --- a/crates/media/src/platform/macos.rs +++ b/crates/media/src/platform/macos.rs @@ -329,3 +329,44 @@ pub fn monitor_bounds(id: u32) -> Bounds { } } } + +pub fn get_display_refresh_rate( + display_id: core_graphics::display::CGDirectDisplayID, +) -> Option { + use core_graphics::display::CGDisplay; + + Some( + CGDisplay::new(display_id) + .display_mode()? + .refresh_rate() + .round() as u32, + ) +} + +pub fn display_for_window( + window: core_graphics::window::CGWindowID, +) -> Option { + use core_foundation::array::CFArray; + use core_graphics::{ + display::{CFDictionary, CGDisplay, CGRect}, + window::{create_description_from_array, kCGWindowBounds}, + }; + + let descriptions = create_description_from_array(CFArray::from_copyable(&[window]))?; + + let window_bounds = CGRect::from_dict_representation( + &descriptions + .get(0)? + .get(unsafe { kCGWindowBounds }) + .downcast::()?, + )?; + + for id in CGDisplay::active_displays().ok()? { + let display = CGDisplay::new(id); + if window_bounds.is_intersects(&display.bounds()) { + return Some(display); + } + } + + None +} diff --git a/crates/media/src/platform/win.rs b/crates/media/src/platform/win.rs index bc98a4575..5331c95f1 100644 --- a/crates/media/src/platform/win.rs +++ b/crates/media/src/platform/win.rs @@ -11,8 +11,9 @@ use windows::Win32::Graphics::Dwm::{ DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS, }; use windows::Win32::Graphics::Gdi::{ - EnumDisplayDevicesW, EnumDisplayMonitors, GetMonitorInfoW, DISPLAY_DEVICEW, HDC, HMONITOR, - MONITORINFOEXW, + EnumDisplayDevicesW, EnumDisplayMonitors, EnumDisplaySettingsW, GetMonitorInfoW, + MonitorFromWindow, DEVMODEW, DISPLAY_DEVICEW, HDC, HMONITOR, MONITORINFO, MONITORINFOEXW, + MONITOR_DEFAULTTONULL, }; use windows::Win32::System::Threading::{ OpenProcess, QueryFullProcessImageNameW, PROCESS_NAME_FORMAT, PROCESS_QUERY_LIMITED_INFORMATION, @@ -304,3 +305,43 @@ pub fn display_names() -> HashMap { names } + +pub fn get_display_refresh_rate(monitor: HMONITOR) -> Option { + let mut monitorinfoexw: MONITORINFOEXW = unsafe { std::mem::zeroed() }; + monitorinfoexw.monitorInfo.cbSize = std::mem::size_of::() as u32; + + if let Err(_) = + unsafe { GetMonitorInfoW(monitor, &mut monitorinfoexw.monitorInfo as *mut MONITORINFO) } + .ok() + { + return None; + } + + let mut dev_mode: DEVMODEW = unsafe { std::mem::zeroed() }; + dev_mode.dmSize = std::mem::size_of::() as u16; + + let device_name = PCWSTR::from_raw(monitorinfoexw.szDevice.as_ptr()); + + if let Err(_) = unsafe { + EnumDisplaySettingsW( + device_name, + windows::Win32::Graphics::Gdi::ENUM_CURRENT_SETTINGS, + &mut dev_mode, + ) + } + .ok() + { + return None; + } + + Some(dev_mode.dmDisplayFrequency) +} + +pub fn display_for_window(window: HWND) -> Option { + let hwmonitor = unsafe { MonitorFromWindow(window, MONITOR_DEFAULTTONULL) }; + if hwmonitor.is_invalid() { + None + } else { + Some(hwmonitor) + } +} diff --git a/crates/media/src/sources/screen_capture.rs b/crates/media/src/sources/screen_capture.rs index bba862350..0ef7f34db 100644 --- a/crates/media/src/sources/screen_capture.rs +++ b/crates/media/src/sources/screen_capture.rs @@ -175,27 +175,34 @@ impl ScreenCaptureSource { let target = match &self.target { ScreenCaptureTarget::Window(w) => { + let window_target = targets + .iter() + .find_map(|t| match t { + Target::Window(window) if window.id == w.id => Some(window), + _ => None, + }) + .unwrap(); + #[cfg(target_os = "macos")] { - let window_target = targets - .iter() - .find_map(|t| match t { - Target::Window(window) if window.id == w.id => Some(window), - _ => None, - }) - .unwrap(); - - display_for_window(window_target.raw_handle).and_then(|display| { + platform::display_for_window(window_target.raw_handle).and_then(|display| { targets.into_iter().find(|t| match t { Target::Display(d) => d.raw_handle.id == display.id, _ => false, }) }) } - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "windows")] { - todo!("implement display_for_window on windows") + platform::display_for_window(window_target.raw_handle).and_then(|display| { + targets.into_iter().find(|t| match t { + Target::Display(d) => d.raw_handle == display, + _ => false, + }) + }) } + #[cfg(not(any(target_os = "windows", target_os = "macos")))] + None } ScreenCaptureTarget::Screen(capture_screen) => targets .iter() @@ -503,57 +510,19 @@ pub fn list_windows() -> Vec<(CaptureWindow, Target)> { pub fn get_target_fps(target: &scap::Target) -> Option { #[cfg(target_os = "macos")] - { - match target { - scap::Target::Display(display) => refresh_rate_for_display(display.raw_handle.id), - scap::Target::Window(window) => { - refresh_rate_for_display(display_for_window(window.raw_handle)?.id) - } + match target { + scap::Target::Display(display) => platform::get_display_refresh_rate(display.raw_handle.id), + scap::Target::Window(window) => { + platform::get_display_refresh_rate(platform::display_for_window(window.raw_handle)?.id) } } - #[cfg(not(target_os = "macos"))] - { - todo!() - } -} - -#[cfg(target_os = "macos")] -fn display_for_window( - window: core_graphics::window::CGWindowID, -) -> Option { - use core_foundation::array::CFArray; - use core_graphics::{ - display::{CFDictionary, CGDisplay, CGRect}, - window::{create_description_from_array, kCGWindowBounds}, - }; - - let descriptions = create_description_from_array(CFArray::from_copyable(&[window]))?; - - let window_bounds = CGRect::from_dict_representation( - &descriptions - .get(0)? - .get(unsafe { kCGWindowBounds }) - .downcast::()?, - )?; - - for id in CGDisplay::active_displays().ok()? { - let display = CGDisplay::new(id); - if window_bounds.is_intersects(&display.bounds()) { - return Some(display); + #[cfg(target_os = "windows")] + match target { + scap::Target::Display(display) => platform::get_display_refresh_rate(display.raw_handle), + scap::Target::Window(window) => { + platform::get_display_refresh_rate(platform::display_for_window(window.raw_handle)?) } } - + #[cfg(not(any(target_os = "windows", target_os = "macos")))] None } - -#[cfg(target_os = "macos")] -fn refresh_rate_for_display(display_id: core_graphics::display::CGDirectDisplayID) -> Option { - use core_graphics::display::CGDisplay; - - Some( - CGDisplay::new(display_id) - .display_mode()? - .refresh_rate() - .round() as u32, - ) -} diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index eb3bb52a7..46eb4ba32 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -specta = { workspace = true, features = ["derive"] } +specta.workspace = true + serde = { version = "1", features = ["derive"] } serde_json = "1.0.127" either = "1.13.0" diff --git a/crates/rendering/src/decoder.rs b/crates/rendering/src/decoder.rs index efc44b16d..4751c43d2 100644 --- a/crates/rendering/src/decoder.rs +++ b/crates/rendering/src/decoder.rs @@ -137,8 +137,14 @@ impl AsyncVideoDecoder { ) .ok() } + #[cfg(target_os = "windows")] + { + decoder + .try_use_hw_device(AVHWDeviceType::AV_HWDEVICE_TYPE_D3D11VA, Pixel::NV12) + .ok() + } - #[cfg(not(target_os = "macos"))] + #[cfg(not(any(target_os = "macos", target_os = "windows")))] None };