Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4db5514
adding macos support
sedataym Sep 25, 2026
ef55ad8
Merge branch 'main' into feature/macos_support_1
sedataym Oct 23, 2026
30d4dd3
macos fix
sedataym Oct 23, 2026
d6cb3e7
macos overlay problem fix
sedataym Oct 23, 2026
e8279d7
test: record portable baseline and isolate native desktop acceptance
sedataym Oct 23, 2026
ea48730
build: unify dependency declarations and version metadata
sedataym Oct 23, 2026
ecaf7c9
refactor: install application as usta package with bundled resources
sedataym Oct 23, 2026
92747a6
refactor: migrate settings and presets to atomic versioned storage
sedataym Oct 23, 2026
e6ce413
refactor: make bootstrap and logging explicit
sedataym Oct 23, 2026
ef9818f
refactor: unify engine contracts and isolate backend compatibility
sedataym Oct 23, 2026
32949f3
fix: own pipeline jobs and suppress stale results without blocking UI
sedataym Oct 23, 2026
8c1557b
refactor: separate views, settings presentation and capture controllers
sedataym Oct 23, 2026
7ba74cf
fix: bound IPC broadcasts and isolate capture workspaces
sedataym Oct 23, 2026
b58f15a
chore: standardize style, translations and contributor documentation
sedataym Oct 23, 2026
61f55ea
ci: verify distributions, platform contracts and native acceptance
sedataym Oct 23, 2026
bb131d2
fix: preserve recovered settings and close final review regressions
sedataym Oct 23, 2026
99a3f42
fix: clarify macOS shortcut permission and use system fixed font
sedataym Oct 23, 2026
ed18150
fix
sedataym Oct 23, 2026
5441d81
overlay fix
sedataym Oct 23, 2026
2212e1e
color dialog error fix
sedataym Oct 27, 2026
b7c6ecc
add tray menu
sedataym Oct 27, 2026
3c17759
tab panel fix
sedataym Oct 27, 2026
00195cb
macos system access settings
sedataym Oct 27, 2026
5ed79ef
dmg self signed settings
sedataym Oct 27, 2026
61ec5e7
platform dependency fix
sedataym Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Bug report
description: Report a reproducible application problem
body:
- type: textarea
id: environment
attributes:
label: Environment
description: OS/version, CPU architecture, desktop/session, Python, Qt and selected OCR/translation/capture engines.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps and expected/actual behavior
description: Include relevant diagnostics, but remove API keys and private screen content.
validations:
required: true
7 changes: 7 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Describe the user-visible problem and resulting behavior.

Validation performed (commands and results):

Linux/macOS native acceptance performed or still unavailable:

