Files
imajviewer/docs/pencere-cascade-yerlesim.md
T
Alhan a65bdc152c feat: jfif/jpe/wbmp format destegi, pencere cascade yerlesimi, konum kaydi duzeltmesi
- file_handler/image_manager: jfif, jpe, wbmp uzantilari
- .desktop + install.sh MimeType: image/vnd.wap.wbmp eklendi
- main.dart: yeni pencere oncekinin saginda acilir (screen_retriever ile ekran tespiti)
- viewer_screen: 2sn polling kaldirildi, konum kaydi tek akisa oturtuldu (acilis + move/resize debounce + close senkron)
- dist/rebuild-deb.sh: .desktop kaynaktan kopyalanir (MimeType/StartupWMClass guncel kalir)
- .deb guncellendi, docs: session-2026-08-03 + plan dokumanlari
2026-08-03 06:44:57 +03:00

112 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pencere Cascade Yerleşimi Planı
> Tarih: 2026-08-03 · Değerlendirme + implementasyon planı (henüz kod değişikliği yapılmadı)
## 1. Sorun
imajViewer'a yeni bir resim açıldığında pencere **hep aynı koordinat ve boyutta** açılıyor (önceki pencerenin üstüne biniyor). İstenen davranış:
- Yeni pencere, önceki pencerenin **x + width** kadar sağına açılsın (yan yana)
- Ekrandan **taşacaksa** alt satıra, satır başından (x baştan) açılsın
Bu, Windows'un klasik "cascade windows" davranışının basit hali.
## 2. Mevcut Durum Analizi
### Pencere açılış akışı (`lib/main.dart`)
```
main(args)
→ WindowPersistence.restore() // window.json'dan son konum/boyut
→ windowOptions = WindowOptions(size: saved ?? 1280x800)
→ waitUntilReadyToShow:
saved varsa → setPosition(saved.position) + setSize(saved.size)
saved yoksa → center()
→ runApp(ImajViewerApp(initialFiles: args))
```
### Konum kaydetme akışı (`lib/screens/viewer_screen.dart` + `lib/services/window_persistence.dart`)
- `_startPolling()`: 2 saniyede bir `windowManager.getBounds()` → `WindowPersistence.saveSync()` → `~/.config/imajviewer/window.json` (Linux) / `%APPDATA%/imajviewer/window.json` (Windows)
- `onWindowEvent` (move/resize/close) → debounce'lu `_doSave()`
### Sorunun kökü
- Her yeni pencere `window.json`'daki **son kaydedilen** konumu okuyor → aynı yere açılıyor
- Cascade mantığı yok; ekran genişliği bilgisi hiç sorgulanmıyor
## 3. Teknik Araştırma (doğrulandı)
### window_manager 0.4.3 (mevcut bağımlılık)
- `setPosition`, `setSize`, `getBounds`, `getPosition`, `getSize`, `center()` → var
- **Ekran/display API'si → YOK** (getScreen/getPrimaryDisplay yok)
### window_manager 0.5.2 (güncel)
- Ekran API'si yine yok — `screen_retriever`'ı bağımlılık olarak içeriyor ama expose etmiyor
### screen_retriever 0.2.2 (pub.dev, window_manager'ın zaten bağımlısı)
- `ScreenRetriever.instance.getPrimaryDisplay()` → `Display`
- `getAllDisplays()` → `List<Display>`
- `Display` alanları:
- `size` (ekran tam boyutu, logical px)
- `visiblePosition` (Offset — çalışma alanı başlangıcı)
- `visibleSize` (Size — görev çubuğu hariç çalışma alanı)
- `scaleFactor`
- Linux (X11) + Windows desteği var
**Karar: `screen_retriever` doğrudan bağımlılık olarak eklenir** (window_manager sürümü değişmez).
## 4. Önerilen Algoritma
`main.dart`'ta, `windowOptions` oluşturulmadan önce:
```
1. saved = WindowPersistence.restore()
2. display = await ScreenRetriever.instance.getPrimaryDisplay()
workArea = display.visiblePosition + display.visibleSize (yoksa display.size)
3. Eğer saved != null:
newX = saved.x + saved.width // önceki pencerenin sağına
newY = saved.y
// Yatay taşma → alt satıra, satır başına
if (newX + pencereGenişliği > workArea.right):
newX = workArea.left
newY = saved.y + saved.height
// Dikey taşma da varsa → en başa sar (0,0)
if (newY + pencereYüksekliği > workArea.bottom):
newX = workArea.left
newY = workArea.top
position = Offset(newX, newY)
4. saved yoksa → center() (mevcut davranış)
```
### Örnek
- Ekran 1920×1080, pencere 1280×800, önceki pencere (100, 50)
- 1. yeni: (1380, 50) — yan yana ✓
- 2. yeni: (100+1280*2 = hesaplanır) → 1380+1280=2660 > 1920 → (0, 850) — alt satır başı ✓
> Not: `saved` her 2 saniyede bir güncellendiği için "önceki pencere" = en son kaydedilmiş konum. Bu, en son açılan pencerenin konumu olur — istenen davranışla uyumlu.
## 5. Yapılacaklar (sıralı)
1. [ ] `pubspec.yaml` → `screen_retriever: ^0.2.2` ekle, `flutter pub get`
2. [ ] `lib/main.dart` → cascade hesabı ekle (yeni bir servis fonksiyonuna taşınabilir)
3. [ ] `lib/services/window_persistence.dart` → `restore()` dışında, cascade hesabı için yardımcı fonksiyon:
- `static Future<Offset?> cascadePosition({required Size windowSize})` (opsiyonel, temizlik için)
4. [ ] Ekran boyutu alınamazsa (hata / çoklu monitör) → mevcut davranışa düş (saved veya center)
5. [ ] Test: ardışık 3-4 resim aç → yan yana dizilim + taşınca alt satır
## 6. Riskler / Açık Sorular
- **Çoklu monitör:** `getPrimaryDisplay` birincil ekranı verir. İmleç hangi ekrandaysa oraya açılsın mı? (başlangıç: primary)
- **Pencere kapatılıp yenisi açılırsa:** `window.json` son kapanan pencerenin konumunu tutar; yeni pencere onun yanına açılır — boşluk oluşabilir, kabul edilebilir
- **Tam ekran / maximize durumu:** saved boyut maximize ise cascade hesabı yine de eski boyutla yapılır; `window.json` sadece normal durumda yazıldığı için risk düşük
- **Pencere ekrandan tamamen dışarıdaysa:** `restore()` zaten `x < -1000 || y < -1000` guard'ı var (window_persistence.dart:44) — yine de sağlamlaştırılabilir
## 7. Kabul Kriterleri
- [ ] Ardışık 2 pencere: ikincisi birincinin hemen sağında
- [ ] Yatay taşma: yeni pencere alt satıra, satır başından başlar
- [ ] İlk açılışta (kayıt yok) pencere yine ortalanır
- [ ] Pencere boyutu/konumu kaydetme davranışı bozulmaz
- [ ] Linux ve Windows'ta çalışır (screen_retriever her ikisini destekliyor)