### Construct a Desktop handle by index or GUID Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Creates a `Desktop` handle using a zero-based index or a GUID. This is a zero-cost operation and does not validate the existence of the desktop. The handle can be used with other functions or methods. ```rust use winvd::get_desktop; fn main() { // By zero-based index let d0 = get_desktop(0u32); println!("Name of desktop 0: {:?}", d0.get_name().unwrap_or_default()); // By GUID (e.g. persisted from a previous session) // let d = get_desktop(some_guid); } ``` -------------------------------- ### get_desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Constructs a `Desktop` handle by its index or GUID. This function does not validate existence. ```APIDOC ## get_desktop ### Description `get_desktop` is a zero-cost constructor; it does **not** validate existence. Pass the result to other functions or call methods on it directly. Any function accepting `Into` can also take a bare `u32`/`i32`/`GUID`. ### Method Rust function call ### Parameters - `index_or_guid` (u32 | i32 | GUID) - The zero-based index or GUID of the desktop. ### Response - `Desktop` - A `Desktop` handle. ### Request Example ```rust use winvd::get_desktop; fn main() { // By zero-based index let d0 = get_desktop(0u32); println!("Name of desktop 0: {:?}", d0.get_name().unwrap_or_default()); // By GUID (e.g. persisted from a previous session) // let d = get_desktop(some_guid); } ``` ``` -------------------------------- ### Get the currently active desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Returns a `Desktop` handle for the current virtual desktop. This handle can be used to query the desktop's index, GUID, name, or wallpaper. Uses `expect` for error handling, assuming the operation should succeed. ```rust use winvd::{get_current_desktop, Error}; fn main() { let desktop = get_current_desktop().expect("failed to get current desktop"); let index = desktop.get_index().unwrap(); let name = desktop.get_name().unwrap_or_else(|_| "".into()); println!("Current desktop: index={}, name={:?}", index, name); // e.g. "Current desktop: index=0, name=\"Work\"" } ``` -------------------------------- ### Subscribe to virtual desktop change events Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt This example demonstrates how to subscribe to virtual desktop change events using a standard MPSC channel. The `listen_desktop_events` function returns a `DesktopEventThread` which must be kept alive to continue receiving events. Events are processed from the receiver end of the channel. ```APIDOC ## `listen_desktop_events` — Subscribe to virtual desktop change events Returns a `DesktopEventThread` that must be kept alive. Events are delivered through any `std::sync::mpsc::Sender`, `crossbeam_channel::Sender`, or `winit::event_loop::EventLoopProxy` where `T: From`. ```rust use winvd::{listen_desktop_events, DesktopEvent}; fn main() { let (tx, rx) = std::sync::mpsc::channel::(); // Keep the thread handle alive; dropping it stops and joins the thread. let _thread = listen_desktop_events(tx).expect("failed to start listener"); for event in rx { match event { DesktopEvent::DesktopChanged { old, new } => { println!("Switched from desktop {} to {}", old.get_index().unwrap_or(99), new.get_index().unwrap_or(99)); } DesktopEvent::DesktopCreated(d) => { println!("New desktop created at index {}", d.get_index().unwrap_or(99)); } DesktopEvent::DesktopDestroyed { destroyed, fallback } => { println!("Desktop destroyed, windows moved to {}", fallback.get_index().unwrap_or(99)); let _ = destroyed; // index no longer valid } DesktopEvent::DesktopNameChanged(d, name) => { println!("Desktop {} renamed to {:?}", d.get_index().unwrap_or(99), name); } DesktopEvent::DesktopWallpaperChanged(d, path) => { println!("Desktop {} wallpaper -> {path}", d.get_index().unwrap_or(99)); } DesktopEvent::DesktopMoved { desktop, old_index, new_index } => { println!("Desktop moved from {old_index} to {new_index}"); let _ = desktop; } DesktopEvent::WindowChanged(hwnd) => { println!("Window {:?} moved between desktops", hwnd); } } } } ``` ``` -------------------------------- ### switch_desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Switches the active virtual desktop to the one specified by index or GUID. ```APIDOC ## switch_desktop ### Description Switches to a different virtual desktop. Accepts an index (`u32`/`i32`) or a `GUID`. ### Method Rust function call ### Parameters - `desktop_identifier` (u32 | i32 | GUID) - The index or GUID of the target desktop. ### Response - `Ok(())` - Indicates the switch was successful. - `Err(winvd::Error)` - An error if the switch fails. ### Request Example ```rust use winvd::switch_desktop; fn main() { // Switch to the third desktop (zero-based index 2) switch_desktop(2u32).expect("switch failed"); // Switch by GUID // let guid = get_desktop(0u32).get_id().unwrap(); // switch_desktop(guid).unwrap(); } ``` ``` -------------------------------- ### Interact with Windows Virtual Desktops in Rust Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README-crate.md Demonstrates getting the desktop count, switching to the second desktop (index 1), and setting up a listener for desktop change events. Requires `std::sync::mpsc` for event handling. The listener thread runs indefinitely until the main thread is terminated. ```rust use winvd::{switch_desktop, get_desktop_count, DesktopEvent, listen_desktop_events}; fn main() { // Desktop count println!("Desktops: {:?}", get_desktop_count().unwrap()); // Go to second desktop, index = 1 switch_desktop(1).unwrap(); // To listen for changes, use crossbeam, mpsc or winit proxy as a sender let (tx, rx) = std::sync::mpsc::channel::(); let _notifications_thread = listen_desktop_events(tx); // Keep the _notifications_thread alive for as long as you wish to listen changes std::thread::spawn(|| { for item in rx { println!("{:?}", item); } }); // Wait for keypress println!("⛔ Press enter to stop"); let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); } ``` -------------------------------- ### Per-desktop wallpaper management Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Enables reading or changing the wallpaper path for a specific virtual desktop, identified by index or GUID. Demonstrates setting a new wallpaper path. ```rust use winvd::get_desktop; fn main() { let d = get_desktop(1u32); let current = d.get_wallpaper().unwrap_or_default(); println!("Current wallpaper: {}", current); d.set_wallpaper(r"C:\Users\Public\Pictures\bg.jpg") .expect("set_wallpaper failed"); } ``` -------------------------------- ### Switch to a different desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Switches the active virtual desktop. Accepts either a zero-based index (`u32`/`i32`) or a desktop GUID. Returns `Ok(())` on success. ```rust use winvd::switch_desktop; fn main() { // Switch to the third desktop (zero-based index 2) switch_desktop(2u32).expect("switch failed"); // Switch by GUID // let guid = get_desktop(0u32).get_id().unwrap(); // switch_desktop(guid).unwrap(); } ``` -------------------------------- ### move_window_to_desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Relocates a specified window (by HWND) to a different virtual desktop (by index or GUID). ```APIDOC ## `move_window_to_desktop` — Relocate a window to another desktop Moves any window (by `HWND`) to the specified desktop (by index or GUID). ```rust use windows::Win32::Foundation::HWND; use winvd::move_window_to_desktop; fn main() { let hwnd: HWND = /* obtain HWND */ unsafe { std::mem::zeroed() }; // Move the window to desktop index 1 move_window_to_desktop(1u32, &hwnd).expect("move failed"); } ``` ``` -------------------------------- ### Read and write desktop names Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Allows reading and setting the name of a virtual desktop. Names are UTF-8 strings. Setting a name is only supported on Windows 11. Includes examples for both reading and writing. ```rust use winvd::get_desktop; fn main() { let d = get_desktop(0u32); // Read println!("Before: {:?}", d.get_name().unwrap_or_default()); // Write d.set_name("Work").expect("set_name failed"); println!("After: {:?}", d.get_name().unwrap()); // After: "Work" } ``` -------------------------------- ### Integrate events into a GUI event loop with winit Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt This example shows how to integrate virtual desktop events into a winit-based GUI application. By passing a `winit::event_loop::EventLoopProxy`, desktop events are routed directly into the application's event loop. This requires enabling the `winit` feature flag in your `Cargo.toml`. ```APIDOC ## `listen_desktop_events` with `winit` — Integrate events into a GUI event loop Pass a `winit` `EventLoopProxy` to route desktop events into a `winit` application's event loop. Requires the `winit` feature flag in `Cargo.toml`. ```toml # Cargo.toml [dependencies] winvd = { version = "0.0.49", features = [] } winit = "0.30" ``` ```rust use winit:: event::Event, event_loop::{ControlFlow, EventLoopBuilder}, }; use winvd::{listen_desktop_events, DesktopEvent, DesktopEventSender}; #[derive(Clone, Debug)] enum AppEvent { Desktop(DesktopEvent), } impl From for AppEvent { fn from(e: DesktopEvent) -> Self { AppEvent::Desktop(e) } } fn main() { let event_loop = EventLoopBuilder::::default().build().unwrap(); let proxy = event_loop.create_proxy(); let _thread = listen_desktop_events(DesktopEventSender::Winit(proxy)).unwrap(); event_loop.set_control_flow(ControlFlow::Wait); event_loop.run(move |event, _| { if let Event::UserEvent(AppEvent::Desktop(e)) = event { println!("Desktop event: {:?}", e); } }).unwrap(); } ``` ``` -------------------------------- ### Get Desktop Count Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the total number of virtual desktops available. ```APIDOC ## GetDesktopCount ### Description Retrieves the total number of virtual desktops available. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters None ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - The total count of virtual desktops. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Get Window Desktop ID Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the unique identifier (GUID) of the virtual desktop a specific window is currently on. ```APIDOC ## GetWindowDesktopId ### Description Retrieves the unique identifier (GUID) of the virtual desktop a specific window is currently on. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window. ### Request Example N/A ### Response #### Success Response - **Return Value** (GUID) - The GUID of the desktop the window is on. Returns a zero GUID or equivalent on error. ### Response Example N/A ``` -------------------------------- ### is_window_on_current_desktop / is_window_on_desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Checks if a window is visible on the current or a specified virtual desktop. `is_window_on_current_desktop` uses the public COM API, while `is_window_on_desktop` accepts a desktop by index or GUID. ```APIDOC ## `is_window_on_current_desktop` / `is_window_on_desktop` — Window visibility checks `is_window_on_current_desktop` uses the public `IVirtualDesktopManager` COM API. `is_window_on_desktop` accepts any desktop by index or GUID. ```rust use windows::Win32::Foundation::HWND; use winvd::{is_window_on_current_desktop, is_window_on_desktop}; fn check(hwnd: HWND) { match is_window_on_current_desktop(hwnd) { Ok(true) => println!("Window is visible on the current desktop"), Ok(false) => println!("Window is on a different desktop"), Err(e) => eprintln!("{:?}", e), } match is_window_on_desktop(0u32, &hwnd) { Ok(b) => println!("On desktop 0? {b}"), Err(e) => eprintln!("{:?}", e), } } ``` ``` -------------------------------- ### Get Desktop Number by ID Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the number of a virtual desktop given its unique identifier (GUID). This function is untested. ```APIDOC ## GetDesktopNumberById ### Description Retrieves the number of a virtual desktop given its unique identifier (GUID). This function is untested. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **desktop_id** (GUID) - The GUID of the desktop to query. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - The number of the specified desktop. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Get Desktop ID by Number Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the unique identifier (GUID) of a virtual desktop given its number. This function is untested. ```APIDOC ## GetDesktopIdByNumber ### Description Retrieves the unique identifier (GUID) of a virtual desktop given its number. This function is untested. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **number** (i32) - The number of the desktop to query. ### Request Example N/A ### Response #### Success Response - **Return Value** (GUID) - The GUID of the specified desktop. Returns a zero GUID or equivalent on error. ### Response Example N/A ``` -------------------------------- ### Move Window to Another Desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Moves a window, identified by its HWND, to a specified virtual desktop identified by its index or GUID. The target desktop must exist. ```rust use windows::Win32::Foundation::HWND; use winvd::move_window_to_desktop; fn main() { let hwnd: HWND = /* obtain HWND */ unsafe { std::mem::zeroed() }; // Move the window to desktop index 1 move_window_to_desktop(1u32, &hwnd).expect("move failed"); } ``` -------------------------------- ### Get Desktop Name Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the name of a virtual desktop. This function is only available on Windows 11. ```APIDOC ## GetDesktopName ### Description Retrieves the name of a virtual desktop. This function is only available on Windows 11. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **desktop_number** (i32) - The number of the desktop to query. - **out_utf8_ptr** (*mut u8) - A mutable pointer to a buffer where the UTF-8 name will be written. - **out_utf8_len** (usize) - The size of the buffer pointed to by `out_utf8_ptr`. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns the number of bytes written to the buffer on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Get Desktop by Window Handle Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Finds the virtual desktop that currently contains a given window handle (HWND). Returns an error if the window handle is invalid. You need to obtain a valid HWND first. ```rust use windows::Win32::Foundation::HWND; use winvd::get_desktop_by_window; fn main() { // Obtain the HWND of a real window via Win32 FindWindow, EnumWindows, etc. let hwnd: HWND = unsafe { windows::Win32::UI::WindowsAndMessaging::FindWindowW( windows::core::w!("Notepad"), None, )}; match get_desktop_by_window(hwnd) { Ok(d) => println!("Window is on desktop {}", d.get_index().unwrap()), Err(e) => eprintln!("Error: {:?}", e), } } ``` -------------------------------- ### Check Window Visibility on Desktops Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Checks if a window is visible on the current desktop using the public COM API, or if it resides on a specific desktop identified by its index or GUID. Ensure the HWND is valid. ```rust use windows::Win32::Foundation::HWND; use winvd::{is_window_on_current_desktop, is_window_on_desktop}; fn check(hwnd: HWND) { match is_window_on_current_desktop(hwnd) { Ok(true) => println!("Window is visible on the current desktop"), Ok(false) => println!("Window is on a different desktop"), Err(e) => eprintln!("{:?}", e), } match is_window_on_desktop(0u32, &hwnd) { Ok(b) => println!("On desktop 0? {b}"), Err(e) => eprintln!("{:?}", e), } } ``` -------------------------------- ### Get Current Desktop Number Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the number of the currently active virtual desktop. ```APIDOC ## GetCurrentDesktopNumber ### Description Retrieves the number of the currently active virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters None ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - The number of the current virtual desktop. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Get Window Desktop Number Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Retrieves the number of the virtual desktop a specific window is currently on. ```APIDOC ## GetWindowDesktopNumber ### Description Retrieves the number of the virtual desktop a specific window is currently on. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - The number of the desktop the window is on. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Create and Remove Virtual Desktops Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Demonstrates creating a new virtual desktop and then removing it, redirecting its windows to a fallback desktop. Ensure you have the necessary permissions to manage virtual desktops. ```rust use winvd::{create_desktop, remove_desktop, get_desktop_count}; fn main() { let before = get_desktop_count().unwrap(); println!("Before: {before} desktops"); let new_desktop = create_desktop().expect("create failed"); println!("Created desktop at index {:?}", new_desktop.get_index().unwrap()); // Remove it, falling back to desktop 0 remove_desktop(new_desktop.get_index().unwrap(), 0u32).expect("remove failed"); println!("After removal: {} desktops", get_desktop_count().unwrap()); } ``` -------------------------------- ### create_desktop / remove_desktop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Functions to manage the lifecycle of virtual desktops. `create_desktop` adds a new desktop and returns its handle, while `remove_desktop` removes a desktop and redirects its windows. ```APIDOC ## `create_desktop` / `remove_desktop` — Manage desktop lifecycle `create_desktop` appends a new desktop and returns its handle. `remove_desktop` removes a desktop and redirects its windows to a fallback desktop. ```rust use winvd::{create_desktop, remove_desktop, get_desktop_count}; fn main() { let before = get_desktop_count().unwrap(); println!("Before: {before} desktops"); let new_desktop = create_desktop().expect("create failed"); println!("Created desktop at index {:?}", new_desktop.get_index().unwrap()); // Remove it, falling back to desktop 0 remove_desktop(new_desktop.get_index().unwrap(), 0u32).expect("remove failed"); println!("After removal: {} desktops", get_desktop_count().unwrap()); } ``` ``` -------------------------------- ### Create Desktop Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Creates a new virtual desktop. This function is only available on Windows 11. ```APIDOC ## CreateDesktop ### Description Creates a new virtual desktop. This function is only available on Windows 11. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters None ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Enumerate all virtual desktops Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Returns a `Vec` containing all virtual desktops in order. Each `Desktop` object can be queried for its index, ID, name, and wallpaper. Assumes enumeration will succeed. ```rust use winvd::get_desktops; fn main() { let desktops = get_desktops().expect("failed to enumerate desktops"); for d in &desktops { let idx = d.get_index().unwrap(); let name = d.get_name().unwrap_or_default(); println!("Desktop {}: {:?}", idx, name); } // Desktop 0: "Work" // Desktop 1: "Media" // Desktop 2: "" } ``` -------------------------------- ### Clean and Build Rust Workspace Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README-crate.md Standard Cargo commands for cleaning the project, generating documentation with all features enabled, and building the release version of the entire workspace. ```bash cargo clean cargo doc --all-features cargo build --release --workspace ``` -------------------------------- ### Desktop::get_wallpaper / Desktop::set_wallpaper Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Reads or changes the wallpaper path for a specific virtual desktop. ```APIDOC ## Desktop::get_wallpaper / Desktop::set_wallpaper ### Description Read or change the wallpaper path for any desktop by index or GUID. ### Method Rust method calls on a `Desktop` handle. ### Parameters - `set_wallpaper`: - `path` (string) - The full path to the new wallpaper image file. ### Response - `get_wallpaper`: - `Ok(string)` - The current wallpaper path. - `Err(winvd::Error)` - An error if the operation fails. - `set_wallpaper`: - `Ok(())` - Indicates success. - `Err(winvd::Error)` - An error if the operation fails. ### Request Example ```rust use winvd::get_desktop; fn main() { let d = get_desktop(1u32); let current = d.get_wallpaper().unwrap_or_default(); println!("Current wallpaper: {}", current); d.set_wallpaper(r"C:\Users\Public\Pictures\bg.jpg") .expect("set_wallpaper failed"); } ``` ``` -------------------------------- ### Correct IVirtualDesktopNotification Implementation Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/note-IVirtualDesktopNotification.md Implement IVirtualDesktopNotification using `ComIn` for parameters to ensure correct COM reference counting. The Windows shell manages the reference count for these incoming parameters. ```rust pub unsafe trait IVirtualDesktopNotification: IUnknown { pub unsafe fn virtual_desktop_created( &self, monitors: ComIn, desktop: ComIn, ) -> HRESULT; pub unsafe fn virtual_desktop_destroy_begin( &self, monitors: ComIn, desktop_destroyed: ComIn, desktop_fallback: ComIn, ) -> HRESULT; // ... } ``` -------------------------------- ### Handle winvd Errors in Rust Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Demonstrates how to use a `match` statement to handle different error types returned by the `winvd` crate's functions, such as `WindowNotFound` or `ComError`. This allows for specific error recovery logic. ```rust use winvd::{get_desktop_by_window, Error}; use windows::Win32::Foundation::HWND; fn check_window(hwnd: HWND) { match get_desktop_by_window(hwnd) { Ok(d) => println!("on desktop {}", d.get_index().unwrap()), Err(Error::WindowNotFound) => println!("window handle is stale"), Err(Error::DesktopNotFound) => println!("desktop no longer exists"), Err(Error::ClassNotRegistered) => println!("explorer.exe is not running"), Err(Error::ComError(hr)) => println!("unhandled COM HRESULT: {:?}", hr), Err(e) => println!("other error: {:?}", e), } } ``` -------------------------------- ### Integrate Desktop Events into a winit GUI Event Loop Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Route desktop events into a `winit` application's event loop by passing a `winit` `EventLoopProxy`. This requires enabling the `winit` feature flag in your `Cargo.toml`. ```toml # Cargo.toml [dependencies] winvd = { version = "0.0.49", features = [] } winit = "0.30" ``` ```rust use winit:: event::Event, event_loop::{ControlFlow, EventLoopBuilder}, }; use winvd::{listen_desktop_events, DesktopEvent, DesktopEventSender}; #[derive(Clone, Debug)] enum AppEvent { Desktop(DesktopEvent), } impl From for AppEvent { fn from(e: DesktopEvent) -> Self { AppEvent::Desktop(e) } } fn main() { let event_loop = EventLoopBuilder::::default().build().unwrap(); let proxy = event_loop.create_proxy(); let _thread = listen_desktop_events(DesktopEventSender::Winit(proxy)).unwrap(); event_loop.set_control_flow(ControlFlow::Wait); event_loop.run(move |event, _| { if let Event::UserEvent(AppEvent::Desktop(e)) = event { println!("Desktop event: {:?}", e); } }).unwrap(); } ``` -------------------------------- ### Virtual Desktop Hotkeys in AutoHotkey V2 Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Defines hotkeys for switching between virtual desktops. Win+Ctrl+1-5 switch to specific desktops, while F14 and F15 cycle to the previous and next desktops respectively. Uses the `MoveOrGoto` function. ```autohotkey ; Hotkeys: Win+Ctrl+1..5 switch desktops; F14/F15 cycle prev/next F13 & 1:: MoveOrGoto(0) F13 & 2:: MoveOrGoto(1) F13 & 3:: MoveOrGoto(2) F13 & 4:: MoveOrGoto(3) F13 & 5:: MoveOrGoto(4) F14 UP:: { cur := DllCall(GetCurrentDesktopNumberProc, "Int") last := DllCall(GetDesktopCountProc, "Int") - 1 MoveOrGoto(cur = 0 ? last : cur - 1) } F15 UP:: { cur := DllCall(GetCurrentDesktopNumberProc, "Int") last := DllCall(GetDesktopCountProc, "Int") - 1 MoveOrGoto(cur = last ? 0 : cur + 1) } ``` -------------------------------- ### Desktop::get_name / Desktop::set_name Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Reads or writes the UTF-8 name of a virtual desktop. Setting a name is a Windows 11-only feature. ```APIDOC ## Desktop::get_name / Desktop::set_name ### Description Read or write the UTF-8 name for any desktop by index or GUID. Setting a name is a Windows 11-only feature. ### Method Rust method calls on a `Desktop` handle. ### Parameters - `set_name`: - `name` (string) - The new name for the desktop. ### Response - `get_name`: - `Ok(string)` - The current name of the desktop. - `Err(winvd::Error)` - An error if the operation fails. - `set_name`: - `Ok(())` - Indicates success. - `Err(winvd::Error)` - An error if the operation fails. ### Request Example ```rust use winvd::get_desktop; fn main() { let d = get_desktop(0u32); // Read println!("Before: {:?}", d.get_name().unwrap_or_default()); // Write d.set_name("Work").expect("set_name failed"); println!("After: {:?}", d.get_name().unwrap()); // After: "Work" } ``` ``` -------------------------------- ### Go To Desktop Number Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Switches the active virtual desktop to the specified desktop number. ```APIDOC ## GoToDesktopNumber ### Description Switches the active virtual desktop to the specified desktop number. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **desktop_number** (i32) - The number of the desktop to switch to. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### get_desktops Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Enumerates all virtual desktops and returns them as a vector of `Desktop` handles. ```APIDOC ## get_desktops ### Description Returns a `Vec` containing every desktop in order. Each element exposes `.get_index()`, `.get_id()`, `.get_name()`, and `.get_wallpaper()`. ### Method Rust function call ### Parameters None ### Response - `Ok(Vec)` - A vector containing `Desktop` handles for all virtual desktops. - `Err(winvd::Error)` - An error if the operation fails. ### Request Example ```rust use winvd::get_desktops; fn main() { let desktops = get_desktops().expect("failed to enumerate desktops"); for d in &desktops { let idx = d.get_index().unwrap(); let name = d.get_name().unwrap_or_default(); println!("Desktop {}: {:?}", idx, name); } // Desktop 0: "Work" // Desktop 1: "Media" // Desktop 2: "" } ``` ``` -------------------------------- ### Move or Go To Virtual Desktop in AutoHotkey V2 Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt A function to navigate to a specified virtual desktop. If the left mouse button is held down, it also moves the active window to that desktop. Requires `MoveWindowToDesktopNumberProc` and `GoToDesktopNumberProc` to be bound. ```autohotkey ; Navigate to a desktop, moving the active window if LButton is held MoveOrGoto(num) { if GetKeyState("LButton") { activeHwnd := WinGetID("A") DllCall(MoveWindowToDesktopNumberProc, "Ptr", activeHwnd, "Int", num, "Int") } DllCall(GoToDesktopNumberProc, "Int", num, "Int") } ``` -------------------------------- ### Subscribe to Virtual Desktop Change Events with std::sync::mpsc Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Use this snippet to subscribe to desktop events and receive them through a standard Rust MPSC channel. Ensure the thread handle returned by `listen_desktop_events` is kept alive to maintain the listener. ```rust use winvd::{listen_desktop_events, DesktopEvent}; fn main() { let (tx, rx) = std::sync::mpsc::channel::(); // Keep the thread handle alive; dropping it stops and joins the thread. let _thread = listen_desktop_events(tx).expect("failed to start listener"); for event in rx { match event { DesktopEvent::DesktopChanged { old, new } => { println!("Switched from desktop {} to {}", old.get_index().unwrap_or(99), new.get_index().unwrap_or(99)); } DesktopEvent::DesktopCreated(d) => { println!("New desktop created at index {}", d.get_index().unwrap_or(99)); } DesktopEvent::DesktopDestroyed { destroyed, fallback } => { println!("Desktop destroyed, windows moved to {}", fallback.get_index().unwrap_or(99)); let _ = destroyed; // index no longer valid } DesktopEvent::DesktopNameChanged(d, name) => { println!("Desktop {} renamed to {:?}", d.get_index().unwrap_or(99), name); } DesktopEvent::DesktopWallpaperChanged(d, path) => { println!("Desktop {} wallpaper -> {path}", d.get_index().unwrap_or(99)); } DesktopEvent::DesktopMoved { desktop, old_index, new_index } => { println!("Desktop moved from {old_index} to {new_index}"); let _ = desktop; } DesktopEvent::WindowChanged(hwnd) => { println!("Window {:?} moved between desktops", hwnd); } } } } ``` -------------------------------- ### Register PostMessage Hook Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Registers a window to receive virtual desktop change notifications via the `PostMessage` API. ```APIDOC ## RegisterPostMessageHook ### Description Registers a window to receive virtual desktop change notifications via the `PostMessage` API. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **listener_hwnd** (HWND) - The handle of the window to register. - **message_offset** (u32) - The offset for the custom window message to be posted. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Pin Window Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Pins a specific window to the current virtual desktop. ```APIDOC ## PinWindow ### Description Pins a specific window to the current virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window to pin. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Query the number of virtual desktops Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Returns the total number of virtual desktops. Handles specific errors like 'ClassNotRegistered' if explorer.exe is not running. ```rust use winvd::{get_desktop_count, Error}; fn main() { match get_desktop_count() { Ok(count) => println!("Active desktops: {}", count), // e.g. "Active desktops: 3" Err(Error::ClassNotRegistered) => eprintln!("explorer.exe is not running"), Err(e) => eprintln!("Error: {:?}", e), } } ``` -------------------------------- ### Rust Function Signatures for VirtualDesktopAccessor Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md This section lists the exported Rust function signatures available in the VirtualDesktopAccessor.dll. These functions allow programmatic access to Windows Virtual Desktop features. ```rust fn GetCurrentDesktopNumber() -> i32 fn GetDesktopCount() -> i32 fn GetDesktopIdByNumber(number: i32) -> GUID // Untested fn GetDesktopNumberById(desktop_id: GUID) -> i32 // Untested fn GetWindowDesktopId(hwnd: HWND) -> GUID fn GetWindowDesktopNumber(hwnd: HWND) -> i32 fn IsWindowOnCurrentVirtualDesktop(hwnd: HWND) -> i32 fn MoveWindowToDesktopNumber(hwnd: HWND, desktop_number: i32) -> i32 fn GoToDesktopNumber(desktop_number: i32) -> i32 fn SetDesktopName(desktop_number: i32, in_name_ptr: *const i8) -> i32 // Win11 only fn GetDesktopName(desktop_number: i32, out_utf8_ptr: *mut u8, out_utf8_len: usize) -> i32 // Win11 only fn RegisterPostMessageHook(listener_hwnd: HWND, message_offset: u32) -> i32 fn UnregisterPostMessageHook(listener_hwnd: HWND) -> i32 fn IsPinnedWindow(hwnd: HWND) -> i32 fn PinWindow(hwnd: HWND) -> i32 fn UnPinWindow(hwnd: HWND) -> i32 fn IsPinnedApp(hwnd: HWND) -> i32 fn PinApp(hwnd: HWND) -> i32 fn UnPinApp(hwnd: HWND) -> i32 fn IsWindowOnDesktopNumber(hwnd: HWND, desktop_number: i32) -> i32 fn CreateDesktop() -> i32 // Win11 only fn RemoveDesktop(remove_desktop_number: i32, fallback_desktop_number: i32) -> i32 // Win11 only ``` -------------------------------- ### Load and Bind VirtualDesktopAccessor.dll in AutoHotkey V2 Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Loads the VirtualDesktopAccessor.dll and binds its exported functions for use in an AutoHotkey V2 script. Ensure the DLL is in the script's directory. ```autohotkey SetWorkingDir(A_ScriptDir) VDA_PATH := A_ScriptDir . "\VirtualDesktopAccessor.dll" hVDA := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr") GetDesktopCountProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "GetDesktopCount", "Ptr") GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "GoToDesktopNumber", "Ptr") GetCurrentDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "GetCurrentDesktopNumber", "Ptr") MoveWindowToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "MoveWindowToDesktopNumber", "Ptr") GetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "GetDesktopName", "Ptr") SetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "SetDesktopName", "Ptr") CreateDesktopProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "CreateDesktop", "Ptr") RemoveDesktopProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "RemoveDesktop", "Ptr") RegisterPostMessageHookProc := DllCall("GetProcAddress", "Ptr", hVDA, "AStr", "RegisterPostMessageHook", "Ptr") ``` -------------------------------- ### UnPin App Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Unpins the application associated with a window from the current virtual desktop. ```APIDOC ## UnPinApp ### Description Unpins the application associated with a window from the current virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window whose application to unpin. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### get_desktop_count Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Queries the total number of virtual desktops currently active. Returns a Result with the count or an error. ```APIDOC ## get_desktop_count ### Description Returns the total number of virtual desktops currently active. All functions returning `Result` use `winvd::Error` for typed error variants. ### Method Rust function call ### Parameters None ### Response - `Ok(count)` (u32) - The number of active virtual desktops. - `Err(winvd::Error)` - An error if the operation fails, e.g., `Error::ClassNotRegistered` if explorer.exe is not running. ### Request Example ```rust use winvd::{get_desktop_count, Error}; fn main() { match get_desktop_count() { Ok(count) => println!("Active desktops: {}", count), // e.g. "Active desktops: 3" Err(Error::ClassNotRegistered) => eprintln!("explorer.exe is not running"), Err(e) => eprintln!("Error: {:?}", e), } } ``` ``` -------------------------------- ### Pin App Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Pins the application associated with a window to the current virtual desktop. ```APIDOC ## PinApp ### Description Pins the application associated with a window to the current virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window whose application to pin. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### UnPin Window Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Unpins a specific window from the current virtual desktop. ```APIDOC ## UnPinWindow ### Description Unpins a specific window from the current virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window to unpin. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### Incorrect IVirtualDesktopNotification Implementation Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/note-IVirtualDesktopNotification.md Avoid implementing IVirtualDesktopNotification by directly using COM object types without `ComIn`. This leads to incorrect reference counting as `windows-rs` will attempt to `Release` the object on drop, causing crashes. ```rust pub unsafe trait IVirtualDesktopNotification: IUnknown { pub unsafe fn virtual_desktop_created( &self, monitors: IObjectArray, // This is wrong, should be ComIn desktop: IVirtualDesktop, // This is wrong, should be ComIn ) -> HRESULT; pub unsafe fn virtual_desktop_destroy_begin( &self, monitors: IObjectArray, // This is wrong, should be ComIn desktop_destroyed: IVirtualDesktop, // This is wrong, should be ComIn desktop_fallback: IVirtualDesktop, // This is wrong, should be ComIn ) -> HRESULT; // ... } ``` -------------------------------- ### Set Desktop Name Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Sets the name of a virtual desktop. This function is only available on Windows 11. ```APIDOC ## SetDesktopName ### Description Sets the name of a virtual desktop. This function is only available on Windows 11. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **desktop_number** (i32) - The number of the desktop to rename. - **in_name_ptr** (*const i8) - A pointer to a null-terminated UTF-8 string representing the new name. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 0 on success. Returns -1 on error. ### Response Example N/A ``` -------------------------------- ### get_desktop_by_window Source: https://context7.com/ciantic/virtualdesktopaccessor/llms.txt Finds the virtual desktop that currently owns a given window. Returns an error if the window handle is invalid. ```APIDOC ## `get_desktop_by_window` — Find which desktop owns a window Looks up the `Desktop` that currently contains the given `HWND`. Returns `Error::WindowNotFound` if the handle is invalid. ```rust use windows::Win32::Foundation::HWND; use winvd::get_desktop_by_window; fn main() { // Obtain the HWND of a real window via Win32 FindWindow, EnumWindows, etc. let hwnd: HWND = unsafe { windows::Win32::UI::WindowsAndMessaging::FindWindowW( windows::core::w!("Notepad"), None, )}; match get_desktop_by_window(hwnd) { Ok(d) => println!("Window is on desktop {}", d.get_index().unwrap()), Err(e) => eprintln!("Error: {:?}", e), } } ``` ``` -------------------------------- ### Is Window Pinned Source: https://github.com/ciantic/virtualdesktopaccessor/blob/rust/README.md Checks if a specific window is pinned to the current virtual desktop. ```APIDOC ## IsPinnedWindow ### Description Checks if a specific window is pinned to the current virtual desktop. ### Method Rust function signature (for DLL export reference) ### Endpoint N/A (DLL Function) ### Parameters - **hwnd** (HWND) - The handle of the window. ### Request Example N/A ### Response #### Success Response - **Return Value** (i32) - Returns 1 if the window is pinned, 0 otherwise. Returns -1 on error. ### Response Example N/A ```