Files
imajviewer/lib/services/window_persistence.dart
Alhan 56ab4b5495 fix: coklu monitorde cascade dogru ekrani kullanir, .deb guncellendi
- window_persistence: onceki pencerenin bulundugu monitorun calisma alani kullanilir (getAllDisplays), primary degil
- viewer_screen: catchError donus tipi duzeltildi (analyze warning)
- dist/imajviewer_1.0.0_amd64.deb yeniden derlendi
2026-08-03 06:54:22 +03:00

106 lines
3.3 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:screen_retriever/screen_retriever.dart';
/// Persists and restores window position and size.
class WindowPersistence {
static File get _configFile {
String dir;
if (Platform.isWindows) {
dir = '${Platform.environment['APPDATA'] ?? Platform.environment['USERPROFILE'] ?? '.'}/imajviewer';
} else {
dir = '${Platform.environment['HOME'] ?? '/tmp'}/.config/imajviewer';
}
return File('$dir/window.json');
}
/// Save window rect synchronously (safe to call before destroy).
static void saveSync({
required Offset position,
required Size size,
}) {
final file = _configFile;
file.parent.createSync(recursive: true);
file.writeAsStringSync(jsonEncode({
'x': position.dx.toInt(),
'y': position.dy.toInt(),
'width': size.width.toInt(),
'height': size.height.toInt(),
}));
}
/// Restore saved window rect. Returns null if no saved config.
static ({Offset position, Size size})? restore() {
final file = _configFile;
if (!file.existsSync()) return null;
try {
final data = jsonDecode(file.readAsStringSync()) as Map<String, dynamic>;
final x = (data['x'] as num?)?.toDouble() ?? 0;
final y = (data['y'] as num?)?.toDouble() ?? 0;
final w = (data['width'] as num?)?.toDouble() ?? 1280;
final h = (data['height'] as num?)?.toDouble() ?? 800;
if (w < 200 || h < 200 || x < -1000 || y < -1000) return null;
return (
position: Offset(x, y),
size: Size(w, h),
);
} catch (_) {
return null;
}
}
/// Cascade: place new window to the right of the previous one.
/// Falls to the next row (row start) when it would overflow the screen,
/// and wraps to the top-left if the next row also overflows.
static Future<Offset> cascadePosition({
required Offset previousPosition,
required Size previousSize,
}) async {
try {
final displays = await screenRetriever.getAllDisplays();
// Önceki pencerenin bulunduğu monitörü bul (çoklu monitör desteği)
Display display = await screenRetriever.getPrimaryDisplay();
for (final d in displays) {
final pos = d.visiblePosition;
final size = d.visibleSize ?? d.size;
if (pos != null &&
previousPosition.dx >= pos.dx &&
previousPosition.dx < pos.dx + size.width &&
previousPosition.dy >= pos.dy &&
previousPosition.dy < pos.dy + size.height) {
display = d;
break;
}
}
final workLeft = display.visiblePosition?.dx ?? 0;
final workTop = display.visiblePosition?.dy ?? 0;
final workWidth = display.visibleSize?.width ?? display.size.width;
final workHeight = display.visibleSize?.height ?? display.size.height;
var x = previousPosition.dx + previousSize.width;
var y = previousPosition.dy;
if (x + previousSize.width > workLeft + workWidth) {
x = workLeft;
y = previousPosition.dy + previousSize.height;
}
if (y + previousSize.height > workTop + workHeight) {
x = workLeft;
y = workTop;
}
return Offset(x, y);
} catch (_) {
// Fallback: keep previous position if screen info is unavailable.
return previousPosition;
}
}
}