Compare commits

..
Author SHA1 Message Date
aclist ae13dc9a89 chore: add newline 2026-11-05 21:14:27 +09:00
aclist d5706f969c change: use base class type 2026-11-05 21:09:42 +09:00
aclist 790e34b20c chore: clear typehinting errors 2026-11-05 21:09:10 +09:00
aclist 35230ae03f feat: capture composited screenshot 2026-11-05 21:08:52 +09:00
aclist 46117ecdda Merge pull request #507 from aclist/prerelease/7.0.0b29-patch-3
fix: add path out of loop
2026-10-26 19:25:32 +09:00
aclist 30119fec46 fix: add path out of loop 2026-10-26 19:24:42 +09:00
aclist ac01818549 Merge pull request #506 from aclist/prerelease/7.0.0b29-patch-2
fix: add /tmp to wizard
2026-10-26 19:21:40 +09:00
aclist d486712a4c fix: add /tmp to wizard 2026-10-26 19:20:17 +09:00
aclist d116702145 Merge pull request #505 from aclist/prerelease/7.0.0b29-patch-1
Prerelease/7.0.0b29 patch 1
2026-10-26 19:11:15 +09:00
aclist 5bee3614bd fix: whitelist /tmp 2026-10-26 19:09:50 +09:00
aclist c73b07991f change: abstract lock file path 2026-10-26 19:09:32 +09:00
aclist 199cd07982 Merge pull request #504 from aclist/prerelease/7.0.0b29
chore: bump version
2026-10-26 18:05:52 +09:00
10 changed files with 123 additions and 14 deletions

No files matched your search

