PyWebWinUI3 1.2.5__tar.gz → 1.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pywebwinui3-1.2.5/PyWebWinUI3.egg-info → pywebwinui3-1.2.6}/PKG-INFO +1 -1
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6/PyWebWinUI3.egg-info}/PKG-INFO +1 -1
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/__init__.py +1 -1
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/core.py +77 -134
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/LICENSE +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/MANIFEST.in +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/NOTICE +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/PyWebWinUI3.egg-info/SOURCES.txt +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/PyWebWinUI3.egg-info/dependency_links.txt +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/PyWebWinUI3.egg-info/requires.txt +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/PyWebWinUI3.egg-info/top_level.txt +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/README.md +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pyproject.toml +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/event.py +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/type.py +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/util.py +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.0.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.1.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.10.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.11.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.12.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.13.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.14.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.15.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.16.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.17.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.18.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.19.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.2.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.20.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.21.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.22.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.23.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.24.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.25.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.26.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.27.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.28.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.29.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.3.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.30.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.31.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.32.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.33.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.34.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.35.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.36.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.37.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.38.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.39.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.4.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.40.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.41.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.42.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.43.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.44.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.45.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.46.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.47.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.48.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.49.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.5.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.50.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.51.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.52.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.53.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.54.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.55.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.56.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.57.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.58.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.59.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.6.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.60.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.61.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.62.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.63.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.64.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.65.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.66.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.67.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.68.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.69.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.7.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.70.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.71.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.72.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.73.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.74.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.75.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.76.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.77.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.78.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.79.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.8.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.80.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.81.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.82.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.83.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.84.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.85.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.86.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.87.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.88.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.89.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.9.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.90.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.91.woff2 +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/Variable-dynamic-subset.min.css +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/SegoeFluentIcons.ttf +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/env.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/assets/2.YxEoeVwz.css +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/BQhJK30C.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/CUVCm1Gs.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/Cm7LUZmC.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/DenSxjN0.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/DoXe6v-Z.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/GYDIE8Th.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/H3JtIqnJ.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/chunks/IoyDzpMI.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/entry/app.Cls2e-Vs.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/entry/start.D4vOV_ze.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/nodes/0.DieTLBBL.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/nodes/1.DCNy7Bof.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/nodes/2.D_z1tXgZ.js +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/version.json +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/index.html +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/requirements.txt +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/setup.cfg +0 -0
- {pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/setup.py +0 -0
|
@@ -4,16 +4,10 @@ import ctypes
|
|
|
4
4
|
import importlib
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
-
import mimetypes
|
|
8
|
-
import os
|
|
9
|
-
import re
|
|
10
|
-
import shutil
|
|
11
7
|
import sys
|
|
12
8
|
import threading
|
|
13
|
-
from http import HTTPStatus
|
|
14
|
-
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
15
9
|
from pathlib import Path
|
|
16
|
-
from urllib.parse import
|
|
10
|
+
from urllib.parse import urlparse, urlunparse
|
|
17
11
|
from ctypes import wintypes
|
|
18
12
|
|
|
19
13
|
import webview
|
|
@@ -32,6 +26,10 @@ DEFAULT_WINDOW_MIN_WIDTH = 100
|
|
|
32
26
|
DEFAULT_WINDOW_MIN_HEIGHT = 100
|
|
33
27
|
|
|
34
28
|
|
|
29
|
+
def _virtual_host_origin(root_name: str, suffix: str) -> str:
|
|
30
|
+
return f"https://{root_name}.{suffix}"
|
|
31
|
+
|
|
32
|
+
|
|
35
33
|
class _Point(ctypes.Structure):
|
|
36
34
|
_fields_ = [
|
|
37
35
|
("x", ctypes.c_long),
|
|
@@ -119,62 +117,6 @@ def _apply_menu_theme_support(theme: str | None, hwnd: int | None = None):
|
|
|
119
117
|
return False
|
|
120
118
|
|
|
121
119
|
|
|
122
|
-
def _default_ui_origin_host(title: str) -> str:
|
|
123
|
-
slug = re.sub(r"[^a-z0-9]+", "-", str(title).casefold()).strip("-")
|
|
124
|
-
if not slug:
|
|
125
|
-
slug = "app"
|
|
126
|
-
slug = re.sub(r"-{2,}", "-", slug)[:48].strip("-")
|
|
127
|
-
if not slug:
|
|
128
|
-
slug = "app"
|
|
129
|
-
return f"{slug}.local"
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
class _UiHttpServer(HTTPServer):
|
|
133
|
-
allow_reuse_address = True
|
|
134
|
-
|
|
135
|
-
def __init__(self, server_address, request_handler_class, main: "MainWindow"):
|
|
136
|
-
super().__init__(server_address, request_handler_class)
|
|
137
|
-
self.main = main
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
class _UiRequestHandler(BaseHTTPRequestHandler):
|
|
141
|
-
server: _UiHttpServer
|
|
142
|
-
|
|
143
|
-
def do_GET(self):
|
|
144
|
-
try:
|
|
145
|
-
path = self.server.main._resolve_server_path(urlparse(self.path).path)
|
|
146
|
-
if path is None or not path.is_file():
|
|
147
|
-
self._send_error("Not found.", HTTPStatus.NOT_FOUND)
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
content_type = mimetypes.guess_type(path.name)[0] or "application/octet-stream"
|
|
151
|
-
self.send_response(HTTPStatus.OK)
|
|
152
|
-
self._send_common_headers(content_type)
|
|
153
|
-
self.send_header("Content-Length", str(path.stat().st_size))
|
|
154
|
-
self.end_headers()
|
|
155
|
-
with path.open("rb") as source:
|
|
156
|
-
shutil.copyfileobj(source, self.wfile, length=64 * 1024)
|
|
157
|
-
except Exception:
|
|
158
|
-
core_logger.debug("Failed to serve UI asset", exc_info=True)
|
|
159
|
-
self._send_error("Failed to serve UI asset.", HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
160
|
-
|
|
161
|
-
def log_message(self, format, *args):
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
def _send_error(self, message: str, status: HTTPStatus):
|
|
165
|
-
body = message.encode("utf-8")
|
|
166
|
-
self.send_response(status)
|
|
167
|
-
self._send_common_headers("text/plain; charset=utf-8")
|
|
168
|
-
self.send_header("Content-Length", str(len(body)))
|
|
169
|
-
self.end_headers()
|
|
170
|
-
self.wfile.write(body)
|
|
171
|
-
|
|
172
|
-
def _send_common_headers(self, content_type: str):
|
|
173
|
-
self.send_header("Content-Type", content_type)
|
|
174
|
-
self.send_header("Cache-Control", "no-store")
|
|
175
|
-
self.send_header("Permissions-Policy", "display-capture=*")
|
|
176
|
-
|
|
177
|
-
|
|
178
120
|
class _JsApi:
|
|
179
121
|
def _init(self, main:MainWindow):
|
|
180
122
|
self.init = main._init_payload
|
|
@@ -200,6 +142,8 @@ class WindowEvents:
|
|
|
200
142
|
|
|
201
143
|
|
|
202
144
|
class MainWindow:
|
|
145
|
+
virtual_host_suffix = "pywebwinui"
|
|
146
|
+
|
|
203
147
|
def __init__(self, title: str, icon: str | None = None):
|
|
204
148
|
self.rootPath = Path(sys._getframe(1).f_code.co_filename).parent.resolve()
|
|
205
149
|
self.packagePath = Path(__file__).parent.resolve() / "web"
|
|
@@ -218,11 +162,8 @@ class MainWindow:
|
|
|
218
162
|
self._pending_sync: dict[str, object] = {}
|
|
219
163
|
self._sync_event = threading.Event()
|
|
220
164
|
self._sync_thread: threading.Thread | None = None
|
|
221
|
-
self.
|
|
222
|
-
self.
|
|
223
|
-
self._ui_origin = ""
|
|
224
|
-
self._ui_bind_host = "127.0.0.1"
|
|
225
|
-
self._ui_origin_host = getattr(self, "ui_origin_host", _default_ui_origin_host(title))
|
|
165
|
+
self._virtual_host_handlers: dict[str, object] = {}
|
|
166
|
+
self._ui_origin = _virtual_host_origin("package", self.virtual_host_suffix)
|
|
226
167
|
self._resource_roots: list[tuple[str, Path]] = [
|
|
227
168
|
("root", self.rootPath),
|
|
228
169
|
("package", self.packagePath),
|
|
@@ -242,13 +183,11 @@ class MainWindow:
|
|
|
242
183
|
}
|
|
243
184
|
)
|
|
244
185
|
self.values.sync = self.queue_sync_value
|
|
245
|
-
self._start_ui_server()
|
|
246
|
-
self._configure_webview2_origin_identity()
|
|
247
186
|
_apply_menu_theme_support(self.values.get("system_theme"))
|
|
248
187
|
|
|
249
188
|
self._window = webview.create_window(
|
|
250
189
|
self.values.get("system_title", self._title),
|
|
251
|
-
|
|
190
|
+
"about:blank",
|
|
252
191
|
js_api=self.api,
|
|
253
192
|
background_color="#202020",
|
|
254
193
|
text_select=True,
|
|
@@ -384,82 +323,86 @@ class MainWindow:
|
|
|
384
323
|
raise FileNotFoundError(f"Frontend entry not found: {entry}")
|
|
385
324
|
return entry
|
|
386
325
|
|
|
387
|
-
def
|
|
388
|
-
|
|
389
|
-
self.
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if self._ui_origin_host == self._ui_bind_host:
|
|
395
|
-
return
|
|
326
|
+
def _resource_url(self, path: Path) -> str:
|
|
327
|
+
path = path.resolve()
|
|
328
|
+
for name, base_path in sorted(self._resource_roots, key=lambda item: len(item[1].parts), reverse=True):
|
|
329
|
+
try:
|
|
330
|
+
relative = path.relative_to(base_path)
|
|
331
|
+
except ValueError:
|
|
332
|
+
continue
|
|
396
333
|
|
|
397
|
-
|
|
398
|
-
if not parsed.scheme or parsed.port is None:
|
|
399
|
-
return
|
|
334
|
+
return f"{_virtual_host_origin(name, self.virtual_host_suffix)}/{relative.as_posix()}"
|
|
400
335
|
|
|
401
|
-
|
|
402
|
-
f'--host-resolver-rules="MAP {self._ui_origin_host} {self._ui_bind_host}"',
|
|
403
|
-
f"--unsafely-treat-insecure-origin-as-secure={parsed.scheme}://{self._ui_origin_host}:{parsed.port}",
|
|
404
|
-
]
|
|
405
|
-
existing = os.environ.get("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "").strip()
|
|
406
|
-
missing = [arg for arg in required_args if arg not in existing]
|
|
407
|
-
if missing:
|
|
408
|
-
os.environ["WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS"] = " ".join(
|
|
409
|
-
[value for value in [existing, *missing] if value]
|
|
410
|
-
).strip()
|
|
411
|
-
|
|
412
|
-
def _stop_ui_server(self):
|
|
413
|
-
if self._ui_server is None:
|
|
414
|
-
return
|
|
415
|
-
try:
|
|
416
|
-
self._ui_server.shutdown()
|
|
417
|
-
self._ui_server.server_close()
|
|
418
|
-
except Exception:
|
|
419
|
-
core_logger.debug("Failed to stop UI server", exc_info=True)
|
|
420
|
-
finally:
|
|
421
|
-
self._ui_server = None
|
|
422
|
-
self._ui_server_thread = None
|
|
423
|
-
|
|
424
|
-
def _resolve_path_under(self, base_path: Path, relative_path: str) -> Path | None:
|
|
425
|
-
candidate = (base_path / relative_path).resolve()
|
|
426
|
-
try:
|
|
427
|
-
candidate.relative_to(base_path)
|
|
428
|
-
except ValueError:
|
|
429
|
-
return None
|
|
430
|
-
return candidate
|
|
336
|
+
raise ValueError(f"Path is outside of registered resource roots: {path}")
|
|
431
337
|
|
|
432
|
-
def
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
338
|
+
def _map_virtual_hosts(self, core_webview):
|
|
339
|
+
parameter = core_webview.GetType().GetMethod("SetVirtualHostNameToFolderMapping").GetParameters()[2]
|
|
340
|
+
access_kind = next(
|
|
341
|
+
value for value in parameter.ParameterType.GetEnumValues()
|
|
342
|
+
if str(value) == "DenyCors"
|
|
343
|
+
)
|
|
436
344
|
|
|
437
345
|
for name, base_path in self._resource_roots:
|
|
438
|
-
|
|
439
|
-
|
|
346
|
+
core_webview.SetVirtualHostNameToFolderMapping(
|
|
347
|
+
f"{name}.{self.virtual_host_suffix}",
|
|
348
|
+
str(base_path),
|
|
349
|
+
access_kind,
|
|
350
|
+
)
|
|
440
351
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
352
|
+
def _configure_virtual_host_window(self, window, target_url: str, *, show: bool = False):
|
|
353
|
+
native = getattr(window, "native", None)
|
|
354
|
+
browser = getattr(native, "browser", None)
|
|
355
|
+
webview_control = getattr(browser, "webview", None)
|
|
356
|
+
if native is None or browser is None or webview_control is None:
|
|
357
|
+
core_logger.debug("WebView2 is unavailable for virtual host mapping")
|
|
358
|
+
return
|
|
444
359
|
|
|
445
|
-
|
|
360
|
+
def load_mapped_url(core_webview):
|
|
361
|
+
self._map_virtual_hosts(core_webview)
|
|
362
|
+
browser.load_url(target_url)
|
|
363
|
+
if show:
|
|
364
|
+
window.show()
|
|
446
365
|
|
|
447
|
-
|
|
448
|
-
path = path.resolve()
|
|
449
|
-
for name, base_path in self._resource_roots:
|
|
366
|
+
def on_initialized(_, args):
|
|
450
367
|
try:
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
368
|
+
if not args.IsSuccess:
|
|
369
|
+
core_logger.error("WebView2 initialization failed before virtual host mapping")
|
|
370
|
+
return
|
|
371
|
+
load_mapped_url(webview_control.CoreWebView2)
|
|
372
|
+
except Exception:
|
|
373
|
+
core_logger.error("Failed to configure WebView2 virtual host mapping", exc_info=True)
|
|
374
|
+
finally:
|
|
375
|
+
try:
|
|
376
|
+
webview_control.CoreWebView2InitializationCompleted -= on_initialized
|
|
377
|
+
except Exception:
|
|
378
|
+
pass
|
|
379
|
+
self._virtual_host_handlers.pop(window.uid, None)
|
|
454
380
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
381
|
+
def configure():
|
|
382
|
+
try:
|
|
383
|
+
core_webview = webview_control.CoreWebView2
|
|
384
|
+
except Exception:
|
|
385
|
+
core_webview = None
|
|
386
|
+
if core_webview is not None:
|
|
387
|
+
load_mapped_url(core_webview)
|
|
388
|
+
return
|
|
389
|
+
self._virtual_host_handlers[window.uid] = on_initialized
|
|
390
|
+
webview_control.CoreWebView2InitializationCompleted += on_initialized
|
|
458
391
|
|
|
459
|
-
|
|
392
|
+
try:
|
|
393
|
+
self._invoke_native_sync(native, configure)
|
|
394
|
+
except Exception:
|
|
395
|
+
core_logger.error("Failed to configure WebView2 virtual host mapping", exc_info=True)
|
|
396
|
+
|
|
397
|
+
def createResourceWindow(self, title: str, url: str, **kwargs):
|
|
398
|
+
keep_hidden = bool(kwargs.pop("hidden", False))
|
|
399
|
+
window = webview.create_window(title, "about:blank", hidden=True, **kwargs)
|
|
400
|
+
self._configure_virtual_host_window(window, url, show=not keep_hidden)
|
|
401
|
+
return window
|
|
460
402
|
|
|
461
403
|
def _before_show(self):
|
|
462
404
|
try:
|
|
405
|
+
self._configure_virtual_host_window(self._window, self._resource_url(self._entry_path()))
|
|
463
406
|
hwnd = self._window.native.Handle.ToInt64()
|
|
464
407
|
_apply_menu_theme_support(self.values.get("system_theme"), hwnd)
|
|
465
408
|
if self._defer_window_chrome:
|
|
@@ -604,7 +547,7 @@ class MainWindow:
|
|
|
604
547
|
with self._sync_lock:
|
|
605
548
|
self._pending_sync.clear()
|
|
606
549
|
self._sync_event.set()
|
|
607
|
-
self.
|
|
550
|
+
self._virtual_host_handlers.clear()
|
|
608
551
|
self.events.closed.set()
|
|
609
552
|
|
|
610
553
|
def _dispatch_sync_values(self, values: dict[str, object]):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.0.woff2
RENAMED
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.1.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.2.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.3.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.4.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.5.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.6.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.7.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.8.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/PretendardVariable.subset.9.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/Pretendard/Variable-dynamic-subset.min.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/assets/2.YxEoeVwz.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/entry/app.Cls2e-Vs.js
RENAMED
|
File without changes
|
{pywebwinui3-1.2.5 → pywebwinui3-1.2.6}/pywebwinui3/web/_app/immutable/entry/start.D4vOV_ze.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|