Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cap for Windows, Part 2 #163

Merged
merged 34 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f88eaea
Improved Titlebars
ItsEeleeya Nov 8, 2024
fb91191
Merge branch 'CapSoftware:main' into windows
ItsEeleeya Nov 9, 2024
945831a
remove unused file
ItsEeleeya Nov 9, 2024
aebc4d2
Update (window-chrome).tsx
ItsEeleeya Nov 10, 2024
faa188d
Merge remote-tracking branch 'upstream/main' into windows
ItsEeleeya Nov 10, 2024
93455d8
(WIP) update windows-rs
ItsEeleeya Nov 10, 2024
88a103d
(macOS) Fix traffic lights resetting and shadows not appearing
ItsEeleeya Nov 10, 2024
1acb8c7
Update windows-rs features
ItsEeleeya Nov 11, 2024
68d96f8
Merge branch 'windows' of https://github.com/ItsEeleeya/Cap into windows
ItsEeleeya Nov 11, 2024
a3c0330
Fix window_names and monitor_bounds for Windows
ItsEeleeya Nov 11, 2024
93540eb
Transparent scrollbar background for prev-recordings view
ItsEeleeya Nov 11, 2024
169acd7
Only (re)position traffic lights on main
ItsEeleeya Nov 11, 2024
d43a3d0
Merge branch 'main' into windows
Brendonovich Nov 12, 2024
186fe3c
use get_next_frame in AVFrameCapture
Brendonovich Nov 12, 2024
2e29697
show placeholder if only one target option
Brendonovich Nov 12, 2024
60e80af
create scap options inside run()
Brendonovich Nov 12, 2024
64649ad
attempt windows pipe implementation
Brendonovich Nov 12, 2024
57bf64e
Titlebar for setup view
ItsEeleeya Nov 12, 2024
57ba307
Merge branch 'windows' of https://github.com/ItsEeleeya/Cap into windows
ItsEeleeya Nov 12, 2024
2da6440
comment-out `get_cursor_image_data`
ItsEeleeya Nov 12, 2024
32fee16
Merge branch 'main' into pr/163
richiemcilroy Nov 12, 2024
cff4bd7
fix: take_screenshot function
richiemcilroy Nov 12, 2024
c7ac213
fix windows recording, encoding, display names, decorations
Brendonovich Nov 12, 2024
0ace2f4
only use windows deps on windows
Brendonovich Nov 12, 2024
59340ff
update selected target if not found
Brendonovich Nov 12, 2024
ac59d49
No debug login, Editor header draggable, Caption buttons transition
ItsEeleeya Nov 12, 2024
cbcb8df
Merge branch 'windows' of https://github.com/ItsEeleeya/Cap into windows
ItsEeleeya Nov 12, 2024
486be63
Use native decorations/shadow for InProgressRecording window
ItsEeleeya Nov 12, 2024
ab95d43
reduce titlebar height
Brendonovich Nov 13, 2024
37710ab
fix mjpeg cameras + mic capture
Brendonovich Nov 13, 2024
4cedf90
windows named pipes for exporting
Brendonovich Nov 13, 2024
9c5b4cd
fix unix
Brendonovich Nov 13, 2024
a88a147
format + typecheck
Brendonovich Nov 13, 2024
29ca228
format
Brendonovich Nov 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 66 additions & 63 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ tokio = { version = "1.39.3", features = [
] }
tauri = { version = "2.0.0" }
specta = { version = "=2.0.0-rc.20" }
scap = { git = "https://github.com/CapSoftware/scap", rev = "b1e140a3fe90" }
nokhwa = { git = "https://github.com/CapSoftware/nokhwa", rev = "c5c7e2298764", features = [
scap = { git = "https://github.com/CapSoftware/scap", rev = "b1e140a3fe905c19b845dfea66b3b1aea02f0472" }
nokhwa = { git = "https://github.com/CapSoftware/nokhwa", rev = "0d3d1f30a78b", features = [
"input-native",
"serialize",
] }
nokhwa-bindings-macos = { git = "https://github.com/CapSoftware/nokhwa", rev = "c5c7e2298764" }
nokhwa-bindings-macos = { git = "https://github.com/CapSoftware/nokhwa", rev = "0d3d1f30a78b" }
wgpu = "22.1.0"

windows = "0.58.0"
windows-sys = "0.59.0"
windows-capture = "=1.3.6"
3 changes: 2 additions & 1 deletion apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,13 @@ swift-rs = "1.0.6"
tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2" }

[target.'cfg(target_os= "windows")'.dependencies]
windows = { version = "0.52.0", features = [
windows = { workspace = true, features = [
"Win32_Foundation",
"Win32_System",
"Win32_UI_WindowsAndMessaging",
"Win32_Graphics_Gdi",
] }
windows-sys = { workspace = true }

[target.'cfg(unix)'.dependencies]
nix = { version = "0.29.0", features = ["fs"] }
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"core:window:allow-minimize",
"core:window:allow-unminimize",
"core:window:allow-maximize",
"core:window:allow-unmaximize",
"core:window:allow-set-size",
"core:window:allow-set-focus",
"core:window:allow-start-dragging",
Expand Down
255 changes: 128 additions & 127 deletions apps/desktop/src-tauri/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,131 +185,132 @@ fn get_cursor_image_data() -> Option<Vec<u8>> {

#[cfg(windows)]
fn get_cursor_image_data() -> Option<Vec<u8>> {
use windows::Win32::Foundation::{BOOL, HWND, POINT};
use windows::Win32::Graphics::Gdi::{
BitBlt, CreateCompatibleBitmap, CreateCompatibleDC, CreateDIBSection, DeleteDC,
DeleteObject, GetDC, GetObjectA, ReleaseDC, SelectObject, BITMAP, BITMAPINFO,
BITMAPINFOHEADER, DIB_RGB_COLORS, SRCCOPY,
};
use windows::Win32::UI::WindowsAndMessaging::{GetCursorInfo, CURSORINFO, CURSORINFO_FLAGS};
use windows::Win32::UI::WindowsAndMessaging::{GetIconInfo, ICONINFO};

unsafe {
// Get cursor info
let mut cursor_info = CURSORINFO {
cbSize: std::mem::size_of::<CURSORINFO>() as u32,
flags: CURSORINFO_FLAGS(0),
hCursor: Default::default(),
ptScreenPos: POINT::default(),
};

// Handle Result return type
if GetCursorInfo(&mut cursor_info).is_err() {
return None;
}

// If no cursor, return None
if cursor_info.hCursor.is_invalid() {
return None;
}

// Get icon info
let mut icon_info = ICONINFO::default();
// Handle Result return type
if GetIconInfo(cursor_info.hCursor, &mut icon_info).is_err() {
return None;
}

// Get bitmap info
let mut bitmap = BITMAP::default();
if GetObjectA(
icon_info.hbmColor,
std::mem::size_of::<BITMAP>() as i32,
Some(&mut bitmap as *mut _ as *mut _),
) == 0
{
return None;
}

// Create compatible DC
let screen_dc = GetDC(HWND(0));
let mem_dc = CreateCompatibleDC(screen_dc);

// Create bitmap info header
let bi = BITMAPINFOHEADER {
biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
biWidth: bitmap.bmWidth,
biHeight: -bitmap.bmHeight, // Negative height for top-down bitmap
biPlanes: 1,
biBitCount: 32,
biCompression: 0,
biSizeImage: 0,
biXPelsPerMeter: 0,
biYPelsPerMeter: 0,
biClrUsed: 0,
biClrImportant: 0,
};

let bitmap_info = BITMAPINFO {
bmiHeader: bi,
bmiColors: [Default::default()],
};

// Create DIB section
let mut bits: *mut std::ffi::c_void = std::ptr::null_mut();
let dib = CreateDIBSection(mem_dc, &bitmap_info, DIB_RGB_COLORS, &mut bits, None, 0);

if dib.is_err() {
return None;
}

let dib = dib.unwrap();

// Select DIB into DC
let old_bitmap = SelectObject(mem_dc, dib);

// Copy cursor image
if BitBlt(
mem_dc,
0,
0,
bitmap.bmWidth,
bitmap.bmHeight,
screen_dc,
cursor_info.ptScreenPos.x,
cursor_info.ptScreenPos.y,
SRCCOPY,
)
.is_err()
{
return None;
}

// Get image data
let size = (bitmap.bmWidth * bitmap.bmHeight * 4) as usize;
let mut image_data = vec![0u8; size];
std::ptr::copy_nonoverlapping(bits, image_data.as_mut_ptr() as *mut _, size);

// Cleanup
SelectObject(mem_dc, old_bitmap);
DeleteObject(dib);
DeleteDC(mem_dc);
ReleaseDC(HWND(0), screen_dc);
DeleteObject(icon_info.hbmColor);
DeleteObject(icon_info.hbmMask);

// Convert to PNG format
let image =
image::RgbaImage::from_raw(bitmap.bmWidth as u32, bitmap.bmHeight as u32, image_data)?;

let mut png_data = Vec::new();
image
.write_to(
&mut std::io::Cursor::new(&mut png_data),
image::ImageFormat::Png,
)
.ok()?;

Some(png_data)
}
return None;
// use windows::Win32::Foundation::{BOOL, HWND, POINT};
// use windows::Win32::Graphics::Gdi::{
// BitBlt, CreateCompatibleBitmap, CreateCompatibleDC, CreateDIBSection, DeleteDC,
// DeleteObject, GetDC, GetObjectA, ReleaseDC, SelectObject, BITMAP, BITMAPINFO,
// BITMAPINFOHEADER, DIB_RGB_COLORS, SRCCOPY,
// };
// use windows::Win32::UI::WindowsAndMessaging::{GetCursorInfo, CURSORINFO, CURSORINFO_FLAGS};
// use windows::Win32::UI::WindowsAndMessaging::{GetIconInfo, ICONINFO};

// unsafe {
// // Get cursor info
// let mut cursor_info = CURSORINFO {
// cbSize: std::mem::size_of::<CURSORINFO>() as u32,
// flags: CURSORINFO_FLAGS(0),
// hCursor: Default::default(),
// ptScreenPos: POINT::default(),
// };

// // Handle Result return type
// if GetCursorInfo(&mut cursor_info).is_err() {
// return None;
// }

// // If no cursor, return None
// if cursor_info.hCursor.is_invalid() {
// return None;
// }

// // Get icon info
// let mut icon_info = ICONINFO::default();
// // Handle Result return type
// if GetIconInfo(cursor_info.hCursor, &mut icon_info).is_err() {
// return None;
// }

// // Get bitmap info
// let mut bitmap = BITMAP::default();
// if GetObjectA(
// icon_info.hbmColor,
// std::mem::size_of::<BITMAP>() as i32,
// Some(&mut bitmap as *mut _ as *mut _),
// ) == 0
// {
// return None;
// }

// // Create compatible DC
// let screen_dc = GetDC(HWND(0));
// let mem_dc = CreateCompatibleDC(screen_dc);

// // Create bitmap info header
// let bi = BITMAPINFOHEADER {
// biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
// biWidth: bitmap.bmWidth,
// biHeight: -bitmap.bmHeight, // Negative height for top-down bitmap
// biPlanes: 1,
// biBitCount: 32,
// biCompression: 0,
// biSizeImage: 0,
// biXPelsPerMeter: 0,
// biYPelsPerMeter: 0,
// biClrUsed: 0,
// biClrImportant: 0,
// };

// let bitmap_info = BITMAPINFO {
// bmiHeader: bi,
// bmiColors: [Default::default()],
// };

// // Create DIB section
// let mut bits: *mut std::ffi::c_void = std::ptr::null_mut();
// let dib = CreateDIBSection(mem_dc, &bitmap_info, DIB_RGB_COLORS, &mut bits, None, 0);

// if dib.is_err() {
// return None;
// }

// let dib = dib.unwrap();

// // Select DIB into DC
// let old_bitmap = SelectObject(mem_dc, dib);

// // Copy cursor image
// if BitBlt(
// mem_dc,
// 0,
// 0,
// bitmap.bmWidth,
// bitmap.bmHeight,
// screen_dc,
// cursor_info.ptScreenPos.x,
// cursor_info.ptScreenPos.y,
// SRCCOPY,
// )
// .is_err()
// {
// return None;
// }

// // Get image data
// let size = (bitmap.bmWidth * bitmap.bmHeight * 4) as usize;
// let mut image_data = vec![0u8; size];
// std::ptr::copy_nonoverlapping(bits, image_data.as_mut_ptr() as *mut _, size);

// // Cleanup
// SelectObject(mem_dc, old_bitmap);
// DeleteObject(dib);
// DeleteDC(mem_dc);
// ReleaseDC(HWND(0), screen_dc);
// DeleteObject(icon_info.hbmColor);
// DeleteObject(icon_info.hbmMask);

// // Convert to PNG format
// let image =
// image::RgbaImage::from_raw(bitmap.bmWidth as u32, bitmap.bmHeight as u32, image_data)?;

// let mut png_data = Vec::new();
// image
// .write_to(
// &mut std::io::Cursor::new(&mut png_data),
// image::ImageFormat::Png,
// )
// .ok()?;

// Some(png_data)
// }
}
Loading
Loading