diff --git a/docs/vision.md b/docs/vision.md new file mode 100644 index 0000000..3a4ffcd --- /dev/null +++ b/docs/vision.md @@ -0,0 +1,248 @@ +> Original product vision, kept as written. The project was renamed from `snapr` to `valw`; phase designs live in `docs/superpowers/specs/`. + +# SPEC.md: macOS tarzı ekran görüntüsü + zoom aracı (niri / Wayland / NixOS) + +> Bu dosyayı projenin köküne `SPEC.md` (veya `CLAUDE.md`) olarak koy ve Claude Code'a +> "SPEC.md'yi oku, Faz 1'den başla" de. Proje adı şimdilik `snapr`, istediğin gibi değiştir. + +## 1. Amaç + +macOS'taki **Cmd+Shift+3/4/5** deneyimini niri üzerinde birebir hissettiren, Rust ile yazılmış tek bir araç: + +- Bölge / pencere / tam ekran yakalama +- macOS'taki gibi **sağ altta beliren küçük önizleme** (tıkla → düzenle, sürükle → bırak, kaydır → kapat) +- Basit bir **düzenleyici** (ok, kutu, metin, kalem, bulanıklaştırma, kırpma) +- **Zoom / büyüteç modu** (woomer benzeri: zoom, pan, flashlight) +- Cmd+Shift+5 benzeri **araç çubuğu** + +## 2. Hedef ortam ve kısıtlar + +- **Compositor:** niri (öncelikli). Diğer wlroots tabanlı compositor'larda çalışması bonus, zorunlu değil. +- **Shell:** Noctalia. Doğrudan bir Noctalia API'sine bağımlı olma; entegrasyon **CLI + standart Wayland protokolleri + freedesktop bildirimleri** üzerinden olsun, böylece Noctalia'nın iç yapısı değişse de araç çalışır. +- **Dağıtım:** NixOS. Proje bir **flake** olarak paketlenmeli. +- **Dil:** Rust (stable). X11 desteği yok, sadece Wayland. + +> ⚠️ Claude Code için: protokol ve IPC desteğini **varsayma, doğrula.** Kodlamaya başlamadan önce +> kullanıcının makinesinde `niri --version`, `niri msg --help`, `wayland-info` çıktılarına bak ve +> hangi protokollerin sunulduğunu raporla. + +## 3. Teknik yaklaşım + +| Konu | Tercih | Not | +|---|---|---| +| Wayland istemcisi | `smithay-client-toolkit` (SCTK) + `wayland-client` | | +| Overlay yüzeyleri | `wlr-layer-shell` | Seçim ekranı, önizleme, zoom modu hepsi layer-shell yüzeyi | +| Ekran yakalama | `ext-image-copy-capture-v1` varsa onu, yoksa `wlr-screencopy-unstable-v1` | İkisini de bir trait arkasına soy | +| Pencere bilgisi | `niri-ipc` crate'i ile niri IPC | Pencere listesi, odaklı pencere, monitör bilgisi. Pencere geometrisi IPC'den alınamıyorsa pencere yakalamada niri'nin kendi `screenshot-window` aksiyonuna düş | +| Çizim | `tiny-skia` (yazılımsal) | Gerekirse sonradan `wgpu`'ya geçilebilir; zoom modunda performans yetmezse ilk aday orası | +| Metin | `cosmic-text` veya `fontdue` | | +| Pano | `wl-clipboard-rs` | PNG olarak kopyala | +| Bildirim | `notify-rust` | Önizleme penceresi yerine fallback olarak | +| Görüntü | `image` crate'i (PNG kaydetme) | | +| Config | `serde` + `toml`, `~/.config/snapr/config.toml` | | +| CLI | `clap` | | + +**HiDPI / kesirli ölçekleme** en baştan düşünülmeli: `wp-fractional-scale-v1` ve `wp-viewporter` kullan, yakalanan görüntü fiziksel piksel çözünürlüğünde olsun. + +**Çoklu monitör:** Seçim modu tüm monitörlerde aynı anda açılmalı; bölge tek monitörle sınırlı olabilir (v1 için yeterli). + +## 4. Özellikler + +### 4.1 Yakalama modları (CLI alt komutları) + +``` +snapr region # Cmd+Shift+4: sürükleyerek bölge seç +snapr window # Cmd+Shift+4 + Space: üzerine gelinen pencere vurgulanır, tıkla → yakala +snapr screen # Cmd+Shift+3: odaklı monitör (veya --all) +snapr toolbar # Cmd+Shift+5: araç çubuğu +snapr zoom # woomer benzeri zoom modu +snapr edit # düzenleyiciyi doğrudan aç +``` + +Ortak bayraklar: `--clipboard-only`, `--no-preview`, `--delay `, `--output `, `--cursor`. + +### 4.2 Bölge seçimi (macOS davranışı) + +- Ekran donar (yakalanmış kare arka plan olarak gösterilir), hafif karartılır. +- İmleç yanında **koordinat / boyut** göstergesi (örn. `640 × 480`). +- Sürüklerken: + - **Shift**: sadece bir eksende genişlet + - **Alt**: merkezden genişlet + - **Space basılı tut**: seçimi taşı +- **Space (sürüklemeden önce)**: pencere moduna geç (macOS'taki kamera ikonu mantığı). +- **Esc**: iptal. +- Bırakınca yakala. + +### 4.3 Pencere modu + +- İmlecin altındaki pencere mavi tonla vurgulanır. +- Tıkla → yakala. Opsiyonel: pencere çevresine gölge ekleme (config ile, macOS'taki gibi, varsayılan kapalı). + +### 4.4 Sağ alt önizleme (macOS'un "floating thumbnail"ı) + +- Yakalamadan sonra odaklı monitörün sağ alt köşesinde, layer-shell ile küçük bir önizleme belirir (kayarak girer). +- Varsayılan **5 sn** sonra kaybolur ve dosya kaydedilir (süre config'den). +- Etkileşimler: + - **Sol tık** → düzenleyicide aç + - **Sağ tık** → küçük menü: Kaydet / Panoya kopyala / Klasörde göster / Sil / Düzenle + - **Sağa kaydır/sürükle** → hemen kaydet ve kapat + - **Dışarı sürükle** → `wl_data_device` ile sürükle-bırak (dosyayı başka bir uygulamaya bırakabilmek) + - Üzerine gelince zamanlayıcı durur +- Önizleme devre dışıysa `notify-send` benzeri bir bildirim gönder (resim + "Düzenle" aksiyonu). Noctalia bildirimleri bunu gösterecektir. + +### 4.5 Düzenleyici + +Normal bir pencere (xdg-toplevel). Araçlar: + +- Ok, dikdörtgen, elips, çizgi, serbest kalem, işaretleyici (yarı saydam) +- Metin (font boyutu, renk) +- Bulanıklaştır / pikselleştir (hassas bilgileri gizlemek için) +- Numaralı işaret (1, 2, 3... baloncukları) +- Kırp +- Renk paleti + kalınlık +- Geri al / yinele (Ctrl+Z / Ctrl+Shift+Z) +- Ctrl+C panoya kopyala, Ctrl+S kaydet, Esc kapat + +> Alternatif: v1'de düzenleyiciyi yazmak yerine **Satty**'yi çağırmak mümkün. Faz planına bak. + +### 4.6 Araç çubuğu (Cmd+Shift+5) + +Ekranın altında ortalanmış yüzen bir çubuk: + +`[Tam ekran] [Pencere] [Bölge] | [Zoom] | Seçenekler ▾ | [Yakala]` + +Seçenekler: kayıt yeri (Masaüstü / Resimler / Pano / Özel), zamanlayıcı (yok / 5 sn / 10 sn), imleci göster, önizlemeyi göster, son seçimi hatırla. + +> Ekran kaydı (video) **v1 kapsamı dışında**. İleride `gpu-screen-recorder` veya `wf-recorder` çağrılarak eklenebilir. + +### 4.7 Zoom modu (woomer'dan esinlenme) + +- Ekranın anlık görüntüsü üzerinde tam ekran layer-shell yüzeyi. +- Fare tekerleği: imlecin olduğu noktaya doğru zoom +- Sol tık + sürükle: pan +- `f`: flashlight aç/kapat; `Ctrl + tekerlek`: flashlight yarıçapı +- `0`: sıfırla, `Esc`/`q`: çık +- Yumuşak (animasyonlu) zoom ve pan +- **Bonus:** zoom modundayken `c` tuşu → o anki görünümü yakala ve önizleme akışına gönder + +> ⚠️ Lisans: woomer'dan kod kopyalanacaksa önce **lisansını kontrol et** ve uyumluysa atıf ekle. +> Tercih edilen yol: davranışı referans alıp kendi implementasyonunu yazmak. Böylece aynı yakalama ve +> çizim altyapısı paylaşılır, woomer'ın ayrı render bağımlılıklarına ihtiyaç kalmaz. + +## 5. Config örneği + +```toml +# ~/.config/snapr/config.toml +[save] +directory = "~/Pictures/Screenshots" +filename = "Screenshot %Y-%m-%d at %H.%M.%S.png" +copy_to_clipboard = true + +[preview] +enabled = true +timeout_secs = 5 +corner = "bottom-right" # top-left | top-right | bottom-left | bottom-right +size = 220 # px, uzun kenar + +[capture] +show_cursor = false +window_shadow = false + +[editor] +backend = "builtin" # builtin | satty +default_color = "#ff3b30" +stroke_width = 4 + +[zoom] +scroll_step = 1.15 +flashlight_radius = 180 +``` + +## 6. niri entegrasyonu + +```kdl +binds { + Mod+Shift+3 { spawn "snapr" "screen"; } + Mod+Shift+4 { spawn "snapr" "region"; } + Mod+Shift+5 { spawn "snapr" "toolbar"; } + Mod+Z { spawn "snapr" "zoom"; } +} +``` + +Layer-shell yüzeylerinin namespace'leri sabit ve belgelenmiş olsun (`snapr-overlay`, `snapr-preview`, `snapr-zoom`), böylece gerekirse niri'de `layer-rule` ile özelleştirilebilir. + +## 7. NixOS paketleme + +- `flake.nix` içinde: + - `packages..default`: `rustPlatform.buildRustPackage` (veya `crane`) + - `devShells..default`: rust toolchain, `pkg-config`, `wayland`, `libxkbcommon`, `fontconfig`, `wayland-protocols` + - `homeManagerModules.default`: `programs.snapr.enable` + `programs.snapr.settings` (TOML'a çevrilir) +- Runtime'da gereken kütüphaneler için doğru `buildInputs`/`nativeBuildInputs` ve gerekirse `wrapProgram` ile `LD_LIBRARY_PATH`. +- `nix build` ve `nix run . -- region` kutudan çıktığı gibi çalışmalı. + +## 8. Mimari + +``` +src/ + main.rs # clap CLI, alt komut yönlendirme + config.rs + capture/ + mod.rs # trait Capturer + ext_copy.rs # ext-image-copy-capture-v1 + wlr_screencopy.rs + niri.rs # niri-ipc sarmalayıcı (pencereler, monitörler, odak) + overlay/ + region.rs # bölge + pencere seçimi + toolbar.rs + zoom.rs + preview.rs # sağ alt önizleme + editor/ + mod.rs + tools.rs # ok, kutu, metin, blur... + history.rs # undo/redo + output.rs # kaydetme, pano, bildirim + render.rs # tiny-skia yardımcıları +``` + +- Her mod kendi başına çalışan kısa ömürlü bir süreç olabilir (daemon gerekmez). Önizleme yakalamadan sonra aynı süreçte yaşar ve zamanlayıcı bitince çıkar. +- İki yakalama aynı anda başlatılırsa ikincisi birincinin bitmesini bekler veya iptal eder (lock dosyası: `$XDG_RUNTIME_DIR/snapr.lock`). + +## 9. Faz planı + +**Faz 0: Keşif** +Kullanıcının sisteminde protokol desteğini tespit et, raporla. Boş SCTK + layer-shell yüzeyi açıp kapatan minimal örnek. `flake.nix` + devShell. + +**Faz 1: Çekirdek yakalama** +`snapr screen` ve `snapr region` (temel sürükle-seç, Esc iptal). PNG kaydetme + panoya kopyalama. Config dosyası. + +**Faz 2: Önizleme** +Sağ alt önizleme, zamanlayıcı, tık → (şimdilik) Satty'de aç, kaydır → kapat. Bildirim fallback'i. + +**Faz 3: Pencere modu + seçim inceliği** +niri IPC ile pencere vurgulama, Space ile mod değiştirme, Shift/Alt/Space modifikatörleri, boyut göstergesi, HiDPI doğruluğu. + +**Faz 4: Zoom modu** +woomer benzeri zoom/pan/flashlight, zoomdan yakalama. + +**Faz 5: Yerleşik düzenleyici** +Araçlar, undo/redo, kırpma, blur. `editor.backend = "builtin"` varsayılan olur. + +**Faz 6: Araç çubuğu + cila** +Cmd+Shift+5 çubuğu, zamanlayıcı, sürükle-bırak, home-manager modülü, README. + +Her fazın sonunda: `cargo clippy -- -D warnings`, `cargo fmt --check`, `nix build` geçmeli ve fazın özelliği niri üzerinde elle test edilmiş olmalı. + +## 10. Kabul kriterleri + +- 2 monitörlü, biri kesirli ölçekli (örn. 1.25) kurulumda bölge seçimi piksel-doğru yakalar. +- Kısayola basmaktan seçim ekranının görünmesine kadar geçen süre < 150 ms hissi verir. +- Önizleme odak çalmaz (klavye odağı almaz), sadece üzerine tıklanınca etkileşir. +- Hiçbir mod ekranda takılı kalan bir overlay bırakmaz; çökme durumunda bile süreç ölünce yüzey kaybolur. +- Noctalia'nın bildirimleriyle ve barıyla çakışmaz (layer z-sırası doğru). + +## 11. Kapsam dışı (v1) + +- X11, GNOME, KDE desteği +- Video / GIF kaydı +- OCR, bulut yükleme +- Kaydırmalı (scrolling) ekran görüntüsü