+3 -3
View File
@@ -121,7 +121,7 @@ def load_steam_icon() -> None:
logger.critical(e)
def load_gui(version: str, is_debug: bool) -> None:
def build_gui(version: str, is_debug: bool) -> App | None:
lock = lock_acquire() # noqa
set_locale()
@@ -151,7 +151,7 @@ def load_gui(version: str, is_debug: bool) -> None:
wizard = SetupWizard(_is_steam_deck, XDG, xdg_paths)
if not wizard.is_setup_complete():
return
return None
setup_logger(XDG.debug)
with open(XDG.debug, "w") as f:
@@ -186,4 +186,4 @@ def load_gui(version: str, is_debug: bool) -> None:
print(boot.all_ok)
load_steam_icon()
app = App(prefs)
app.run(None)
return app
+1
View File
@@ -96,6 +96,7 @@ LOG_FILTERS = ("CRITICAL", "WARNING", "INFO", "DEBUG")
TMP_PATH = "/tmp"
TMP_TARBALL = "/tmp/dzgui.tar.gz"
TMP_EXE = "/tmp/dzgui/dzgui"
LOCK_FILE = "/tmp/dzgui.flock"
DAYZ_COMMUNITY_ROOT = "Missions"
+3 -2
View File
@@ -5,8 +5,9 @@ import sys
from pathlib import Path
from typing import TextIO
from dzgui.views.dialogs.early_alert import EarlyAlertDialog
from dzgui.const.constants import LOCK_FILE
from dzgui.util.strings import cannot_acquire_lock
from dzgui.views.dialogs.early_alert import EarlyAlertDialog
def lock_release(lock: TextIO) -> None:
@@ -15,7 +16,7 @@ def lock_release(lock: TextIO) -> None:
def lock_acquire() -> TextIO:
lockfile = Path("/tmp/dzgui.flock")
lockfile = Path(LOCK_FILE)
lock = open(lockfile, "w")
try:
fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+5 -2
View File
@@ -42,6 +42,9 @@ def main() -> None:
test_libgi_missing()
# NOTE: only import ligbirepository modules after the above check
from dzgui.app_init import load_gui
from dzgui.app_init import build_gui
load_gui(version, args.debug)
app = build_gui(version, args.debug)
if app is None:
sys.exit(0)
app.run(None)
+6 -2
View File
@@ -1,7 +1,7 @@
import logging
import subprocess
from dzgui.const.constants import APP_NAME, FLATPAK_APPID, GTK_APP_ID
from dzgui.const.constants import APP_NAME, FLATPAK_APPID, GTK_APP_ID, TMP_PATH
logger = logging.getLogger(APP_NAME)
@@ -18,7 +18,11 @@ def apply_overrides(xdg: dict[str, str]) -> None:
]
subprocess.run([*args], capture_output=True)
for path in xdg.values():
paths: list[str] = []
paths.extend([*xdg.values()])
paths.append(TMP_PATH)
for path in paths:
args = [
"flatpak",
"--user",
+80
View File
@@ -0,0 +1,80 @@
from pathlib import Path
from typing import cast, TYPE_CHECKING
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib # noqa E402
if TYPE_CHECKING:
from dzgui.controllers.mc import Controller
from dzgui.views.base import OuterWindow
from dzgui.views.mixins.context_mixin import ContextMixin
from gi.repository import GdkPixbuf
# TODO: randomize/mock PII distance values
class IdleScreenshot:
def __init__(
self, controller: "Controller", window: "OuterWindow", scrot_path: Path
) -> None:
self.window = window
self.controller = controller
self.scrot_path = scrot_path
clock = window.get_frame_clock()
if clock is None:
raise TypeError("Widget not realized, FrameClock not initialized")
clock.connect("after-paint", self.callback)
def callback(self, clock: Gdk.FrameClock) -> None:
GLib.timeout_add(1000, self.check_idle)
def check_idle(self) -> bool:
tv = self.controller.get_active_treeview()
loaded = tv.is_loaded()
if loaded is True:
self.emit_key_press(tv)
GLib.timeout_add(1000, self.save_and_quit)
return True
return False
def emit_key_press(self, widget: "ContextMixin") -> None:
window = widget.get_parent_window()
if window is None:
raise TypeError(f"Failed to find a valid parent window for {widget}")
event = Gdk.EventKey.new(Gdk.EventType.KEY_PRESS)
# NOTE: GTK introspection returns Gdk.Event type
event_key = cast(Gdk.EventKey, event)
event_key.keyval = Gdk.KEY_l
event_key.state = Gdk.ModifierType.CONTROL_MASK
event_key.window = window
event_key.time = Gdk.CURRENT_TIME
event_key.send_event = True
# TODO: suppress errors from synthetic key events
widget.present_menu(widget, event)
def save_and_quit(self) -> None:
self.save_pixbuf()
self.controller.save_res_and_quit()
def save_pixbuf(self) -> None:
pixbuf = self.capture_application()
if pixbuf:
pixbuf.savev(str(self.scrot_path), "png", [], [])
def capture_application(self) -> "GdkPixbuf.Pixbuf":
# NOTE: composited context menu over X11 window
root = Gdk.get_default_root_window()
xwindow = self.window.get_window()
if xwindow is None:
raise ValueError("Failed to get a valid X11 window")
index, x, y = xwindow.get_origin()
width, height = self.window.get_size()
application = Gdk.pixbuf_get_from_window(root, x, y, width, height)
if application is None:
raise ValueError("Failed to get a valid GdkPixbuf")
return application
+20 -2
View File
@@ -1,7 +1,7 @@
import logging
import signal
from typing import TYPE_CHECKING, Literal, Self
from typing import Any, Literal, Self, TYPE_CHECKING
from dzgui.const.constants import (
APP_NAME,
@@ -47,7 +47,7 @@ logger = logging.getLogger(APP_NAME)
class OuterWindow(Gtk.ApplicationWindow):
def __init__(self, app: Gtk.Application) -> None:
def __init__(self, app: "App") -> None:
super().__init__(
application=app, title=APP_NAME, border_width=10, icon_name=APP_NAME_LOWER
)
@@ -78,6 +78,15 @@ class OuterWindow(Gtk.ApplicationWindow):
MainController.loaded = True
MainController.populate_model(MainController.get_active_treeview())
try:
from dzgui.util.save_screenshot import IdleScreenshot
scrot = app.get_automation_param("screenshot_path")
self.fullscreen()
IdleScreenshot(MainController, self, scrot)
except KeyError:
pass
def _on_delete_event(self, window: "OuterWindow", event: Gdk.EventKey) -> None:
self.halt_proc_and_quit()
@@ -291,6 +300,14 @@ class App(ColorAwareApp, Gtk.Application): # type: ignore
self._setup_signals()
self.connect("activate", self._on_activate)
self.automation_params: dict[str, Any] = {}
def get_automation_param(self, key: str) -> Any:
return self.automation_params[key]
def set_automation_param(self, key: str, value: Any) -> None:
self.automation_params[key] = value
def _on_activate(self, app: Self) -> None:
self.win = OuterWindow(app)
@@ -331,4 +348,5 @@ class App(ColorAwareApp, Gtk.Application): # type: ignore
) -> None:
self.win.halt_proc_and_quit()
MainController = Controller()
+3
View File
@@ -14,6 +14,7 @@ from dzgui.const.constants import (
HERO_PATH,
FLATPAK_ROOT_PATH,
LEGACY_CONFIG_PATH,
TMP_PATH
)
from dzgui.const.boilerplate import config_boilerplate
from dzgui.const.endpoints import STEAM_API_SETUP
@@ -432,6 +433,8 @@ class FlatpakOverridePage(EnumeratedWizardPage):
store = Gtk.ListStore(str)
for path in xdg_paths.values():
store.append((str(path),))
store.append((TMP_PATH,))
tree = SimpleTree(store, wizard.tree_column)
tree.set_halign(Gtk.Align.CENTER)
+1 -3
View File
@@ -16,9 +16,7 @@ logger = logging.getLogger(APP_NAME)
class ContextMixin(TreeView):
def present_menu(
self,
widget: Gtk.Widget,
event: Gdk.EventButton | Gdk.EventKey,
self, widget: Gtk.Widget, event: Gdk.Event
) -> bool:
if self.menu is None:
+1
View File
@@ -3,6 +3,7 @@ from pathlib import Path
root = Path(__file__).resolve().parents[1]
def get_entrypoint() -> None:
p = root.joinpath("pyproject.toml")
with open(p, "rb") as f: