|
| 1 | +# Cap Cursor Info |
| 2 | + |
| 3 | +A cross-platform Rust crate for detecting cursor shapes and providing accurate cursor assets with hotspot information. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- 🖱️ **Cross-platform cursor detection** - Support for macOS and Windows |
| 8 | +- 🎯 **Accurate hotspot information** - Precise cursor positioning data |
| 9 | +- 🎨 **High-quality SVG assets** - Scalable cursor graphics for all supported shapes |
| 10 | +- 🔍 **Real-time cursor monitoring** - Track cursor changes as they happen |
| 11 | +- 📦 **Serialization support** - Built-in serde and specta support |
| 12 | +- 🛠️ **Development tools** - Interactive viewer and CLI monitoring |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +Add this to your `Cargo.toml`: |
| 17 | + |
| 18 | +```toml |
| 19 | +[dependencies] |
| 20 | +cap-cursor-info = "0.0.0" |
| 21 | +``` |
| 22 | + |
| 23 | +### Platform-specific dependencies |
| 24 | + |
| 25 | +The crate automatically includes platform-specific dependencies: |
| 26 | + |
| 27 | +- **macOS**: Uses `objc2` and `objc2-app-kit` for cursor detection |
| 28 | +- **Windows**: Uses `windows` crate for Win32 API integration |
| 29 | + |
| 30 | +## Usage |
| 31 | + |
| 32 | +### Basic Usage |
| 33 | + |
| 34 | +```rust |
| 35 | +use cap_cursor_info::{CursorShape, CursorShapeMacOS, CursorShapeWindows}; |
| 36 | + |
| 37 | +// Create a cursor shape |
| 38 | +let cursor = CursorShape::MacOS(CursorShapeMacOS::Arrow); |
| 39 | + |
| 40 | +// Resolve to get SVG asset and hotspot |
| 41 | +if let Some(resolved) = cursor.resolve() { |
| 42 | + println!("SVG: {}", resolved.raw); |
| 43 | + println!("Hotspot: ({}, {})", resolved.hotspot.0, resolved.hotspot.1); |
| 44 | +} |
| 45 | + |
| 46 | +// Display cursor information |
| 47 | +println!("Cursor: {}", cursor); // Output: "MacOS|Arrow" |
| 48 | +``` |
| 49 | + |
| 50 | +### Platform-specific Detection |
| 51 | + |
| 52 | +#### macOS |
| 53 | + |
| 54 | +```rust |
| 55 | +#[cfg(target_os = "macos")] |
| 56 | +use cap_cursor_info::CursorShapeMacOS; |
| 57 | + |
| 58 | +// Detect cursor from hash (macOS uses image hashing) |
| 59 | +let hash = "de2d1f4a81e520b65fd1317b845b00a1c51a4d1f71cca3cd4ccdab52b98d1ac9"; |
| 60 | +if let Some(cursor) = CursorShapeMacOS::from_hash(hash) { |
| 61 | + println!("Detected cursor: {:?}", cursor); |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +#### Windows |
| 66 | + |
| 67 | +```rust |
| 68 | +#[cfg(target_os = "windows")] |
| 69 | +use cap_cursor_info::CursorShape; |
| 70 | +use windows::Win32::UI::WindowsAndMessaging::HCURSOR; |
| 71 | + |
| 72 | +// Convert from Windows HCURSOR |
| 73 | +let hcursor: HCURSOR = get_current_cursor(); // Your implementation |
| 74 | +if let Ok(cursor) = CursorShape::try_from(&hcursor) { |
| 75 | + println!("Detected cursor: {}", cursor); |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +### Serialization |
| 80 | + |
| 81 | +The crate supports serde serialization: |
| 82 | + |
| 83 | +```rust |
| 84 | +use cap_cursor_info::CursorShape; |
| 85 | +use serde_json; |
| 86 | + |
| 87 | +let cursor = CursorShape::MacOS(CursorShapeMacOS::Arrow); |
| 88 | +let json = serde_json::to_string(&cursor).unwrap(); |
| 89 | +println!("{}", json); // "MacOS|Arrow" |
| 90 | + |
| 91 | +let deserialized: CursorShape = serde_json::from_str(&json).unwrap(); |
| 92 | +``` |
| 93 | + |
| 94 | +## Supported Cursors |
| 95 | + |
| 96 | +### macOS Cursors |
| 97 | + |
| 98 | +- `Arrow` - Standard arrow pointer |
| 99 | +- `ContextualMenu` - Context menu indicator |
| 100 | +- `ClosedHand` - Closed hand for dragging |
| 101 | +- `Crosshair` - Precision crosshair |
| 102 | +- `DragCopy` - Copy operation indicator |
| 103 | +- `DragLink` - Link operation indicator |
| 104 | +- `IBeam` - Text selection cursor |
| 105 | +- `IBeamVerticalForVerticalLayout` - Vertical text cursor |
| 106 | +- `OpenHand` - Open hand for grabbable items |
| 107 | +- `OperationNotAllowed` - Prohibited operation |
| 108 | +- `PointingHand` - Clickable link pointer |
| 109 | +- `ResizeDown/Up/Left/Right` - Directional resize cursors |
| 110 | +- `ResizeLeftRight/UpDown` - Bidirectional resize cursors |
| 111 | + |
| 112 | +### Windows Cursors |
| 113 | + |
| 114 | +- `Arrow` - Standard arrow pointer |
| 115 | +- `IBeam` - Text selection cursor |
| 116 | +- `Wait` - Loading/busy indicator |
| 117 | +- `Cross` - Crosshair cursor |
| 118 | +- `UpArrow` - Vertical selection |
| 119 | +- `SizeNWSE/NESW/WE/NS/All` - Various resize cursors |
| 120 | +- `No` - Prohibited operation |
| 121 | +- `Hand` - Clickable link pointer |
| 122 | +- `AppStarting` - Application loading |
| 123 | +- `Help` - Help/question cursor |
| 124 | +- `Pin/Person` - Specialized cursors |
| 125 | +- `Pen` - Drawing/writing cursor |
| 126 | + |
| 127 | +## Development Tools |
| 128 | + |
| 129 | +### Interactive Cursor Viewer |
| 130 | + |
| 131 | +Open `cursors.html` in your browser to: |
| 132 | +- View all cursor assets with accurate scaling |
| 133 | +- See hotspot positions visually |
| 134 | +- Copy hotspot coordinates for development |
| 135 | +- Test cursor appearance on different backgrounds |
| 136 | + |
| 137 | +### CLI Monitoring Tool |
| 138 | + |
| 139 | +Run the example to monitor cursor changes in real-time: |
| 140 | + |
| 141 | +```bash |
| 142 | +cargo run --example cli |
| 143 | +``` |
| 144 | + |
| 145 | +This will: |
| 146 | +- Display current cursor information |
| 147 | +- Show hash values (macOS) or handle info (Windows) |
| 148 | +- Update in real-time as you move between applications |
| 149 | + |
| 150 | +## Platform Details |
| 151 | + |
| 152 | +### macOS Implementation |
| 153 | + |
| 154 | +macOS cursor detection uses SHA-256 hashing of the cursor's TIFF image data. This approach is necessary because: |
| 155 | +- `NSCursor` instances cannot be compared directly |
| 156 | +- Cursors are resolution-independent |
| 157 | +- Hash comparison provides reliable identification |
| 158 | + |
| 159 | +### Windows Implementation |
| 160 | + |
| 161 | +Windows cursor detection uses `HCURSOR` handle comparison with a cached lookup table of system cursors loaded at runtime. |
| 162 | + |
| 163 | +## Asset Information |
| 164 | + |
| 165 | +All cursor assets are: |
| 166 | +- **Format**: SVG for scalability |
| 167 | +- **Quality**: High-fidelity reproductions of system cursors |
| 168 | +- **Hotspots**: Precisely measured for accurate positioning |
| 169 | +- **License**: See individual asset licenses in `assets/` directories |
| 170 | + |
| 171 | +### Hotspot Coordinates |
| 172 | + |
| 173 | +Hotspot coordinates are normalized (0.0 to 1.0) relative to the cursor's dimensions: |
| 174 | +- `(0.0, 0.0)` = Top-left corner |
| 175 | +- `(1.0, 1.0)` = Bottom-right corner |
| 176 | +- `(0.5, 0.5)` = Center |
| 177 | + |
| 178 | +## Contributing |
| 179 | + |
| 180 | +We welcome contributions! Please: |
| 181 | + |
| 182 | +1. Test on both macOS and Windows when possible |
| 183 | +2. Include hotspot measurements for new cursor assets |
| 184 | +3. Update the HTML viewer when adding new cursors |
| 185 | +4. Run the CLI example to verify cursor detection |
| 186 | + |
| 187 | +## License |
| 188 | + |
| 189 | +This project is released under the Apple User Agreement for macOS assets. See individual license files in the assets directories for specific terms. |
0 commit comments