Settings/preset migration or packaging impact, if applicable:
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Checks
on:
push:
pull_request:
jobs:
portable:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14]
python: ['3.10', '3.14']
runs-on: ${{ matrix.os }}
env:
QT_QPA_PLATFORM: offscreen
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libegl1 libopengl0 libxkbcommon0
- run: python -m pip install --upgrade pip
- run: python -m pip install -e '.[dev]'
- run: ruff check .
- run: ruff format --check .
- run: mypy
- run: python -m pip check
- run: python -m unittest discover -s tests -v
27 changes: 27 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Package
on:
push:
pull_request:
jobs:
artifacts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.14'
- run: sudo apt-get update && sudo apt-get install -y libegl1 libopengl0 libxkbcommon0
- run: python -m pip install '.[dev]'
- run: python -m build
- run: USTA_REQUIRE_ARTIFACTS=1 python -m unittest tests.packaging.test_artifacts -v
- name: Install wheel into a clean environment
run: |
python -m venv /tmp/usta-wheel-test
/tmp/usta-wheel-test/bin/python -m pip install dist/*.whl
cd /tmp
/tmp/usta-wheel-test/bin/python -c "from importlib.metadata import distribution; from usta.resource_paths import resource_path; import usta.main; assert resource_path('resources/translations/tr/LC_MESSAGES/messages.mo').is_file(); assert any(e.name == 'usta' for e in distribution('usta').entry_points)"
/tmp/usta-wheel-test/bin/python -m pip check
- uses: actions/upload-artifact@v4
with:
name: python-distributions
path: dist/*
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,16 @@ target/

#Ipython Notebook
.ipynb_checkpoints

# Local environments and tooling
.venv/
.ruff_cache/
.mypy_cache/
.pytest_cache/
.superpowers/

# Local native/runtime scratch
/:memory:.ses

# Reusable macOS build recipe
!packaging/macos/usta.spec
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

## Unreleased

- Package the application as `usta`, including OCR models and translation catalogs.
- Consolidate dependency/version declarations and optional Paddle support.
- Preserve legacy settings/presets while migrating to atomic, versioned JSON.
- Separate tab widgets, window lifecycle, settings presentation and capture controllers.
- Own capture and translation jobs explicitly and invalidate stale results after stop/configuration changes.
- Bound IPC queues and isolate temporary capture files per session.
- Add regression tests, packaging checks, style/type checks and contributor documentation.

Linux KDE/GNOME and macOS native behavior remain required release acceptance checks; see `docs/compatibility.md` for actual verification status.
31 changes: 31 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Contributing to USTA

USTA uses Python and PySide6. Keep user-visible behavior and Linux/macOS native window rules stable when refactoring.

## Development setup

Create a virtual environment (Linux Portal users need system PyGObject/GStreamer packages and `--system-site-packages`), then run:

```sh
python -m pip install -e '.[dev]'
python run.py
```

Paddle is opt-in: `python -m pip install -e '.[paddle]'`. Its native runtime must be available for your interpreter/architecture. Existing default OCR engines remain installed by the standard setup.

## Before opening a pull request

```sh
ruff check .
ruff format --check .
mypy
QT_QPA_PLATFORM=offscreen python -m unittest discover -s tests -v
python -m build
python -m pip check
```

Do not use real translation APIs, private screenshots, or automatic model downloads in unit tests. Regression tests should reproduce a specific user-visible failure. Native desktop tests are opt-in; see [testing](docs/testing.md). Report skipped or unavailable platform checks honestly.

Keep each change focused. Separate mechanical formatting/moves from behavior fixes. Update documentation and translations when changing user-facing text. Never commit API keys, local settings, or screen content.

See [architecture](docs/architecture.md), [development](docs/development.md), and [compatibility](docs/compatibility.md) for module boundaries and release checks.
7 changes: 7 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include LICENSE README.md CONTRIBUTING.md CHANGELOG.md requirements*.txt babel.cfg
recursive-include docs *.md
recursive-include tests *.py
recursive-include packaging *
recursive-include scripts *.sh
recursive-include src/usta/resources *.onnx *.po *.mo
recursive-include src/usta/ui/assets *.png *.svg
55 changes: 52 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# USTA (Universal Screen Translator Application)
Real-time OCR translation for games, videos and desktop.

[![USTA demo cover](src/ui/assets/usta_cover.png)](https://www.youtube.com/watch?v=jGHMmDznum8)
[![USTA demo cover](src/usta/ui/assets/usta_cover.png)](https://www.youtube.com/watch?v=jGHMmDznum8)

By "sniping" a specific area of your screen, USTA continuously monitors that region, extracts text using OCR (Optical Character Recognition), and overlays the translated text instantly, making it perfect for playing untranslated games or watching foreign media.

> **Note:** Current version is optimized for **KDE Plasma and GNOME (Wayland)** using **xcb** mode. Future versions will expand compatibility.
> **Platforms:** Linux KDE Plasma/GNOME (Wayland with xcb) and macOS. See [compatibility and validation status](docs/compatibility.md).

## 🚀 Key Features

Expand Down Expand Up @@ -54,7 +54,7 @@ While currently focused on KDE/Linux, support for the following is planned:
- [ ] **Native Linux Packaging:** Distribution via `.deb` (Debian/Ubuntu), AUR (Arch Linux), and **Flatpak**.
- [ ] **Other Linux DEs:** Full native Wayland support without xcb.
- [ ] **Windows Support:** Integration with Windows-native capture and OCR APIs.
- [ ] **macOS Support:** Support for macOS native APIs and capture systems.
- [x] **macOS Support:** Native capture, Apple Vision OCR, fullscreen overlays and global shortcuts.

---

Expand Down Expand Up @@ -207,6 +207,28 @@ instead.

---

### Apple Vision OCR on macOS

On macOS, select **Apple Vision** in the **OCR Engine** menu to recognize text
locally using Apple's Vision framework. Select the source language in the
translation settings, or choose **Auto** for automatic language detection.
Language availability depends on your macOS version; unsupported selections use
automatic detection with a warning in the console.

The macOS dependency is included in `requirements.txt`. To add it to an existing
installation, run `.venv/bin/python -m pip install 'pyobjc-framework-Vision>=10.0'`
and restart USTA. Apple Vision does not appear in the engine list on Linux or Windows.

## macOS global shortcut permissions

If startup reports missing Accessibility permission, open **System Settings → Privacy & Security → Accessibility** and allow the app/terminal running USTA (or the Python app shown by macOS). Restart USTA after granting access. The log includes the Python executable to help identify the launcher. USTA cannot grant this permission itself; screen capture/OCR and global keyboard access are separate capabilities.

USTA reports missing Accessibility permission once per denied period and preserves event-tap startup, since macOS Input Monitoring permission can be separate. Linux shortcut behavior is unchanged. See [Apple's Accessibility permission guide](https://support.apple.com/guide/mac-help/mh43185/mac).

## Development and contributions

See [CONTRIBUTING](CONTRIBUTING.md) for development setup, tests and code standards, [architecture](docs/architecture.md) for module boundaries, and [testing](docs/testing.md) for native desktop checks. Install optional Paddle support with `pip install '.[paddle]'` when its native runtime is available.

## 🛠️ Tech Stack
* **GUI:** PySide6
* **OCR:** pytesseract, easyocr
Expand All @@ -226,3 +248,30 @@ USTA may process visible screen content, interact with local desktop capture mec
The developers, maintainers, contributors, and distributors of USTA shall not be held liable for any direct, indirect, incidental, consequential, special, exemplary, or punitive damages resulting from the application, including damages caused by user configuration, third-party services, external integrations, dependency behavior, system incompatibilities, or any other circumstance connected to the use of the software.

If you do not accept full responsibility for the risks described above, you should not install, run, or use USTA.

## System tray and window shortcuts

At startup, a balloon points to the tray icon for ten seconds to show where the USTA menu is. It does not require notification permission or take keyboard focus.

The USTA tray menu lets you show/hide the main window and translation overlay
independently, start or stop OCR, select a capture region, select a temporary
region, and quit. Start is disabled while OCR is running; Stop is disabled while
OCR is stopped.
Temporary region selection is available while OCR is running and restores the
original region after ten seconds. Hiding either window keeps OCR and translation
running. Shown windows stay above other applications, retaining the existing
macOS fullscreen overlay behavior and Linux window-manager support.

The **Show/hide main window** shortcut (default **Shift+Alt+M**) uses the same action
as the tray menu. Existing saved shortcut combinations are retained. Closing the
main window with **X** hides it; use **Quit Application** in the tray menu to exit.

On Linux, a desktop with system tray support is required to display the icon
(some GNOME configurations need a tray extension). If no tray is available, **X**
exits normally so the application cannot become inaccessible in the background.

## macOS application package

See [Building and installing the macOS DMG](docs/macos-dmg.md) for the Apple Silicon build recipe, bundled engines, permissions and signing details.

Apple-trusted distribution DMGs require a Developer ID Application identity and notarization. Free persistent self-signed builds use `USTA_SIGNING_MODE=self-signed` with the pinned Keychain certificate and produce `-selfsigned.dmg`; they are not Apple-notarized. The build refuses silent ad-hoc fallback; explicit local builds use `USTA_ALLOW_ADHOC=1` and a `-dev.dmg` filename. See [macOS signing setup](docs/macos-dmg.md).
13 changes: 6 additions & 7 deletions docs/appimage.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
# USTA AppImage Packaging

This document describes the AppImage packaging strategy for USTA without changing the
application source code.
This document describes the AppImage packaging strategy for USTA using the installed application package.

## Strategy

USTA is a Python/PySide6 application with the runtime entry point declared in
`pyproject.toml` as `usta = "src.main:main"`. The AppImage build creates an
`pyproject.toml` as `usta = "usta.main:main"`. The AppImage build creates an
AppDir containing:

- the installed USTA Python package,
- Python wheel dependencies from `requirements.txt`,
- the application icon from `src/ui/assets/usta.png`,
- Python dependencies from the project metadata,
- the application icon from `src/usta/ui/assets/usta.png`,
- a desktop entry from `packaging/appimage/usta.desktop`,
- an `AppRun` wrapper from `packaging/appimage/AppRun`.

The wrapper starts the app with `python3 -m src.main` and sets `QT_QPA_PLATFORM=xcb`
The wrapper starts the app with `python3 -m usta.main` and sets `QT_QPA_PLATFORM=xcb`
unless the user already provided a different value.

## Why some dependencies remain system dependencies
Expand Down Expand Up @@ -139,5 +138,5 @@ Validate the following:

## Notes

This build path avoids changes to application modules such as `src/main.py` and keeps
This build path avoids changes to application modules such as `src/usta/main.py` and keeps
all AppImage-specific behavior in `packaging/appimage` and `scripts`.
18 changes: 18 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Architecture

The installed package is `usta`, in `src/usta`. `usta`, `python -m usta` and the repository's `run.py` enter `usta.main.main`. Main configures logging and runtime directories before creating Qt widgets.

- `application` contains persistent value models, typed translation jobs/results, controllers, the capture pipeline and its Qt thread adapter.
- `core/ocr` and `core/translation` implement existing providers. The lazy registry gives capability lists and manager factories one naming source. Backend `read_text` remains a string boundary; pipeline input uses `OCRResult` and translation requests/results carry immutable session metadata.
- `core/screenshot` owns native capture, including Portal/PipeWire/GStreamer state. Native implementations load only when selected. `core/platform` resolves OS/desktop-specific overrides.
- `infrastructure` owns atomic storage, primitive-only legacy migration, runtime paths, logging and Unix socket broadcasting.
- `ui` owns widgets, settings presentation, region selector windows and Cocoa window helpers. Tabs own their widgets and emit actions; they do not access worker internals. Core engines must not import UI.
- `resources` contains unchanged ONNX models and gettext catalogs. `resource_paths` retains extracted installed resources for the application lifetime.

## Thread ownership

The GUI submits immutable settings to the worker. Its capture loop owns screenshot and OCR instances. One translation executor creates a separate translator for each immutable job. Session identifiers invalidate results after stop or configuration change. GUI stop requests do not wait on the network; closing the window waits asynchronously for capture cleanup. Socket I/O runs on its own thread with bounded queues and per-client pending bytes.

## Persistence

Settings/presets use schema-versioned JSON under the existing platform config directory. Writes use a private temporary file and atomic replacement. Legacy local pickle files are read using a globals-rejecting unpickler and remain untouched after migration. Unsupported/corrupt JSON is preserved rather than silently overwritten. Downgrading does not backport later JSON edits to the old pickle files.
13 changes: 13 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Compatibility record

The cleanup preserves the existing Linux KDE/GNOME capture paths and macOS Cocoa window behavior. No new Windows support is claimed.

| Environment | Automated contracts | Native acceptance |
| --- | --- | --- |
| macOS / Python 3.14 (local environment) | Passed during each phase; final results in execution ledger | Passed outside sandbox: native fullscreen Space/overlay/focus restoration, shortcut lifecycle and Apple Vision recognition (23 Oct 2026) |
| KDE Wayland with xcb | Portable contracts | Requires real Linux desktop; unverified |
| GNOME Wayland with xcb | Portable contracts | Requires real Linux desktop; unverified |

Manual acceptance: launch; select OCR and translator; select/cancel region; test multiple screens and DPI lock; start/stop/restart; use both shortcuts; restore temporary region after 10 seconds; save/reload presets; restart settings; listen to IPC. On macOS also test another application's native fullscreen Space, focus restoration and Retina. On Linux test Portal allow/deny/cancel and KDE Spectacle fallback. Record OS, CPU architecture, Python/Qt/native tool versions and results before a release.

CI definitions include Python 3.10/3.14 on Linux and macOS, but these remote jobs have not been run during the local cleanup. Python 3.10 is the language/API floor; dependency wheel availability must be verified by that matrix. Multi-monitor/Retina hardware combinations beyond this local host still need manual acceptance.
11 changes: 11 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Development

Use the setup and checks in [CONTRIBUTING](../CONTRIBUTING.md). Python 3.10 is the declared language/API floor, correcting the former inaccurate 3.8 claim. The local cleanup is verified on Python 3.14; other interpreter/native dependency combinations need their own install evidence. ML wheels may have narrower platform/interpreter availability.

Runtime dependencies are declared in `pyproject.toml`; `requirements.txt` delegates to the same source. The `dev` extra contains checks/build tooling, and `paddle` contains the opt-in Paddle dependencies. Version metadata comes from `usta._version` without importing the GUI.

Use `python -m build` to produce wheel and sdist. After a build run `python -m unittest tests.packaging.test_artifacts -v` to inspect all resource bytes in both artifacts. Packaging validation must also install a wheel into a fresh environment and import from outside the repository.

The AppImage script installs the same project metadata once and starts `python -m usta`. Desktop services, native OCR executables and host GStreamer remain system dependencies. See [AppImage](appimage.md).

Ruff checks imports, unused values and syntax/style correctness; its formatter provides one consistent layout. Mypy currently checks settings/results/storage boundaries; expand coverage as native SDK annotations become practical. Avoid broad suppressions for the entire codebase.
Loading
Loading