# إغلاق مشكلة DPI في Nexamas.UI والـShowcase

## السبب الحقيقي

كان `MASApplicationWindow.Geometry.Dpi` يعتمد في مسار النافذة الحية على نسبة حجم سطح OpenGL إلى حجم `SKGLControl`.
في تطبيق PerMonitorV2 تكون القيمتان أصلًا بوحدات device pixels، لذلك تبقى النسبة `1.0` حتى عند Windows Scale يساوي 125% أو 150%.

أصبح المصدر الأساسي الآن:

```vb
SKGLControl.DeviceDpi / 96.0F
```

مع إبقاء نسبة السطح/التحكم fallback فقط للسيناريوهات القديمة أو offscreen.

## ما تغير

- Nexamas.UI:
  - `MASSkiaHostThemeCoordinator` يقرأ `DeviceDpi` الحقيقي.
  - `MASSkiaHostRenderDriver` يبني ThemeContext من DPI الحقيقي ولا يعيد تثبيته على 1 من نسبة framebuffer.
  - بوابة مصدرية جديدة: `Per-monitor DeviceDpi source policy PASS.`
- Showcase:
  - Manifest صريح لـPerMonitorV2 مع fallback قديم `true/pm`.
  - Runtime report يسجل قيمتين مستقلتين:
    - `observedHostDeviceDpiScale`
    - `observedDpiScale` من Public API.
  - الاختبار يميز بين خطأ إعداد Windows وخطأ Nexamas.UI بدل رسالة عامة.

## أسرع اختبار أول

اضبط Windows Scale على 125% للشاشة التي يفتح عليها الـShowcase، ثم من جذر هذا الـworkspace:

```powershell
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass `
  -File .\Run-NexamasDpiClosure.ps1 `
  -ExpectedDpiScale 1.25 `
  -QuickProbeOnly
```

هذا يبني المكتبة، يشغل اختبارات المصدر، يحدث DLL الخارجية داخل الـShowcase، ثم يفحص صفحة DPI واحدة فقط.

بعد PASS شغل الإثبات الكامل لـ125% بدون إعادة بناء المكتبة:

```powershell
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass `
  -File .\Run-NexamasDpiClosure.ps1 `
  -ExpectedDpiScale 1.25 `
  -SkipLibraryRefresh
```

ثم غيّر Scale إلى 100% و150% وشغل الأمر نفسه بالقيمة المناسبة مع `-SkipLibraryRefresh`.

> يجب إعادة إثبات 100% أيضًا، لأن DLL تغيرت، وبوابة القبول ترفض جمع أدلة ناتجة عن DLL hashes مختلفة.
