Merge branch 'ghostty-org:main' into ms_MY

This commit is contained in:
яυzαιηι
2025-05-08 01:49:32 +08:00
committed by GitHub
133 changed files with 4021 additions and 2147 deletions

View File

@ -1,4 +1,4 @@
labels: ["needs confirmation"] labels: ["needs-confirmation"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
@ -14,22 +14,37 @@ body:
description: | description: |
Provide a detailed description of the issue. Include relevant information, such as: Provide a detailed description of the issue. Include relevant information, such as:
- The feature or configuration option you encounter the issue with. - The feature or configuration option you encounter the issue with.
- The expected behavior. - Screenshots, screen recordings, or other supporting media (as needed).
- The actual behavior (and how it deviates from the expected behavior, if it is not immediately obvious).
- Relevant Ghostty logs or other stacktraces.
- Relevant screenshots, screen recordings, or other supporting media (as needed).
- If this is a regression of an existing issue that was closed or resolved, please include the previous item reference (Discussion, Issue, PR, commit) in your description. - If this is a regression of an existing issue that was closed or resolved, please include the previous item reference (Discussion, Issue, PR, commit) in your description.
>[!TIP] > [!TIP]
> **Not sure what information to include?** > **Not sure what information to include?**
> Here are some recommendations: > Here are some recommendations:
> - **Input issues:** include your keyboard layout, a screenshot of the terminal inspector's logged keystrokes (Linux: <kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>i</kbd>; MacOS: <kbd>cmd</kbd>+<kbd>alt</kbd>+<kbd>i</kbd>), input method, Linux input method engine (IBus, Fcitx 5, or none) and its version. > - **Input issues:** include your keyboard layout, a screenshot of logged keystrokes from the terminal inspector's "Keyboard" tab (Linux: <kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>i</kbd>; MacOS: <kbd>cmd</kbd>+<kbd>alt</kbd>+<kbd>i</kbd>), input method, Linux input method engine (IBus, Fcitx 5, or none) and its version.
> - **Font issues:** include the problematic character(s), the output of `ghostty +show-face` for these character(s), and if they work in other applications. > - **Font issues:** include the problematic character(s), the output of `ghostty +show-face` for these character(s), and if they work in other applications.
> - **VT issues (including image rendering issues):** attach an [asciinema](https://docs.asciinema.org/getting-started/) cast file, shell script, or text file for reproduction. > - **Terminal emulation issues (including image rendering issues):** attach an [asciinema](https://docs.asciinema.org/getting-started/) cast file, shell script, or text file for reproduction.
> - **Renderer issues:** (Linux) include your OpenGL version, graphics card, driver version. > - **Renderer issues:** (Linux) include your OpenGL version, graphics card, driver version.
> - **Crashes:** (macOS) include the [Sentry UUID](https://github.com/ghostty-org/ghostty?tab=readme-ov-file#crash-reports); (Linux) try to reproduce using a debug build and provide the stack trace.
placeholder: | placeholder: |
Example: When using SSH to connect to my remote Linux machine from my local macOS device in Ghostty, I try to run `clear`, and the screen does not clear. Instead, I see the following error message printed to the terminal: `Error opening terminal: xterm-ghostty.` When using SSH to connect to my remote Linux machine from my local macOS device in Ghostty, I try to run `clear`, and the screen does not clear. Instead, I see the following error message printed to the terminal: `Error opening terminal: xterm-ghostty.`
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
Describe how you expect Ghostty to behave in this situation. Include any relevant documentation links.
placeholder: |
The screen is cleared and the prompt is redrawn at the top of the window.
validations:
required: true
- type: textarea
attributes:
label: Actual Behavior
description: |
Describe how Ghostty actually behaves in this situation. If it is not immediately obvious how the actual behavior differs from the expected behavior described above, please be sure to mention the deviation specifically.
placeholder: |
The screen is not cleared, and an error is printed: `Error opening terminal: xterm-ghostty`.
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -44,6 +59,12 @@ body:
4. Observe `xterm-ghostty` error message above. 4. Observe `xterm-ghostty` error message above.
validations: validations:
required: true required: true
- type: textarea
attributes:
label: Ghostty Logs
description: |
Provide any captured Ghostty logs or stacktraces during your issue reproduction in this field. On Linux, logs can be found by running `ghostty` from the command-line; on macOS, logs can be viewed with `sudo log stream --level debug --predicate 'subsystem=="com.mitchellh.ghostty"'` from another terminal emulator.
render: text
- type: textarea - type: textarea
attributes: attributes:
label: Ghostty Version label: Ghostty Version
@ -93,9 +114,9 @@ body:
required: false required: false
- type: textarea - type: textarea
attributes: attributes:
label: Ghostty Configuration label: Minimal Ghostty Configuration
description: | description: |
Please provide the minimum configuration needed to reproduce this issue. If you cannot determine this, paste the output of `ghostty +show-config` here. Please provide the **minimum** configuration needed to reproduce this issue. If you can still reproduce the issue with one of the lines removed, do not include that line. If and **only** if you are not able to determine this, paste the contents of your Ghostty configuration file here.
placeholder: | placeholder: |
font-family = CommitMono Nerd Font font-family = CommitMono Nerd Font
font-family-bold = CommitMono Nerd Font font-family-bold = CommitMono Nerd Font
@ -112,15 +133,15 @@ body:
attributes: attributes:
label: Additional Relevant Configuration label: Additional Relevant Configuration
description: | description: |
If your issue involves other programs, tools, or applications in addition to Ghostty (e.g. Neovim, tmux, Zellij, etc.), please provide the minimum configuration needed for all relevant programs to reproduce the issue here. If you use custom CSS or shaders for Ghostty, also include them here, if applicable to your issue. If your issue involves other programs, tools, or applications in addition to Ghostty (e.g. Neovim, tmux, Zellij, etc.), please provide the minimum configuration and versions needed for all relevant programs to reproduce the issue here. If you use custom CSS or shaders for Ghostty, also include them here, if applicable to your issue.
placeholder: | placeholder: |
`tmux.conf` #### `tmux.conf` (tmux 3.5a)
--- ```
set -g default-terminal "tmux-256color" set -g default-terminal "tmux-256color"
set-option -sa terminal-overrides ",xterm*:Tc" set-option -sa terminal-overrides ",xterm*:Tc"
set -g base-index 1 set -g base-index 1
setw -g pane-base-index 1 setw -g pane-base-index 1
render: text ```
validations: validations:
required: false required: false
- type: markdown - type: markdown
@ -137,3 +158,5 @@ body:
required: true required: true
- label: I have searched the Ghostty repository (both open and closed Discussions and Issues) and confirm this is not a duplicate of an existing issue or discussion. - label: I have searched the Ghostty repository (both open and closed Discussions and Issues) and confirm this is not a duplicate of an existing issue or discussion.
required: true required: true
- label: I have checked the "Preview" tab on all text fields to ensure that everything looks right, and have wrapped all configuration and code in code blocks with a group of three backticks (` ``` `) on separate lines.
required: true

14
.github/scripts/check-translations.sh vendored Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
old_pot=$(mktemp)
cp po/com.mitchellh.ghostty.pot "$old_pot"
zig build update-translations
# Compare previous POT to current POT
msgcmp "$old_pot" po/com.mitchellh.ghostty.pot --use-untranslated
# Compare all other POs to current POT
for f in po/*.po; do
# Ignore untranslated entries
msgcmp --use-untranslated "$f" po/com.mitchellh.ghostty.pot;
done

View File

@ -1,189 +0,0 @@
# /// script
# requires-python = ">=3.9"
# dependencies = [
# "githubkit",
# "loguru",
# ]
# ///
from __future__ import annotations
import asyncio
import os
import re
import sys
from collections.abc import Iterator
from contextlib import contextmanager
from itertools import chain
from githubkit import GitHub
from githubkit.exception import RequestFailed
from loguru import logger
ORG_NAME = "ghostty-org"
REPO_NAME = "ghostty"
ALLOWED_PARENT_TEAM = "localization"
LOCALIZATION_TEAM_NAME_PATTERN = re.compile(r"[a-z]{2}_[A-Z]{2}")
LEVEL_MAP = {"DEBUG": "DBG", "WARNING": "WRN", "ERROR": "ERR"}
logger.remove()
logger.add(
sys.stderr,
format=lambda record: (
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
f"<level>{LEVEL_MAP[record['level'].name]}</level> | "
"<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
"<level>{message}</level>\n"
),
backtrace=True,
diagnose=True,
)
@contextmanager
def log_fail(message: str, *, die: bool = True) -> Iterator[None]:
try:
yield
except RequestFailed as exc:
logger.error(message)
logger.error(exc)
logger.error(exc.response.raw_response.json())
if die:
sys.exit(1)
gh = GitHub(os.environ["GITHUB_TOKEN"])
with log_fail("Invalid token"):
# Do the simplest request as a test
gh.rest.rate_limit.get()
async def fetch_and_parse_codeowners() -> dict[str, str]:
logger.debug("Fetching CODEOWNERS file...")
with log_fail("Failed to fetch CODEOWNERS file"):
content = (
await gh.rest.repos.async_get_content(
ORG_NAME,
REPO_NAME,
"CODEOWNERS",
headers={"Accept": "application/vnd.github.raw+json"},
)
).text
logger.debug("Parsing CODEOWNERS file...")
codeowners: dict[str, str] = {}
for line in content.splitlines():
if not line or line.lstrip().startswith("#"):
continue
# This assumes that all entries only list one owner
# and that this owner is a team (ghostty-org/foobar)
path, owner = line.split()
path = path.lstrip("/")
owner = owner.removeprefix(f"@{ORG_NAME}/")
if not is_localization_team(owner):
logger.debug(f"Skipping non-l11n codeowner {owner!r} for {path}")
continue
codeowners[path] = owner
logger.debug(f"Found codeowner {owner!r} for {path}")
return codeowners
async def get_team_members(team_name: str) -> list[str]:
logger.debug(f"Fetching team {team_name!r}...")
with log_fail(f"Failed to fetch team {team_name!r}"):
team = (await gh.rest.teams.async_get_by_name(ORG_NAME, team_name)).parsed_data
if team.parent and team.parent.slug == ALLOWED_PARENT_TEAM:
logger.debug(f"Fetching team {team_name!r} members...")
with log_fail(f"Failed to fetch team {team_name!r} members"):
resp = await gh.rest.teams.async_list_members_in_org(ORG_NAME, team_name)
members = [m.login for m in resp.parsed_data]
logger.debug(f"Team {team_name!r} members: {', '.join(members)}")
return members
logger.warning(f"Team {team_name} does not have a {ALLOWED_PARENT_TEAM!r} parent")
return []
async def get_changed_files(pr_number: int) -> list[str]:
logger.debug("Gathering changed files...")
with log_fail("Failed to gather changed files"):
diff_entries = (
await gh.rest.pulls.async_list_files(
ORG_NAME,
REPO_NAME,
pr_number,
per_page=3000,
headers={"Accept": "application/vnd.github+json"},
)
).parsed_data
return [d.filename for d in diff_entries]
async def request_review(pr_number: int, user: str, pr_author: str) -> None:
if user == pr_author:
logger.debug(f"Skipping review request for {user!r} (is PR author)")
logger.debug(f"Requesting review from {user!r}...")
with log_fail(f"Failed to request review from {user}", die=False):
await gh.rest.pulls.async_request_reviewers(
ORG_NAME,
REPO_NAME,
pr_number,
headers={"Accept": "application/vnd.github+json"},
data={"reviewers": [user]},
)
def is_localization_team(team_name: str) -> bool:
return LOCALIZATION_TEAM_NAME_PATTERN.fullmatch(team_name) is not None
async def get_pr_author(pr_number: int) -> str:
logger.debug("Fetching PR author...")
with log_fail("Failed to fetch PR author"):
resp = await gh.rest.pulls.async_get(ORG_NAME, REPO_NAME, pr_number)
pr_author = resp.parsed_data.user.login
logger.debug(f"Found author: {pr_author!r}")
return pr_author
async def main() -> None:
logger.debug("Reading PR number...")
pr_number = int(os.environ["PR_NUMBER"])
logger.debug(f"Starting review request process for PR #{pr_number}...")
changed_files = await get_changed_files(pr_number)
logger.debug(f"Changed files: {', '.join(map(repr, changed_files))}")
pr_author = await get_pr_author(pr_number)
codeowners = await fetch_and_parse_codeowners()
found_owners = set[str]()
for file in changed_files:
logger.debug(f"Finding owner for {file!r}...")
for path, owner in codeowners.items():
if file.startswith(path):
logger.debug(f"Found owner: {owner!r}")
break
else:
logger.debug("No owner found")
continue
found_owners.add(owner)
member_lists = await asyncio.gather(
*(get_team_members(owner) for owner in found_owners)
)
await asyncio.gather(
*(
request_review(pr_number, user, pr_author)
for user in chain.from_iterable(member_lists)
)
)
if __name__ == "__main__":
asyncio.run(main())

View File

@ -1,37 +0,0 @@
name: Request Review
on:
pull_request:
types:
- opened
- synchronize
env:
PY_COLORS: 1
jobs:
review:
runs-on: namespace-profile-ghostty-xsm
steps:
- uses: actions/checkout@v4
- name: Setup Cache
uses: namespacelabs/nscloud-cache-action@v1.2.0
with:
path: |
/nix
/zig
- uses: cachix/install-nix-action@v30
with:
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v15
with:
name: ghostty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Request Localization Review
env:
GITHUB_TOKEN: ${{ secrets.GH_REVIEW_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: nix develop -c uv run .github/scripts/request_review.py

View File

@ -21,6 +21,8 @@ jobs:
- build-macos-matrix - build-macos-matrix
- build-windows - build-windows
- build-windows-cross - build-windows-cross
- flatpak-check-zig-cache
- flatpak
- test - test
- test-gtk - test-gtk
- test-sentry-linux - test-sentry-linux
@ -351,15 +353,19 @@ jobs:
os: os:
[namespace-profile-ghostty-snap, namespace-profile-ghostty-snap-arm64] [namespace-profile-ghostty-snap, namespace-profile-ghostty-snap-arm64]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: test needs: [test, build-dist]
env: env:
ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_LOCAL_CACHE_DIR: /zig/local-cache
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
steps: steps:
- uses: actions/checkout@v4 - name: Download Source Tarball Artifacts
uses: actions/download-artifact@v4
with: with:
fetch-depth: 0 name: source-tarball
fetch-tags: true - name: Extract tarball
run: |
mkdir dist
tar --verbose --extract --strip-components 1 --directory dist --file ghostty-source.tar.gz
- name: Setup Cache - name: Setup Cache
uses: namespacelabs/nscloud-cache-action@v1.2.0 uses: namespacelabs/nscloud-cache-action@v1.2.0
with: with:
@ -368,7 +374,14 @@ jobs:
/zig /zig
- run: sudo apt install -y udev - run: sudo apt install -y udev
- run: sudo systemctl start systemd-udevd - run: sudo systemctl start systemd-udevd
# Workaround until this is fixed: https://github.com/canonical/lxd-pkg-snap/pull/789
- run: |
_LXD_SNAP_DEVCGROUP_CONFIG="/var/lib/snapd/cgroup/snap.lxd.device"
sudo mkdir -p /var/lib/snapd/cgroup
echo 'self-managed=true' | sudo tee "${_LXD_SNAP_DEVCGROUP_CONFIG}"
- uses: snapcore/action-build@v1 - uses: snapcore/action-build@v1
with:
path: dist
build-windows: build-windows:
runs-on: windows-2022 runs-on: windows-2022
@ -734,7 +747,7 @@ jobs:
translations: translations:
if: github.repository == 'ghostty-org/ghostty' if: github.repository == 'ghostty-org/ghostty'
runs-on: namespace-profile-ghostty-sm runs-on: namespace-profile-ghostty-xsm
timeout-minutes: 60 timeout-minutes: 60
env: env:
ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_LOCAL_CACHE_DIR: /zig/local-cache
@ -757,23 +770,11 @@ jobs:
skipPush: true skipPush: true
useDaemon: false # sometimes fails on short jobs useDaemon: false # sometimes fails on short jobs
- name: check translations - name: check translations
run: | run: nix develop -c .github/scripts/check-translations.sh
old_pot=$(mktemp)
cp po/com.mitchellh.ghostty.pot "$old_pot"
nix develop -c zig build update-translations
# Compare previous POT to current POT
msgcmp "$old_pot" po/com.mitchellh.ghostty.pot --use-untranslated
# Compare all other POs to current POT
for f in po/*.po; do
# Ignore untranslated entries
msgcmp --use-untranslated "$f" po/com.mitchellh.ghostty.pot;
done
blueprint-compiler: blueprint-compiler:
if: github.repository == 'ghostty-org/ghostty' if: github.repository == 'ghostty-org/ghostty'
runs-on: namespace-profile-ghostty-sm runs-on: namespace-profile-ghostty-xsm
timeout-minutes: 60 timeout-minutes: 60
env: env:
ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_LOCAL_CACHE_DIR: /zig/local-cache
@ -863,3 +864,56 @@ jobs:
file: dist/src/build/docker/debian/Dockerfile file: dist/src/build/docker/debian/Dockerfile
build-args: | build-args: |
DISTRO_VERSION=12 DISTRO_VERSION=12
flatpak-check-zig-cache:
if: github.repository == 'ghostty-org/ghostty'
runs-on: namespace-profile-ghostty-xsm
env:
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Cache
uses: namespacelabs/nscloud-cache-action@v1.2.0
with:
path: |
/nix
/zig
- name: Setup Nix
uses: cachix/install-nix-action@v30
with:
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v15
with:
name: ghostty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
useDaemon: false # sometimes fails on short jobs
- name: Check Flatpak Zig Dependencies
run: nix develop -c ./flatpak/build-support/check-zig-cache.sh
flatpak:
if: github.repository == 'ghostty-org/ghostty'
name: "Flatpak"
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-47
options: --privileged
strategy:
fail-fast: false
matrix:
variant:
- arch: x86_64
runner: namespace-profile-ghostty-md
- arch: aarch64
runner: namespace-profile-ghostty-md-arm64
runs-on: ${{ matrix.variant.runner }}
needs: [flatpak-check-zig-cache, test]
steps:
- uses: actions/checkout@v4
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
bundle: com.mitchellh.ghostty
manifest-path: flatpak/com.mitchellh.ghostty.yml
cache-key: flatpak-builder-${{ github.sha }}
arch: ${{ matrix.variant.arch }}
verbose: true

View File

@ -50,6 +50,8 @@ jobs:
if ! git diff --exit-code build.zig.zon; then if ! git diff --exit-code build.zig.zon; then
nix develop -c ./nix/build-support/check-zig-cache.sh --update nix develop -c ./nix/build-support/check-zig-cache.sh --update
nix develop -c ./nix/build-support/check-zig-cache.sh nix develop -c ./nix/build-support/check-zig-cache.sh
nix develop -c ./flatpak/build-support/check-zig-cache.sh --update
nix develop -c ./flatpak/build-support/check-zig-cache.sh
fi fi
# Verify the build still works. We choose an arbitrary build type # Verify the build still works. We choose an arbitrary build type
@ -69,6 +71,7 @@ jobs:
build.zig.zon.nix build.zig.zon.nix
build.zig.zon.txt build.zig.zon.txt
build.zig.zon.json build.zig.zon.json
flatpak/zig-packages.json
body: | body: |
Upstream revision: https://github.com/mbadolato/iTerm2-Color-Schemes/tree/${{ steps.zig_fetch.outputs.upstream_rev }} Upstream revision: https://github.com/mbadolato/iTerm2-Color-Schemes/tree/${{ steps.zig_fetch.outputs.upstream_rev }}
labels: dependencies labels: dependencies

2
.gitignore vendored
View File

@ -14,6 +14,8 @@ zig-out/
example/*.wasm example/*.wasm
test/ghostty test/ghostty
test/cases/**/*.actual.png test/cases/**/*.actual.png
flatpak/builddir/
flatpak/repo/
glad.zip glad.zip
/Box_test.ppm /Box_test.ppm

View File

@ -144,7 +144,7 @@
# Shell # Shell
/src/shell-integration/ @ghostty-org/shell /src/shell-integration/ @ghostty-org/shell
/src/termio/shell-integration.zig @ghostty-org/shell /src/termio/shell_integration.zig @ghostty-org/shell
# Terminal # Terminal
/src/simd/ @ghostty-org/terminal /src/simd/ @ghostty-org/terminal

View File

@ -20,8 +20,8 @@
}, },
.z2d = .{ .z2d = .{
// vancluever/z2d // vancluever/z2d
.url = "https://github.com/vancluever/z2d/archive/1e89605a624940c310c7a1d81b46a7c5c05919e3.tar.gz", .url = "https://github.com/vancluever/z2d/archive/1bf4bc81819385f4b24596445c9a7cf3b3592b08.tar.gz",
.hash = "z2d-0.6.0-j5P_HvLdCABu-dXpCeRM7Uk4m16vULg1980lMNCQj4_C", .hash = "z2d-0.6.1-j5P_HlerCgBokMgrkl9QhJUKXuZWBGdPnH7cSXwv_ScW",
.lazy = true, .lazy = true,
}, },
.zig_objc = .{ .zig_objc = .{
@ -103,8 +103,8 @@
// Other // Other
.apple_sdk = .{ .path = "./pkg/apple-sdk" }, .apple_sdk = .{ .path = "./pkg/apple-sdk" },
.iterm2_themes = .{ .iterm2_themes = .{
.url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/4c57d8c11d352a4aeda6928b65d78794c28883a5.tar.gz", .url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/1e4957e65005908993250f8f07be3f70e805195e.tar.gz",
.hash = "N-V-__8AAEH8MwQaEsARbyV42-bSZGcu1am8xtg2h67wTFC3", .hash = "N-V-__8AAHOASAQuLADcCSHLHEJiKFVLZiCD9Aq2rh5GT01A",
.lazy = true, .lazy = true,
}, },
}, },

12
build.zig.zon.json generated
View File

@ -54,10 +54,10 @@
"url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz", "url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz",
"hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA=" "hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA="
}, },
"N-V-__8AAEH8MwQaEsARbyV42-bSZGcu1am8xtg2h67wTFC3": { "N-V-__8AAHOASAQuLADcCSHLHEJiKFVLZiCD9Aq2rh5GT01A": {
"name": "iterm2_themes", "name": "iterm2_themes",
"url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/4c57d8c11d352a4aeda6928b65d78794c28883a5.tar.gz", "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/1e4957e65005908993250f8f07be3f70e805195e.tar.gz",
"hash": "sha256-c+twvkEPiz1DaULYlnGXLxis19Q2h+TgBJxoARMasjU=" "hash": "sha256-xpDitXpZrdU/EcgLyG4G0cEiT4r42viy+DJALmy2sQE="
}, },
"N-V-__8AAJrvXQCqAT8Mg9o_tk6m0yf5Fz-gCNEOKLyTSerD": { "N-V-__8AAJrvXQCqAT8Mg9o_tk6m0yf5Fz-gCNEOKLyTSerD": {
"name": "libpng", "name": "libpng",
@ -124,10 +124,10 @@
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz", "url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
"hash": "sha256-nkzSCr6W5sTG7enDBXEIhgEm574uLD41UVR2wlC+HBM=" "hash": "sha256-nkzSCr6W5sTG7enDBXEIhgEm574uLD41UVR2wlC+HBM="
}, },
"z2d-0.6.0-j5P_HvLdCABu-dXpCeRM7Uk4m16vULg1980lMNCQj4_C": { "z2d-0.6.1-j5P_HlerCgBokMgrkl9QhJUKXuZWBGdPnH7cSXwv_ScW": {
"name": "z2d", "name": "z2d",
"url": "https://github.com/vancluever/z2d/archive/1e89605a624940c310c7a1d81b46a7c5c05919e3.tar.gz", "url": "https://github.com/vancluever/z2d/archive/1bf4bc81819385f4b24596445c9a7cf3b3592b08.tar.gz",
"hash": "sha256-PEKVSUZ6teRbDyhFPWSiuBSe40pgr0kVRivIY8Cn8HQ=" "hash": "sha256-wiJs6/LUiy+ApC5s7VPypbBukjBr4vjx3v/l9OrT70U="
}, },
"zf-0.10.3-OIRy8aiIAACLrBllz0zjxaH0aOe5oNm3KtEMyCntST-9": { "zf-0.10.3-OIRy8aiIAACLrBllz0zjxaH0aOe5oNm3KtEMyCntST-9": {
"name": "zf", "name": "zf",

12
build.zig.zon.nix generated
View File

@ -170,11 +170,11 @@ in
}; };
} }
{ {
name = "N-V-__8AAEH8MwQaEsARbyV42-bSZGcu1am8xtg2h67wTFC3"; name = "N-V-__8AAHOASAQuLADcCSHLHEJiKFVLZiCD9Aq2rh5GT01A";
path = fetchZigArtifact { path = fetchZigArtifact {
name = "iterm2_themes"; name = "iterm2_themes";
url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/4c57d8c11d352a4aeda6928b65d78794c28883a5.tar.gz"; url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/1e4957e65005908993250f8f07be3f70e805195e.tar.gz";
hash = "sha256-c+twvkEPiz1DaULYlnGXLxis19Q2h+TgBJxoARMasjU="; hash = "sha256-xpDitXpZrdU/EcgLyG4G0cEiT4r42viy+DJALmy2sQE=";
}; };
} }
{ {
@ -282,11 +282,11 @@ in
}; };
} }
{ {
name = "z2d-0.6.0-j5P_HvLdCABu-dXpCeRM7Uk4m16vULg1980lMNCQj4_C"; name = "z2d-0.6.1-j5P_HlerCgBokMgrkl9QhJUKXuZWBGdPnH7cSXwv_ScW";
path = fetchZigArtifact { path = fetchZigArtifact {
name = "z2d"; name = "z2d";
url = "https://github.com/vancluever/z2d/archive/1e89605a624940c310c7a1d81b46a7c5c05919e3.tar.gz"; url = "https://github.com/vancluever/z2d/archive/1bf4bc81819385f4b24596445c9a7cf3b3592b08.tar.gz";
hash = "sha256-PEKVSUZ6teRbDyhFPWSiuBSe40pgr0kVRivIY8Cn8HQ="; hash = "sha256-wiJs6/LUiy+ApC5s7VPypbBukjBr4vjx3v/l9OrT70U=";
}; };
} }
{ {

4
build.zig.zon.txt generated
View File

@ -27,8 +27,8 @@ https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.
https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz
https://github.com/glfw/glfw/archive/e7ea71be039836da3a98cea55ae5569cb5eb885c.tar.gz https://github.com/glfw/glfw/archive/e7ea71be039836da3a98cea55ae5569cb5eb885c.tar.gz
https://github.com/jcollie/ghostty-gobject/releases/download/0.14.0-2025-03-18-21-1/ghostty-gobject-0.14.0-2025-03-18-21-1.tar.zst https://github.com/jcollie/ghostty-gobject/releases/download/0.14.0-2025-03-18-21-1/ghostty-gobject-0.14.0-2025-03-18-21-1.tar.zst
https://github.com/mbadolato/iTerm2-Color-Schemes/archive/4c57d8c11d352a4aeda6928b65d78794c28883a5.tar.gz https://github.com/mbadolato/iTerm2-Color-Schemes/archive/1e4957e65005908993250f8f07be3f70e805195e.tar.gz
https://github.com/mitchellh/libxev/archive/3df9337a9e84450a58a2c4af434ec1a036f7b494.tar.gz https://github.com/mitchellh/libxev/archive/3df9337a9e84450a58a2c4af434ec1a036f7b494.tar.gz
https://github.com/mitchellh/zig-objc/archive/3ab0d37c7d6b933d6ded1b3a35b6b60f05590a98.tar.gz https://github.com/mitchellh/zig-objc/archive/3ab0d37c7d6b933d6ded1b3a35b6b60f05590a98.tar.gz
https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz
https://github.com/vancluever/z2d/archive/1e89605a624940c310c7a1d81b46a7c5c05919e3.tar.gz https://github.com/vancluever/z2d/archive/1bf4bc81819385f4b24596445c9a7cf3b3592b08.tar.gz

View File

@ -1,59 +0,0 @@
# Note: the flatpak build is likely broken right now and is not actively
# maintained. We may completely remove this file in the future. For now,
# we want to keep _trying_ but its something with known issues.
app-id: com.mitchellh.ghostty
runtime: org.gnome.Platform
runtime-version: "43"
sdk: org.gnome.Sdk
default-branch: tip
command: ghostty
build-options:
append-path: /app/tmp/zig
strip: false
no-debuginfo: true
# Note: we have to use cleanup-commands because flatpak-builder doesn't
# run "cleanup" on its own: https://github.com/flatpak/flatpak-builder/issues/14
cleanup-commands:
- "rm -rf /app/tmp"
finish-args:
# 3D rendering
- --device=dri
# Windowing
- --share=ipc
- --socket=x11
- --socket=wayland
# Files (we are a terminal so we need all of them)
- --filesystem=host
# So we can escape the sandbox
- --talk-name=org.freedesktop.Flatpak
modules:
# Note: this should be kept in sync with our flake.nix. Over time this
# should stabilize to being a release version and not a nightly.
- name: zig
buildsystem: simple
build-commands:
- mkdir -p /app/tmp/zig
- cp -r ./* /app/tmp/zig
sources:
- type: archive
url: https://ziglang.org/builds/zig-linux-x86_64-0.12.0-dev.141+ddf5859c2.tar.xz
sha256: eaf519b1ec3cb0f3c9bcbc47ead5f50610f9c106279a35b9feb09bed8afc628b
only-arches:
- x86_64
- type: archive
url: https://ziglang.org/builds/zig-linux-aarch64-0.12.0-dev.141+ddf5859c2.tar.xz
sha256: 4f918ae185a5dc281b5d30be92cd4c36ebd77b8665729c5e2c47a8eeccd243e8
only-arches:
- aarch64
- name: ghostty
buildsystem: simple
build-commands:
- MACH_SDK_PATH="$(pwd)/vendor/mach-sdk" zig build -Doptimize=ReleaseSafe -Dcpu=baseline -Dflatpak=true -Dapp-runtime=gtk --prefix /app
sources:
- type: dir
path: .
skip:
- .flatpak-builder
- zig-cache
- zig-out

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>com.mitchellh.ghostty</id>
<launchable type="desktop-id">com.mitchellh.ghostty.desktop</launchable>
<name>Ghostty</name>
<url type="homepage">https://ghostty.org</url>
<url type="help">https://ghostty.org/docs</url>
<url type="bugtracker">https://github.com/ghostty-org/ghostty/discussions</url>
<url type="contact">https://ghostty.org/docs/help</url>
<url type="contribute">https://github.com/ghostty-org/ghostty/blob/main/CONTRIBUTING.md</url>
<url type="translate">https://github.com/ghostty-org/ghostty/blob/main/po/README_TRANSLATORS.md</url>
<url type="vcs-browser">https://github.com/ghostty-org/ghostty</url>
<summary>Ghostty is a fast, feature-rich, and cross-platform terminal emulator</summary>
<metadata_license>MIT</metadata_license>
<project_license>MIT</project_license>
<content_rating type="oars-1.1" />
<developer id="com.mitchellh">
<name>Mitchell Hashimoto</name>
</developer>
<update_contact>m@mitchellh.com</update_contact>
<description>
<p>
Ghostty is a terminal emulator that differentiates itself by being fast,
feature-rich, and native. While there are many excellent terminal
emulators available, they all force you to choose between speed,
features, or native UIs. Ghostty provides all three.
</p>
</description>
<recommends>
<control>keyboard</control>
<control>pointing</control>
</recommends>
<requires>
<!--
Mobile/tablet AND desktop supported
Ref: https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines#display-size
-->
<display_length compare="ge">360</display_length>
</requires>
<translation type="gettext">com.mitchellh.ghostty</translation>
<!--
TODO: Generate manifest location data.
Ref: https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines#manifest-location
<custom>
<value key="flathub::manifest">https://github.com/ghostty-org/ghostty/blob/<hash>/flatpak/com.mitchellh.ghostty.yml</value>
</custom>
-->
<releases>
<!-- TODO: Generate this automatically -->
<release version="1.0.1" date="2024-12-31">
<url type="details">https://ghostty.org/docs/install/release-notes/1-0-1</url>
</release>
</releases>
</component>

View File

@ -0,0 +1,108 @@
#!/usr/bin/env bash
#
# This script checks if the flatpak/zig-packages.json file is up-to-date.
# If the `--update` flag is passed, it will update all necessary
# files to be up to date.
#
# The files owned by this are:
#
# - flatpak/zig-packages.json
#
# All of these are auto-generated and should not be edited manually.
# Nothing in this script should fail.
set -eu
set -o pipefail
WORK_DIR=$(mktemp -d)
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
echo "could not create temp dir"
exit 1
fi
function cleanup {
rm -rf "$WORK_DIR"
}
trap cleanup EXIT
help() {
echo ""
echo "To fix, please (manually) re-run the script from the repository root,"
echo "commit, and submit a PR with the update:"
echo ""
echo " ./flatpak/build-support/check-zig-cache.sh --update"
echo " git add flatpak/zig-packages.json"
echo " git commit -m \"flatpak: update zig-packages.json\""
echo ""
}
# Turn Nix's base64 hashes into regular hexadecimal form
decode_hash() {
input=$1
input=${input#sha256-}
echo "$input" | base64 -d | od -vAn -t x1 | tr -d ' \n'
}
ROOT="$(realpath "$(dirname "$0")/../../")"
ZIG_PACKAGES_JSON="$ROOT/flatpak/zig-packages.json"
BUILD_ZIG_ZON_JSON="$ROOT/build.zig.zon.json"
if [ ! -f "${BUILD_ZIG_ZON_JSON}" ]; then
echo -e "\nERROR: build.zig.zon2json-lock missing."
help
exit 1
fi
if [ -f "${ZIG_PACKAGES_JSON}" ]; then
OLD_HASH=$(sha512sum "${ZIG_PACKAGES_JSON}" | awk '{print $1}')
fi
while read -r url sha256 dest; do
src_type=archive
sha256=$(decode_hash "$sha256")
git_commit=
if [[ "$url" =~ ^git\+* ]]; then
src_type=git
sha256=
url=${url#git+}
git_commit=${url##*#}
url=${url%%/\?ref*}
url=${url%%#*}
fi
jq \
-nec \
--arg type "$src_type" \
--arg url "$url" \
--arg git_commit "$git_commit" \
--arg dest "$dest" \
--arg sha256 "$sha256" \
'{
type: $type,
url: $url,
commit: $git_commit,
dest: $dest,
sha256: $sha256,
} | with_entries(select(.value != ""))'
done < <(jq -rc 'to_entries[] | [.value.url, .value.hash, "vendor/p/\(.key)"] | @tsv' "$BUILD_ZIG_ZON_JSON") |
jq -s '.' >"$WORK_DIR/zig-packages.json"
NEW_HASH=$(sha512sum "$WORK_DIR/zig-packages.json" | awk '{print $1}')
if [ "${OLD_HASH}" == "${NEW_HASH}" ]; then
echo -e "\nOK: flatpak/zig-packages.json unchanged."
exit 0
elif [ "${1:-}" != "--update" ]; then
echo -e "\nERROR: flatpak/zig-packages.json needs to be updated."
echo ""
echo " * Old hash: ${OLD_HASH}"
echo " * New hash: ${NEW_HASH}"
help
exit 1
else
mv "$WORK_DIR/zig-packages.json" "$ZIG_PACKAGES_JSON"
echo -e "\nOK: flatpak/zig-packages.json updated."
exit 0
fi

View File

@ -0,0 +1,63 @@
app-id: com.mitchellh.ghostty.Devel
runtime: org.gnome.Platform
runtime-version: "48"
sdk: org.gnome.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.ziglang
default-branch: tip
command: ghostty
# Integrate the rename into zig build, maybe?
rename-desktop-file: com.mitchellh.ghostty.desktop
rename-appdata-file: com.mitchellh.ghostty.metainfo.xml
rename-icon: com.mitchellh.ghostty
desktop-file-name-suffix: " (Devel)"
finish-args:
# 3D rendering
- --device=dri
# Windowing
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
# Allow user to specify additional config files in home by default
- --filesystem=home:ro
# So we can escape the sandbox
- --talk-name=org.freedesktop.Flatpak
cleanup:
- /include
- /lib/girepository-1.0
- /lib/pkgconfig
- /share/gir-1.0
- /share/pkgconfig
- /share/vala
- "*.la"
- "*.a"
- "*.so"
modules:
- dependencies.yml
- name: ghostty
buildsystem: simple
build-options:
append-path: /usr/lib/sdk/ziglang
build-commands:
- zig build
-Doptimize=Debug
-Dcpu=baseline
-Dflatpak=true
-Dstrip=false
-fno-sys=oniguruma
--prefix /app
--search-prefix /app
--system $PWD/vendor/p
sources:
- type: dir
path: ..
skip:
- flatpak/.flatpak-builder
- flatpak/builddir
- flatpak/repo
- zig-cache
- zig-out
- zig-packages.json

View File

@ -0,0 +1,58 @@
app-id: com.mitchellh.ghostty
runtime: org.gnome.Platform
runtime-version: "48"
sdk: org.gnome.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.ziglang
default-branch: tip
command: ghostty
finish-args:
# 3D rendering
- --device=dri
# Windowing
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
# Allow user to specify additional config files in home by default
- --filesystem=home:ro
# So we can escape the sandbox
- --talk-name=org.freedesktop.Flatpak
cleanup:
- /include
- /lib/girepository-1.0
- /lib/pkgconfig
- /share/gir-1.0
- /share/pkgconfig
- /share/vala
- "*.la"
- "*.a"
- "*.so"
modules:
- dependencies.yml
- name: ghostty
buildsystem: simple
build-options:
append-path: /usr/lib/sdk/ziglang
build-commands:
- zig build
-Doptimize=ReleaseFast
-Dcpu=baseline
-Dflatpak=true
-Dstrip=false
-fno-sys=oniguruma
--prefix /app
--search-prefix /app
--system $PWD/vendor/p
sources:
- type: dir
path: ..
skip:
- flatpak/.flatpak-builder
- flatpak/builddir
- flatpak/repo
- zig-cache
- zig-out
- zig-packages.json

66
flatpak/dependencies.yml Normal file
View File

@ -0,0 +1,66 @@
name: dependencies-meta
buildsystem: simple
build-commands:
- true
modules:
- name: bzip2-redirect
buildsystem: simple
build-commands:
- install -Dm644 libbzip2.so /app/lib/libbzip2.so
sources:
- type: inline
contents: INPUT(libbz2.so)
dest-filename: libbzip2.so
- name: blueprint-compiler
buildsystem: meson
cleanup:
- "*"
sources:
- type: git
url: https://gitlab.gnome.org/jwestman/blueprint-compiler.git
tag: v0.16.0
commit: 04ef0944db56ab01307a29aaa7303df6067cb3c0
x-checker-data:
type: git
tag-pattern: ^v([\d.]+)$
- name: gtk4-layer-shell
buildsystem: meson
sources:
# no x-checker-data since this should be synchronized with Nix
#
# TODO: Automate this with check-zig-cache.sh
- type: archive
url: https://github.com/wmww/gtk4-layer-shell/archive/refs/tags/v1.1.0.tar.gz
sha256: 98284281260a5eef5b4f63a55f16c4bf6a788a1020a6db037ecb0f71fa336988
- name: pandoc
buildsystem: simple
cleanup:
- "*"
build-commands:
- install -Dm755 bin/pandoc /app/bin/pandoc
sources:
- type: archive
sha256: d04c95c138202f87d6b00ac19aa3dd874c681f60a9feb3b55c74f764d6d1a17d
url: https://github.com/jgm/pandoc/releases/download/3.6.3/pandoc-3.6.3-linux-amd64.tar.gz
only-arches: [x86_64]
x-checker-data:
type: json
url: https://api.github.com/repos/jgm/pandoc/releases/latest
url-query:
.assets[] | select(.name=="pandoc-" + $version + "-linux-amd64.tar.gz")
| .browser_download_url
version-query: .tag_name
- type: archive
sha256: 4e774cb1bdb6e56bc55b8eb79200bd9aa6a39905a04ecda7267f5149116f0881
url: https://github.com/jgm/pandoc/releases/download/3.6.3/pandoc-3.6.3-linux-arm64.tar.gz
only-arches: [aarch64]
x-checker-data:
type: json
url: https://api.github.com/repos/jgm/pandoc/releases/latest
url-query:
.assets[] | select(.name=="pandoc-" + $version + "-linux-arm64.tar.gz")
| .browser_download_url
version-query: .tag_name

3
flatpak/exceptions.json Normal file
View File

@ -0,0 +1,3 @@
{
"com.mitchellh.ghostty": ["finish-args-flatpak-spawn-access"]
}

206
flatpak/zig-packages.json Normal file
View File

@ -0,0 +1,206 @@
[
{
"type": "archive",
"url": "https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz",
"dest": "vendor/p/N-V-__8AALw2uwF_03u4JRkZwRLc3Y9hakkYV7NKRR9-RIZJ",
"sha256": "6cca98943d1a990766cef61077c09aff5938063fe17a1efe1228e5412b6d6ad9"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz",
"dest": "vendor/p/N-V-__8AAIrfdwARSa-zMmxWwFuwpXf1T3asIN7s5jqi9c1v",
"sha256": "3ba2dd92158718acec5caaf1a716043b5aa055c27b081d914af3ccb40dce8a55"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/freetype-1220b81f6ecfb3fd222f76cf9106fecfa6554ab07ec7fdc4124b9bb063ae2adf969d.tar.gz",
"dest": "vendor/p/N-V-__8AAKLKpwC4H27Ps_0iL3bPkQb-z6ZVSrB-x_3EEkub",
"sha256": "427201f5d5151670d05c1f5b45bef5dda1f2e7dd971ef54f0feaaa7ffd2ab90c"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/gettext-0.24.tar.gz",
"dest": "vendor/p/N-V-__8AADcZkgn4cMhTUpIz6mShCKyqqB-NBtf_S2bHaTC-",
"sha256": "c918503d593d70daf4844d175a13d816afacb667c06fba1ec9dcd5002c1518b7"
},
{
"type": "archive",
"url": "https://github.com/glfw/glfw/archive/e7ea71be039836da3a98cea55ae5569cb5eb885c.tar.gz",
"dest": "vendor/p/N-V-__8AAMrJSwAUGb9-vTzkNR-5LXS81MR__ZRVfF3tWgG6",
"sha256": "3373755d402531e6c1a395f53f2fbd6318ca5e067a79a72a59109b526c0b290a"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/glslang-12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1.tar.gz",
"dest": "vendor/p/N-V-__8AABzkUgISeKGgXAzgtutgJsZc0-kkeqBBscJgMkvy",
"sha256": "14a2edbb509cb3e51a9a53e3f5e435dbf5971604b4b833e63e6076e8c0a997b5"
},
{
"type": "archive",
"url": "https://github.com/jcollie/ghostty-gobject/releases/download/0.14.0-2025-03-18-21-1/ghostty-gobject-0.14.0-2025-03-18-21-1.tar.zst",
"dest": "vendor/p/gobject-0.2.0-Skun7IWDlQAOKu4BV7LapIxL9Imbq1JRmzvcIkazvAxR",
"sha256": "85672997459ddd7c9d4fe458efe548a315cf842cde95ed48a7be984a1f8a98b2"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/gtk4-layer-shell-1.1.0.tar.gz",
"dest": "vendor/p/N-V-__8AALiNBAA-_0gprYr92CjrMj1I5bqNu0TSJOnjFNSr",
"sha256": "98284281260a5eef5b4f63a55f16c4bf6a788a1020a6db037ecb0f71fa336988"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/harfbuzz-11.0.0.tar.xz",
"dest": "vendor/p/N-V-__8AAG02ugUcWec-Ndp-i7JTsJ0dgF8nnJRUInkGLG7G",
"sha256": "f16351bafe214725fe2c1d5b59f0d93e49905a4b247899fb90d70cff953a2b9b"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/highway-66486a10623fa0d72fe91260f96c892e41aceb06.tar.gz",
"dest": "vendor/p/N-V-__8AAGmZhABbsPJLfbqrh6JTHsXhY6qCaLAQyx25e0XE",
"sha256": "87d4f8893ef4e08f224973608ffebf94268a81380ba79c12e8841968c80aa212"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz",
"dest": "vendor/p/N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3",
"sha256": "a05fd01e04cf11ab781e28387c621d2e420f1e6044c8e27a25e603ea99ef7860"
},
{
"type": "archive",
"url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/1e4957e65005908993250f8f07be3f70e805195e.tar.gz",
"dest": "vendor/p/N-V-__8AAHOASAQuLADcCSHLHEJiKFVLZiCD9Aq2rh5GT01A",
"sha256": "c690e2b57a59add53f11c80bc86e06d1c1224f8af8daf8b2f832402e6cb6b101"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/libpng-1220aa013f0c83da3fb64ea6d327f9173fa008d10e28bc9349eac3463457723b1c66.tar.gz",
"dest": "vendor/p/N-V-__8AAJrvXQCqAT8Mg9o_tk6m0yf5Fz-gCNEOKLyTSerD",
"sha256": "fecc95b46cf05e8e3fc8a414750e0ba5aad00d89e9fdf175e94ff041caf1a03a"
},
{
"type": "archive",
"url": "https://github.com/mitchellh/libxev/archive/3df9337a9e84450a58a2c4af434ec1a036f7b494.tar.gz",
"dest": "vendor/p/libxev-0.0.0-86vtc-ziEgDbLP0vihUn1MhsxNKY4GJEga6BEr7oyHpz",
"sha256": "a0a66a03d77bf631e7a7f1eca89590137dc57e7e447b91b85679507a942e638a"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/libxml2-2.11.5.tar.gz",
"dest": "vendor/p/N-V-__8AAG3RoQEyRC2Vw7Qoro5SYBf62IHn3HjqtNVY6aWK",
"sha256": "6c28059e2e3eeb42b5b4b16489e3916a6346c1095a74fee3bc65cdc5d89a6215"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/oniguruma-1220c15e72eadd0d9085a8af134904d9a0f5dfcbed5f606ad60edc60ebeccd9706bb.tar.gz",
"dest": "vendor/p/N-V-__8AAHjwMQDBXnLq3Q2QhaivE0kE2aD138vtX2Bq1g7c",
"sha256": "001aa1202e78448f4c0bf1a48c76e556876b36f16d92ce3207eccfd61d99f2a0"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/pixels-12207ff340169c7d40c570b4b6a97db614fe47e0d83b5801a932dcd44917424c8806.tar.gz",
"dest": "vendor/p/N-V-__8AADYiAAB_80AWnH1AxXC0tql9thT-R-DYO1gBqTLc",
"sha256": "55e83b16d091082502bf149bf457f31f42092c5982650e3ffbae7b48871bf11a"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/plasma_wayland_protocols-12207e0851c12acdeee0991e893e0132fc87bb763969a585dc16ecca33e88334c566.tar.gz",
"dest": "vendor/p/N-V-__8AAKYZBAB-CFHBKs3u4JkeiT4BMvyHu3Y5aaWF3Bbs",
"sha256": "5c58ba214acd8e6bca3426dc08b022c46a8dd997b29a1b3e28badf71c20df441"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/sentry-1220446be831adcca918167647c06c7b825849fa3fba5f22da394667974537a9c77e.tar.gz",
"dest": "vendor/p/N-V-__8AAPlZGwBEa-gxrcypGBZ2R8Bse4JYSfo_ul8i2jlG",
"sha256": "2ac6497cc8d61a8d31093e47addb8c9b2c45b16b0705bb334a835b6423c318df"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/spirv_cross-1220fb3b5586e8be67bc3feb34cbe749cf42a60d628d2953632c2f8141302748c8da.tar.gz",
"dest": "vendor/p/N-V-__8AANb6pwD7O1WG6L5nvD_rNMvnSc9Cpg1ijSlTYywv",
"sha256": "b52b6fcfc45e7fa69b1f06a1362c155473444e2cc09995556b156c53ba6657e3"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/utfcpp-1220d4d18426ca72fc2b7e56ce47273149815501d0d2395c2a98c726b31ba931e641.tar.gz",
"dest": "vendor/p/N-V-__8AAHffAgDU0YQmynL8K35WzkcnMUmBVQHQ0jlcKpjH",
"sha256": "ffc668a310e77607d393f3c18b32715f223da1eac4c4d6e0579a11df8e6b59cf"
},
{
"type": "git",
"url": "https://github.com/rockorager/libvaxis",
"commit": "1f41c121e8fc153d9ce8c6eb64b2bbab68ad7d23",
"dest": "vendor/p/vaxis-0.1.0-BWNV_FUICQAFZnTCL11TUvnUr1Y0_ZdqtXHhd51d76Rn"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz",
"dest": "vendor/p/N-V-__8AAKrHGAAs2shYq8UkE6bGcR1QJtLTyOE_lcosMn6t",
"sha256": "ea4191d68e437677e51f3aacde27829810144e931d397a327dc6035e2c39c50d"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
"dest": "vendor/p/N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
"sha256": "5cedcadde81b75e60f23e5e83b5dd2b8eb4efb9f8f79bd7a347d148aeb0530f8"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
"dest": "vendor/p/N-V-__8AAAzZywE3s51XfsLbP9eyEw57ae9swYB9aGB6fCMs",
"sha256": "9e4cd20abe96e6c4c6ede9c3057108860126e7be2e2c3e35515476c250be1c13"
},
{
"type": "archive",
"url": "https://github.com/vancluever/z2d/archive/1bf4bc81819385f4b24596445c9a7cf3b3592b08.tar.gz",
"dest": "vendor/p/z2d-0.6.1-j5P_HlerCgBokMgrkl9QhJUKXuZWBGdPnH7cSXwv_ScW",
"sha256": "c2226cebf2d48b2f80a42e6ced53f2a5b06e92306be2f8f1deffe5f4ead3ef45"
},
{
"type": "archive",
"url": "https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz",
"dest": "vendor/p/zf-0.10.3-OIRy8aiIAACLrBllz0zjxaH0aOe5oNm3KtEMyCntST-9",
"sha256": "de7ba535077fe2b678a5a7972585f002588d37244db08397feadf3d4907c0bb2"
},
{
"type": "git",
"url": "https://codeberg.org/atman/zg",
"commit": "4a002763419a34d61dcbb1f415821b83b9bf8ddc",
"dest": "vendor/p/zg-0.13.4-AAAAAGiZ7QLz4pvECFa_wG4O4TP4FLABHHbemH2KakWM"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/zig_js-12205a66d423259567764fa0fc60c82be35365c21aeb76c5a7dc99698401f4f6fefc.tar.gz",
"dest": "vendor/p/N-V-__8AAB9YCQBaZtQjJZVndk-g_GDIK-NTZcIa63bFp9yZ",
"sha256": "7f235e0956c2f5401a28963a261019953d00e3bf4cfc029830f2161196c3583d"
},
{
"type": "archive",
"url": "https://github.com/mitchellh/zig-objc/archive/3ab0d37c7d6b933d6ded1b3a35b6b60f05590a98.tar.gz",
"dest": "vendor/p/zig_objc-0.0.0-Ir_Sp3TyAADEVRTxXlScq3t_uKAM91MYNerZkHfbD0yt",
"sha256": "ce7d6d47ac614a60e56b8509dedf869e2e0d8b747c75e48aded11eec31b3357c"
},
{
"type": "archive",
"url": "https://codeberg.org/ifreund/zig-wayland/archive/f3c5d503e540ada8cbcb056420de240af0c094f7.tar.gz",
"dest": "vendor/p/wayland-0.4.0-dev-lQa1kjfIAQCmhhQu3xF0KH-94-TzeMXOqfnP0-Dg6Wyy",
"sha256": "13bec6675e403d86db3b55b39ae262f1e1bdfe24056dcd82824341c6308b5219"
},
{
"type": "git",
"url": "https://github.com/TUSF/zigimg",
"commit": "31268548fe3276c0e95f318a6c0d2ab10565b58d",
"dest": "vendor/p/zigimg-0.1.0-lly-O6N2EABOxke8dqyzCwhtUCAafqP35zC7wsZ4Ddxj"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz",
"dest": "vendor/p/ziglyph-0.11.2-AAAAAHPtHwB4Mbzn1KvOV7Wpjo82NYEc_v0WC8oCLrkf",
"sha256": "72c7bdf3e16df105235fe3fcf32c987dac49389190f4ced89b0ee31710f3f3d9"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz",
"dest": "vendor/p/N-V-__8AAB0eQwD-0MdOEBmz7intriBReIsIDNlukNVoNu6o",
"sha256": "17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c"
}
]

View File

@ -279,6 +279,13 @@ typedef struct {
ghostty_input_mods_e mods; ghostty_input_mods_e mods;
} ghostty_input_trigger_s; } ghostty_input_trigger_s;
typedef struct {
const char* action_key;
const char* action;
const char* title;
const char* description;
} ghostty_command_s;
typedef enum { typedef enum {
GHOSTTY_BUILD_MODE_DEBUG, GHOSTTY_BUILD_MODE_DEBUG,
GHOSTTY_BUILD_MODE_RELEASE_SAFE, GHOSTTY_BUILD_MODE_RELEASE_SAFE,
@ -350,6 +357,11 @@ typedef struct {
size_t len; size_t len;
} ghostty_config_color_list_s; } ghostty_config_color_list_s;
// config.Palette
typedef struct {
ghostty_config_color_s colors[256];
} ghostty_config_palette_s;
// apprt.Target.Key // apprt.Target.Key
typedef enum { typedef enum {
GHOSTTY_TARGET_APP, GHOSTTY_TARGET_APP,
@ -417,6 +429,13 @@ typedef enum {
GHOSTTY_FULLSCREEN_NON_NATIVE_PADDED_NOTCH, GHOSTTY_FULLSCREEN_NON_NATIVE_PADDED_NOTCH,
} ghostty_action_fullscreen_e; } ghostty_action_fullscreen_e;
// apprt.action.FloatWindow
typedef enum {
GHOSTTY_FLOAT_WINDOW_ON,
GHOSTTY_FLOAT_WINDOW_OFF,
GHOSTTY_FLOAT_WINDOW_TOGGLE,
} ghostty_action_float_window_e;
// apprt.action.SecureInput // apprt.action.SecureInput
typedef enum { typedef enum {
GHOSTTY_SECURE_INPUT_ON, GHOSTTY_SECURE_INPUT_ON,
@ -573,6 +592,7 @@ typedef enum {
GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW, GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS, GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL, GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE,
GHOSTTY_ACTION_TOGGLE_VISIBILITY, GHOSTTY_ACTION_TOGGLE_VISIBILITY,
GHOSTTY_ACTION_MOVE_TAB, GHOSTTY_ACTION_MOVE_TAB,
GHOSTTY_ACTION_GOTO_TAB, GHOSTTY_ACTION_GOTO_TAB,
@ -597,6 +617,7 @@ typedef enum {
GHOSTTY_ACTION_RENDERER_HEALTH, GHOSTTY_ACTION_RENDERER_HEALTH,
GHOSTTY_ACTION_OPEN_CONFIG, GHOSTTY_ACTION_OPEN_CONFIG,
GHOSTTY_ACTION_QUIT_TIMER, GHOSTTY_ACTION_QUIT_TIMER,
GHOSTTY_ACTION_FLOAT_WINDOW,
GHOSTTY_ACTION_SECURE_INPUT, GHOSTTY_ACTION_SECURE_INPUT,
GHOSTTY_ACTION_KEY_SEQUENCE, GHOSTTY_ACTION_KEY_SEQUENCE,
GHOSTTY_ACTION_COLOR_CHANGE, GHOSTTY_ACTION_COLOR_CHANGE,
@ -625,6 +646,7 @@ typedef union {
ghostty_action_mouse_over_link_s mouse_over_link; ghostty_action_mouse_over_link_s mouse_over_link;
ghostty_action_renderer_health_e renderer_health; ghostty_action_renderer_health_e renderer_health;
ghostty_action_quit_timer_e quit_timer; ghostty_action_quit_timer_e quit_timer;
ghostty_action_float_window_e float_window;
ghostty_action_secure_input_e secure_input; ghostty_action_secure_input_e secure_input;
ghostty_action_key_sequence_s key_sequence; ghostty_action_key_sequence_s key_sequence;
ghostty_action_color_change_s color_change; ghostty_action_color_change_s color_change;
@ -724,6 +746,7 @@ void ghostty_surface_set_color_scheme(ghostty_surface_t,
ghostty_color_scheme_e); ghostty_color_scheme_e);
ghostty_input_mods_e ghostty_surface_key_translation_mods(ghostty_surface_t, ghostty_input_mods_e ghostty_surface_key_translation_mods(ghostty_surface_t,
ghostty_input_mods_e); ghostty_input_mods_e);
void ghostty_surface_commands(ghostty_surface_t, ghostty_command_s**, size_t*);
bool ghostty_surface_key(ghostty_surface_t, ghostty_input_key_s); bool ghostty_surface_key(ghostty_surface_t, ghostty_input_key_s);
bool ghostty_surface_key_is_binding(ghostty_surface_t, ghostty_input_key_s); bool ghostty_surface_key_is_binding(ghostty_surface_t, ghostty_input_key_s);
void ghostty_surface_text(ghostty_surface_t, const char*, uintptr_t); void ghostty_surface_text(ghostty_surface_t, const char*, uintptr_t);

View File

@ -34,6 +34,10 @@
A5333E242B5A22D9008AEFF7 /* Ghostty.Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */; }; A5333E242B5A22D9008AEFF7 /* Ghostty.Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */; };
A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */; }; A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */; };
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; }; A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; };
A53A297B2DB2E49700B6E02C /* CommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A297A2DB2E49400B6E02C /* CommandPalette.swift */; };
A53A297F2DB4480F00B6E02C /* EventModifiers+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A297E2DB4480A00B6E02C /* EventModifiers+Extension.swift */; };
A53A29812DB44A6100B6E02C /* KeyboardShortcut+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A29802DB44A5E00B6E02C /* KeyboardShortcut+Extension.swift */; };
A53A29882DB69D2F00B6E02C /* TerminalCommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A29872DB69D2C00B6E02C /* TerminalCommandPalette.swift */; };
A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */; }; A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */; };
A53D0C8E2B53B0EA00305CE6 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; }; A53D0C8E2B53B0EA00305CE6 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; };
A53D0C942B53B43700305CE6 /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53D0C932B53B43700305CE6 /* iOSApp.swift */; }; A53D0C942B53B43700305CE6 /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53D0C932B53B43700305CE6 /* iOSApp.swift */; };
@ -138,6 +142,10 @@
A5333E212B5A2128008AEFF7 /* SurfaceView_AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurfaceView_AppKit.swift; sourceTree = "<group>"; }; A5333E212B5A2128008AEFF7 /* SurfaceView_AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurfaceView_AppKit.swift; sourceTree = "<group>"; };
A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; }; A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
A53A297A2DB2E49400B6E02C /* CommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandPalette.swift; sourceTree = "<group>"; };
A53A297E2DB4480A00B6E02C /* EventModifiers+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EventModifiers+Extension.swift"; sourceTree = "<group>"; };
A53A29802DB44A5E00B6E02C /* KeyboardShortcut+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyboardShortcut+Extension.swift"; sourceTree = "<group>"; };
A53A29872DB69D2C00B6E02C /* TerminalCommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalCommandPalette.swift; sourceTree = "<group>"; };
A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Action.swift; sourceTree = "<group>"; }; A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Action.swift; sourceTree = "<group>"; };
A53D0C932B53B43700305CE6 /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; }; A53D0C932B53B43700305CE6 /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
A53D0C992B543F3B00305CE6 /* Ghostty.App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.App.swift; sourceTree = "<group>"; }; A53D0C992B543F3B00305CE6 /* Ghostty.App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.App.swift; sourceTree = "<group>"; };
@ -267,6 +275,7 @@
A5CBD05A2CA0C5910017A1AE /* QuickTerminal */, A5CBD05A2CA0C5910017A1AE /* QuickTerminal */,
A5E112912AF73E4D00C6E0C2 /* ClipboardConfirmation */, A5E112912AF73E4D00C6E0C2 /* ClipboardConfirmation */,
A57D79252C9C8782001D522E /* Secure Input */, A57D79252C9C8782001D522E /* Secure Input */,
A53A29742DB2E04900B6E02C /* Command Palette */,
A534263E2A7DCC5800EBB7A2 /* Settings */, A534263E2A7DCC5800EBB7A2 /* Settings */,
A51BFC1C2B2FB5AB00E92F16 /* About */, A51BFC1C2B2FB5AB00E92F16 /* About */,
A54B0CE72D0CEC9800CBEFF8 /* Colorized Ghostty Icon */, A54B0CE72D0CEC9800CBEFF8 /* Colorized Ghostty Icon */,
@ -288,8 +297,10 @@
A52FFF582CAA4FF1000C6A5B /* Fullscreen.swift */, A52FFF582CAA4FF1000C6A5B /* Fullscreen.swift */,
A59630962AEE163600D64628 /* HostingWindow.swift */, A59630962AEE163600D64628 /* HostingWindow.swift */,
A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */, A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */,
A53A29802DB44A5E00B6E02C /* KeyboardShortcut+Extension.swift */,
A59FB5D02AE0DEA7009128F3 /* MetalView.swift */, A59FB5D02AE0DEA7009128F3 /* MetalView.swift */,
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */, A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */,
A53A297E2DB4480A00B6E02C /* EventModifiers+Extension.swift */,
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */, C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */,
A599CDAF2CF103F20049FA26 /* NSAppearance+Extension.swift */, A599CDAF2CF103F20049FA26 /* NSAppearance+Extension.swift */,
A5A2A3CB2D444AB80033CF96 /* NSApplication+Extension.swift */, A5A2A3CB2D444AB80033CF96 /* NSApplication+Extension.swift */,
@ -319,6 +330,15 @@
path = Settings; path = Settings;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A53A29742DB2E04900B6E02C /* Command Palette */ = {
isa = PBXGroup;
children = (
A53A297A2DB2E49400B6E02C /* CommandPalette.swift */,
A53A29872DB69D2C00B6E02C /* TerminalCommandPalette.swift */,
);
path = "Command Palette";
sourceTree = "<group>";
};
A53D0C912B53B41900305CE6 /* App */ = { A53D0C912B53B41900305CE6 /* App */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -667,6 +687,7 @@
A5A2A3CA2D4445E30033CF96 /* Dock.swift in Sources */, A5A2A3CA2D4445E30033CF96 /* Dock.swift in Sources */,
A51BFC222B2FB6B400E92F16 /* AboutView.swift in Sources */, A51BFC222B2FB6B400E92F16 /* AboutView.swift in Sources */,
A5278A9B2AA05B2600CD3039 /* Ghostty.Input.swift in Sources */, A5278A9B2AA05B2600CD3039 /* Ghostty.Input.swift in Sources */,
A53A29812DB44A6100B6E02C /* KeyboardShortcut+Extension.swift in Sources */,
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */, A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */,
C1F26EE92B76CBFC00404083 /* VibrantLayer.m in Sources */, C1F26EE92B76CBFC00404083 /* VibrantLayer.m in Sources */,
A59630972AEE163600D64628 /* HostingWindow.swift in Sources */, A59630972AEE163600D64628 /* HostingWindow.swift in Sources */,
@ -691,6 +712,8 @@
A5A2A3CC2D444ABB0033CF96 /* NSApplication+Extension.swift in Sources */, A5A2A3CC2D444ABB0033CF96 /* NSApplication+Extension.swift in Sources */,
A59630A22AF0415000D64628 /* Ghostty.TerminalSplit.swift in Sources */, A59630A22AF0415000D64628 /* Ghostty.TerminalSplit.swift in Sources */,
A5FEB3002ABB69450068369E /* main.swift in Sources */, A5FEB3002ABB69450068369E /* main.swift in Sources */,
A53A297F2DB4480F00B6E02C /* EventModifiers+Extension.swift in Sources */,
A53A297B2DB2E49700B6E02C /* CommandPalette.swift in Sources */,
A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */, A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */,
A51B78472AF4B58B00F3EDB9 /* TerminalWindow.swift in Sources */, A51B78472AF4B58B00F3EDB9 /* TerminalWindow.swift in Sources */,
A57D79272C9C879B001D522E /* SecureInput.swift in Sources */, A57D79272C9C879B001D522E /* SecureInput.swift in Sources */,
@ -706,6 +729,7 @@
A52FFF572CA90484000C6A5B /* QuickTerminalScreen.swift in Sources */, A52FFF572CA90484000C6A5B /* QuickTerminalScreen.swift in Sources */,
A5CC36132C9CD72D004D6760 /* SecureInputOverlay.swift in Sources */, A5CC36132C9CD72D004D6760 /* SecureInputOverlay.swift in Sources */,
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */, A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */,
A53A29882DB69D2F00B6E02C /* TerminalCommandPalette.swift in Sources */,
A51BFC202B2FB64F00E92F16 /* AboutController.swift in Sources */, A51BFC202B2FB64F00E92F16 /* AboutController.swift in Sources */,
A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */, A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */,
A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */, A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */,

View File

@ -52,6 +52,8 @@ class AppDelegate: NSObject,
@IBOutlet private var menuSelectSplitLeft: NSMenuItem? @IBOutlet private var menuSelectSplitLeft: NSMenuItem?
@IBOutlet private var menuSelectSplitRight: NSMenuItem? @IBOutlet private var menuSelectSplitRight: NSMenuItem?
@IBOutlet private var menuReturnToDefaultSize: NSMenuItem? @IBOutlet private var menuReturnToDefaultSize: NSMenuItem?
@IBOutlet private var menuFloatOnTop: NSMenuItem?
@IBOutlet private var menuUseAsDefault: NSMenuItem?
@IBOutlet private var menuIncreaseFontSize: NSMenuItem? @IBOutlet private var menuIncreaseFontSize: NSMenuItem?
@IBOutlet private var menuDecreaseFontSize: NSMenuItem? @IBOutlet private var menuDecreaseFontSize: NSMenuItem?
@ -59,6 +61,7 @@ class AppDelegate: NSObject,
@IBOutlet private var menuChangeTitle: NSMenuItem? @IBOutlet private var menuChangeTitle: NSMenuItem?
@IBOutlet private var menuQuickTerminal: NSMenuItem? @IBOutlet private var menuQuickTerminal: NSMenuItem?
@IBOutlet private var menuTerminalInspector: NSMenuItem? @IBOutlet private var menuTerminalInspector: NSMenuItem?
@IBOutlet private var menuCommandPalette: NSMenuItem?
@IBOutlet private var menuEqualizeSplits: NSMenuItem? @IBOutlet private var menuEqualizeSplits: NSMenuItem?
@IBOutlet private var menuMoveSplitDividerUp: NSMenuItem? @IBOutlet private var menuMoveSplitDividerUp: NSMenuItem?
@ -174,6 +177,12 @@ class AppDelegate: NSObject,
handler: localEventHandler) handler: localEventHandler)
// Notifications // Notifications
NotificationCenter.default.addObserver(
self,
selector: #selector(windowDidBecomeKey),
name: NSWindow.didBecomeKeyNotification,
object: nil
)
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
selector: #selector(quickTerminalDidChangeVisibility), selector: #selector(quickTerminalDidChangeVisibility),
@ -199,6 +208,7 @@ class AppDelegate: NSObject,
] ]
let center = UNUserNotificationCenter.current() let center = UNUserNotificationCenter.current()
center.setNotificationCategories([ center.setNotificationCategories([
UNNotificationCategory( UNNotificationCategory(
identifier: Ghostty.userNotificationCategory, identifier: Ghostty.userNotificationCategory,
@ -231,6 +241,9 @@ class AppDelegate: NSObject,
// If we're back manually then clear the hidden state because macOS handles it. // If we're back manually then clear the hidden state because macOS handles it.
self.hiddenState = nil self.hiddenState = nil
// Clear the dock badge when the app becomes active
self.setDockBadge(nil)
// First launch stuff // First launch stuff
if (!applicationHasBecomeActive) { if (!applicationHasBecomeActive) {
applicationHasBecomeActive = true applicationHasBecomeActive = true
@ -398,10 +411,12 @@ class AppDelegate: NSObject,
syncMenuShortcut(config, action: "increase_font_size:1", menuItem: self.menuIncreaseFontSize) syncMenuShortcut(config, action: "increase_font_size:1", menuItem: self.menuIncreaseFontSize)
syncMenuShortcut(config, action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize) syncMenuShortcut(config, action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize)
syncMenuShortcut(config, action: "reset_font_size", menuItem: self.menuResetFontSize) syncMenuShortcut(config, action: "reset_font_size", menuItem: self.menuResetFontSize)
syncMenuShortcut(config, action: "change_title_prompt", menuItem: self.menuChangeTitle) syncMenuShortcut(config, action: "prompt_surface_title", menuItem: self.menuChangeTitle)
syncMenuShortcut(config, action: "toggle_quick_terminal", menuItem: self.menuQuickTerminal) syncMenuShortcut(config, action: "toggle_quick_terminal", menuItem: self.menuQuickTerminal)
syncMenuShortcut(config, action: "toggle_visibility", menuItem: self.menuToggleVisibility) syncMenuShortcut(config, action: "toggle_visibility", menuItem: self.menuToggleVisibility)
syncMenuShortcut(config, action: "toggle_window_float_on_top", menuItem: self.menuFloatOnTop)
syncMenuShortcut(config, action: "inspector:toggle", menuItem: self.menuTerminalInspector) syncMenuShortcut(config, action: "inspector:toggle", menuItem: self.menuTerminalInspector)
syncMenuShortcut(config, action: "toggle_command_palette", menuItem: self.menuCommandPalette)
syncMenuShortcut(config, action: "toggle_secure_input", menuItem: self.menuSecureInput) syncMenuShortcut(config, action: "toggle_secure_input", menuItem: self.menuSecureInput)
@ -419,15 +434,15 @@ class AppDelegate: NSObject,
/// action string used for the Ghostty configuration. /// action string used for the Ghostty configuration.
private func syncMenuShortcut(_ config: Ghostty.Config, action: String, menuItem: NSMenuItem?) { private func syncMenuShortcut(_ config: Ghostty.Config, action: String, menuItem: NSMenuItem?) {
guard let menu = menuItem else { return } guard let menu = menuItem else { return }
guard let equiv = config.keyEquivalent(for: action) else { guard let shortcut = config.keyboardShortcut(for: action) else {
// No shortcut, clear the menu item // No shortcut, clear the menu item
menu.keyEquivalent = "" menu.keyEquivalent = ""
menu.keyEquivalentModifierMask = [] menu.keyEquivalentModifierMask = []
return return
} }
menu.keyEquivalent = equiv.key menu.keyEquivalent = shortcut.key.character.description
menu.keyEquivalentModifierMask = equiv.modifiers menu.keyEquivalentModifierMask = .init(swiftUIFlags: shortcut.modifiers)
} }
private func focusedSurface() -> ghostty_surface_t? { private func focusedSurface() -> ghostty_surface_t? {
@ -491,6 +506,10 @@ class AppDelegate: NSObject,
return event return event
} }
@objc private func windowDidBecomeKey(_ notification: Notification) {
syncFloatOnTopMenu(notification.object as? NSWindow)
}
@objc private func quickTerminalDidChangeVisibility(_ notification: Notification) { @objc private func quickTerminalDidChangeVisibility(_ notification: Notification) {
guard let quickController = notification.object as? QuickTerminalController else { return } guard let quickController = notification.object as? QuickTerminalController else { return }
self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off } self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off }
@ -511,6 +530,53 @@ class AppDelegate: NSObject,
@objc private func ghosttyBellDidRing(_ notification: Notification) { @objc private func ghosttyBellDidRing(_ notification: Notification) {
// Bounce the dock icon if we're not focused. // Bounce the dock icon if we're not focused.
NSApp.requestUserAttention(.informationalRequest) NSApp.requestUserAttention(.informationalRequest)
// Handle setting the dock badge based on permissions
ghosttyUpdateBadgeForBell()
}
private func ghosttyUpdateBadgeForBell() {
let center = UNUserNotificationCenter.current()
center.getNotificationSettings { settings in
switch settings.authorizationStatus {
case .authorized:
// Already authorized, check badge setting and set if enabled
if settings.badgeSetting == .enabled {
DispatchQueue.main.async {
self.setDockBadge()
}
}
case .notDetermined:
// Not determined yet, request authorization for badge
center.requestAuthorization(options: [.badge]) { granted, error in
if let error = error {
Self.logger.warning("Error requesting badge authorization: \(error)")
return
}
if granted {
// Permission granted, set the badge
DispatchQueue.main.async {
self.setDockBadge()
}
}
}
case .denied, .provisional, .ephemeral:
// In these known non-authorized states, do not attempt to set the badge.
break
@unknown default:
// Handle future unknown states by doing nothing.
break
}
}
}
private func setDockBadge(_ label: String? = "") {
NSApp.dockTile.badgeLabel = label
NSApp.dockTile.display()
} }
private func ghosttyConfigDidChange(config: Ghostty.Config) { private func ghosttyConfigDidChange(config: Ghostty.Config) {
@ -790,12 +856,12 @@ class AppDelegate: NSObject,
hiddenState?.restore() hiddenState?.restore()
hiddenState = nil hiddenState = nil
} }
@IBAction func bringAllToFront(_ sender: Any) { @IBAction func bringAllToFront(_ sender: Any) {
if !NSApp.isActive { if !NSApp.isActive {
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
} }
NSApplication.shared.arrangeInFront(sender) NSApplication.shared.arrangeInFront(sender)
} }
@ -846,3 +912,50 @@ class AppDelegate: NSObject,
} }
} }
} }
// MARK: Floating Windows
extension AppDelegate {
func syncFloatOnTopMenu(_ window: NSWindow?) {
guard let window = (window ?? NSApp.keyWindow) as? TerminalWindow else {
// If some other window became key we always turn this off
self.menuFloatOnTop?.state = .off
return
}
self.menuFloatOnTop?.state = window.level == .floating ? .on : .off
}
@IBAction func floatOnTop(_ menuItem: NSMenuItem) {
menuItem.state = menuItem.state == .on ? .off : .on
guard let window = NSApp.keyWindow else { return }
window.level = menuItem.state == .on ? .floating : .normal
}
@IBAction func useAsDefault(_ sender: NSMenuItem) {
let ud = UserDefaults.standard
let key = TerminalWindow.defaultLevelKey
if (menuFloatOnTop?.state == .on) {
ud.set(NSWindow.Level.floating, forKey: key)
} else {
ud.removeObject(forKey: key)
}
}
}
// MARK: NSMenuItemValidation
extension AppDelegate: NSMenuItemValidation {
func validateMenuItem(_ item: NSMenuItem) -> Bool {
switch item.action {
case #selector(floatOnTop(_:)),
#selector(useAsDefault(_:)):
// Float on top items only active if the key window is a primary
// terminal window (not quick terminal).
return NSApp.keyWindow is TerminalWindow
default:
return true
}
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"> <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -21,9 +21,11 @@
<outlet property="menuCloseAllWindows" destination="yKr-Vi-Yqw" id="Zet-Ir-zbm"/> <outlet property="menuCloseAllWindows" destination="yKr-Vi-Yqw" id="Zet-Ir-zbm"/>
<outlet property="menuCloseTab" destination="Obb-Mk-j8J" id="Gda-L0-gdz"/> <outlet property="menuCloseTab" destination="Obb-Mk-j8J" id="Gda-L0-gdz"/>
<outlet property="menuCloseWindow" destination="W5w-UZ-crk" id="6ff-BT-ENV"/> <outlet property="menuCloseWindow" destination="W5w-UZ-crk" id="6ff-BT-ENV"/>
<outlet property="menuCommandPalette" destination="et6-de-Mh7" id="53t-cu-dm5"/>
<outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/> <outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/>
<outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/> <outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/>
<outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/> <outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/>
<outlet property="menuFloatOnTop" destination="uRj-7z-1Nh" id="94n-o9-Jol"/>
<outlet property="menuIncreaseFontSize" destination="CIH-ey-Z6x" id="hkc-9C-80E"/> <outlet property="menuIncreaseFontSize" destination="CIH-ey-Z6x" id="hkc-9C-80E"/>
<outlet property="menuMoveSplitDividerDown" destination="Zj7-2W-fdF" id="997-LL-nlN"/> <outlet property="menuMoveSplitDividerDown" destination="Zj7-2W-fdF" id="997-LL-nlN"/>
<outlet property="menuMoveSplitDividerLeft" destination="wSR-ny-j1a" id="HCZ-CI-2ob"/> <outlet property="menuMoveSplitDividerLeft" destination="wSR-ny-j1a" id="HCZ-CI-2ob"/>
@ -55,6 +57,7 @@
<outlet property="menuTerminalInspector" destination="QwP-M5-fvh" id="wJi-Dh-S9f"/> <outlet property="menuTerminalInspector" destination="QwP-M5-fvh" id="wJi-Dh-S9f"/>
<outlet property="menuToggleFullScreen" destination="8kY-Pi-KaY" id="yQg-6V-OO6"/> <outlet property="menuToggleFullScreen" destination="8kY-Pi-KaY" id="yQg-6V-OO6"/>
<outlet property="menuToggleVisibility" destination="DOX-wA-ilh" id="iBj-Bc-2bq"/> <outlet property="menuToggleVisibility" destination="DOX-wA-ilh" id="iBj-Bc-2bq"/>
<outlet property="menuUseAsDefault" destination="TrB-O8-g8H" id="af4-Jh-2HU"/>
<outlet property="menuZoomSplit" destination="oPd-mn-IEH" id="wTu-jK-egI"/> <outlet property="menuZoomSplit" destination="oPd-mn-IEH" id="wTu-jK-egI"/>
</connections> </connections>
</customObject> </customObject>
@ -249,6 +252,12 @@
</connections> </connections>
</menuItem> </menuItem>
<menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/> <menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/>
<menuItem title="Command Palette" id="et6-de-Mh7">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleCommandPalette:" target="-1" id="FcT-XD-gM1"/>
</connections>
</menuItem>
<menuItem title="Change Title..." id="24I-xg-qIq"> <menuItem title="Change Title..." id="24I-xg-qIq">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
<connections> <connections>
@ -395,6 +404,19 @@
<action selector="returnToDefaultSize:" target="-1" id="Bpt-GO-UU1"/> <action selector="returnToDefaultSize:" target="-1" id="Bpt-GO-UU1"/>
</connections> </connections>
</menuItem> </menuItem>
<menuItem isSeparatorItem="YES" id="Cm3-gn-vtj"/>
<menuItem title="Float on Top" id="uRj-7z-1Nh">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="floatOnTop:" target="bbz-4X-AYv" id="N58-PO-7pj"/>
</connections>
</menuItem>
<menuItem title="Use as Default" id="TrB-O8-g8H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAsDefault:" target="bbz-4X-AYv" id="RHA-Nl-L2U"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="CpM-rI-Sc1"/> <menuItem isSeparatorItem="YES" id="CpM-rI-Sc1"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ"> <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>

View File

@ -0,0 +1,276 @@
import SwiftUI
struct CommandOption: Identifiable, Hashable {
let id = UUID()
let title: String
let description: String?
let symbols: [String]?
let action: () -> Void
static func == (lhs: CommandOption, rhs: CommandOption) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
struct CommandPaletteView: View {
@Binding var isPresented: Bool
var backgroundColor: Color = Color(nsColor: .windowBackgroundColor)
var options: [CommandOption]
@State private var query = ""
@State private var selectedIndex: UInt?
@State private var hoveredOptionID: UUID?
// The options that we should show, taking into account any filtering from
// the query.
var filteredOptions: [CommandOption] {
if query.isEmpty {
return options
} else {
return options.filter { $0.title.localizedCaseInsensitiveContains(query) }
}
}
var selectedOption: CommandOption? {
guard let selectedIndex else { return nil }
return if selectedIndex < filteredOptions.count {
filteredOptions[Int(selectedIndex)]
} else {
filteredOptions.last
}
}
var body: some View {
let scheme: ColorScheme = if OSColor(backgroundColor).isLightColor {
.light
} else {
.dark
}
VStack(alignment: .leading, spacing: 0) {
CommandPaletteQuery(query: $query) { event in
switch (event) {
case .exit:
isPresented = false
case .submit:
isPresented = false
selectedOption?.action()
case .move(.up):
if filteredOptions.isEmpty { break }
let current = selectedIndex ?? UInt(filteredOptions.count)
selectedIndex = (current == 0)
? UInt(filteredOptions.count - 1)
: current - 1
case .move(.down):
if filteredOptions.isEmpty { break }
let current = selectedIndex ?? UInt.max
selectedIndex = (current >= UInt(filteredOptions.count - 1))
? 0
: current + 1
case .move(_):
// Unknown, ignore
break
}
}
.onChange(of: query) { newValue in
// If the user types a query then we want to make sure the first
// value is selected. If the user clears the query and we were selecting
// the first, we unset any selection.
if !newValue.isEmpty {
if selectedIndex == nil {
selectedIndex = 0
}
} else {
if let selectedIndex, selectedIndex == 0 {
self.selectedIndex = nil
}
}
}
Divider()
CommandTable(
options: filteredOptions,
selectedIndex: $selectedIndex,
hoveredOptionID: $hoveredOptionID) { option in
isPresented = false
option.action()
}
}
.frame(maxWidth: 500)
.background(
ZStack {
Rectangle()
.fill(.ultraThinMaterial)
Rectangle()
.fill(backgroundColor)
.blendMode(.color)
}
.compositingGroup()
)
.clipShape(RoundedRectangle(cornerRadius: 10))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color(nsColor: .tertiaryLabelColor).opacity(0.75))
)
.shadow(radius: 32, x: 0, y: 12)
.padding()
.environment(\.colorScheme, scheme)
}
}
/// The text field for building the query for the command palette.
fileprivate struct CommandPaletteQuery: View {
@Binding var query: String
var onEvent: ((KeyboardEvent) -> Void)? = nil
@FocusState private var isTextFieldFocused: Bool
enum KeyboardEvent {
case exit
case submit
case move(MoveCommandDirection)
}
var body: some View {
ZStack {
Group {
Button { onEvent?(.move(.up)) } label: { Color.clear }
.buttonStyle(PlainButtonStyle())
.keyboardShortcut(.upArrow, modifiers: [])
Button { onEvent?(.move(.down)) } label: { Color.clear }
.buttonStyle(PlainButtonStyle())
.keyboardShortcut(.downArrow, modifiers: [])
Button { onEvent?(.move(.up)) } label: { Color.clear }
.buttonStyle(PlainButtonStyle())
.keyboardShortcut(.init("p"), modifiers: [.control])
Button { onEvent?(.move(.down)) } label: { Color.clear }
.buttonStyle(PlainButtonStyle())
.keyboardShortcut(.init("n"), modifiers: [.control])
}
.frame(width: 0, height: 0)
.accessibilityHidden(true)
TextField("Execute a command…", text: $query)
.padding()
.font(.system(size: 20, weight: .light))
.frame(height: 48)
.textFieldStyle(.plain)
.focused($isTextFieldFocused)
.onAppear {
isTextFieldFocused = true
}
.onChange(of: isTextFieldFocused) { focused in
if !focused {
onEvent?(.exit)
}
}
.onExitCommand { onEvent?(.exit) }
.onMoveCommand { onEvent?(.move($0)) }
.onSubmit { onEvent?(.submit) }
}
}
}
fileprivate struct CommandTable: View {
var options: [CommandOption]
@Binding var selectedIndex: UInt?
@Binding var hoveredOptionID: UUID?
var action: (CommandOption) -> Void
var body: some View {
if options.isEmpty {
Text("No matches")
.foregroundStyle(.secondary)
.padding()
} else {
ScrollViewReader { proxy in
ScrollView {
VStack(alignment: .leading, spacing: 0) {
ForEach(Array(options.enumerated()), id: \.1.id) { index, option in
CommandRow(
option: option,
isSelected: {
if let selected = selectedIndex {
return selected == index ||
(selected >= options.count &&
index == options.count - 1)
} else {
return false
}
}(),
hoveredID: $hoveredOptionID
) {
action(option)
}
}
}
.padding(10)
}
.frame(maxHeight: 200)
.onChange(of: selectedIndex) { _ in
guard let selectedIndex,
selectedIndex < options.count else { return }
proxy.scrollTo(
options[Int(selectedIndex)].id)
}
}
}
}
}
/// A single row in the command palette.
fileprivate struct CommandRow: View {
let option: CommandOption
var isSelected: Bool
@Binding var hoveredID: UUID?
var action: () -> Void
var body: some View {
Button(action: action) {
HStack {
Text(option.title)
Spacer()
if let symbols = option.symbols {
ShortcutSymbolsView(symbols: symbols)
.foregroundStyle(.secondary)
}
}
.padding(8)
.background(
isSelected
? Color.accentColor.opacity(0.2)
: (hoveredID == option.id
? Color.secondary.opacity(0.2)
: Color.clear)
)
.cornerRadius(5)
}
.help(option.description ?? "")
.buttonStyle(.plain)
.onHover { hovering in
hoveredID = hovering ? option.id : nil
}
}
}
/// A row of Text representing a shortcut.
fileprivate struct ShortcutSymbolsView: View {
let symbols: [String]
var body: some View {
HStack(spacing: 1) {
ForEach(symbols, id: \.self) { symbol in
Text(symbol)
.frame(minWidth: 13)
}
}
}
}

View File

@ -0,0 +1,105 @@
import SwiftUI
import GhosttyKit
struct TerminalCommandPaletteView: View {
/// The surface that this command palette represents.
let surfaceView: Ghostty.SurfaceView
/// Set this to true to show the view, this will be set to false if any actions
/// result in the view disappearing.
@Binding var isPresented: Bool
/// The configuration so we can lookup keyboard shortcuts.
@ObservedObject var ghosttyConfig: Ghostty.Config
/// The callback when an action is submitted.
var onAction: ((String) -> Void)
// The commands available to the command palette.
private var commandOptions: [CommandOption] {
guard let surface = surfaceView.surface else { return [] }
var ptr: UnsafeMutablePointer<ghostty_command_s>? = nil
var count: Int = 0
ghostty_surface_commands(surface, &ptr, &count)
guard let ptr else { return [] }
let buffer = UnsafeBufferPointer(start: ptr, count: count)
return Array(buffer).filter { c in
let key = String(cString: c.action_key)
switch (key) {
case "toggle_tab_overview",
"toggle_window_decorations":
return false
default:
return true
}
}.map { c in
let action = String(cString: c.action)
return CommandOption(
title: String(cString: c.title),
description: String(cString: c.description),
symbols: ghosttyConfig.keyboardShortcut(for: action)?.keyList
) {
onAction(action)
}
}
}
var body: some View {
ZStack {
if isPresented {
GeometryReader { geometry in
VStack {
Spacer().frame(height: geometry.size.height * 0.05)
ResponderChainInjector(responder: surfaceView)
.frame(width: 0, height: 0)
CommandPaletteView(
isPresented: $isPresented,
backgroundColor: ghosttyConfig.backgroundColor,
options: commandOptions
)
.transition(
.move(edge: .top)
.combined(with: .opacity)
.animation(.spring(response: 0.4, dampingFraction: 0.8))
) // Spring animation
.zIndex(1) // Ensure it's on top
Spacer()
}
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .top)
}
}
}
.onChange(of: isPresented) { newValue in
// When the command palette disappears we need to send focus back to the
// surface view we were overlaid on top of. There's probably a better way
// to handle the first responder state here but I don't know it.
if !newValue {
// Has to be on queue because onChange happens on a user-interactive
// thread and Xcode is mad about this call on that.
DispatchQueue.main.async {
surfaceView.window?.makeFirstResponder(surfaceView)
}
}
}
}
}
/// This is done to ensure that the given view is in the responder chain.
fileprivate struct ResponderChainInjector: NSViewRepresentable {
let responder: NSResponder
func makeNSView(context: Context) -> NSView {
let dummy = NSView()
DispatchQueue.main.async {
dummy.nextResponder = responder
}
return dummy
}
func updateNSView(_ nsView: NSView, context: Context) {}
}

View File

@ -1,5 +1,6 @@
import Cocoa import Cocoa
import SwiftUI import SwiftUI
import Combine
import GhosttyKit import GhosttyKit
/// A base class for windows that can contain Ghostty windows. This base class implements /// A base class for windows that can contain Ghostty windows. This base class implements
@ -45,6 +46,9 @@ class BaseTerminalController: NSWindowController,
didSet { surfaceTreeDidChange(from: oldValue, to: surfaceTree) } didSet { surfaceTreeDidChange(from: oldValue, to: surfaceTree) }
} }
/// This can be set to show/hide the command palette.
@Published var commandPaletteIsShowing: Bool = false
/// Whether the terminal surface should focus when the mouse is over it. /// Whether the terminal surface should focus when the mouse is over it.
var focusFollowsMouse: Bool { var focusFollowsMouse: Bool {
self.derivedConfig.focusFollowsMouse self.derivedConfig.focusFollowsMouse
@ -68,6 +72,9 @@ class BaseTerminalController: NSWindowController,
/// The configuration derived from the Ghostty config so we don't need to rely on references. /// The configuration derived from the Ghostty config so we don't need to rely on references.
private var derivedConfig: DerivedConfig private var derivedConfig: DerivedConfig
/// The cancellables related to our focused surface.
private var focusedSurfaceCancellables: Set<AnyCancellable> = []
struct SavedFrame { struct SavedFrame {
let window: NSRect let window: NSRect
let screen: NSRect let screen: NSRect
@ -107,6 +114,16 @@ class BaseTerminalController: NSWindowController,
selector: #selector(ghosttyConfigDidChangeBase(_:)), selector: #selector(ghosttyConfigDidChangeBase(_:)),
name: .ghosttyConfigDidChange, name: .ghosttyConfigDidChange,
object: nil) object: nil)
center.addObserver(
self,
selector: #selector(ghosttyCommandPaletteDidToggle(_:)),
name: .ghosttyCommandPaletteDidToggle,
object: nil)
center.addObserver(
self,
selector: #selector(ghosttyMaximizeDidToggle(_:)),
name: .ghosttyMaximizeDidToggle,
object: nil)
// Listen for local events that we need to know of outside of // Listen for local events that we need to know of outside of
// single surface handlers. // single surface handlers.
@ -144,6 +161,7 @@ class BaseTerminalController: NSWindowController,
// Our focus state requires that this window is key and our currently // Our focus state requires that this window is key and our currently
// focused surface is the surface in this leaf. // focused surface is the surface in this leaf.
let focused: Bool = (window?.isKeyWindow ?? false) && let focused: Bool = (window?.isKeyWindow ?? false) &&
!commandPaletteIsShowing &&
focusedSurface != nil && focusedSurface != nil &&
leaf.surface == focusedSurface! leaf.surface == focusedSurface!
leaf.surface.focusDidChange(focused) leaf.surface.focusDidChange(focused)
@ -209,16 +227,29 @@ class BaseTerminalController: NSWindowController,
// We only care if the configuration is a global configuration, not a // We only care if the configuration is a global configuration, not a
// surface-specific one. // surface-specific one.
guard notification.object == nil else { return } guard notification.object == nil else { return }
// Get our managed configuration object out // Get our managed configuration object out
guard let config = notification.userInfo?[ guard let config = notification.userInfo?[
Notification.Name.GhosttyConfigChangeKey Notification.Name.GhosttyConfigChangeKey
] as? Ghostty.Config else { return } ] as? Ghostty.Config else { return }
// Update our derived config // Update our derived config
self.derivedConfig = DerivedConfig(config) self.derivedConfig = DerivedConfig(config)
} }
@objc private func ghosttyCommandPaletteDidToggle(_ notification: Notification) {
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
guard surfaceTree?.contains(view: surfaceView) ?? false else { return }
toggleCommandPalette(nil)
}
@objc private func ghosttyMaximizeDidToggle(_ notification: Notification) {
guard let window else { return }
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
guard surfaceTree?.contains(view: surfaceView) ?? false else { return }
window.zoom(nil)
}
// MARK: Local Events // MARK: Local Events
private func localEventHandler(_ event: NSEvent) -> NSEvent? { private func localEventHandler(_ event: NSEvent) -> NSEvent? {
@ -259,7 +290,26 @@ class BaseTerminalController: NSWindowController,
func surfaceTreeDidChange() {} func surfaceTreeDidChange() {}
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?) { func focusedSurfaceDidChange(to: Ghostty.SurfaceView?) {
let lastFocusedSurface = focusedSurface
focusedSurface = to focusedSurface = to
// Important to cancel any prior subscriptions
focusedSurfaceCancellables = []
// Setup our title listener. If we have a focused surface we always use that.
// Otherwise, we try to use our last focused surface. In either case, we only
// want to care if the surface is in the tree so we don't listen to titles of
// closed surfaces.
if let titleSurface = focusedSurface ?? lastFocusedSurface,
surfaceTree?.contains(view: titleSurface) ?? false {
// If we have a surface, we want to listen for title changes.
titleSurface.$title
.sink { [weak self] in self?.titleDidChange(to: $0) }
.store(in: &focusedSurfaceCancellables)
} else {
// There is no surface to listen to titles for.
titleDidChange(to: "👻")
}
} }
func titleDidChange(to: String) { func titleDidChange(to: String) {
@ -288,6 +338,15 @@ class BaseTerminalController: NSWindowController,
func zoomStateDidChange(to: Bool) {} func zoomStateDidChange(to: Bool) {}
func performAction(_ action: String, on surfaceView: Ghostty.SurfaceView) {
guard let surface = surfaceView.surface else { return }
let len = action.utf8CString.count
if (len == 0) { return }
_ = action.withCString { cString in
ghostty_surface_binding_action(surface, cString, UInt(len - 1))
}
}
// MARK: Fullscreen // MARK: Fullscreen
/// Toggle fullscreen for the given mode. /// Toggle fullscreen for the given mode.
@ -337,14 +396,6 @@ class BaseTerminalController: NSWindowController,
} }
} }
func fullscreenDidChange() {
// For some reason focus can get lost when we change fullscreen. Regardless of
// mode above we just move it back.
if let focusedSurface {
Ghostty.moveFocus(to: focusedSurface)
}
}
// MARK: Clipboard Confirmation // MARK: Clipboard Confirmation
@objc private func onConfirmClipboardRequest(notification: SwiftUI.Notification) { @objc private func onConfirmClipboardRequest(notification: SwiftUI.Notification) {
@ -619,6 +670,10 @@ class BaseTerminalController: NSWindowController,
ghostty.changeFontSize(surface: surface, .reset) ghostty.changeFontSize(surface: surface, .reset)
} }
@IBAction func toggleCommandPalette(_ sender: Any?) {
commandPaletteIsShowing.toggle()
}
@objc func resetTerminal(_ sender: Any) { @objc func resetTerminal(_ sender: Any) {
guard let surface = focusedSurface?.surface else { return } guard let surface = focusedSurface?.surface else { return }
ghostty.resetTerminal(surface: surface) ghostty.resetTerminal(surface: surface)

View File

@ -121,9 +121,7 @@ class TerminalController: BaseTerminalController {
} }
override func fullscreenDidChange() { func fullscreenDidChange() {
super.fullscreenDidChange()
// When our fullscreen state changes, we resync our appearance because some // When our fullscreen state changes, we resync our appearance because some
// properties change when fullscreen or not. // properties change when fullscreen or not.
guard let focusedSurface else { return } guard let focusedSurface else { return }
@ -192,7 +190,7 @@ class TerminalController: BaseTerminalController {
} }
let action = "goto_tab:\(tab)" let action = "goto_tab:\(tab)"
if let equiv = ghostty.config.keyEquivalent(for: action) { if let equiv = ghostty.config.keyboardShortcut(for: action) {
window.keyEquivalent = "\(equiv)" window.keyEquivalent = "\(equiv)"
} else { } else {
window.keyEquivalent = "" window.keyEquivalent = ""

View File

@ -8,9 +8,6 @@ protocol TerminalViewDelegate: AnyObject {
/// Called when the currently focused surface changed. This can be nil. /// Called when the currently focused surface changed. This can be nil.
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?) func focusedSurfaceDidChange(to: Ghostty.SurfaceView?)
/// The title of the terminal should change.
func titleDidChange(to: String)
/// The URL of the pwd should change. /// The URL of the pwd should change.
func pwdDidChange(to: URL?) func pwdDidChange(to: URL?)
@ -23,6 +20,9 @@ protocol TerminalViewDelegate: AnyObject {
/// This is called when a split is zoomed. /// This is called when a split is zoomed.
func zoomStateDidChange(to: Bool) func zoomStateDidChange(to: Bool)
/// Perform an action. At the time of writing this is only triggered by the command palette.
func performAction(_ action: String, on: Ghostty.SurfaceView)
} }
/// The view model is a required implementation for TerminalView callers. This contains /// The view model is a required implementation for TerminalView callers. This contains
@ -32,6 +32,9 @@ protocol TerminalViewModel: ObservableObject {
/// The tree of terminal surfaces (splits) within the view. This is mutated by TerminalView /// The tree of terminal surfaces (splits) within the view. This is mutated by TerminalView
/// and children. This should be @Published. /// and children. This should be @Published.
var surfaceTree: Ghostty.SplitNode? { get set } var surfaceTree: Ghostty.SplitNode? { get set }
/// The command palette state.
var commandPaletteIsShowing: Bool { get set }
} }
/// The main terminal view. This terminal view supports splits. /// The main terminal view. This terminal view supports splits.
@ -44,24 +47,19 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
// An optional delegate to receive information about terminal changes. // An optional delegate to receive information about terminal changes.
weak var delegate: (any TerminalViewDelegate)? = nil weak var delegate: (any TerminalViewDelegate)? = nil
// The most recently focused surface, equal to focusedSurface when
// it is non-nil.
@State private var lastFocusedSurface: Weak<Ghostty.SurfaceView> = .init()
// This seems like a crutch after switching from SwiftUI to AppKit lifecycle. // This seems like a crutch after switching from SwiftUI to AppKit lifecycle.
@FocusState private var focused: Bool @FocusState private var focused: Bool
// Various state values sent back up from the currently focused terminals. // Various state values sent back up from the currently focused terminals.
@FocusedValue(\.ghosttySurfaceView) private var focusedSurface @FocusedValue(\.ghosttySurfaceView) private var focusedSurface
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle
@FocusedValue(\.ghosttySurfacePwd) private var surfacePwd @FocusedValue(\.ghosttySurfacePwd) private var surfacePwd
@FocusedValue(\.ghosttySurfaceZoomed) private var zoomedSplit @FocusedValue(\.ghosttySurfaceZoomed) private var zoomedSplit
@FocusedValue(\.ghosttySurfaceCellSize) private var cellSize @FocusedValue(\.ghosttySurfaceCellSize) private var cellSize
// The title for our window
private var title: String {
if let surfaceTitle, !surfaceTitle.isEmpty {
return surfaceTitle
}
return "👻"
}
// The pwd of the focused surface as a URL // The pwd of the focused surface as a URL
private var pwdURL: URL? { private var pwdURL: URL? {
guard let surfacePwd, surfacePwd != "" else { return nil } guard let surfacePwd, surfacePwd != "" else { return nil }
@ -75,42 +73,55 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
case .error: case .error:
ErrorView() ErrorView()
case .ready: case .ready:
VStack(spacing: 0) { ZStack {
// If we're running in debug mode we show a warning so that users VStack(spacing: 0) {
// know that performance will be degraded. // If we're running in debug mode we show a warning so that users
if (Ghostty.info.mode == GHOSTTY_BUILD_MODE_DEBUG || Ghostty.info.mode == GHOSTTY_BUILD_MODE_RELEASE_SAFE) { // know that performance will be degraded.
DebugBuildWarningView() if (Ghostty.info.mode == GHOSTTY_BUILD_MODE_DEBUG || Ghostty.info.mode == GHOSTTY_BUILD_MODE_RELEASE_SAFE) {
} DebugBuildWarningView()
}
Ghostty.TerminalSplit(node: $viewModel.surfaceTree) Ghostty.TerminalSplit(node: $viewModel.surfaceTree)
.environmentObject(ghostty) .environmentObject(ghostty)
.focused($focused) .focused($focused)
.onAppear { self.focused = true } .onAppear { self.focused = true }
.onChange(of: focusedSurface) { newValue in .onChange(of: focusedSurface) { newValue in
self.delegate?.focusedSurfaceDidChange(to: newValue) // We want to keep track of our last focused surface so even if
} // we lose focus we keep this set to the last non-nil value.
.onChange(of: title) { newValue in if newValue != nil {
self.delegate?.titleDidChange(to: newValue) lastFocusedSurface = .init(newValue)
} self.delegate?.focusedSurfaceDidChange(to: newValue)
.onChange(of: pwdURL) { newValue in }
self.delegate?.pwdDidChange(to: newValue) }
} .onChange(of: pwdURL) { newValue in
.onChange(of: cellSize) { newValue in self.delegate?.pwdDidChange(to: newValue)
guard let size = newValue else { return } }
self.delegate?.cellSizeDidChange(to: size) .onChange(of: cellSize) { newValue in
} guard let size = newValue else { return }
.onChange(of: viewModel.surfaceTree?.hashValue) { _ in self.delegate?.cellSizeDidChange(to: size)
// This is funky, but its the best way I could think of to detect }
// ANY CHANGE within the deeply nested surface tree -- detecting a change .onChange(of: viewModel.surfaceTree?.hashValue) { _ in
// in the hash value. // This is funky, but its the best way I could think of to detect
self.delegate?.surfaceTreeDidChange() // ANY CHANGE within the deeply nested surface tree -- detecting a change
} // in the hash value.
.onChange(of: zoomedSplit) { newValue in self.delegate?.surfaceTreeDidChange()
self.delegate?.zoomStateDidChange(to: newValue ?? false) }
.onChange(of: zoomedSplit) { newValue in
self.delegate?.zoomStateDidChange(to: newValue ?? false)
}
}
// Ignore safe area to extend up in to the titlebar region if we have the "hidden" titlebar style
.ignoresSafeArea(.container, edges: ghostty.config.macosTitlebarStyle == "hidden" ? .top : [])
if let surfaceView = lastFocusedSurface.value {
TerminalCommandPaletteView(
surfaceView: surfaceView,
isPresented: $viewModel.commandPaletteIsShowing,
ghosttyConfig: ghostty.config) { action in
self.delegate?.performAction(action, on: surfaceView)
} }
}
} }
// Ignore safe area to extend up in to the titlebar region if we have the "hidden" titlebar style
.ignoresSafeArea(.container, edges: ghostty.config.macosTitlebarStyle == "hidden" ? .top : [])
} }
} }
} }

View File

@ -1,6 +1,9 @@
import Cocoa import Cocoa
class TerminalWindow: NSWindow { class TerminalWindow: NSWindow {
/// This is the key in UserDefaults to use for the default `level` value.
static let defaultLevelKey: String = "TerminalDefaultLevel"
@objc dynamic var keyEquivalent: String = "" @objc dynamic var keyEquivalent: String = ""
/// This is used to determine if certain elements should be drawn light or dark and should /// This is used to determine if certain elements should be drawn light or dark and should
@ -63,6 +66,8 @@ class TerminalWindow: NSWindow {
if titlebarTabs { if titlebarTabs {
generateToolbar() generateToolbar()
} }
level = UserDefaults.standard.value(forKey: Self.defaultLevelKey) as? NSWindow.Level ?? .normal
} }
deinit { deinit {

View File

@ -496,6 +496,9 @@ extension Ghostty {
case GHOSTTY_ACTION_OPEN_CONFIG: case GHOSTTY_ACTION_OPEN_CONFIG:
ghostty_config_open() ghostty_config_open()
case GHOSTTY_ACTION_FLOAT_WINDOW:
toggleFloatWindow(app, target: target, mode: action.action.float_window)
case GHOSTTY_ACTION_SECURE_INPUT: case GHOSTTY_ACTION_SECURE_INPUT:
toggleSecureInput(app, target: target, mode: action.action.secure_input) toggleSecureInput(app, target: target, mode: action.action.secure_input)
@ -520,6 +523,12 @@ extension Ghostty {
case GHOSTTY_ACTION_RENDERER_HEALTH: case GHOSTTY_ACTION_RENDERER_HEALTH:
rendererHealth(app, target: target, v: action.action.renderer_health) rendererHealth(app, target: target, v: action.action.renderer_health)
case GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE:
toggleCommandPalette(app, target: target)
case GHOSTTY_ACTION_TOGGLE_MAXIMIZE:
toggleMaximize(app, target: target)
case GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL: case GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL:
toggleQuickTerminal(app, target: target) toggleQuickTerminal(app, target: target)
@ -742,6 +751,51 @@ extension Ghostty {
} }
} }
private static func toggleCommandPalette(
_ app: ghostty_app_t,
target: ghostty_target_s) {
switch (target.tag) {
case GHOSTTY_TARGET_APP:
Ghostty.logger.warning("toggle command palette does nothing with an app target")
return
case GHOSTTY_TARGET_SURFACE:
guard let surface = target.target.surface else { return }
guard let surfaceView = self.surfaceView(from: surface) else { return }
NotificationCenter.default.post(
name: .ghosttyCommandPaletteDidToggle,
object: surfaceView
)
default:
assertionFailure()
}
}
private static func toggleMaximize(
_ app: ghostty_app_t,
target: ghostty_target_s
) {
switch (target.tag) {
case GHOSTTY_TARGET_APP:
Ghostty.logger.warning("toggle maximize does nothing with an app target")
return
case GHOSTTY_TARGET_SURFACE:
guard let surface = target.target.surface else { return }
guard let surfaceView = self.surfaceView(from: surface) else { return }
NotificationCenter.default.post(
name: .ghosttyMaximizeDidToggle,
object: surfaceView
)
default:
assertionFailure()
}
}
private static func toggleVisibility( private static func toggleVisibility(
_ app: ghostty_app_t, _ app: ghostty_app_t,
target: ghostty_target_s target: ghostty_target_s
@ -1001,6 +1055,43 @@ extension Ghostty {
} }
} }
private static func toggleFloatWindow(
_ app: ghostty_app_t,
target: ghostty_target_s,
mode mode_raw: ghostty_action_float_window_e
) {
guard let mode = SetFloatWIndow.from(mode_raw) else { return }
switch (target.tag) {
case GHOSTTY_TARGET_APP:
Ghostty.logger.warning("toggle float window does nothing with an app target")
return
case GHOSTTY_TARGET_SURFACE:
guard let surface = target.target.surface else { return }
guard let surfaceView = self.surfaceView(from: surface) else { return }
guard let window = surfaceView.window as? TerminalWindow else { return }
switch (mode) {
case .on:
window.level = .floating
case .off:
window.level = .normal
case .toggle:
window.level = window.level == .floating ? .normal : .floating
}
if let appDelegate = NSApplication.shared.delegate as? AppDelegate {
appDelegate.syncFloatOnTopMenu(window)
}
default:
assertionFailure()
}
}
private static func toggleSecureInput( private static func toggleSecureInput(
_ app: ghostty_app_t, _ app: ghostty_app_t,
target: ghostty_target_s, target: ghostty_target_s,
@ -1306,7 +1397,7 @@ extension Ghostty {
name: Notification.didContinueKeySequence, name: Notification.didContinueKeySequence,
object: surfaceView, object: surfaceView,
userInfo: [ userInfo: [
Notification.KeySequenceKey: keyEquivalent(for: v.trigger) as Any Notification.KeySequenceKey: keyboardShortcut(for: v.trigger) as Any
] ]
) )
} else { } else {

View File

@ -102,11 +102,11 @@ extension Ghostty {
/// configuration would be "quit" action. /// configuration would be "quit" action.
/// ///
/// Returns nil if there is no key equivalent for the given action. /// Returns nil if there is no key equivalent for the given action.
func keyEquivalent(for action: String) -> KeyEquivalent? { func keyboardShortcut(for action: String) -> KeyboardShortcut? {
guard let cfg = self.config else { return nil } guard let cfg = self.config else { return nil }
let trigger = ghostty_config_trigger(cfg, action, UInt(action.count)) let trigger = ghostty_config_trigger(cfg, action, UInt(action.count))
return Ghostty.keyEquivalent(for: trigger) return Ghostty.keyboardShortcut(for: trigger)
} }
#endif #endif

View File

@ -1,66 +1,52 @@
import Cocoa import Cocoa
import SwiftUI
import GhosttyKit import GhosttyKit
extension Ghostty { extension Ghostty {
// MARK: Key Equivalents // MARK: Keyboard Shortcuts
/// Returns the "keyEquivalent" string for a given input key. This doesn't always have a corresponding key. /// Returns the SwiftUI KeyEquivalent for a given key. Note that not all keys known by
static func keyEquivalent(key: ghostty_input_key_e) -> String? { /// Ghostty have a macOS equivalent since macOS doesn't allow all keys as equivalents.
static func keyEquivalent(key: ghostty_input_key_e) -> KeyEquivalent? {
return Self.keyToEquivalent[key] return Self.keyToEquivalent[key]
} }
/// A convenience struct that has the key + modifiers for some keybinding.
struct KeyEquivalent: CustomStringConvertible {
let key: String
let modifiers: NSEvent.ModifierFlags
var description: String {
var key = self.key
// Note: the order below matters; it matches the ordering modifiers
// shown for macOS menu shortcut labels.
if modifiers.contains(.command) { key = "\(key)" }
if modifiers.contains(.shift) { key = "\(key)" }
if modifiers.contains(.option) { key = "\(key)" }
if modifiers.contains(.control) { key = "\(key)" }
return key
}
}
/// Return the key equivalent for the given trigger. /// Return the key equivalent for the given trigger.
/// ///
/// Returns nil if the trigger can't be processed. This should only happen for unknown trigger types /// Returns nil if the trigger doesn't have an equivalent KeyboardShortcut. This is possible
/// or keys. /// because Ghostty input triggers are a superset of what can be represented by a macOS
static func keyEquivalent(for trigger: ghostty_input_trigger_s) -> KeyEquivalent? { /// KeyboardShortcut. For example, macOS doesn't have any way to represent function keys
let equiv: String /// (F1, F2, ...) with a KeyboardShortcut. This doesn't represent a practical issue because input
/// handling for Ghostty is handled at a lower level (usually). This function should generally only
/// be used for things like NSMenu that only support keyboard shortcuts anyways.
static func keyboardShortcut(for trigger: ghostty_input_trigger_s) -> KeyboardShortcut? {
let key: KeyEquivalent
switch (trigger.tag) { switch (trigger.tag) {
case GHOSTTY_TRIGGER_TRANSLATED: case GHOSTTY_TRIGGER_TRANSLATED:
if let v = Ghostty.keyEquivalent(key: trigger.key.translated) { if let v = Ghostty.keyEquivalent(key: trigger.key.translated) {
equiv = v key = v
} else { } else {
return nil return nil
} }
case GHOSTTY_TRIGGER_PHYSICAL: case GHOSTTY_TRIGGER_PHYSICAL:
if let v = Ghostty.keyEquivalent(key: trigger.key.physical) { if let v = Ghostty.keyEquivalent(key: trigger.key.physical) {
equiv = v key = v
} else { } else {
return nil return nil
} }
case GHOSTTY_TRIGGER_UNICODE: case GHOSTTY_TRIGGER_UNICODE:
guard let scalar = UnicodeScalar(trigger.key.unicode) else { return nil } guard let scalar = UnicodeScalar(trigger.key.unicode) else { return nil }
equiv = String(scalar) key = KeyEquivalent(Character(scalar))
default: default:
return nil return nil
} }
return KeyEquivalent( return KeyboardShortcut(
key: equiv, key,
modifiers: Ghostty.eventModifierFlags(mods: trigger.mods) modifiers: EventModifiers(nsFlags: Ghostty.eventModifierFlags(mods: trigger.mods)))
)
} }
// MARK: Mods // MARK: Mods
@ -96,8 +82,10 @@ extension Ghostty {
return ghostty_input_mods_e(mods) return ghostty_input_mods_e(mods)
} }
/// A map from the Ghostty key enum to the keyEquivalent string for shortcuts. /// A map from the Ghostty key enum to the keyEquivalent string for shortcuts. Note that
static let keyToEquivalent: [ghostty_input_key_e : String] = [ /// not all ghostty key enum values are represented here because not all of them can be
/// mapped to a KeyEquivalent.
static let keyToEquivalent: [ghostty_input_key_e : KeyEquivalent] = [
// 0-9 // 0-9
GHOSTTY_KEY_ZERO: "0", GHOSTTY_KEY_ZERO: "0",
GHOSTTY_KEY_ONE: "1", GHOSTTY_KEY_ONE: "1",
@ -152,48 +140,19 @@ extension Ghostty {
GHOSTTY_KEY_SLASH: "/", GHOSTTY_KEY_SLASH: "/",
// Function keys // Function keys
GHOSTTY_KEY_UP: "\u{F700}", GHOSTTY_KEY_UP: .upArrow,
GHOSTTY_KEY_DOWN: "\u{F701}", GHOSTTY_KEY_DOWN: .downArrow,
GHOSTTY_KEY_LEFT: "\u{F702}", GHOSTTY_KEY_LEFT: .leftArrow,
GHOSTTY_KEY_RIGHT: "\u{F703}", GHOSTTY_KEY_RIGHT: .rightArrow,
GHOSTTY_KEY_HOME: "\u{F729}", GHOSTTY_KEY_HOME: .home,
GHOSTTY_KEY_END: "\u{F72B}", GHOSTTY_KEY_END: .end,
GHOSTTY_KEY_INSERT: "\u{F727}", GHOSTTY_KEY_DELETE: .delete,
GHOSTTY_KEY_DELETE: "\u{F728}", GHOSTTY_KEY_PAGE_UP: .pageUp,
GHOSTTY_KEY_PAGE_UP: "\u{F72C}", GHOSTTY_KEY_PAGE_DOWN: .pageDown,
GHOSTTY_KEY_PAGE_DOWN: "\u{F72D}", GHOSTTY_KEY_ESCAPE: .escape,
GHOSTTY_KEY_ESCAPE: "\u{1B}", GHOSTTY_KEY_ENTER: .return,
GHOSTTY_KEY_ENTER: "\r", GHOSTTY_KEY_TAB: .tab,
GHOSTTY_KEY_TAB: "\t", GHOSTTY_KEY_BACKSPACE: .delete,
GHOSTTY_KEY_BACKSPACE: "\u{7F}",
GHOSTTY_KEY_PRINT_SCREEN: "\u{F72E}",
GHOSTTY_KEY_PAUSE: "\u{F72F}",
GHOSTTY_KEY_F1: "\u{F704}",
GHOSTTY_KEY_F2: "\u{F705}",
GHOSTTY_KEY_F3: "\u{F706}",
GHOSTTY_KEY_F4: "\u{F707}",
GHOSTTY_KEY_F5: "\u{F708}",
GHOSTTY_KEY_F6: "\u{F709}",
GHOSTTY_KEY_F7: "\u{F70A}",
GHOSTTY_KEY_F8: "\u{F70B}",
GHOSTTY_KEY_F9: "\u{F70C}",
GHOSTTY_KEY_F10: "\u{F70D}",
GHOSTTY_KEY_F11: "\u{F70E}",
GHOSTTY_KEY_F12: "\u{F70F}",
GHOSTTY_KEY_F13: "\u{F710}",
GHOSTTY_KEY_F14: "\u{F711}",
GHOSTTY_KEY_F15: "\u{F712}",
GHOSTTY_KEY_F16: "\u{F713}",
GHOSTTY_KEY_F17: "\u{F714}",
GHOSTTY_KEY_F18: "\u{F715}",
GHOSTTY_KEY_F19: "\u{F716}",
GHOSTTY_KEY_F20: "\u{F717}",
GHOSTTY_KEY_F21: "\u{F718}",
GHOSTTY_KEY_F22: "\u{F719}",
GHOSTTY_KEY_F23: "\u{F71A}",
GHOSTTY_KEY_F24: "\u{F71B}",
GHOSTTY_KEY_F25: "\u{F71C}",
] ]
static let asciiToKey: [UInt8 : ghostty_input_key_e] = [ static let asciiToKey: [UInt8 : ghostty_input_key_e] = [

View File

@ -45,8 +45,6 @@ extension Ghostty {
/// this one. /// this one.
@Binding var zoomedSurface: SurfaceView? @Binding var zoomedSurface: SurfaceView?
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle: String?
var body: some View { var body: some View {
let center = NotificationCenter.default let center = NotificationCenter.default
let pubZoom = center.publisher(for: Notification.didToggleSplitZoom) let pubZoom = center.publisher(for: Notification.didToggleSplitZoom)
@ -77,7 +75,6 @@ extension Ghostty {
.onReceive(pubZoom) { onZoom(notification: $0) } .onReceive(pubZoom) { onZoom(notification: $0) }
} }
} }
.navigationTitle(surfaceTitle ?? "Ghostty")
.id(node) // Needed for change detection on node .id(node) // Needed for change detection on node
} else { } else {
// On these events we want to reset the split state and call it. // On these events we want to reset the split state and call it.

View File

@ -31,7 +31,6 @@ extension Ghostty {
}, right: { }, right: {
InspectorViewRepresentable(surfaceView: surfaceView) InspectorViewRepresentable(surfaceView: surfaceView)
.focused($inspectorFocus) .focused($inspectorFocus)
.focusedValue(\.ghosttySurfaceTitle, surfaceView.title)
.focusedValue(\.ghosttySurfaceView, surfaceView) .focusedValue(\.ghosttySurfaceView, surfaceView)
}) })
} }

View File

@ -33,11 +33,13 @@ extension NSEvent {
.subtracting([.control, .command])) .subtracting([.control, .command]))
// Our unshifted codepoint is the codepoint with no modifiers. We // Our unshifted codepoint is the codepoint with no modifiers. We
// ignore multi-codepoint values. // ignore multi-codepoint values. We have to use `byApplyingModifiers`
// instead of `charactersIgnoringModifiers` because the latter changes
// behavior with ctrl pressed and we don't want any of that.
key_ev.unshifted_codepoint = 0 key_ev.unshifted_codepoint = 0
if type == .keyDown || type == .keyUp { if type == .keyDown || type == .keyUp {
if let charactersIgnoringModifiers, if let chars = characters(byApplyingModifiers: []),
let codepoint = charactersIgnoringModifiers.unicodeScalars.first let codepoint = chars.unicodeScalars.first
{ {
key_ev.unshifted_codepoint = codepoint.value key_ev.unshifted_codepoint = codepoint.value
} }

View File

@ -42,6 +42,28 @@ extension Ghostty {
// MARK: Swift Types for C Types // MARK: Swift Types for C Types
extension Ghostty { extension Ghostty {
enum SetFloatWIndow {
case on
case off
case toggle
static func from(_ c: ghostty_action_float_window_e) -> Self? {
switch (c) {
case GHOSTTY_FLOAT_WINDOW_ON:
return .on
case GHOSTTY_FLOAT_WINDOW_OFF:
return .off
case GHOSTTY_FLOAT_WINDOW_TOGGLE:
return .toggle
default:
return nil
}
}
}
enum SetSecureInput { enum SetSecureInput {
case on case on
case off case off
@ -256,6 +278,10 @@ extension Notification.Name {
/// Ring the bell /// Ring the bell
static let ghosttyBellDidRing = Notification.Name("com.mitchellh.ghostty.ghosttyBellDidRing") static let ghosttyBellDidRing = Notification.Name("com.mitchellh.ghostty.ghosttyBellDidRing")
static let ghosttyCommandPaletteDidToggle = Notification.Name("com.mitchellh.ghostty.commandPaletteDidToggle")
/// Toggle maximize of current window
static let ghosttyMaximizeDidToggle = Notification.Name("com.mitchellh.ghostty.maximizeDidToggle")
} }
// NOTE: I am moving all of these to Notification.Name extensions over time. This // NOTE: I am moving all of these to Notification.Name extensions over time. This

View File

@ -6,14 +6,12 @@ extension Ghostty {
/// Render a terminal for the active app in the environment. /// Render a terminal for the active app in the environment.
struct Terminal: View { struct Terminal: View {
@EnvironmentObject private var ghostty: Ghostty.App @EnvironmentObject private var ghostty: Ghostty.App
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle: String?
var body: some View { var body: some View {
if let app = self.ghostty.app { if let app = self.ghostty.app {
SurfaceForApp(app) { surfaceView in SurfaceForApp(app) { surfaceView in
SurfaceWrapper(surfaceView: surfaceView) SurfaceWrapper(surfaceView: surfaceView)
} }
.navigationTitle(surfaceTitle ?? "Ghostty")
} }
} }
} }
@ -83,7 +81,6 @@ extension Ghostty {
Surface(view: surfaceView, size: geo.size) Surface(view: surfaceView, size: geo.size)
.focused($surfaceFocus) .focused($surfaceFocus)
.focusedValue(\.ghosttySurfaceTitle, title)
.focusedValue(\.ghosttySurfacePwd, surfaceView.pwd) .focusedValue(\.ghosttySurfacePwd, surfaceView.pwd)
.focusedValue(\.ghosttySurfaceView, surfaceView) .focusedValue(\.ghosttySurfaceView, surfaceView)
.focusedValue(\.ghosttySurfaceCellSize, surfaceView.cellSize) .focusedValue(\.ghosttySurfaceCellSize, surfaceView.cellSize)
@ -329,7 +326,7 @@ extension Ghostty {
Spacer() Spacer()
} }
Text(verbatim: "\(size.columns)c \(size.rows)r") Text(verbatim: "\(size.columns) \(size.rows)")
.padding(.init(top: padding, leading: padding, bottom: padding, trailing: padding)) .padding(.init(top: padding, leading: padding, bottom: padding, trailing: padding))
.background( .background(
RoundedRectangle(cornerRadius: 4) RoundedRectangle(cornerRadius: 4)
@ -496,15 +493,6 @@ extension FocusedValues {
typealias Value = Ghostty.SurfaceView typealias Value = Ghostty.SurfaceView
} }
var ghosttySurfaceTitle: String? {
get { self[FocusedGhosttySurfaceTitle.self] }
set { self[FocusedGhosttySurfaceTitle.self] = newValue }
}
struct FocusedGhosttySurfaceTitle: FocusedValueKey {
typealias Value = String
}
var ghosttySurfacePwd: String? { var ghosttySurfacePwd: String? {
get { self[FocusedGhosttySurfacePwd.self] } get { self[FocusedGhosttySurfacePwd.self] }
set { self[FocusedGhosttySurfacePwd.self] = newValue } set { self[FocusedGhosttySurfacePwd.self] = newValue }

View File

@ -43,7 +43,7 @@ extension Ghostty {
@Published var hoverUrl: String? = nil @Published var hoverUrl: String? = nil
// The currently active key sequence. The sequence is not active if this is empty. // The currently active key sequence. The sequence is not active if this is empty.
@Published var keySequence: [Ghostty.KeyEquivalent] = [] @Published var keySequence: [KeyboardShortcut] = []
// The time this surface last became focused. This is a ContinuousClock.Instant // The time this surface last became focused. This is a ContinuousClock.Instant
// on supported platforms. // on supported platforms.
@ -526,7 +526,7 @@ extension Ghostty {
@objc private func ghosttyDidContinueKeySequence(notification: SwiftUI.Notification) { @objc private func ghosttyDidContinueKeySequence(notification: SwiftUI.Notification) {
guard let keyAny = notification.userInfo?[Ghostty.Notification.KeySequenceKey] else { return } guard let keyAny = notification.userInfo?[Ghostty.Notification.KeySequenceKey] else { return }
guard let key = keyAny as? Ghostty.KeyEquivalent else { return } guard let key = keyAny as? KeyboardShortcut else { return }
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
self?.keySequence.append(key) self?.keySequence.append(key)
} }
@ -975,7 +975,14 @@ extension Ghostty {
event: event, event: event,
translationEvent: translationEvent, translationEvent: translationEvent,
text: translationEvent.ghosttyCharacters, text: translationEvent.ghosttyCharacters,
composing: markedText.length > 0
// We're composing if we have preedit (the obvious case). But we're also
// composing if we don't have preedit and we had marked text before,
// because this input probably just reset the preedit state. It shouldn't
// be encoded. Example: Japanese begin composing, the press backspace.
// This should only cancel the composing state but not actually delete
// the prior input characters (prior to the composing).
composing: markedText.length > 0 || markedTextBefore
) )
} }
} }
@ -1169,7 +1176,12 @@ extension Ghostty {
var key_ev = event.ghosttyKeyEvent(action, translationMods: translationEvent?.modifierFlags) var key_ev = event.ghosttyKeyEvent(action, translationMods: translationEvent?.modifierFlags)
key_ev.composing = composing key_ev.composing = composing
if let text {
// For text, we only encode UTF8 if we don't have a single control
// character. Control characters are encoded by Ghostty itself.
// Without this, `ctrl+enter` does the wrong thing.
if let text, text.count > 0,
let codepoint = text.utf8.first, codepoint >= 0x20 {
return text.withCString { ptr in return text.withCString { ptr in
key_ev.text = ptr key_ev.text = ptr
return ghostty_surface_key(surface, key_ev) return ghostty_surface_key(surface, key_ev)

View File

@ -0,0 +1,27 @@
import SwiftUI
// MARK: EventModifiers to NSEvent and Back
extension EventModifiers {
init(nsFlags: NSEvent.ModifierFlags) {
var result: SwiftUI.EventModifiers = []
if nsFlags.contains(.shift) { result.insert(.shift) }
if nsFlags.contains(.control) { result.insert(.control) }
if nsFlags.contains(.option) { result.insert(.option) }
if nsFlags.contains(.command) { result.insert(.command) }
if nsFlags.contains(.capsLock) { result.insert(.capsLock) }
self = result
}
}
extension NSEvent.ModifierFlags {
init(swiftUIFlags: SwiftUI.EventModifiers) {
var result: NSEvent.ModifierFlags = []
if swiftUIFlags.contains(.shift) { result.insert(.shift) }
if swiftUIFlags.contains(.control) { result.insert(.control) }
if swiftUIFlags.contains(.option) { result.insert(.option) }
if swiftUIFlags.contains(.command) { result.insert(.command) }
if swiftUIFlags.contains(.capsLock) { result.insert(.capsLock) }
self = result
}
}

View File

@ -171,6 +171,13 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
guard let savedState = SavedState(window) else { return } guard let savedState = SavedState(window) else { return }
self.savedState = savedState self.savedState = savedState
// Get our current first responder on this window. For non-native fullscreen
// we have to restore this because for some reason the operations below
// lose it (see: https://github.com/ghostty-org/ghostty/issues/6999).
// I don't know the root cause here so if we can figure that out there may
// be a nicer way than this.
let firstResponder = window.firstResponder
// We hide the dock if the window is on a screen with the dock. // We hide the dock if the window is on a screen with the dock.
// We must hide the dock FIRST then hide the menu: // We must hide the dock FIRST then hide the menu:
// If you specify autoHideMenuBar, it must be accompanied by either hideDock or autoHideDock. // If you specify autoHideMenuBar, it must be accompanied by either hideDock or autoHideDock.
@ -207,6 +214,10 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
// https://github.com/ghostty-org/ghostty/issues/1996 // https://github.com/ghostty-org/ghostty/issues/1996
DispatchQueue.main.async { DispatchQueue.main.async {
self.window.setFrame(self.fullscreenFrame(screen), display: true) self.window.setFrame(self.fullscreenFrame(screen), display: true)
if let firstResponder {
self.window.makeFirstResponder(firstResponder)
}
self.delegate?.fullscreenDidChange() self.delegate?.fullscreenDidChange()
} }
} }
@ -220,6 +231,9 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
let center = NotificationCenter.default let center = NotificationCenter.default
center.removeObserver(self, name: NSWindow.didChangeScreenNotification, object: window) center.removeObserver(self, name: NSWindow.didChangeScreenNotification, object: window)
// See enter where we do the same thing to understand why.
let firstResponder = window.firstResponder
// Unhide our elements // Unhide our elements
if savedState.dock { if savedState.dock {
unhideDock() unhideDock()
@ -258,6 +272,10 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
} }
} }
if let firstResponder {
window.makeFirstResponder(firstResponder)
}
// Unset our saved state, we're restored! // Unset our saved state, we're restored!
self.savedState = nil self.savedState = nil
@ -355,16 +373,23 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
self.styleMask = window.styleMask self.styleMask = window.styleMask
self.dock = window.screen?.hasDock ?? false self.dock = window.screen?.hasDock ?? false
// We hide the menu only if this window is not on any fullscreen if let cgWindowId = window.cgWindowId {
// spaces. We do this because fullscreen spaces already hide the // We hide the menu only if this window is not on any fullscreen
// menu and if we insert/remove this presentation option we get // spaces. We do this because fullscreen spaces already hide the
// issues (see #7075) // menu and if we insert/remove this presentation option we get
let activeSpace = CGSSpace.active() // issues (see #7075)
let spaces = CGSSpace.list(for: window.cgWindowId) let activeSpace = CGSSpace.active()
if spaces.contains(activeSpace) { let spaces = CGSSpace.list(for: cgWindowId)
self.menu = activeSpace.type != .fullscreen if spaces.contains(activeSpace) {
self.menu = activeSpace.type != .fullscreen
} else {
self.menu = spaces.allSatisfy { $0.type != .fullscreen }
}
} else { } else {
self.menu = spaces.allSatisfy { $0.type != .fullscreen } // Window doesn't have a window device, its not visible or something.
// In this case, we assume we can hide the menu. We may want to do
// something more sophisticated but this works for now.
self.menu = true
} }
} }
} }

View File

@ -0,0 +1,53 @@
import SwiftUI
extension KeyboardShortcut: @retroactive CustomStringConvertible {
public var keyList: [String] {
var result: [String] = []
if modifiers.contains(.control) {
result.append("")
}
if modifiers.contains(.option) {
result.append("")
}
if modifiers.contains(.shift) {
result.append("")
}
if modifiers.contains(.command) {
result.append("")
}
let keyString: String
switch key {
case .return: keyString = ""
case .escape: keyString = ""
case .delete: keyString = ""
case .space: keyString = ""
case .tab: keyString = ""
case .upArrow: keyString = ""
case .downArrow: keyString = ""
case .leftArrow: keyString = ""
case .rightArrow: keyString = ""
case .pageUp: keyString = ""
case .pageDown: keyString = ""
case .home: keyString = ""
case .end: keyString = ""
default:
keyString = String(key.character.uppercased())
}
result.append(keyString)
return result
}
public var description: String {
return self.keyList.joined()
}
}
// This is available in macOS 14 so this only applies to early macOS versions.
extension KeyEquivalent: @retroactive Equatable {
public static func == (lhs: KeyEquivalent, rhs: KeyEquivalent) -> Bool {
lhs.character == rhs.character
}
}

View File

@ -2,7 +2,11 @@ import AppKit
extension NSWindow { extension NSWindow {
/// Get the CGWindowID type for the window (used for low level CoreGraphics APIs). /// Get the CGWindowID type for the window (used for low level CoreGraphics APIs).
var cgWindowId: CGWindowID { var cgWindowId: CGWindowID? {
CGWindowID(windowNumber) // "If the window doesnt have a window device, the value of this
// property is equal to or less than 0." - Docs. In practice I've
// found this is true if a window is not visible.
guard windowNumber > 0 else { return nil }
return CGWindowID(windowNumber)
} }
} }

View File

@ -3,7 +3,7 @@
class Weak<T: AnyObject> { class Weak<T: AnyObject> {
weak var value: T? weak var value: T?
init(_ value: T) { init(_ value: T? = nil) {
self.value = value self.value = value
} }
} }

View File

@ -3,6 +3,8 @@
lib, lib,
stdenv, stdenv,
bashInteractive, bashInteractive,
appstream,
flatpak-builder,
gdb, gdb,
#, glxinfo # unused #, glxinfo # unused
ncurses, ncurses,
@ -128,6 +130,8 @@ in
# build only has the qemu-system files. # build only has the qemu-system files.
qemu qemu
appstream
flatpak-builder
gdb gdb
snapcraft snapcraft
valgrind valgrind

View File

@ -1,20 +1,20 @@
pub const c = @import("c.zig").c; pub const c = @import("c.zig").c;
// OpenGL // OpenGL
pub extern fn ImGui_ImplOpenGL3_Init(?[*:0]const u8) callconv(.C) bool; pub extern fn ImGui_ImplOpenGL3_Init(?[*:0]const u8) callconv(.c) bool;
pub extern fn ImGui_ImplOpenGL3_Shutdown() callconv(.C) void; pub extern fn ImGui_ImplOpenGL3_Shutdown() callconv(.c) void;
pub extern fn ImGui_ImplOpenGL3_NewFrame() callconv(.C) void; pub extern fn ImGui_ImplOpenGL3_NewFrame() callconv(.c) void;
pub extern fn ImGui_ImplOpenGL3_RenderDrawData(*c.ImDrawData) callconv(.C) void; pub extern fn ImGui_ImplOpenGL3_RenderDrawData(*c.ImDrawData) callconv(.c) void;
// Metal // Metal
pub extern fn ImGui_ImplMetal_Init(*anyopaque) callconv(.C) bool; pub extern fn ImGui_ImplMetal_Init(*anyopaque) callconv(.c) bool;
pub extern fn ImGui_ImplMetal_Shutdown() callconv(.C) void; pub extern fn ImGui_ImplMetal_Shutdown() callconv(.c) void;
pub extern fn ImGui_ImplMetal_NewFrame(*anyopaque) callconv(.C) void; pub extern fn ImGui_ImplMetal_NewFrame(*anyopaque) callconv(.c) void;
pub extern fn ImGui_ImplMetal_RenderDrawData(*c.ImDrawData, *anyopaque, *anyopaque) callconv(.C) void; pub extern fn ImGui_ImplMetal_RenderDrawData(*c.ImDrawData, *anyopaque, *anyopaque) callconv(.c) void;
// OSX // OSX
pub extern fn ImGui_ImplOSX_Init(*anyopaque) callconv(.C) bool; pub extern fn ImGui_ImplOSX_Init(*anyopaque) callconv(.c) bool;
pub extern fn ImGui_ImplOSX_Shutdown() callconv(.C) void; pub extern fn ImGui_ImplOSX_Shutdown() callconv(.c) void;
pub extern fn ImGui_ImplOSX_NewFrame(*anyopaque) callconv(.C) void; pub extern fn ImGui_ImplOSX_NewFrame(*anyopaque) callconv(.c) void;
test {} test {}

View File

@ -333,7 +333,7 @@ pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Eve
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn joystickCallbackWrapper(jid: c_int, event: c_int) callconv(.C) void { pub fn joystickCallbackWrapper(jid: c_int, event: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
Joystick{ .jid = @as(Joystick.Id, @enumFromInt(jid)) }, Joystick{ .jid = @as(Joystick.Id, @enumFromInt(jid)) },
@as(Event, @enumFromInt(event)), @as(Event, @enumFromInt(event)),

View File

@ -389,7 +389,7 @@ pub inline fn setCallback(comptime callback: ?fn (monitor: Monitor, event: Event
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn monitorCallbackWrapper(monitor: ?*c.GLFWmonitor, event: c_int) callconv(.C) void { pub fn monitorCallbackWrapper(monitor: ?*c.GLFWmonitor, event: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
Monitor{ .handle = monitor.? }, Monitor{ .handle = monitor.? },
@as(Event, @enumFromInt(event)), @as(Event, @enumFromInt(event)),

View File

@ -1230,7 +1230,7 @@ pub inline fn setPosCallback(self: Window, comptime callback: ?fn (window: Windo
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn posCallbackWrapper(handle: ?*c.GLFWwindow, xpos: c_int, ypos: c_int) callconv(.C) void { pub fn posCallbackWrapper(handle: ?*c.GLFWwindow, xpos: c_int, ypos: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(i32, @intCast(xpos)), @as(i32, @intCast(xpos)),
@ -1263,7 +1263,7 @@ pub inline fn setSizeCallback(self: Window, comptime callback: ?fn (window: Wind
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn sizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void { pub fn sizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(i32, @intCast(width)), @as(i32, @intCast(width)),
@ -1304,7 +1304,7 @@ pub inline fn setCloseCallback(self: Window, comptime callback: ?fn (window: Win
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn closeCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void { pub fn closeCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
}); });
@ -1341,7 +1341,7 @@ pub inline fn setRefreshCallback(self: Window, comptime callback: ?fn (window: W
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn refreshCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void { pub fn refreshCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
}); });
@ -1379,7 +1379,7 @@ pub inline fn setFocusCallback(self: Window, comptime callback: ?fn (window: Win
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn focusCallbackWrapper(handle: ?*c.GLFWwindow, focused: c_int) callconv(.C) void { pub fn focusCallbackWrapper(handle: ?*c.GLFWwindow, focused: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
focused == c.GLFW_TRUE, focused == c.GLFW_TRUE,
@ -1413,7 +1413,7 @@ pub inline fn setIconifyCallback(self: Window, comptime callback: ?fn (window: W
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn iconifyCallbackWrapper(handle: ?*c.GLFWwindow, iconified: c_int) callconv(.C) void { pub fn iconifyCallbackWrapper(handle: ?*c.GLFWwindow, iconified: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
iconified == c.GLFW_TRUE, iconified == c.GLFW_TRUE,
@ -1448,7 +1448,7 @@ pub inline fn setMaximizeCallback(self: Window, comptime callback: ?fn (window:
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn maximizeCallbackWrapper(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.C) void { pub fn maximizeCallbackWrapper(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
maximized == c.GLFW_TRUE, maximized == c.GLFW_TRUE,
@ -1483,7 +1483,7 @@ pub inline fn setFramebufferSizeCallback(self: Window, comptime callback: ?fn (w
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn framebufferSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void { pub fn framebufferSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(u32, @intCast(width)), @as(u32, @intCast(width)),
@ -1519,7 +1519,7 @@ pub inline fn setContentScaleCallback(self: Window, comptime callback: ?fn (wind
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn windowScaleCallbackWrapper(handle: ?*c.GLFWwindow, xscale: f32, yscale: f32) callconv(.C) void { pub fn windowScaleCallbackWrapper(handle: ?*c.GLFWwindow, xscale: f32, yscale: f32) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
xscale, xscale,
@ -1871,7 +1871,7 @@ pub inline fn setKeyCallback(self: Window, comptime callback: ?fn (window: Windo
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn keyCallbackWrapper(handle: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.C) void { pub fn keyCallbackWrapper(handle: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(Key, @enumFromInt(key)), @as(Key, @enumFromInt(key)),
@ -1917,7 +1917,7 @@ pub inline fn setCharCallback(self: Window, comptime callback: ?fn (window: Wind
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn charCallbackWrapper(handle: ?*c.GLFWwindow, codepoint: c_uint) callconv(.C) void { pub fn charCallbackWrapper(handle: ?*c.GLFWwindow, codepoint: c_uint) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(u21, @intCast(codepoint)), @as(u21, @intCast(codepoint)),
@ -1958,7 +1958,7 @@ pub inline fn setMouseButtonCallback(self: Window, comptime callback: ?fn (windo
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn mouseButtonCallbackWrapper(handle: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) callconv(.C) void { pub fn mouseButtonCallbackWrapper(handle: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as(MouseButton, @enumFromInt(button)), @as(MouseButton, @enumFromInt(button)),
@ -1996,7 +1996,7 @@ pub inline fn setCursorPosCallback(self: Window, comptime callback: ?fn (window:
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn cursorPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: f64, ypos: f64) callconv(.C) void { pub fn cursorPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: f64, ypos: f64) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
xpos, xpos,
@ -2030,7 +2030,7 @@ pub inline fn setCursorEnterCallback(self: Window, comptime callback: ?fn (windo
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn cursorEnterCallbackWrapper(handle: ?*c.GLFWwindow, entered: c_int) callconv(.C) void { pub fn cursorEnterCallbackWrapper(handle: ?*c.GLFWwindow, entered: c_int) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
entered == c.GLFW_TRUE, entered == c.GLFW_TRUE,
@ -2067,7 +2067,7 @@ pub inline fn setScrollCallback(self: Window, comptime callback: ?fn (window: Wi
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn scrollCallbackWrapper(handle: ?*c.GLFWwindow, xoffset: f64, yoffset: f64) callconv(.C) void { pub fn scrollCallbackWrapper(handle: ?*c.GLFWwindow, xoffset: f64, yoffset: f64) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
xoffset, xoffset,
@ -2110,7 +2110,7 @@ pub inline fn setDropCallback(self: Window, comptime callback: ?fn (window: Wind
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn dropCallbackWrapper(handle: ?*c.GLFWwindow, path_count: c_int, paths: [*c][*c]const u8) callconv(.C) void { pub fn dropCallbackWrapper(handle: ?*c.GLFWwindow, path_count: c_int, paths: [*c][*c]const u8) callconv(.c) void {
@call(.always_inline, user_callback, .{ @call(.always_inline, user_callback, .{
from(handle.?), from(handle.?),
@as([*][*:0]const u8, @ptrCast(paths))[0..@as(u32, @intCast(path_count))], @as([*][*:0]const u8, @ptrCast(paths))[0..@as(u32, @intCast(path_count))],

View File

@ -300,7 +300,7 @@ pub inline fn mustGetErrorString() [:0]const u8 {
pub fn setErrorCallback(comptime callback: ?fn (error_code: ErrorCode, description: [:0]const u8) void) void { pub fn setErrorCallback(comptime callback: ?fn (error_code: ErrorCode, description: [:0]const u8) void) void {
if (callback) |user_callback| { if (callback) |user_callback| {
const CWrapper = struct { const CWrapper = struct {
pub fn errorCallbackWrapper(err_int: c_int, c_description: [*c]const u8) callconv(.C) void { pub fn errorCallbackWrapper(err_int: c_int, c_description: [*c]const u8) callconv(.c) void {
convertError(err_int) catch |error_code| { convertError(err_int) catch |error_code| {
user_callback(error_code, mem.sliceTo(c_description, 0)); user_callback(error_code, mem.sliceTo(c_description, 0));
}; };

View File

@ -161,7 +161,7 @@ pub const GLProc = *const fn () callconv(if (builtin.os.tag == .windows and buil
/// @thread_safety This function may be called from any thread. /// @thread_safety This function may be called from any thread.
/// ///
/// see also: context_glext, glfwExtensionSupported /// see also: context_glext, glfwExtensionSupported
pub fn getProcAddress(proc_name: [*:0]const u8) callconv(.C) ?GLProc { pub fn getProcAddress(proc_name: [*:0]const u8) callconv(.c) ?GLProc {
internal_debug.assertInitialized(); internal_debug.assertInitialized();
if (c.glfwGetProcAddress(proc_name)) |proc_address| return @ptrCast(proc_address); if (c.glfwGetProcAddress(proc_name)) |proc_address| return @ptrCast(proc_address);
return null; return null;

View File

@ -33,7 +33,7 @@ pub fn initVulkanLoader(loader_function: ?VKGetInstanceProcAddr) void {
c.glfwInitVulkanLoader(loader_function orelse null); c.glfwInitVulkanLoader(loader_function orelse null);
} }
pub const VKGetInstanceProcAddr = *const fn (vk_instance: c.VkInstance, name: [*c]const u8) callconv(.C) ?VKProc; pub const VKGetInstanceProcAddr = *const fn (vk_instance: c.VkInstance, name: [*c]const u8) callconv(.c) ?VKProc;
/// Returns whether the Vulkan loader and an ICD have been found. /// Returns whether the Vulkan loader and an ICD have been found.
/// ///
@ -127,7 +127,7 @@ pub const VKProc = *const fn () callconv(if (builtin.os.tag == .windows and buil
/// @pointer_lifetime The returned function pointer is valid until the library is terminated. /// @pointer_lifetime The returned function pointer is valid until the library is terminated.
/// ///
/// @thread_safety This function may be called from any thread. /// @thread_safety This function may be called from any thread.
pub fn getInstanceProcAddress(vk_instance: ?*anyopaque, proc_name: [*:0]const u8) callconv(.C) ?VKProc { pub fn getInstanceProcAddress(vk_instance: ?*anyopaque, proc_name: [*:0]const u8) callconv(.c) ?VKProc {
internal_debug.assertInitialized(); internal_debug.assertInitialized();
if (c.glfwGetInstanceProcAddress(if (vk_instance) |v| @as(c.VkInstance, @ptrCast(v)) else null, proc_name)) |proc_address| return proc_address; if (c.glfwGetInstanceProcAddress(if (vk_instance) |v| @as(c.VkInstance, @ptrCast(v)) else null, proc_name)) |proc_address| return proc_address;
return null; return null;

View File

@ -77,11 +77,11 @@ pub const Blob = struct {
comptime T: type, comptime T: type,
key: ?*anyopaque, key: ?*anyopaque,
ptr: ?*T, ptr: ?*T,
comptime destroycb: ?*const fn (?*T) callconv(.C) void, comptime destroycb: ?*const fn (?*T) callconv(.c) void,
replace: bool, replace: bool,
) bool { ) bool {
const Callback = struct { const Callback = struct {
pub fn callback(data: ?*anyopaque) callconv(.C) void { pub fn callback(data: ?*anyopaque) callconv(.c) void {
@call(.{ .modifier = .always_inline }, destroycb, .{ @call(.{ .modifier = .always_inline }, destroycb, .{
@as(?*T, @ptrCast(@alignCast(data))), @as(?*T, @ptrCast(@alignCast(data))),
}); });

View File

@ -84,7 +84,7 @@ pub const MutableArray = opaque {
a: *const Elem, a: *const Elem,
b: *const Elem, b: *const Elem,
context: ?*Context, context: ?*Context,
) callconv(.C) ComparisonResult, ) callconv(.c) ComparisonResult,
) void { ) void {
CFArraySortValues( CFArraySortValues(
self, self,
@ -155,7 +155,7 @@ test "array sorting" {
void, void,
null, null,
struct { struct {
fn compare(a: *const u8, b: *const u8, _: ?*void) callconv(.C) ComparisonResult { fn compare(a: *const u8, b: *const u8, _: ?*void) callconv(.c) ComparisonResult {
if (a.* > b.*) return .greater; if (a.* > b.*) return .greater;
if (a.* == b.*) return .equal; if (a.* == b.*) return .equal;
return .less; return .less;

View File

@ -66,7 +66,7 @@ pub const DisplayLink = opaque {
flagsIn: c.CVOptionFlags, flagsIn: c.CVOptionFlags,
flagsOut: *c.CVOptionFlags, flagsOut: *c.CVOptionFlags,
inner_userinfo: ?*anyopaque, inner_userinfo: ?*anyopaque,
) callconv(.C) c.CVReturn { ) callconv(.c) c.CVReturn {
_ = inNow; _ = inNow;
_ = inOutputTime; _ = inOutputTime;
_ = flagsIn; _ = flagsIn;

View File

@ -13,8 +13,8 @@ pub threadlocal var context: Context = undefined;
/// The getProcAddress param is an anytype so that we can accept multiple /// The getProcAddress param is an anytype so that we can accept multiple
/// forms of the function depending on what we're interfacing with. /// forms of the function depending on what we're interfacing with.
pub fn load(getProcAddress: anytype) !c_int { pub fn load(getProcAddress: anytype) !c_int {
const GlProc = *const fn () callconv(.C) void; const GlProc = *const fn () callconv(.c) void;
const GlfwFn = *const fn ([*:0]const u8) callconv(.C) ?GlProc; const GlfwFn = *const fn ([*:0]const u8) callconv(.c) ?GlProc;
const res = switch (@TypeOf(getProcAddress)) { const res = switch (@TypeOf(getProcAddress)) {
// glfw // glfw

View File

@ -5,8 +5,8 @@ const Envelope = @import("envelope.zig").Envelope;
/// sentry_transport_t /// sentry_transport_t
pub const Transport = opaque { pub const Transport = opaque {
pub const SendFunc = *const fn (envelope: *Envelope, state: ?*anyopaque) callconv(.C) void; pub const SendFunc = *const fn (envelope: *Envelope, state: ?*anyopaque) callconv(.c) void;
pub const FreeFunc = *const fn (state: ?*anyopaque) callconv(.C) void; pub const FreeFunc = *const fn (state: ?*anyopaque) callconv(.c) void;
pub fn init(f: SendFunc) *Transport { pub fn init(f: SendFunc) *Transport {
return @ptrCast(c.sentry_transport_new(@ptrCast(f)).?); return @ptrCast(c.sentry_transport_new(@ptrCast(f)).?);

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-20 08:07+0100\n" "PO-Revision-Date: 2025-03-20 08:07+0100\n"
"Last-Translator: Francesc Arpi <francesc.arpi@gmail.com>\n" "Last-Translator: Francesc Arpi <francesc.arpi@gmail.com>\n"
"Language-Team: \n" "Language-Team: \n"
@ -43,8 +43,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"S'han trobat un o més errors de configuració. Si us plau, revisa els errors a " "S'han trobat un o més errors de configuració. Si us plau, revisa els errors "
"continuació i torna a carregar la configuració o ignora aquests errors." "a continuació i torna a carregar la configuració o ignora aquests errors."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -56,6 +56,30 @@ msgstr "Ignora"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Carrega la configuració" msgstr "Carrega la configuració"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Divideix cap amunt"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Divideix cap avall"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Divideix a l'esquerra"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Divideix a la dreta"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,33 +111,13 @@ msgstr "Divideix"
msgid "Change Title…" msgid "Change Title…"
msgstr "Canvia el títol…" msgstr "Canvia el títol…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Divideix cap amunt"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Divideix cap avall"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Divideix a l'esquerra"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Divideix a la dreta"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Pestanya" msgstr "Pestanya"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nova pestanya" msgstr "Nova pestanya"
@ -150,7 +154,7 @@ msgid "Terminal Inspector"
msgstr "Inspector de terminal" msgstr "Inspector de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Sobre Ghostty" msgstr "Sobre Ghostty"
@ -201,13 +205,32 @@ msgstr ""
"Enganxar aquest text al terminal pot ser perillós, ja que sembla que es " "Enganxar aquest text al terminal pot ser perillós, ja que sembla que es "
"podrien executar algunes ordres." "podrien executar algunes ordres."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Inspector de terminal" msgstr "Menú principal"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Copiat al porta-retalls" msgstr "Mostra les pestanyes obertes"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es veurà "
"afectat."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "S'ha tornat a carregar la configuració"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desenvolupadors de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -245,25 +268,10 @@ msgstr "Totes les sessions del terminal en aquesta pestanya es tancaran."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "El procés actualment en execució en aquesta divisió es tancarà." msgstr "El procés actualment en execució en aquesta divisió es tancarà."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Menú principal" msgstr "Copiat al porta-retalls"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Mostra les pestanyes obertes" msgstr "Ghostty: Inspector de terminal"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es "
"veurà afectat."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "S'ha tornat a carregar la configuració"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Desenvolupadors de Ghostty"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -54,6 +54,30 @@ msgstr ""
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -85,33 +109,13 @@ msgstr ""
msgid "Change Title…" msgid "Change Title…"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "" msgstr ""
@ -148,7 +152,7 @@ msgid "Terminal Inspector"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "" msgstr ""
@ -193,12 +197,29 @@ msgid ""
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "" msgstr ""
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr ""
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr ""
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "" msgstr ""
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
@ -237,23 +258,10 @@ msgstr ""
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "" msgstr ""
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "" msgstr ""
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr ""
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr ""
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-06 14:57+0100\n" "PO-Revision-Date: 2025-03-06 14:57+0100\n"
"Last-Translator: Robin <r@rpfaeffle.com>\n" "Last-Translator: Robin <r@rpfaeffle.com>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n" "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@ -55,6 +55,30 @@ msgstr ""
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Konfiguration neu laden" msgstr "Konfiguration neu laden"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Fenster nach oben teilen"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Fenster nach unten teilen"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Fenter nach links teilen"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Fenster nach rechts teilen"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -86,33 +110,13 @@ msgstr "Fenster teilen"
msgid "Change Title…" msgid "Change Title…"
msgstr "Titel bearbeiten…" msgstr "Titel bearbeiten…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Fenster nach oben teilen"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Fenster nach unten teilen"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Fenter nach links teilen"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Fenster nach rechts teilen"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Tab" msgstr "Tab"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Neuer Tab" msgstr "Neuer Tab"
@ -149,7 +153,7 @@ msgid "Terminal Inspector"
msgstr "Terminalinspektor" msgstr "Terminalinspektor"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Über Ghostty" msgstr "Über Ghostty"
@ -200,13 +204,32 @@ msgstr ""
"Diesen Text in das Terminal einzufügen könnte möglicherweise gefährlich " "Diesen Text in das Terminal einzufügen könnte möglicherweise gefährlich "
"sein. Es scheint, dass Anweisungen ausgeführt werden könnten." "sein. Es scheint, dass Anweisungen ausgeführt werden könnten."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Hauptmenü"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Offene Tabs einblenden"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr "" msgstr ""
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:312
msgid "Copied to clipboard" msgid ""
msgstr "In die Zwischenablage kopiert" "⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
"sein."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Konfiguration wurde neu geladen"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty-Entwickler"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -244,25 +267,10 @@ msgstr "Alle Terminalsitzungen in diesem Tab werden beendet."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Der aktuell laufende Prozess in diesem geteilten Fenster wird beendet." msgstr "Der aktuell laufende Prozess in diesem geteilten Fenster wird beendet."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Hauptmenü" msgstr "In die Zwischenablage kopiert"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Offene Tabs einblenden"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "" msgstr ""
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
"sein."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Konfiguration wurde neu geladen"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Ghostty-Entwickler"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-28 17:46+0200\n" "PO-Revision-Date: 2025-03-28 17:46+0200\n"
"Last-Translator: Miguel Peredo <miguelp@quientienemail.com>\n" "Last-Translator: Miguel Peredo <miguelp@quientienemail.com>\n"
"Language-Team: Spanish <es@tp.org.es>\n" "Language-Team: Spanish <es@tp.org.es>\n"
@ -43,8 +43,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Se encontraron uno o más errores de configuración. Por favor revise los errores a continuación, " "Se encontraron uno o más errores de configuración. Por favor revise los "
"y recargue su configuración o ignore estos errores." "errores a continuación, y recargue su configuración o ignore estos errores."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -56,6 +56,30 @@ msgstr "Ignorar"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recargar configuración" msgstr "Recargar configuración"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Dividir arriba"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Dividir abajo"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Dividir a la izquierda"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Dividir a la derecha"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,33 +111,13 @@ msgstr "Dividir"
msgid "Change Title…" msgid "Change Title…"
msgstr "Cambiar título…" msgstr "Cambiar título…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Dividir arriba"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Dividir abajo"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Dividir a la izquierda"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Dividir a la derecha"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Pestaña" msgstr "Pestaña"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nueva pestaña" msgstr "Nueva pestaña"
@ -150,7 +154,7 @@ msgid "Terminal Inspector"
msgstr "Inspector de la terminal" msgstr "Inspector de la terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Acerca de Ghostty" msgstr "Acerca de Ghostty"
@ -201,13 +205,32 @@ msgstr ""
"Pegar este texto en la terminal puede ser peligroso ya que parece que " "Pegar este texto en la terminal puede ser peligroso ya que parece que "
"algunos comandos podrían ejecutarse." "algunos comandos podrían ejecutarse."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Inspector de la terminal" msgstr "Menú principal"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Copiado al portapapeles" msgstr "Ver pestañas abiertas"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no "
"será óptimo."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -245,23 +268,10 @@ msgstr "Todas las sesiones de terminal en esta pestaña serán terminadas."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "El proceso actualmente en ejecución en esta división será terminado." msgstr "El proceso actualmente en ejecución en esta división será terminado."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Menú principal" msgstr "Copiado al portapapeles"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Ver pestañas abiertas" msgstr "Ghostty: Inspector de la terminal"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no será óptimo."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-22 09:31+0100\n" "PO-Revision-Date: 2025-03-22 09:31+0100\n"
"Last-Translator: Kirwiisp <swiip__@hotmail.com>\n" "Last-Translator: Kirwiisp <swiip__@hotmail.com>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"
@ -43,8 +43,9 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Une ou plusieurs erreurs de configuration ont été trouvées. Veuillez lire les erreurs ci-dessous," "Une ou plusieurs erreurs de configuration ont été trouvées. Veuillez lire "
"et recharger votre configuration ou bien ignorer ces erreurs." "les erreurs ci-dessous,et recharger votre configuration ou bien ignorer ces "
"erreurs."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -56,6 +57,30 @@ msgstr "Ignorer"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recharger la configuration" msgstr "Recharger la configuration"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Panneau en haut"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Panneau en bas"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Panneau à gauche"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Panneau à droite"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,33 +112,13 @@ msgstr "Créer panneau"
msgid "Change Title…" msgid "Change Title…"
msgstr "Changer le titre…" msgstr "Changer le titre…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Panneau en haut"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Panneau en bas"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Panneau à gauche"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Panneau à droite"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Onglet" msgstr "Onglet"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nouvel onglet" msgstr "Nouvel onglet"
@ -150,7 +155,7 @@ msgid "Terminal Inspector"
msgstr "Inspecteur de terminal" msgstr "Inspecteur de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "À propos de Ghostty" msgstr "À propos de Ghostty"
@ -168,8 +173,8 @@ msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Une application essaie de lire depuis le presse-papiers." "Une application essaie de lire depuis le presse-papiers.Le contenu actuel du "
"Le contenu actuel du presse-papiers est affiché ci-dessous." "presse-papiers est affiché ci-dessous."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -186,8 +191,8 @@ msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Une application essaie d'écrire dans le presse-papiers." "Une application essaie d'écrire dans le presse-papiers.Le contenu actuel du "
"Le contenu actuel du presse-papiers est affiché ci-dessous." "presse-papiers est affiché ci-dessous."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
@ -198,16 +203,35 @@ msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
"Coller ce texte dans le terminal pourrait être dangereux, " "Coller ce texte dans le terminal pourrait être dangereux, il semblerait que "
"il semblerait que certaines commandes pourraient être exécutées." "certaines commandes pourraient être exécutées."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Inspecteur" msgstr "Menu principal"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Copié dans le presse-papiers" msgstr "Voir les onglets ouverts"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront "
"dégradées."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Recharger la configuration"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Les développeurs de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -245,24 +269,10 @@ msgstr "Toutes les sessions de cet onglet vont être arrêtées."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Le processus en cours dans ce panneau va être arrêté." msgstr "Le processus en cours dans ce panneau va être arrêté."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Menu principal" msgstr "Copié dans le presse-papiers"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Voir les onglets ouverts" msgstr "Ghostty: Inspecteur"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront dégradées."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Recharger la configuration"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Les développeurs de Ghostty"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-20 15:19+0700\n" "PO-Revision-Date: 2025-03-20 15:19+0700\n"
"Last-Translator: Satrio Bayu Aji <halosatrio@gmail.com>\n" "Last-Translator: Satrio Bayu Aji <halosatrio@gmail.com>\n"
"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n" "Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
@ -42,8 +42,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Ditemukan satu atau lebih kesalahan konfigurasi. Silakan tinjau kesalahan di bawah ini, " "Ditemukan satu atau lebih kesalahan konfigurasi. Silakan tinjau kesalahan di "
"dan muat ulang konfigurasi anda atau abaikan kesalahan ini." "bawah ini, dan muat ulang konfigurasi anda atau abaikan kesalahan ini."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -55,6 +55,30 @@ msgstr "Abaikan"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Muat ulang konfigurasi" msgstr "Muat ulang konfigurasi"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Belah atas"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Belah bawah"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Belah kiri"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Belah kanan"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -86,33 +110,13 @@ msgstr "Belah"
msgid "Change Title…" msgid "Change Title…"
msgstr "Ubah judul…" msgstr "Ubah judul…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Belah atas"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Belah bawah"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Belah kiri"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Belah kanan"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Tab" msgstr "Tab"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Tab baru" msgstr "Tab baru"
@ -149,7 +153,7 @@ msgid "Terminal Inspector"
msgstr "Inspektur terminal" msgstr "Inspektur terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Tentang Ghostty" msgstr "Tentang Ghostty"
@ -167,8 +171,8 @@ msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Aplikasi sedang mencoba membaca dari papan klip. Isi papan klip " "Aplikasi sedang mencoba membaca dari papan klip. Isi papan klip saat ini "
"saat ini ditampilkan di bawah ini." "ditampilkan di bawah ini."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -185,8 +189,8 @@ msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Aplikasi sedang mencoba menulis ke papan klip. Isi papan klip " "Aplikasi sedang mencoba menulis ke papan klip. Isi papan klip saat ini "
"saat ini ditampilkan di bawah ini." "ditampilkan di bawah ini."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
@ -200,13 +204,31 @@ msgstr ""
"Menempelkan teks ini ke terminal mungkin berbahaya karena sepertinya " "Menempelkan teks ini ke terminal mungkin berbahaya karena sepertinya "
"beberapa perintah mungkin dijalankan." "beberapa perintah mungkin dijalankan."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Inspektur terminal" msgstr "Menu utama"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Disalin ke papan klip" msgstr "Lihat tab terbuka"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Memuat ulang konfigurasi"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Pengembang Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -244,23 +266,10 @@ msgstr "Semua sesi terminal di tab ini akan diakhiri."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Proses yang sedang berjalan dalam belahan ini akan diakhiri." msgstr "Proses yang sedang berjalan dalam belahan ini akan diakhiri."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Menu utama" msgstr "Disalin ke papan klip"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Lihat tab terbuka" msgstr "Ghostty: Inspektur terminal"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Memuat ulang konfigurasi"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Pengembang Ghostty"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-21 00:08+0900\n" "PO-Revision-Date: 2025-03-21 00:08+0900\n"
"Last-Translator: Lon Sagisawa <lon@sagisawa.me>\n" "Last-Translator: Lon Sagisawa <lon@sagisawa.me>\n"
"Language-Team: Japanese\n" "Language-Team: Japanese\n"
@ -44,8 +44,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"設定ファイルにエラーがあります。以下のエラーを確認し、" "設定ファイルにエラーがあります。以下のエラーを確認し、設定ファイルの再読み込"
"設定ファイルの再読み込みをするか、無視してください。" "みをするか、無視してください。"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -57,6 +57,30 @@ msgstr "無視"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "設定ファイルの再読み込み" msgstr "設定ファイルの再読み込み"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "上に分割"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "下に分割"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "左に分割"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "右に分割"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,33 +112,13 @@ msgstr "分割"
msgid "Change Title…" msgid "Change Title…"
msgstr "タイトルを変更…" msgstr "タイトルを変更…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "上に分割"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "下に分割"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "左に分割"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "右に分割"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "タブ" msgstr "タブ"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "新しいタブ" msgstr "新しいタブ"
@ -151,7 +155,7 @@ msgid "Terminal Inspector"
msgstr "端末インスペクター" msgstr "端末インスペクター"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Ghostty について" msgstr "Ghostty について"
@ -169,8 +173,8 @@ msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"アプリケーションがクリップボードを読み取ろうとしています。" "アプリケーションがクリップボードを読み取ろうとしています。現在のクリップボー"
"現在のクリップボードの内容は以下の通りです。" "ドの内容は以下の通りです。"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -187,8 +191,8 @@ msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"アプリケーションがクリップボードに書き込もうとしています。" "アプリケーションがクリップボードに書き込もうとしています。現在のクリップボー"
"現在のクリップボードの内容は以下の通りです。" "ドの内容は以下の通りです。"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
@ -199,16 +203,34 @@ msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
"このテキストには実行可能なコマンドが含まれており、" "このテキストには実行可能なコマンドが含まれており、ターミナルに貼り付けるのは"
"ターミナルに貼り付けるのは危険な可能性があります。" "危険な可能性があります。"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: 端末インスペクター" msgstr "メインメニュー"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "クリップボードにコピーしました" msgstr "開いているすべてのタブを表示"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "設定を再読み込みしました"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty 開発者"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -246,23 +268,10 @@ msgstr "タブ内のすべてのターミナルセッションが終了します
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "分割ウィンドウ内のすべてのプロセスが終了します。" msgstr "分割ウィンドウ内のすべてのプロセスが終了します。"
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "メインメニュー" msgstr "クリップボードにコピーしました"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "開いているすべてのタブを表示" msgstr "Ghostty: 端末インスペクター"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "設定を再読み込みしました"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Ghostty 開発者"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-23 14:17+0100\n" "PO-Revision-Date: 2025-03-23 14:17+0100\n"
"Last-Translator: Andrej Daskalov <andrej.daskalov@gmail.com>\n" "Last-Translator: Andrej Daskalov <andrej.daskalov@gmail.com>\n"
"Language-Team: Macedonian\n" "Language-Team: Macedonian\n"
@ -41,7 +41,10 @@ msgstr "Грешки во конфигурацијата"
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "Пронајдени се една или повеќе грешки во конфигурацијата. Прегледајте ги грешките подолу и повторно вчитајте ја конфигурацијата или игнорирајте ги овие грешки." msgstr ""
"Пронајдени се една или повеќе грешки во конфигурацијата. Прегледајте ги "
"грешките подолу и повторно вчитајте ја конфигурацијата или игнорирајте ги "
"овие грешки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -53,6 +56,30 @@ msgstr "Игнорирај"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Одново вчитај конфигурација" msgstr "Одново вчитај конфигурација"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Подели нагоре"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Подели надолу"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Подели налево"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Подели надесно"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -84,33 +111,13 @@ msgstr "Подели"
msgid "Change Title…" msgid "Change Title…"
msgstr "Промени наслов…" msgstr "Промени наслов…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Подели нагоре"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Подели надолу"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Подели налево"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Подели надесно"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Јазиче" msgstr "Јазиче"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Ново јазиче" msgstr "Ново јазиче"
@ -147,7 +154,7 @@ msgid "Terminal Inspector"
msgstr "Инспектор на терминал" msgstr "Инспектор на терминал"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "За Ghostty" msgstr "За Ghostty"
@ -164,7 +171,9 @@ msgstr "Авторизирај пристап до привремена мемо
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "Апликација се обидува да чита од привремената меморија. Содржината е прикажана подолу." msgstr ""
"Апликација се обидува да чита од привремената меморија. Содржината е "
"прикажана подолу."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -180,7 +189,9 @@ msgstr "Дозволи"
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "Апликација се обидува да запише во привремената меморија. Содржината е прикажана подолу." msgstr ""
"Апликација се обидува да запише во привремената меморија. Содржината е "
"прикажана подолу."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
@ -190,15 +201,35 @@ msgstr "Предупредување: Потенцијално небезбед
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "Вметнувањето на овој текст во терминалот може да биде опасно, бидејќи изгледа како да ќе се извршат одредени команди." msgstr ""
"Вметнувањето на овој текст во терминалот може да биде опасно, бидејќи "
"изгледа како да ќе се извршат одредени команди."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Инспектор на терминал" msgstr "Главно мени"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Копирано во привремена меморија" msgstr "Прегледај отворени јазичиња"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфигурацијата е одново вчитана"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Развивачи на Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -236,23 +267,10 @@ msgstr "Сите сесии во ова јазиче ќе бидат преки
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Процесот кој моментално се извршува во оваа поделба ќе биде прекинат." msgstr "Процесот кој моментално се извршува во оваа поделба ќе биде прекинат."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Главно мени" msgstr "Копирано во привремена меморија"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Прегледај отворени јазичиња" msgstr "Ghostty: Инспектор на терминал"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Конфигурацијата е одново вчитана"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Развивачи на Ghostty"

View File

@ -10,6 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-04-14 16:25+0200\n" "PO-Revision-Date: 2025-04-14 16:25+0200\n"
"Last-Translator: cryptocode <cryptocode@zolo.io>\n" "Last-Translator: cryptocode <cryptocode@zolo.io>\n"
"Language-Team: Norwegian Bokmal <l10n-no@lister.huftis.org>\n" "Language-Team: Norwegian Bokmal <l10n-no@lister.huftis.org>\n"
@ -45,8 +46,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Én eller flere konfigurasjonsfeil ble funnet. Vennligst gjennomgå feilene under, " "Én eller flere konfigurasjonsfeil ble funnet. Vennligst gjennomgå feilene "
"og enten last konfigurasjonen din på nytt eller ignorer disse feilene." "under, og enten last konfigurasjonen din på nytt eller ignorer disse feilene."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -58,6 +59,30 @@ msgstr "Ignorer"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Last konfigurasjon på nytt" msgstr "Last konfigurasjon på nytt"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Splitt opp"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Splitt ned"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Splitt venstre"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Splitt høyre"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,33 +114,13 @@ msgstr "Splitt"
msgid "Change Title…" msgid "Change Title…"
msgstr "Endre tittel…" msgstr "Endre tittel…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Splitt opp"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Splitt ned"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Splitt venstre"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Splitt høyre"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Fane" msgstr "Fane"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Ny fane" msgstr "Ny fane"
@ -152,7 +157,7 @@ msgid "Terminal Inspector"
msgstr "Terminalinspektør" msgstr "Terminalinspektør"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Om Ghostty" msgstr "Om Ghostty"
@ -203,13 +208,30 @@ msgstr ""
"Det ser ut som at kommandoer vil bli kjørt hvis du limer inn dette, vurder " "Det ser ut som at kommandoer vil bli kjørt hvis du limer inn dette, vurder "
"om du mener det er trygt." "om du mener det er trygt."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Terminalinspektør" msgstr "Hovedmeny"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Kopiert til utklippstavlen" msgstr "Se åpne faner"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Konfigurasjonen ble lastet på nytt"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty-utviklere"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -247,23 +269,10 @@ msgstr "Alle terminaløkter i denne fanen vil bli avsluttet."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Den kjørende prosessen for denne splitten vil bli avsluttet." msgstr "Den kjørende prosessen for denne splitten vil bli avsluttet."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Hovedmeny" msgstr "Kopiert til utklippstavlen"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Se åpne faner" msgstr "Ghostty: Terminalinspektør"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Konfigurasjonen ble lastet på nytt"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Ghostty-utviklere"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-24 15:00+0100\n" "PO-Revision-Date: 2025-03-24 15:00+0100\n"
"Last-Translator: Nico Geesink <geesinknico@gmail.com>\n" "Last-Translator: Nico Geesink <geesinknico@gmail.com>\n"
"Language-Team: Dutch <vertaling@vrijschrift.org>\n" "Language-Team: Dutch <vertaling@vrijschrift.org>\n"
@ -43,8 +43,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Er zijn één of meer configuratiefouten gevonden. Bekijk de onderstaande fouten " "Er zijn één of meer configuratiefouten gevonden. Bekijk de onderstaande "
"en herlaad je configuratie of negeer deze fouten." "fouten en herlaad je configuratie of negeer deze fouten."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -56,6 +56,30 @@ msgstr "Negeer"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Herlaad configuratie" msgstr "Herlaad configuratie"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Splits naar boven"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Splits naar beneden"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Splits naar links"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Splits naar rechts"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,33 +111,13 @@ msgstr "Splitsen"
msgid "Change Title…" msgid "Change Title…"
msgstr "Wijzig titel…" msgstr "Wijzig titel…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Splits naar boven"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Splits naar beneden"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Splits naar links"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Splits naar rechts"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Tabblad" msgstr "Tabblad"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nieuw tabblad" msgstr "Nieuw tabblad"
@ -150,7 +154,7 @@ msgid "Terminal Inspector"
msgstr "Terminal inspecteur" msgstr "Terminal inspecteur"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Over Ghostty" msgstr "Over Ghostty"
@ -198,16 +202,35 @@ msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
"Het plakken van deze tekst in de terminal is mogelijk gevaarlijk, omdat " "Het plakken van deze tekst in de terminal is mogelijk gevaarlijk, omdat het "
"het lijkt op een commando dat uitgevoerd kan worden." "lijkt op een commando dat uitgevoerd kan worden."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: terminal inspecteur" msgstr "Hoofdmenu"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Gekopieerd naar klembord" msgstr "Open tabbladen bekijken"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan "
"normaal."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "De configuratie is herladen"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty ontwikkelaars"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -243,26 +266,13 @@ msgstr "Alle terminalsessies binnen dit tabblad zullen worden beëindigd."
#: src/apprt/gtk/CloseDialog.zig:99 #: src/apprt/gtk/CloseDialog.zig:99
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Alle processen die nu draaien in deze splitsing zullen worden beëindigd."
#: src/apprt/gtk/Window.zig:200
msgid "Main Menu"
msgstr "Hoofdmenu"
#: src/apprt/gtk/Window.zig:221
msgid "View Open Tabs"
msgstr "Open tabbladen bekijken"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "" msgstr ""
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan normaal." "Alle processen die nu draaien in deze splitsing zullen worden beëindigd."
#: src/apprt/gtk/Window.zig:725 #: src/apprt/gtk/Surface.zig:1243
msgid "Reloaded the configuration" msgid "Copied to clipboard"
msgstr "De configuratie is herladen" msgstr "Gekopieerd naar klembord"
#: src/apprt/gtk/Window.zig:941 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty Developers" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty ontwikkelaars" msgstr "Ghostty: terminal inspecteur"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-18 11:48+0100\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-17 12:15+0100\n" "PO-Revision-Date: 2025-03-17 12:15+0100\n"
"Last-Translator: Bartosz Sokorski <b.sokorski@gmail.com>\n" "Last-Translator: Bartosz Sokorski <b.sokorski@gmail.com>\n"
"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n" "Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
@ -45,8 +45,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Znaleziono jeden lub więcej błędów konfiguracji. Sprawdź błędy wylistowane poniżej " "Znaleziono jeden lub więcej błędów konfiguracji. Sprawdź błędy wylistowane "
"i przeładuj konfigurację lub zignoruj je." "poniżej i przeładuj konfigurację lub zignoruj je."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -58,6 +58,30 @@ msgstr "Zignoruj"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Przeładuj konfigurację" msgstr "Przeładuj konfigurację"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Podziel w górę"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Podziel w dół"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Podziel w lewo"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Podziel w prawo"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,33 +113,13 @@ msgstr "Podział"
msgid "Change Title…" msgid "Change Title…"
msgstr "Zmień tytuł…" msgstr "Zmień tytuł…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Podziel w górę"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Podziel w dół"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Podziel w lewo"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Podziel w prawo"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Karta" msgstr "Karta"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nowa karta" msgstr "Nowa karta"
@ -152,7 +156,7 @@ msgid "Terminal Inspector"
msgstr "Inspektor terminala" msgstr "Inspektor terminala"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:958 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "O Ghostty" msgstr "O Ghostty"
@ -203,31 +207,31 @@ msgstr ""
"Wklejenie tego tekstu do terminala może być niebezpieczne, ponieważ może " "Wklejenie tego tekstu do terminala może być niebezpieczne, ponieważ może "
"spowodować wykonanie komend." "spowodować wykonanie komend."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Window.zig:201
msgid "Main Menu" msgid "Main Menu"
msgstr "Menu główne" msgstr "Menu główne"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs" msgid "View Open Tabs"
msgstr "Zobacz otwarte karty" msgstr "Zobacz otwarte karty"
#: src/apprt/gtk/Window.zig:295 #: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid "" msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded." "⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona." msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona."
#: src/apprt/gtk/Window.zig:725 #: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration" msgid "Reloaded the configuration"
msgstr "Przeładowano konfigurację" msgstr "Przeładowano konfigurację"
#: src/apprt/gtk/Window.zig:939 #: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers" msgid "Ghostty Developers"
msgstr "Twórcy Ghostty" msgstr "Twórcy Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Inspektor terminala Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Zamknij" msgstr "Zamknij"
@ -264,6 +268,10 @@ msgstr "Wszystkie sesje terminala w obecnej karcie zostaną zakończone."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Wszyskie trwające procesy w obecnym podziale zostaną zakończone." msgstr "Wszyskie trwające procesy w obecnym podziale zostaną zakończone."
#: src/apprt/gtk/Surface.zig:1242 #: src/apprt/gtk/Surface.zig:1243
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Skopiowano do schowka" msgstr "Skopiowano do schowka"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Inspektor terminala Ghostty"

View File

@ -8,11 +8,11 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-28 11:04-0300\n" "PO-Revision-Date: 2025-03-28 11:04-0300\n"
"Last-Translator: Gustavo Peres <gsodevel@gmail.com>\n" "Last-Translator: Gustavo Peres <gsodevel@gmail.com>\n"
"Language-Team: Brazilian Portuguese <ldpbr-" "Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge."
"translation@lists.sourceforge.net>\n" "net>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -45,8 +45,8 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Um ou mais erros de configuração encontrados. Por favor revise os erros abaixo, " "Um ou mais erros de configuração encontrados. Por favor revise os erros "
"e ou recarregue sua configuração, ou ignore esses erros." "abaixo, e ou recarregue sua configuração, ou ignore esses erros."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -58,6 +58,30 @@ msgstr "Ignorar"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recarregar configuração" msgstr "Recarregar configuração"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Dividir para cima"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Dividir para baixo"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Dividir à esquerda"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Dividir à direita"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,33 +113,13 @@ msgstr "Dividir"
msgid "Change Title…" msgid "Change Title…"
msgstr "Mudar título…" msgstr "Mudar título…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Dividir para cima"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Dividir para baixo"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Dividir à esquerda"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Dividir à direita"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Aba" msgstr "Aba"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Nova aba" msgstr "Nova aba"
@ -152,7 +156,7 @@ msgid "Terminal Inspector"
msgstr "Inspetor de terminal" msgstr "Inspetor de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Sobre o Ghostty" msgstr "Sobre o Ghostty"
@ -170,8 +174,8 @@ msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Uma aplicação está tentando ler da área de transferência. O conteúdo " "Uma aplicação está tentando ler da área de transferência. O conteúdo atual "
"atual da área de transferência está sendo exibido abaixo." "da área de transferência está sendo exibido abaixo."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -203,13 +207,31 @@ msgstr ""
"Colar esse texto em um terminal pode ser perigoso, pois parece que alguns " "Colar esse texto em um terminal pode ser perigoso, pois parece que alguns "
"comandos podem ser executados." "comandos podem ser executados."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Inspetor de terminal" msgstr "Menu Principal"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Copiado para a área de transferência" msgstr "Visualizar abas abertas"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Configuração recarregada"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desenvolvedores Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -247,23 +269,10 @@ msgstr "Todas as sessões de terminal nessa aba serão finalizadas."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "O processo atual rodando nessa divisão será finalizado." msgstr "O processo atual rodando nessa divisão será finalizado."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Menu Principal" msgstr "Copiado para a área de transferência"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Visualizar abas abertas" msgstr "Ghostty: Inspetor de terminal"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Configuração recarregada"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Desenvolvedores Ghostty"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:28-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-24 00:01+0500\n" "PO-Revision-Date: 2025-03-24 00:01+0500\n"
"Last-Translator: blackzeshi <sergey_zhuzhgov@mail.ru>\n" "Last-Translator: blackzeshi <sergey_zhuzhgov@mail.ru>\n"
"Language-Team: Russian <gnu@d07.ru>\n" "Language-Team: Russian <gnu@d07.ru>\n"
@ -44,9 +44,9 @@ msgstr "Ошибки конфигурации"
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Конфигурация содержит ошибки. Проверьте их ниже, а затем" "Конфигурация содержит ошибки. Проверьте их ниже, а затем либо перезагрузите "
"либо перезагрузите конфигурацию, либо проигнорируйте ошибки." "конфигурацию, либо проигнорируйте ошибки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -58,6 +58,30 @@ msgstr "Игнорировать"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Обновить конфигурацию" msgstr "Обновить конфигурацию"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Сплит вверх"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Сплит вниз"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Сплит влево"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Сплит вправо"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,33 +113,13 @@ msgstr "Сплит"
msgid "Change Title…" msgid "Change Title…"
msgstr "Изменить заголовок…" msgstr "Изменить заголовок…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Сплит вверх"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Сплит вниз"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Сплит влево"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Сплит вправо"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Вкладка" msgstr "Вкладка"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Новая вкладка" msgstr "Новая вкладка"
@ -152,7 +156,7 @@ msgid "Terminal Inspector"
msgstr "Инспектор терминала" msgstr "Инспектор терминала"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "О Ghostty" msgstr "О Ghostty"
@ -169,9 +173,9 @@ msgstr "Разрешить доступ к буферу обмена"
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Приложение пытается прочитать данные из буфера обмена. Эти данные " "Приложение пытается прочитать данные из буфера обмена. Эти данные отображены "
"отображены ниже." "ниже."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
@ -187,9 +191,8 @@ msgstr "Разрешить"
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Приложение пытается записать данные в буфер обмена. Эти данные " "Приложение пытается записать данные в буфер обмена. Эти данные показаны ниже."
"показаны ниже."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
@ -199,17 +202,36 @@ msgstr "Внимание! Вставляемые данные могут нан
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
"Вставка этого текста в терминал может быть опасной. Это выглядит " "Вставка этого текста в терминал может быть опасной. Это выглядит как "
ак команды, которые могут быть исполнены." "команды, которые могут быть исполнены."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: инспектор терминала" msgstr "Главное меню"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Скопировано в буфер обмена" msgstr "Просмотреть открытые вкладки"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на "
"производительность."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфигурация была обновлена"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Разработчики Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -247,24 +269,10 @@ msgstr "Все сессии терминала в этой вкладке буд
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Процесс, работающий в этой сплит-области, будет остановлен." msgstr "Процесс, работающий в этой сплит-области, будет остановлен."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Главное меню" msgstr "Скопировано в буфер обмена"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Просмотреть открытые вкладки" msgstr "Ghostty: инспектор терминала"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на производительность."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Конфигурация была обновлена"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Разработчики Ghostty"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-24 22:01+0300\n" "PO-Revision-Date: 2025-03-24 22:01+0300\n"
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
"Language-Team: Turkish\n" "Language-Team: Turkish\n"
@ -57,6 +57,30 @@ msgstr "Yok Say"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Yapılandırmayı Yeniden Yükle" msgstr "Yapılandırmayı Yeniden Yükle"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Yukarı Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Aşağı Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Sola Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Sağa Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,33 +112,13 @@ msgstr "Böl"
msgid "Change Title…" msgid "Change Title…"
msgstr "Başlığı Değiştir…" msgstr "Başlığı Değiştir…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Yukarı Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Aşağı Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Sola Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Sağa Doğru Böl"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Sekme" msgstr "Sekme"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Yeni Sekme" msgstr "Yeni Sekme"
@ -151,7 +155,7 @@ msgid "Terminal Inspector"
msgstr "Uçbirim Denetçisi" msgstr "Uçbirim Denetçisi"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Ghostty Hakkında" msgstr "Ghostty Hakkında"
@ -202,13 +206,32 @@ msgstr ""
"Bu metni uçbirime yapıştırmak tehlikeli olabilir; çünkü bir komut " "Bu metni uçbirime yapıştırmak tehlikeli olabilir; çünkü bir komut "
"yürütülebilecekmiş gibi duruyor." "yürütülebilecekmiş gibi duruyor."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Uçbirim Denetçisi" msgstr "Ana Menü"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Panoya kopyalandı" msgstr "Açık Sekmeleri Görüntüle"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghosttynin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
"Başarım normale göre daha düşük olacaktır."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Yapılandırma yeniden yüklendi"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty Geliştiricileri"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -246,25 +269,10 @@ msgstr "Bu sekmedeki tüm uçbirim oturumları sonlandırılacaktır."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Bu bölmedeki şu anda çalışan süreç sonlandırılacaktır." msgstr "Bu bölmedeki şu anda çalışan süreç sonlandırılacaktır."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Ana Menü" msgstr "Panoya kopyalandı"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Açık Sekmeleri Görüntüle" msgstr "Ghostty: Uçbirim Denetçisi"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghosttynin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
"Başarım normale göre daha düşük olacaktır."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Yapılandırma yeniden yüklendi"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Ghostty Geliştiricileri"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-03-16 20:16+0200\n" "PO-Revision-Date: 2025-03-16 20:16+0200\n"
"Last-Translator: Danylo Zalizchuk <danilmail0110@gmail.com>\n" "Last-Translator: Danylo Zalizchuk <danilmail0110@gmail.com>\n"
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n" "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
@ -44,8 +44,9 @@ msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
"Виявлено одну або декілька помилок у конфігурації. Будь ласка, перегляньте наведені " "Виявлено одну або декілька помилок у конфігурації. Будь ласка, перегляньте "
"нижче помилки і або перезавантажте конфігурацію, або проігноруйте ці помилки." "наведені нижче помилки і або перезавантажте конфігурацію, або проігноруйте "
"ці помилки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
@ -57,6 +58,30 @@ msgstr "Ігнорувати"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Перезавантажити конфігурацію" msgstr "Перезавантажити конфігурацію"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Розділити панель вгору"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Розділити панель вниз"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Розділити панель ліворуч"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Розділити панель праворуч"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,33 +113,13 @@ msgstr "Розділена панель"
msgid "Change Title…" msgid "Change Title…"
msgstr "Змінити заголовок…" msgstr "Змінити заголовок…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "Розділити панель вгору"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "Розділити панель вниз"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "Розділити панель ліворуч"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "Розділити панель праворуч"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "Вкладка" msgstr "Вкладка"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "Нова вкладка" msgstr "Нова вкладка"
@ -151,7 +156,7 @@ msgid "Terminal Inspector"
msgstr "Інспектор терміналу" msgstr "Інспектор терміналу"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Про Ghostty" msgstr "Про Ghostty"
@ -202,13 +207,31 @@ msgstr ""
"Вставка цього тексту в термінал може бути небезпечною, оскільки виглядає " "Вставка цього тексту в термінал може бути небезпечною, оскільки виглядає "
"так, ніби деякі команди можуть бути виконані." "так, ніби деякі команди можуть бути виконані."
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty: Інспектор терміналу" msgstr "Головне меню"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "Скопійовано в буфер обміну" msgstr "Переглянути відкриті вкладки"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфігурацію перезавантажено"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Розробники Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -247,24 +270,10 @@ msgid "The currently running process in this split will be terminated."
msgstr "" msgstr ""
"Поточний процес, що виконується в цій розділеній панелі, буде завершено." "Поточний процес, що виконується в цій розділеній панелі, буде завершено."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "Головне меню" msgstr "Скопійовано в буфер обміну"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "Переглянути відкриті вкладки" msgstr "Ghostty: Інспектор терміналу"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "Конфігурацію перезавантажено"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Розробники Ghostty"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-04-22 08:57-0700\n"
"PO-Revision-Date: 2025-02-27 09:16+0100\n" "PO-Revision-Date: 2025-02-27 09:16+0100\n"
"Last-Translator: Leah <hi@pluie.me>\n" "Last-Translator: Leah <hi@pluie.me>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n" "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@ -55,6 +55,30 @@ msgstr "忽略"
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "重新加载配置" msgstr "重新加载配置"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "向上分屏"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "向下分屏"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "向左分屏"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "向右分屏"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -86,33 +110,13 @@ msgstr "分屏"
msgid "Change Title…" msgid "Change Title…"
msgstr "更改标题……" msgstr "更改标题……"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "向上分屏"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "向下分屏"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "向左分屏"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "向右分屏"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "标签页" msgstr "标签页"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:248
msgid "New Tab" msgid "New Tab"
msgstr "新建标签页" msgstr "新建标签页"
@ -149,7 +153,7 @@ msgid "Terminal Inspector"
msgstr "终端调试器" msgstr "终端调试器"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1003
msgid "About Ghostty" msgid "About Ghostty"
msgstr "关于 Ghostty" msgstr "关于 Ghostty"
@ -194,13 +198,30 @@ msgid ""
"commands may be executed." "commands may be executed."
msgstr "将以下内容粘贴至终端内将可能执行有害命令。" msgstr "将以下内容粘贴至终端内将可能执行有害命令。"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/Window.zig:201
msgid "Ghostty: Terminal Inspector" msgid "Main Menu"
msgstr "Ghostty 终端调试器" msgstr "主菜单"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Window.zig:222
msgid "Copied to clipboard" msgid "View Open Tabs"
msgstr "已复制至剪贴板" msgstr "浏览标签页"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "已重新加载配置"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty 开发团队"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -238,23 +259,10 @@ msgstr "标签页内所有运行中的进程将被终止。"
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "分屏内正在运行中的进程将被终止。" msgstr "分屏内正在运行中的进程将被终止。"
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1243
msgid "Main Menu" msgid "Copied to clipboard"
msgstr "主菜单" msgstr "已复制至剪贴板"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/inspector.zig:144
msgid "View Open Tabs" msgid "Ghostty: Terminal Inspector"
msgstr "浏览标签页" msgstr "Ghostty 终端调试器"
#: src/apprt/gtk/Window.zig:295
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
#: src/apprt/gtk/Window.zig:725
msgid "Reloaded the configuration"
msgstr "已重新加载配置"
#: src/apprt/gtk/Window.zig:941
msgid "Ghostty Developers"
msgstr "Ghostty 开发团队"

View File

@ -70,7 +70,6 @@ parts:
plugin: nil plugin: nil
build-attributes: [enable-patchelf] build-attributes: [enable-patchelf]
build-packages: build-packages:
- blueprint-compiler
- libgtk-4-dev - libgtk-4-dev
- libadwaita-1-dev - libadwaita-1-dev
# TODO: Add when the Snap is updated to Ubuntu 24.10+ # TODO: Add when the Snap is updated to Ubuntu 24.10+
@ -80,7 +79,7 @@ parts:
- patchelf - patchelf
- gettext - gettext
override-build: | override-build: |
craftctl set version=$(git describe --abbrev=8) craftctl set version=$(cat VERSION)
$CRAFT_PART_SRC/../../zig/src/zig build -Dpatch-rpath=\$ORIGIN/../usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR:/snap/core24/current/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR -Doptimize=ReleaseFast $CRAFT_PART_SRC/../../zig/src/zig build -Dpatch-rpath=\$ORIGIN/../usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR:/snap/core24/current/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR -Doptimize=ReleaseFast
cp -rp zig-out/* $CRAFT_PART_INSTALL/ cp -rp zig-out/* $CRAFT_PART_INSTALL/
sed -i 's|Icon=com.mitchellh.ghostty|Icon=/snap/ghostty/current/share/icons/hicolor/512x512/apps/com.mitchellh.ghostty.png|g' $CRAFT_PART_INSTALL/share/applications/com.mitchellh.ghostty.desktop sed -i 's|Icon=com.mitchellh.ghostty|Icon=/snap/ghostty/current/share/icons/hicolor/512x512/apps/com.mitchellh.ghostty.png|g' $CRAFT_PART_INSTALL/share/applications/com.mitchellh.ghostty.desktop

View File

@ -4119,6 +4119,14 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, .unlocked); }, .unlocked);
}, },
.scroll_to_selection => {
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
const sel = self.io.terminal.screen.selection orelse return false;
const tl = sel.topLeft(&self.io.terminal.screen);
self.io.terminal.screen.scroll(.{ .pin = tl });
},
.scroll_page_up => { .scroll_page_up => {
const rows: isize = @intCast(self.size.grid().rows); const rows: isize = @intCast(self.size.grid().rows);
self.io.queueMessage(.{ self.io.queueMessage(.{
@ -4289,12 +4297,24 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
{}, {},
), ),
.toggle_window_float_on_top => return try self.rt_app.performAction(
.{ .surface = self },
.float_window,
.toggle,
),
.toggle_secure_input => return try self.rt_app.performAction( .toggle_secure_input => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.secure_input, .secure_input,
.toggle, .toggle,
), ),
.toggle_command_palette => return try self.rt_app.performAction(
.{ .surface = self },
.toggle_command_palette,
{},
),
.select_all => { .select_all => {
const sel = self.io.terminal.screen.selectAll(); const sel = self.io.terminal.screen.selectAll();
if (sel) |s| { if (sel) |s| {

View File

@ -107,6 +107,9 @@ pub const Action = union(Key) {
/// Toggle the quick terminal in or out. /// Toggle the quick terminal in or out.
toggle_quick_terminal, toggle_quick_terminal,
/// Toggle the command palette. This currently only works on macOS.
toggle_command_palette,
/// Toggle the visibility of all Ghostty terminal windows. /// Toggle the visibility of all Ghostty terminal windows.
toggle_visibility, toggle_visibility,
@ -202,6 +205,10 @@ pub const Action = union(Key) {
/// happen and can be ignored or cause a restart it isn't that important. /// happen and can be ignored or cause a restart it isn't that important.
quit_timer: QuitTimer, quit_timer: QuitTimer,
/// Set the window floating state. A floating window is one that is
/// always on top of other windows even when not focused.
float_window: FloatWindow,
/// Set the secure input functionality on or off. "Secure input" means /// Set the secure input functionality on or off. "Secure input" means
/// that the user is currently at some sort of prompt where they may be /// that the user is currently at some sort of prompt where they may be
/// entering a password or other sensitive information. This can be used /// entering a password or other sensitive information. This can be used
@ -244,6 +251,8 @@ pub const Action = union(Key) {
/// Closes the currently focused window. /// Closes the currently focused window.
close_window, close_window,
/// Called when the bell character is seen. The apprt should do whatever
/// it needs to ring the bell. This is usually a sound or visual effect.
ring_bell, ring_bell,
/// Sync with: ghostty_action_tag_e /// Sync with: ghostty_action_tag_e
@ -259,6 +268,7 @@ pub const Action = union(Key) {
toggle_tab_overview, toggle_tab_overview,
toggle_window_decorations, toggle_window_decorations,
toggle_quick_terminal, toggle_quick_terminal,
toggle_command_palette,
toggle_visibility, toggle_visibility,
move_tab, move_tab,
goto_tab, goto_tab,
@ -283,6 +293,7 @@ pub const Action = union(Key) {
renderer_health, renderer_health,
open_config, open_config,
quit_timer, quit_timer,
float_window,
secure_input, secure_input,
key_sequence, key_sequence,
color_change, color_change,
@ -419,6 +430,12 @@ pub const Fullscreen = enum(c_int) {
macos_non_native_padded_notch, macos_non_native_padded_notch,
}; };
pub const FloatWindow = enum(c_int) {
on,
off,
toggle,
};
pub const SecureInput = enum(c_int) { pub const SecureInput = enum(c_int) {
on, on,
off, off,

View File

@ -43,15 +43,15 @@ pub const App = struct {
/// Callback called to wakeup the event loop. This should trigger /// Callback called to wakeup the event loop. This should trigger
/// a full tick of the app loop. /// a full tick of the app loop.
wakeup: *const fn (AppUD) callconv(.C) void, wakeup: *const fn (AppUD) callconv(.c) void,
/// Callback called to handle an action. /// Callback called to handle an action.
action: *const fn (*App, apprt.Target.C, apprt.Action.C) callconv(.C) bool, action: *const fn (*App, apprt.Target.C, apprt.Action.C) callconv(.c) bool,
/// Read the clipboard value. The return value must be preserved /// Read the clipboard value. The return value must be preserved
/// by the host until the next call. If there is no valid clipboard /// by the host until the next call. If there is no valid clipboard
/// value then this should return null. /// value then this should return null.
read_clipboard: *const fn (SurfaceUD, c_int, *apprt.ClipboardRequest) callconv(.C) void, read_clipboard: *const fn (SurfaceUD, c_int, *apprt.ClipboardRequest) callconv(.c) void,
/// This may be called after a read clipboard call to request /// This may be called after a read clipboard call to request
/// confirmation that the clipboard value is safe to read. The embedder /// confirmation that the clipboard value is safe to read. The embedder
@ -61,13 +61,13 @@ pub const App = struct {
[*:0]const u8, [*:0]const u8,
*apprt.ClipboardRequest, *apprt.ClipboardRequest,
apprt.ClipboardRequestType, apprt.ClipboardRequestType,
) callconv(.C) void, ) callconv(.c) void,
/// Write the clipboard value. /// Write the clipboard value.
write_clipboard: *const fn (SurfaceUD, [*:0]const u8, c_int, bool) callconv(.C) void, write_clipboard: *const fn (SurfaceUD, [*:0]const u8, c_int, bool) callconv(.c) void,
/// Close the current surface given by this function. /// Close the current surface given by this function.
close_surface: ?*const fn (SurfaceUD, bool) callconv(.C) void = null, close_surface: ?*const fn (SurfaceUD, bool) callconv(.c) void = null,
}; };
/// This is the key event sent for ghostty_surface_key and /// This is the key event sent for ghostty_surface_key and
@ -1487,6 +1487,23 @@ pub const CAPI = struct {
return @intCast(@as(input.Mods.Backing, @bitCast(result))); return @intCast(@as(input.Mods.Backing, @bitCast(result)));
} }
/// Returns the current possible commands for a surface
/// in the output parameter. The memory is owned by libghostty
/// and doesn't need to be freed.
export fn ghostty_surface_commands(
surface: *Surface,
out: *[*]const input.Command.C,
len: *usize,
) void {
// In the future we may use this information to filter
// some commands.
_ = surface;
const commands = input.command.defaultsC;
out.* = commands.ptr;
len.* = commands.len;
}
/// Send this for raw keypresses (i.e. the keyDown event on macOS). /// Send this for raw keypresses (i.e. the keyDown event on macOS).
/// This will handle the keymap translation and send the appropriate /// This will handle the keymap translation and send the appropriate
/// key and char events. /// key and char events.

View File

@ -228,12 +228,14 @@ pub const App = struct {
.toggle_tab_overview, .toggle_tab_overview,
.toggle_window_decorations, .toggle_window_decorations,
.toggle_quick_terminal, .toggle_quick_terminal,
.toggle_command_palette,
.toggle_visibility, .toggle_visibility,
.goto_tab, .goto_tab,
.move_tab, .move_tab,
.inspector, .inspector,
.render_inspector, .render_inspector,
.quit_timer, .quit_timer,
.float_window,
.secure_input, .secure_input,
.key_sequence, .key_sequence,
.desktop_notification, .desktop_notification,

View File

@ -159,6 +159,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
opengl: bool = false, opengl: bool = false,
/// disable GLES, Ghostty can't use GLES /// disable GLES, Ghostty can't use GLES
@"gl-disable-gles": bool = false, @"gl-disable-gles": bool = false,
// GTK's new renderer can cause blurry font when using fractional scaling.
@"gl-no-fractional": bool = false, @"gl-no-fractional": bool = false,
/// Disabling Vulkan can improve startup times by hundreds of /// Disabling Vulkan can improve startup times by hundreds of
/// milliseconds on some systems. We don't use Vulkan so we can just /// milliseconds on some systems. We don't use Vulkan so we can just
@ -190,7 +191,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
// For the remainder of "why" see the 4.14 comment below. // For the remainder of "why" see the 4.14 comment below.
gdk_disable.@"gles-api" = true; gdk_disable.@"gles-api" = true;
gdk_disable.vulkan = true; gdk_disable.vulkan = true;
gdk_debug.@"gl-no-fractional" = true;
break :environment; break :environment;
} }
if (gtk_version.runtimeAtLeast(4, 14, 0)) { if (gtk_version.runtimeAtLeast(4, 14, 0)) {
@ -201,8 +201,12 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
// //
// Upstream issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/6589 // Upstream issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/6589
gdk_debug.@"gl-disable-gles" = true; gdk_debug.@"gl-disable-gles" = true;
gdk_debug.@"gl-no-fractional" = true;
gdk_debug.@"vulkan-disable" = true; gdk_debug.@"vulkan-disable" = true;
if (gtk_version.runtimeUntil(4, 17, 5)) {
// Removed at GTK v4.17.5
gdk_debug.@"gl-no-fractional" = true;
}
break :environment; break :environment;
} }
// Versions prior to 4.14 are a bit of an unknown for Ghostty. It // Versions prior to 4.14 are a bit of an unknown for Ghostty. It
@ -488,6 +492,8 @@ pub fn performAction(
// Unimplemented // Unimplemented
.close_all_windows, .close_all_windows,
.float_window,
.toggle_command_palette,
.toggle_visibility, .toggle_visibility,
.cell_size, .cell_size,
.key_sequence, .key_sequence,
@ -1290,6 +1296,13 @@ pub fn run(self: *App) !void {
// Setup our actions // Setup our actions
self.initActions(); self.initActions();
// On startup, we want to check for configuration errors right away
// so we can show our error window. We also need to setup other initial
// state.
self.syncConfigChanges(null) catch |err| {
log.warn("error handling configuration changes err={}", .{err});
};
while (self.running) { while (self.running) {
_ = glib.MainContext.iteration(self.ctx, 1); _ = glib.MainContext.iteration(self.ctx, 1);
@ -1514,7 +1527,7 @@ fn adwNotifyDark(
style_manager: *adw.StyleManager, style_manager: *adw.StyleManager,
_: *gobject.ParamSpec, _: *gobject.ParamSpec,
self: *App, self: *App,
) callconv(.C) void { ) callconv(.c) void {
const color_scheme: apprt.ColorScheme = if (style_manager.getDark() == 0) const color_scheme: apprt.ColorScheme = if (style_manager.getDark() == 0)
.light .light
else else

View File

@ -18,88 +18,37 @@ pub fn init(
/// The minor version of the minimum Adwaita version that is required to use /// The minor version of the minimum Adwaita version that is required to use
/// this resource. /// this resource.
comptime minor: u16, comptime minor: u16,
/// `blp` signifies that the resource is a Blueprint that has been compiled
/// to GTK Builder XML at compile time. `ui` signifies that the resource is
/// a GTK Builder XML file that is included in the Ghostty source (perhaps
/// because the Blueprint compiler on some target platforms cannot compile a
/// Blueprint that generates the necessary resources).
comptime kind: enum { blp, ui },
) Builder { ) Builder {
const resource_path = comptime resource_path: { const resource_path = comptime resource_path: {
const gresource = @import("gresource.zig"); const gresource = @import("gresource.zig");
switch (kind) { // Check to make sure that our file is listed as a
.blp => { // `blueprint_file` in `gresource.zig`. If it isn't Ghostty
// Check to make sure that our file is listed as a // could crash at runtime when we try and load a nonexistent
// `blueprint_file` in `gresource.zig`. If it isn't Ghostty // GResource.
// could crash at runtime when we try and load a nonexistent for (gresource.blueprint_files) |file| {
// GResource. if (major != file.major or minor != file.minor or !std.mem.eql(u8, file.name, name)) continue;
for (gresource.blueprint_files) |file| { // Use @embedFile to make sure that the `.blp` file exists
if (major != file.major or minor != file.minor or !std.mem.eql(u8, file.name, name)) continue; // at compile time. Zig _should_ discard the data so that
// Use @embedFile to make sure that the `.blp` file exists // it doesn't end up in the final executable. At runtime we
// at compile time. Zig _should_ discard the data so that // will load the data from a GResource.
// it doesn't end up in the final executable. At runtime we const blp_filename = std.fmt.comptimePrint(
// will load the data from a GResource. "ui/{d}.{d}/{s}.blp",
const blp_filename = std.fmt.comptimePrint( .{
"ui/{d}.{d}/{s}.blp", file.major,
.{ file.minor,
file.major, file.name,
file.minor, },
file.name, );
}, _ = @embedFile(blp_filename);
); break :resource_path std.fmt.comptimePrint(
_ = @embedFile(blp_filename); "/com/mitchellh/ghostty/ui/{d}.{d}/{s}.ui",
break :resource_path std.fmt.comptimePrint( .{
"/com/mitchellh/ghostty/ui/{d}.{d}/{s}.ui", file.major,
.{ file.minor,
file.major, file.name,
file.minor, },
file.name, );
}, } else @compileError("missing blueprint file '" ++ name ++ "' in gresource.zig");
);
} else @compileError("missing blueprint file '" ++ name ++ "' in gresource.zig");
},
.ui => {
// Check to make sure that our file is listed as a `ui_file` in
// `gresource.zig`. If it isn't Ghostty could crash at runtime
// when we try and load a nonexistent GResource.
for (gresource.ui_files) |file| {
if (major != file.major or minor != file.minor or !std.mem.eql(u8, file.name, name)) continue;
// Use @embedFile to make sure that the `.ui` file exists
// at compile time. Zig _should_ discard the data so that
// it doesn't end up in the final executable. At runtime we
// will load the data from a GResource.
const ui_filename = std.fmt.comptimePrint(
"ui/{d}.{d}/{s}.ui",
.{
file.major,
file.minor,
file.name,
},
);
_ = @embedFile(ui_filename);
// Also use @embedFile to make sure that a matching `.blp`
// file exists at compile time. Zig _should_ discard the
// data so that it doesn't end up in the final executable.
const blp_filename = std.fmt.comptimePrint(
"ui/{d}.{d}/{s}.blp",
.{
file.major,
file.minor,
file.name,
},
);
_ = @embedFile(blp_filename);
break :resource_path std.fmt.comptimePrint(
"/com/mitchellh/ghostty/ui/{d}.{d}/{s}.ui",
.{
file.major,
file.minor,
file.name,
},
);
} else @compileError("missing ui file '" ++ name ++ "' in gresource.zig");
},
}
}; };
return .{ return .{

View File

@ -71,14 +71,14 @@ fn init(
) !void { ) !void {
var builder = switch (DialogType) { var builder = switch (DialogType) {
adw.AlertDialog => switch (request) { adw.AlertDialog => switch (request) {
.osc_52_read => Builder.init("ccw-osc-52-read", 1, 5, .blp), .osc_52_read => Builder.init("ccw-osc-52-read", 1, 5),
.osc_52_write => Builder.init("ccw-osc-52-write", 1, 5, .blp), .osc_52_write => Builder.init("ccw-osc-52-write", 1, 5),
.paste => Builder.init("ccw-paste", 1, 5, .blp), .paste => Builder.init("ccw-paste", 1, 5),
}, },
adw.MessageDialog => switch (request) { adw.MessageDialog => switch (request) {
.osc_52_read => Builder.init("ccw-osc-52-read", 1, 2, .ui), .osc_52_read => Builder.init("ccw-osc-52-read", 1, 2),
.osc_52_write => Builder.init("ccw-osc-52-write", 1, 2, .ui), .osc_52_write => Builder.init("ccw-osc-52-write", 1, 2),
.paste => Builder.init("ccw-paste", 1, 2, .ui), .paste => Builder.init("ccw-paste", 1, 2),
}, },
else => unreachable, else => unreachable,
}; };
@ -152,7 +152,7 @@ fn init(
} }
} }
fn gtkResponse(_: *DialogType, response: [*:0]u8, self: *ClipboardConfirmation) callconv(.C) void { fn gtkResponse(_: *DialogType, response: [*:0]u8, self: *ClipboardConfirmation) callconv(.c) void {
if (std.mem.orderZ(u8, response, "ok") == .eq) { if (std.mem.orderZ(u8, response, "ok") == .eq) {
self.core_surface.completeClipboardRequest( self.core_surface.completeClipboardRequest(
self.pending_req, self.pending_req,
@ -165,7 +165,7 @@ fn gtkResponse(_: *DialogType, response: [*:0]u8, self: *ClipboardConfirmation)
self.destroy(); self.destroy();
} }
fn gtkRevealButtonClicked(_: *gtk.Button, self: *ClipboardConfirmation) callconv(.C) void { fn gtkRevealButtonClicked(_: *gtk.Button, self: *ClipboardConfirmation) callconv(.c) void {
self.text_view_scroll.as(gtk.Widget).setSensitive(@intFromBool(true)); self.text_view_scroll.as(gtk.Widget).setSensitive(@intFromBool(true));
self.text_view.as(gtk.Widget).removeCssClass("blurred"); self.text_view.as(gtk.Widget).removeCssClass("blurred");
@ -173,7 +173,7 @@ fn gtkRevealButtonClicked(_: *gtk.Button, self: *ClipboardConfirmation) callconv
self.reveal_button.as(gtk.Widget).setVisible(@intFromBool(false)); self.reveal_button.as(gtk.Widget).setVisible(@intFromBool(false));
} }
fn gtkHideButtonClicked(_: *gtk.Button, self: *ClipboardConfirmation) callconv(.C) void { fn gtkHideButtonClicked(_: *gtk.Button, self: *ClipboardConfirmation) callconv(.c) void {
self.text_view_scroll.as(gtk.Widget).setSensitive(@intFromBool(false)); self.text_view_scroll.as(gtk.Widget).setSensitive(@intFromBool(false));
self.text_view.as(gtk.Widget).addCssClass("blurred"); self.text_view.as(gtk.Widget).addCssClass("blurred");

View File

@ -64,7 +64,7 @@ fn responseCallback(
_: *DialogType, _: *DialogType,
response: [*:0]const u8, response: [*:0]const u8,
target: *Target, target: *Target,
) callconv(.C) void { ) callconv(.c) void {
const alloc = target.allocator(); const alloc = target.allocator();
defer alloc.destroy(target); defer alloc.destroy(target);
@ -141,7 +141,7 @@ pub const Target = union(enum) {
} }
}; };
fn findActiveWindow(data: ?*const anyopaque, _: ?*const anyopaque) callconv(.C) c_int { fn findActiveWindow(data: ?*const anyopaque, _: ?*const anyopaque) callconv(.c) c_int {
const window: *gtk.Window = @ptrCast(@alignCast(@constCast(data orelse return -1))); const window: *gtk.Window = @ptrCast(@alignCast(@constCast(data orelse return -1)));
// Confusingly, `isActive` returns 1 when active, // Confusingly, `isActive` returns 1 when active,

View File

@ -30,8 +30,8 @@ pub fn maybePresent(app: *App, window: ?*Window) void {
if (app.config._diagnostics.empty()) return; if (app.config._diagnostics.empty()) return;
var builder = switch (DialogType) { var builder = switch (DialogType) {
adw.AlertDialog => Builder.init("config-errors-dialog", 1, 5, .blp), adw.AlertDialog => Builder.init("config-errors-dialog", 1, 5),
adw.MessageDialog => Builder.init("config-errors-dialog", 1, 2, .ui), adw.MessageDialog => Builder.init("config-errors-dialog", 1, 2),
else => unreachable, else => unreachable,
}; };
defer builder.deinit(); defer builder.deinit();
@ -67,7 +67,7 @@ pub fn maybePresent(app: *App, window: ?*Window) void {
} }
} }
fn onResponse(_: *DialogType, response: [*:0]const u8, app: *App) callconv(.C) void { fn onResponse(_: *DialogType, response: [*:0]const u8, app: *App) callconv(.c) void {
if (std.mem.orderZ(u8, response, "reload") == .eq) { if (std.mem.orderZ(u8, response, "reload") == .eq) {
app.reloadConfig(.app, .{}) catch |err| { app.reloadConfig(.app, .{}) catch |err| {
log.warn("error reloading config error={}", .{err}); log.warn("error reloading config error={}", .{err});

View File

@ -221,12 +221,12 @@ fn translateMouseButton(button: c_uint) ?c_int {
}; };
} }
fn gtkDestroy(_: *gtk.GLArea, self: *ImguiWidget) callconv(.C) void { fn gtkDestroy(_: *gtk.GLArea, self: *ImguiWidget) callconv(.c) void {
log.debug("imgui widget destroy", .{}); log.debug("imgui widget destroy", .{});
self.deinit(); self.deinit();
} }
fn gtkRealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.C) void { fn gtkRealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.c) void {
log.debug("gl surface realized", .{}); log.debug("gl surface realized", .{});
// We need to make the context current so we can call GL functions. // We need to make the context current so we can call GL functions.
@ -242,7 +242,7 @@ fn gtkRealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.C) void {
_ = cimgui.ImGui_ImplOpenGL3_Init(null); _ = cimgui.ImGui_ImplOpenGL3_Init(null);
} }
fn gtkUnrealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.C) void { fn gtkUnrealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.c) void {
_ = area; _ = area;
log.debug("gl surface unrealized", .{}); log.debug("gl surface unrealized", .{});
@ -250,7 +250,7 @@ fn gtkUnrealize(area: *gtk.GLArea, self: *ImguiWidget) callconv(.C) void {
cimgui.ImGui_ImplOpenGL3_Shutdown(); cimgui.ImGui_ImplOpenGL3_Shutdown();
} }
fn gtkResize(area: *gtk.GLArea, width: c_int, height: c_int, self: *ImguiWidget) callconv(.C) void { fn gtkResize(area: *gtk.GLArea, width: c_int, height: c_int, self: *ImguiWidget) callconv(.c) void {
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO(); const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
const scale_factor = area.as(gtk.Widget).getScaleFactor(); const scale_factor = area.as(gtk.Widget).getScaleFactor();
@ -273,7 +273,7 @@ fn gtkResize(area: *gtk.GLArea, width: c_int, height: c_int, self: *ImguiWidget)
active_style.* = style.*; active_style.* = style.*;
} }
fn gtkRender(_: *gtk.GLArea, _: *gdk.GLContext, self: *ImguiWidget) callconv(.C) c_int { fn gtkRender(_: *gtk.GLArea, _: *gdk.GLContext, self: *ImguiWidget) callconv(.c) c_int {
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
// Setup our frame. We render twice because some ImGui behaviors // Setup our frame. We render twice because some ImGui behaviors
@ -307,7 +307,7 @@ fn gtkMouseMotion(
x: f64, x: f64,
y: f64, y: f64,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) void { ) callconv(.c) void {
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO(); const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
const scale_factor: f64 = @floatFromInt(self.gl_area.as(gtk.Widget).getScaleFactor()); const scale_factor: f64 = @floatFromInt(self.gl_area.as(gtk.Widget).getScaleFactor());
@ -325,7 +325,7 @@ fn gtkMouseDown(
_: f64, _: f64,
_: f64, _: f64,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) void { ) callconv(.c) void {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -343,7 +343,7 @@ fn gtkMouseUp(
_: f64, _: f64,
_: f64, _: f64,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) void { ) callconv(.c) void {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -359,7 +359,7 @@ fn gtkMouseScroll(
x: f64, x: f64,
y: f64, y: f64,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) c_int { ) callconv(.c) c_int {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -373,7 +373,7 @@ fn gtkMouseScroll(
return @intFromBool(true); return @intFromBool(true);
} }
fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *ImguiWidget) callconv(.C) void { fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *ImguiWidget) callconv(.c) void {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -381,7 +381,7 @@ fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *ImguiWidget) callconv(.C)
cimgui.c.ImGuiIO_AddFocusEvent(io, true); cimgui.c.ImGuiIO_AddFocusEvent(io, true);
} }
fn gtkFocusLeave(_: *gtk.EventControllerFocus, self: *ImguiWidget) callconv(.C) void { fn gtkFocusLeave(_: *gtk.EventControllerFocus, self: *ImguiWidget) callconv(.c) void {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -393,7 +393,7 @@ fn gtkInputCommit(
_: *gtk.IMMulticontext, _: *gtk.IMMulticontext,
bytes: [*:0]u8, bytes: [*:0]u8,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) void { ) callconv(.c) void {
self.queueRender(); self.queueRender();
cimgui.c.igSetCurrentContext(self.ig_ctx); cimgui.c.igSetCurrentContext(self.ig_ctx);
@ -407,7 +407,7 @@ fn gtkKeyPressed(
keycode: c_uint, keycode: c_uint,
gtk_mods: gdk.ModifierType, gtk_mods: gdk.ModifierType,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) c_int { ) callconv(.c) c_int {
return @intFromBool(self.keyEvent( return @intFromBool(self.keyEvent(
.press, .press,
ec_key, ec_key,
@ -423,7 +423,7 @@ fn gtkKeyReleased(
keycode: c_uint, keycode: c_uint,
gtk_mods: gdk.ModifierType, gtk_mods: gdk.ModifierType,
self: *ImguiWidget, self: *ImguiWidget,
) callconv(.C) void { ) callconv(.c) void {
_ = self.keyEvent( _ = self.keyEvent(
.release, .release,
ec_key, ec_key,

View File

@ -104,7 +104,7 @@ pub fn maybeShow(self: *ResizeOverlay) void {
/// Actually update the overlay widget. This should only be called from a GTK /// Actually update the overlay widget. This should only be called from a GTK
/// idle handler. /// idle handler.
fn gtkUpdate(ud: ?*anyopaque) callconv(.C) c_int { fn gtkUpdate(ud: ?*anyopaque) callconv(.c) c_int {
const self: *ResizeOverlay = @ptrCast(@alignCast(ud orelse return 0)); const self: *ResizeOverlay = @ptrCast(@alignCast(ud orelse return 0));
// No matter what our idler is complete with this callback // No matter what our idler is complete with this callback
@ -198,7 +198,7 @@ fn setPosition(label: *gtk.Label, config: *DerivedConfig) void {
/// If this fires, it means that the delay period has expired and the resize /// If this fires, it means that the delay period has expired and the resize
/// overlay widget should be hidden. /// overlay widget should be hidden.
fn gtkTimerExpired(ud: ?*anyopaque) callconv(.C) c_int { fn gtkTimerExpired(ud: ?*anyopaque) callconv(.c) c_int {
const self: *ResizeOverlay = @ptrCast(@alignCast(ud orelse return 0)); const self: *ResizeOverlay = @ptrCast(@alignCast(ud orelse return 0));
self.timer = null; self.timer = null;
if (self.label) |label| hide(label); if (self.label) |label| hide(label);

View File

@ -1025,7 +1025,7 @@ pub fn setTitle(self: *Surface, slice: [:0]const u8, source: SetTitleSource) !vo
self.update_title_timer = glib.timeoutAdd(75, updateTitleTimerExpired, self); self.update_title_timer = glib.timeoutAdd(75, updateTitleTimerExpired, self);
} }
fn updateTitleTimerExpired(ud: ?*anyopaque) callconv(.C) c_int { fn updateTitleTimerExpired(ud: ?*anyopaque) callconv(.c) c_int {
const self: *Surface = @ptrCast(@alignCast(ud.?)); const self: *Surface = @ptrCast(@alignCast(ud.?));
self.updateTitleLabels(); self.updateTitleLabels();
@ -1061,7 +1061,7 @@ pub fn promptTitle(self: *Surface) !void {
if (!adw_version.atLeast(1, 5, 0)) return; if (!adw_version.atLeast(1, 5, 0)) return;
const window = self.container.window() orelse return; const window = self.container.window() orelse return;
var builder = Builder.init("prompt-title-dialog", 1, 5, .blp); var builder = Builder.init("prompt-title-dialog", 1, 5);
defer builder.deinit(); defer builder.deinit();
const entry = builder.getObject(gtk.Entry, "title_entry").?; const entry = builder.getObject(gtk.Entry, "title_entry").?;
@ -1265,7 +1265,7 @@ fn gtkClipboardRead(
source: ?*gobject.Object, source: ?*gobject.Object,
res: *gio.AsyncResult, res: *gio.AsyncResult,
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) void { ) callconv(.c) void {
const clipboard = gobject.ext.cast(gdk.Clipboard, source orelse return) orelse return; const clipboard = gobject.ext.cast(gdk.Clipboard, source orelse return) orelse return;
const req: *ClipboardRequest = @ptrCast(@alignCast(ud orelse return)); const req: *ClipboardRequest = @ptrCast(@alignCast(ud orelse return));
const self = req.self; const self = req.self;
@ -1349,7 +1349,7 @@ pub fn showDesktopNotification(
app.sendNotification(body.ptr, notification); app.sendNotification(body.ptr, notification);
} }
fn gtkRealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.C) void { fn gtkRealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.c) void {
log.debug("gl surface realized", .{}); log.debug("gl surface realized", .{});
// We need to make the context current so we can call GL functions. // We need to make the context current so we can call GL functions.
@ -1377,7 +1377,7 @@ fn gtkRealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.C) void {
/// This is called when the underlying OpenGL resources must be released. /// This is called when the underlying OpenGL resources must be released.
/// This is usually due to the OpenGL area changing GDK surfaces. /// This is usually due to the OpenGL area changing GDK surfaces.
fn gtkUnrealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.C) void { fn gtkUnrealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.c) void {
log.debug("gl surface unrealized", .{}); log.debug("gl surface unrealized", .{});
// See gtkRealize for why we do this here. // See gtkRealize for why we do this here.
@ -1405,7 +1405,7 @@ fn gtkUnrealize(gl_area: *gtk.GLArea, self: *Surface) callconv(.C) void {
} }
/// render signal /// render signal
fn gtkRender(_: *gtk.GLArea, _: *gdk.GLContext, self: *Surface) callconv(.C) c_int { fn gtkRender(_: *gtk.GLArea, _: *gdk.GLContext, self: *Surface) callconv(.c) c_int {
self.render() catch |err| { self.render() catch |err| {
log.err("surface failed to render: {}", .{err}); log.err("surface failed to render: {}", .{err});
return 0; return 0;
@ -1415,7 +1415,7 @@ fn gtkRender(_: *gtk.GLArea, _: *gdk.GLContext, self: *Surface) callconv(.C) c_i
} }
/// resize signal /// resize signal
fn gtkResize(gl_area: *gtk.GLArea, width: c_int, height: c_int, self: *Surface) callconv(.C) void { fn gtkResize(gl_area: *gtk.GLArea, width: c_int, height: c_int, self: *Surface) callconv(.c) void {
// Some debug output to help understand what GTK is telling us. // Some debug output to help understand what GTK is telling us.
{ {
const scale_factor = scale: { const scale_factor = scale: {
@ -1471,7 +1471,7 @@ fn gtkResize(gl_area: *gtk.GLArea, width: c_int, height: c_int, self: *Surface)
} }
/// "destroy" signal for surface /// "destroy" signal for surface
fn gtkDestroy(_: *gtk.GLArea, self: *Surface) callconv(.C) void { fn gtkDestroy(_: *gtk.GLArea, self: *Surface) callconv(.c) void {
log.debug("gl destroy", .{}); log.debug("gl destroy", .{});
const alloc = self.app.core_app.alloc; const alloc = self.app.core_app.alloc;
@ -1505,7 +1505,7 @@ fn gtkMouseDown(
x: f64, x: f64,
y: f64, y: f64,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
const event = gesture.as(gtk.EventController).getCurrentEvent() orelse return; const event = gesture.as(gtk.EventController).getCurrentEvent() orelse return;
const gtk_mods = event.getModifierState(); const gtk_mods = event.getModifierState();
@ -1538,7 +1538,7 @@ fn gtkMouseUp(
_: f64, _: f64,
_: f64, _: f64,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
const event = gesture.as(gtk.EventController).getCurrentEvent() orelse return; const event = gesture.as(gtk.EventController).getCurrentEvent() orelse return;
const gtk_mods = event.getModifierState(); const gtk_mods = event.getModifierState();
@ -1557,7 +1557,7 @@ fn gtkMouseMotion(
x: f64, x: f64,
y: f64, y: f64,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
const event = ec.as(gtk.EventController).getCurrentEvent() orelse return; const event = ec.as(gtk.EventController).getCurrentEvent() orelse return;
const scaled = self.scaledCoordinates(x, y); const scaled = self.scaledCoordinates(x, y);
@ -1603,7 +1603,7 @@ fn gtkMouseMotion(
fn gtkMouseLeave( fn gtkMouseLeave(
ec_motion: *gtk.EventControllerMotion, ec_motion: *gtk.EventControllerMotion,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
const event = ec_motion.as(gtk.EventController).getCurrentEvent() orelse return; const event = ec_motion.as(gtk.EventController).getCurrentEvent() orelse return;
// Get our modifiers // Get our modifiers
@ -1618,14 +1618,14 @@ fn gtkMouseLeave(
fn gtkMouseScrollPrecisionBegin( fn gtkMouseScrollPrecisionBegin(
_: *gtk.EventControllerScroll, _: *gtk.EventControllerScroll,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
self.precision_scroll = true; self.precision_scroll = true;
} }
fn gtkMouseScrollPrecisionEnd( fn gtkMouseScrollPrecisionEnd(
_: *gtk.EventControllerScroll, _: *gtk.EventControllerScroll,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
self.precision_scroll = false; self.precision_scroll = false;
} }
@ -1634,7 +1634,7 @@ fn gtkMouseScroll(
x: f64, x: f64,
y: f64, y: f64,
self: *Surface, self: *Surface,
) callconv(.C) c_int { ) callconv(.c) c_int {
const scaled = self.scaledCoordinates(x, y); const scaled = self.scaledCoordinates(x, y);
// GTK doesn't support any of the scroll mods. // GTK doesn't support any of the scroll mods.
@ -1664,7 +1664,7 @@ fn gtkKeyPressed(
keycode: c_uint, keycode: c_uint,
gtk_mods: gdk.ModifierType, gtk_mods: gdk.ModifierType,
self: *Surface, self: *Surface,
) callconv(.C) c_int { ) callconv(.c) c_int {
return @intFromBool(self.keyEvent( return @intFromBool(self.keyEvent(
.press, .press,
ec_key, ec_key,
@ -1680,7 +1680,7 @@ fn gtkKeyReleased(
keycode: c_uint, keycode: c_uint,
state: gdk.ModifierType, state: gdk.ModifierType,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
_ = self.keyEvent( _ = self.keyEvent(
.release, .release,
ec_key, ec_key,
@ -1971,7 +1971,7 @@ pub fn keyEvent(
fn gtkInputPreeditStart( fn gtkInputPreeditStart(
_: *gtk.IMMulticontext, _: *gtk.IMMulticontext,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
// log.warn("GTKIM: preedit start", .{}); // log.warn("GTKIM: preedit start", .{});
// Start our composing state for the input method and reset our // Start our composing state for the input method and reset our
@ -1983,7 +1983,7 @@ fn gtkInputPreeditStart(
fn gtkInputPreeditChanged( fn gtkInputPreeditChanged(
ctx: *gtk.IMMulticontext, ctx: *gtk.IMMulticontext,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
// Any preedit change should mark that we're composing. Its possible this // Any preedit change should mark that we're composing. Its possible this
// is false using fcitx5-hangul and typing "dkssud<space>" ("안녕"). The // is false using fcitx5-hangul and typing "dkssud<space>" ("안녕"). The
// second "s" results in a "commit" for "" which sets composing to false, // second "s" results in a "commit" for "" which sets composing to false,
@ -2009,7 +2009,7 @@ fn gtkInputPreeditChanged(
fn gtkInputPreeditEnd( fn gtkInputPreeditEnd(
_: *gtk.IMMulticontext, _: *gtk.IMMulticontext,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
// log.warn("GTKIM: preedit end", .{}); // log.warn("GTKIM: preedit end", .{});
// End our composing state for GTK, allowing us to commit the text. // End our composing state for GTK, allowing us to commit the text.
@ -2025,7 +2025,7 @@ fn gtkInputCommit(
_: *gtk.IMMulticontext, _: *gtk.IMMulticontext,
bytes: [*:0]u8, bytes: [*:0]u8,
self: *Surface, self: *Surface,
) callconv(.C) void { ) callconv(.c) void {
const str = std.mem.sliceTo(bytes, 0); const str = std.mem.sliceTo(bytes, 0);
// log.debug("GTKIM: input commit composing={} keyevent={} str={s}", .{ // log.debug("GTKIM: input commit composing={} keyevent={} str={s}", .{
@ -2100,7 +2100,7 @@ fn gtkInputCommit(
}; };
} }
fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *Surface) callconv(.C) void { fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *Surface) callconv(.c) void {
if (!self.realized) return; if (!self.realized) return;
// Notify our IM context // Notify our IM context
@ -2125,7 +2125,7 @@ fn gtkFocusEnter(_: *gtk.EventControllerFocus, self: *Surface) callconv(.C) void
}; };
} }
fn gtkFocusLeave(_: *gtk.EventControllerFocus, self: *Surface) callconv(.C) void { fn gtkFocusLeave(_: *gtk.EventControllerFocus, self: *Surface) callconv(.c) void {
if (!self.realized) return; if (!self.realized) return;
// Notify our IM context // Notify our IM context
@ -2243,7 +2243,7 @@ fn gtkDrop(
_: f64, _: f64,
_: f64, _: f64,
self: *Surface, self: *Surface,
) callconv(.C) c_int { ) callconv(.c) c_int {
const alloc = self.app.core_app.alloc; const alloc = self.app.core_app.alloc;
if (g_value_holds(value, gdk.FileList.getGObjectType())) { if (g_value_holds(value, gdk.FileList.getGObjectType())) {
@ -2395,7 +2395,7 @@ fn g_value_holds(value_: ?*gobject.Value, g_type: gobject.Type) bool {
return false; return false;
} }
fn gtkPromptTitleResponse(source_object: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.C) void { fn gtkPromptTitleResponse(source_object: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.c) void {
if (!adw_version.supportsDialogs()) return; if (!adw_version.supportsDialogs()) return;
const dialog = gobject.ext.cast(adw.AlertDialog, source_object.?).?; const dialog = gobject.ext.cast(adw.AlertDialog, source_object.?).?;
const self: *Surface = @ptrCast(@alignCast(ud)); const self: *Surface = @ptrCast(@alignCast(ud));

View File

@ -161,7 +161,7 @@ pub fn closeWithConfirmation(tab: *Tab) void {
} }
} }
fn gtkDestroy(_: *gtk.Box, self: *Tab) callconv(.C) void { fn gtkDestroy(_: *gtk.Box, self: *Tab) callconv(.c) void {
log.debug("tab box destroy", .{}); log.debug("tab box destroy", .{});
const alloc = self.window.app.core_app.alloc; const alloc = self.window.app.core_app.alloc;

View File

@ -227,7 +227,7 @@ pub fn createWindow(window: *Window) !*Window {
return new_window; return new_window;
} }
fn adwPageAttached(_: *adw.TabView, page: *adw.TabPage, _: c_int, self: *TabView) callconv(.C) void { fn adwPageAttached(_: *adw.TabView, page: *adw.TabPage, _: c_int, self: *TabView) callconv(.c) void {
const child = page.getChild().as(gobject.Object); const child = page.getChild().as(gobject.Object);
const tab: *Tab = @ptrCast(@alignCast(child.getData(Tab.GHOSTTY_TAB) orelse return)); const tab: *Tab = @ptrCast(@alignCast(child.getData(Tab.GHOSTTY_TAB) orelse return));
tab.window = self.window; tab.window = self.window;
@ -239,7 +239,7 @@ fn adwClosePage(
_: *adw.TabView, _: *adw.TabView,
page: *adw.TabPage, page: *adw.TabPage,
self: *TabView, self: *TabView,
) callconv(.C) c_int { ) callconv(.c) c_int {
const child = page.getChild().as(gobject.Object); const child = page.getChild().as(gobject.Object);
const tab: *Tab = @ptrCast(@alignCast(child.getData(Tab.GHOSTTY_TAB) orelse return 0)); const tab: *Tab = @ptrCast(@alignCast(child.getData(Tab.GHOSTTY_TAB) orelse return 0));
self.tab_view.closePageFinish(page, @intFromBool(self.forcing_close)); self.tab_view.closePageFinish(page, @intFromBool(self.forcing_close));
@ -251,7 +251,7 @@ fn adwClosePage(
fn adwTabViewCreateWindow( fn adwTabViewCreateWindow(
_: *adw.TabView, _: *adw.TabView,
self: *TabView, self: *TabView,
) callconv(.C) ?*adw.TabView { ) callconv(.c) ?*adw.TabView {
const window = createWindow(self.window) catch |err| { const window = createWindow(self.window) catch |err| {
log.warn("error creating new window error={}", .{err}); log.warn("error creating new window error={}", .{err});
return null; return null;
@ -259,7 +259,7 @@ fn adwTabViewCreateWindow(
return window.notebook.tab_view; return window.notebook.tab_view;
} }
fn adwSelectPage(_: *adw.TabView, _: *gobject.ParamSpec, self: *TabView) callconv(.C) void { fn adwSelectPage(_: *adw.TabView, _: *gobject.ParamSpec, self: *TabView) callconv(.c) void {
const page = self.tab_view.getSelectedPage() orelse return; const page = self.tab_view.getSelectedPage() orelse return;
// If the tab was previously marked as needing attention // If the tab was previously marked as needing attention

View File

@ -101,7 +101,7 @@ fn gtkLeftEnter(
_: f64, _: f64,
_: f64, _: f64,
right: *gtk.Label, right: *gtk.Label,
) callconv(.C) void { ) callconv(.c) void {
right.as(gtk.Widget).removeCssClass("hidden"); right.as(gtk.Widget).removeCssClass("hidden");
} }
@ -110,6 +110,6 @@ fn gtkLeftEnter(
fn gtkLeftLeave( fn gtkLeftLeave(
_: *gtk.EventControllerMotion, _: *gtk.EventControllerMotion,
right: *gtk.Label, right: *gtk.Label,
) callconv(.C) void { ) callconv(.c) void {
right.as(gtk.Widget).addCssClass("hidden"); right.as(gtk.Widget).addCssClass("hidden");
} }

View File

@ -25,6 +25,7 @@ const input = @import("../../input.zig");
const CoreSurface = @import("../../Surface.zig"); const CoreSurface = @import("../../Surface.zig");
const App = @import("App.zig"); const App = @import("App.zig");
const Builder = @import("Builder.zig");
const Color = configpkg.Config.Color; const Color = configpkg.Config.Color;
const Surface = @import("Surface.zig"); const Surface = @import("Surface.zig");
const Menu = @import("menu.zig").Menu; const Menu = @import("menu.zig").Menu;
@ -242,12 +243,19 @@ pub fn init(self: *Window, app: *App) !void {
} }
{ {
const btn = gtk.Button.newFromIconName("tab-new-symbolic"); const btn = adw.SplitButton.new();
btn.setIconName("tab-new-symbolic");
btn.as(gtk.Widget).setTooltipText(i18n._("New Tab")); btn.as(gtk.Widget).setTooltipText(i18n._("New Tab"));
_ = gtk.Button.signals.clicked.connect( btn.setDropdownTooltip(i18n._("New Split"));
var builder = Builder.init("menu-headerbar-split_menu", 1, 0);
defer builder.deinit();
btn.setMenuModel(builder.getObject(gio.MenuModel, "menu"));
_ = adw.SplitButton.signals.clicked.connect(
btn, btn,
*Window, *Window,
gtkTabNewClick, adwNewTabClick,
self, self,
.{}, .{},
); );
@ -784,7 +792,7 @@ fn gtkWindowNotifyIsActive(
_: *adw.ApplicationWindow, _: *adw.ApplicationWindow,
_: *gobject.ParamSpec, _: *gobject.ParamSpec,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
if (!self.isQuickTerminal()) return; if (!self.isQuickTerminal()) return;
// Hide when we're unfocused // Hide when we're unfocused
@ -824,6 +832,11 @@ fn gtkTabNewClick(_: *gtk.Button, self: *Window) callconv(.c) void {
self.performBindingAction(.{ .new_tab = {} }); self.performBindingAction(.{ .new_tab = {} });
} }
/// Create a new surface (tab or split).
fn adwNewTabClick(_: *adw.SplitButton, self: *Window) callconv(.c) void {
self.performBindingAction(.{ .new_tab = {} });
}
/// Create a new tab from the AdwTabOverview. We can't copy gtkTabNewClick /// Create a new tab from the AdwTabOverview. We can't copy gtkTabNewClick
/// because we need to return an AdwTabPage from this function. /// because we need to return an AdwTabPage from this function.
fn gtkNewTabFromOverview(_: *adw.TabOverview, self: *Window) callconv(.c) *adw.TabPage { fn gtkNewTabFromOverview(_: *adw.TabOverview, self: *Window) callconv(.c) *adw.TabPage {
@ -870,7 +883,7 @@ fn adwTabOverviewOpen(
fn adwTabOverviewFocusTimer( fn adwTabOverviewFocusTimer(
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) c_int { ) callconv(.c) c_int {
if (!adw_version.supportsTabOverview()) unreachable; if (!adw_version.supportsTabOverview()) unreachable;
const self: *Window = @ptrCast(@alignCast(ud orelse return 0)); const self: *Window = @ptrCast(@alignCast(ud orelse return 0));
self.adw_tab_overview_focus_timer = null; self.adw_tab_overview_focus_timer = null;
@ -957,7 +970,7 @@ fn gtkActionAbout(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
const name = "Ghostty"; const name = "Ghostty";
const icon = "com.mitchellh.ghostty"; const icon = "com.mitchellh.ghostty";
const website = "https://ghostty.org"; const website = "https://ghostty.org";
@ -1001,7 +1014,7 @@ fn gtkActionClose(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.closeWithConfirmation(); self.closeWithConfirmation();
} }
@ -1009,7 +1022,7 @@ fn gtkActionNewWindow(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_window = {} }); self.performBindingAction(.{ .new_window = {} });
} }
@ -1017,7 +1030,7 @@ fn gtkActionNewTab(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_tab = {} }); self.performBindingAction(.{ .new_tab = {} });
} }
@ -1025,7 +1038,7 @@ fn gtkActionCloseTab(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .close_tab = {} }); self.performBindingAction(.{ .close_tab = {} });
} }
@ -1033,7 +1046,7 @@ fn gtkActionSplitRight(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_split = .right }); self.performBindingAction(.{ .new_split = .right });
} }
@ -1041,7 +1054,7 @@ fn gtkActionSplitDown(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_split = .down }); self.performBindingAction(.{ .new_split = .down });
} }
@ -1049,7 +1062,7 @@ fn gtkActionSplitLeft(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_split = .left }); self.performBindingAction(.{ .new_split = .left });
} }
@ -1057,15 +1070,15 @@ fn gtkActionSplitUp(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .new_split = .right }); self.performBindingAction(.{ .new_split = .up });
} }
fn gtkActionToggleInspector( fn gtkActionToggleInspector(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .inspector = .toggle }); self.performBindingAction(.{ .inspector = .toggle });
} }
@ -1073,7 +1086,7 @@ fn gtkActionCopy(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .copy_to_clipboard = {} }); self.performBindingAction(.{ .copy_to_clipboard = {} });
} }
@ -1081,7 +1094,7 @@ fn gtkActionPaste(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .paste_from_clipboard = {} }); self.performBindingAction(.{ .paste_from_clipboard = {} });
} }
@ -1089,7 +1102,7 @@ fn gtkActionReset(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .reset = {} }); self.performBindingAction(.{ .reset = {} });
} }
@ -1097,7 +1110,7 @@ fn gtkActionClear(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .clear_screen = {} }); self.performBindingAction(.{ .clear_screen = {} });
} }
@ -1105,7 +1118,7 @@ fn gtkActionPromptTitle(
_: *gio.SimpleAction, _: *gio.SimpleAction,
_: ?*glib.Variant, _: ?*glib.Variant,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
self.performBindingAction(.{ .prompt_surface_title = {} }); self.performBindingAction(.{ .prompt_surface_title = {} });
} }
@ -1120,7 +1133,7 @@ fn gtkTitlebarMenuActivate(
btn: *gtk.MenuButton, btn: *gtk.MenuButton,
_: *gobject.ParamSpec, _: *gobject.ParamSpec,
self: *Window, self: *Window,
) callconv(.C) void { ) callconv(.c) void {
// debian 12 is stuck on GTK 4.8 // debian 12 is stuck on GTK 4.8
if (!gtk_version.atLeast(4, 10, 0)) return; if (!gtk_version.atLeast(4, 10, 0)) return;
const active = btn.getActive() != 0; const active = btn.getActive() != 0;

View File

@ -4,62 +4,157 @@ pub const c = @cImport({
@cInclude("adwaita.h"); @cInclude("adwaita.h");
}); });
const adwaita_version = std.SemanticVersion{
.major = c.ADW_MAJOR_VERSION,
.minor = c.ADW_MINOR_VERSION,
.patch = c.ADW_MICRO_VERSION,
};
const required_blueprint_version = std.SemanticVersion{
.major = 0,
.minor = 16,
.patch = 0,
};
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
const alloc = gpa.allocator(); defer _ = debug_allocator.deinit();
const alloc = debug_allocator.allocator();
var it = try std.process.argsWithAllocator(alloc); var it = try std.process.argsWithAllocator(alloc);
defer it.deinit(); defer it.deinit();
_ = it.next(); _ = it.next();
const major = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMajorVersion, 10); const required_adwaita_version = std.SemanticVersion{
const minor = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMinorVersion, 10); .major = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMajorVersion, 10),
.minor = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMinorVersion, 10),
.patch = 0,
};
const output = it.next() orelse return error.NoOutput; const output = it.next() orelse return error.NoOutput;
const input = it.next() orelse return error.NoInput; const input = it.next() orelse return error.NoInput;
if (c.ADW_MAJOR_VERSION < major or (c.ADW_MAJOR_VERSION == major and c.ADW_MINOR_VERSION < minor)) { if (adwaita_version.order(required_adwaita_version) == .lt) {
// If the Adwaita version is too old, generate an "empty" file. std.debug.print(
const file = try std.fs.createFileAbsolute(output, .{ \\`libadwaita` is too old.
.truncate = true, \\
}); \\Ghostty requires a version {} or newer of `libadwaita` to
try file.writeAll( \\compile this blueprint. Please install it, ensure that it is
\\<?xml version="1.0" encoding="UTF-8"?> \\available on your PATH, and then retry building Ghostty.
\\<interface domain="com.mitchellh.ghostty"/> , .{required_adwaita_version});
); std.posix.exit(1);
defer file.close();
return;
} }
var compiler = std.process.Child.init( {
&.{ var stdout: std.ArrayListUnmanaged(u8) = .empty;
"blueprint-compiler", defer stdout.deinit(alloc);
"compile", var stderr: std.ArrayListUnmanaged(u8) = .empty;
"--output", defer stderr.deinit(alloc);
output,
input,
},
alloc,
);
const term = compiler.spawnAndWait() catch |err| switch (err) { var blueprint_compiler = std.process.Child.init(
error.FileNotFound => { &.{
std.log.err( "blueprint-compiler",
\\`blueprint-compiler` not found. "--version",
},
alloc,
);
blueprint_compiler.stdout_behavior = .Pipe;
blueprint_compiler.stderr_behavior = .Pipe;
try blueprint_compiler.spawn();
try blueprint_compiler.collectOutput(
alloc,
&stdout,
&stderr,
std.math.maxInt(u16),
);
const term = blueprint_compiler.wait() catch |err| switch (err) {
error.FileNotFound => {
std.debug.print(
\\`blueprint-compiler` not found.
\\
\\Ghostty requires version {} or newer of
\\`blueprint-compiler` as a build-time dependency starting
\\from version 1.2. Please install it, ensure that it is
\\available on your PATH, and then retry building Ghostty.
\\
, .{required_blueprint_version});
std.posix.exit(1);
},
else => return err,
};
switch (term) {
.Exited => |rc| {
if (rc != 0) std.process.exit(1);
},
else => std.process.exit(1),
}
const version = try std.SemanticVersion.parse(std.mem.trim(u8, stdout.items, &std.ascii.whitespace));
if (version.order(required_blueprint_version) == .lt) {
std.debug.print(
\\`blueprint-compiler` is the wrong version.
\\ \\
\\Ghostty requires `blueprint-compiler` as a build-time dependency starting from version 1.2. \\Ghostty requires version {} or newer of
\\Please install it, ensure that it is available on your PATH, and then retry building Ghostty. \\`blueprint-compiler` as a build-time dependency starting
, .{}); \\from version 1.2. Please install it, ensure that it is
\\available on your PATH, and then retry building Ghostty.
\\
, .{required_blueprint_version});
std.posix.exit(1); std.posix.exit(1);
}, }
else => return err, }
};
switch (term) { {
.Exited => |rc| { var stdout: std.ArrayListUnmanaged(u8) = .empty;
if (rc != 0) std.process.exit(1); defer stdout.deinit(alloc);
}, var stderr: std.ArrayListUnmanaged(u8) = .empty;
else => std.process.exit(1), defer stderr.deinit(alloc);
var blueprint_compiler = std.process.Child.init(
&.{
"blueprint-compiler",
"compile",
"--output",
output,
input,
},
alloc,
);
blueprint_compiler.stdout_behavior = .Pipe;
blueprint_compiler.stderr_behavior = .Pipe;
try blueprint_compiler.spawn();
try blueprint_compiler.collectOutput(
alloc,
&stdout,
&stderr,
std.math.maxInt(u16),
);
const term = blueprint_compiler.wait() catch |err| switch (err) {
error.FileNotFound => {
std.debug.print(
\\`blueprint-compiler` not found.
\\
\\Ghostty requires version {} or newer of
\\`blueprint-compiler` as a build-time dependency starting
\\from version 1.2. Please install it, ensure that it is
\\available on your PATH, and then retry building Ghostty.
\\
, .{required_blueprint_version});
std.posix.exit(1);
},
else => return err,
};
switch (term) {
.Exited => |rc| {
if (rc != 0) {
std.debug.print("{s}", .{stderr.items});
std.process.exit(1);
}
},
else => {
std.debug.print("{s}", .{stderr.items});
std.process.exit(1);
},
}
} }
} }

View File

@ -1,32 +0,0 @@
const std = @import("std");
const build_options = @import("build_options");
const gtk = @import("gtk");
const adw = @import("adw");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = gpa.allocator();
const filename = filename: {
var it = try std.process.argsWithAllocator(alloc);
defer it.deinit();
_ = it.next() orelse return error.NoFilename;
break :filename try alloc.dupeZ(u8, it.next() orelse return error.NoFilename);
};
defer alloc.free(filename);
const data = try std.fs.cwd().readFileAllocOptions(alloc, filename, std.math.maxInt(u16), null, 1, 0);
defer alloc.free(data);
if (gtk.initCheck() == 0) {
std.debug.print("{s}: skipping builder check because we can't connect to display!\n", .{filename});
return;
}
adw.init();
const builder = gtk.Builder.newFromString(data.ptr, @intCast(data.len));
defer builder.unref();
}

View File

@ -53,19 +53,6 @@ const icons = [_]struct {
}, },
}; };
pub const VersionedBuilderXML = struct {
major: u16,
minor: u16,
name: []const u8,
};
pub const ui_files = [_]VersionedBuilderXML{
.{ .major = 1, .minor = 2, .name = "config-errors-dialog" },
.{ .major = 1, .minor = 2, .name = "ccw-osc-52-read" },
.{ .major = 1, .minor = 2, .name = "ccw-osc-52-write" },
.{ .major = 1, .minor = 2, .name = "ccw-paste" },
};
pub const VersionedBlueprint = struct { pub const VersionedBlueprint = struct {
major: u16, major: u16,
minor: u16, minor: u16,
@ -75,21 +62,27 @@ pub const VersionedBlueprint = struct {
pub const blueprint_files = [_]VersionedBlueprint{ pub const blueprint_files = [_]VersionedBlueprint{
.{ .major = 1, .minor = 5, .name = "prompt-title-dialog" }, .{ .major = 1, .minor = 5, .name = "prompt-title-dialog" },
.{ .major = 1, .minor = 5, .name = "config-errors-dialog" }, .{ .major = 1, .minor = 5, .name = "config-errors-dialog" },
.{ .major = 1, .minor = 0, .name = "menu-headerbar-split_menu" },
.{ .major = 1, .minor = 0, .name = "menu-surface-context_menu" }, .{ .major = 1, .minor = 0, .name = "menu-surface-context_menu" },
.{ .major = 1, .minor = 0, .name = "menu-window-titlebar_menu" }, .{ .major = 1, .minor = 0, .name = "menu-window-titlebar_menu" },
.{ .major = 1, .minor = 5, .name = "ccw-osc-52-read" }, .{ .major = 1, .minor = 5, .name = "ccw-osc-52-read" },
.{ .major = 1, .minor = 5, .name = "ccw-osc-52-write" }, .{ .major = 1, .minor = 5, .name = "ccw-osc-52-write" },
.{ .major = 1, .minor = 5, .name = "ccw-paste" }, .{ .major = 1, .minor = 5, .name = "ccw-paste" },
.{ .major = 1, .minor = 2, .name = "config-errors-dialog" },
.{ .major = 1, .minor = 2, .name = "ccw-osc-52-read" },
.{ .major = 1, .minor = 2, .name = "ccw-osc-52-write" },
.{ .major = 1, .minor = 2, .name = "ccw-paste" },
}; };
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
const alloc = gpa.allocator(); defer _ = debug_allocator.deinit();
const alloc = debug_allocator.allocator();
var extra_ui_files = std.ArrayList([]const u8).init(alloc); var extra_ui_files: std.ArrayListUnmanaged([]const u8) = .empty;
defer { defer {
for (extra_ui_files.items) |item| alloc.free(item); for (extra_ui_files.items) |item| alloc.free(item);
extra_ui_files.deinit(); extra_ui_files.deinit(alloc);
} }
var it = try std.process.argsWithAllocator(alloc); var it = try std.process.argsWithAllocator(alloc);
@ -97,7 +90,7 @@ pub fn main() !void {
while (it.next()) |argument| { while (it.next()) |argument| {
if (std.mem.eql(u8, std.fs.path.extension(argument), ".ui")) { if (std.mem.eql(u8, std.fs.path.extension(argument), ".ui")) {
try extra_ui_files.append(try alloc.dupe(u8, argument)); try extra_ui_files.append(alloc, try alloc.dupe(u8, argument));
} }
} }
@ -131,16 +124,11 @@ pub fn main() !void {
\\ <gresource prefix="/com/mitchellh/ghostty/ui"> \\ <gresource prefix="/com/mitchellh/ghostty/ui">
\\ \\
); );
for (ui_files) |ui_file| {
try writer.print(
" <file compressed=\"true\" preprocess=\"xml-stripblanks\" alias=\"{0d}.{1d}/{2s}.ui\">src/apprt/gtk/ui/{0d}.{1d}/{2s}.ui</file>\n",
.{ ui_file.major, ui_file.minor, ui_file.name },
);
}
for (extra_ui_files.items) |ui_file| { for (extra_ui_files.items) |ui_file| {
const stem = std.fs.path.stem(ui_file);
for (blueprint_files) |file| { for (blueprint_files) |file| {
if (!std.mem.eql(u8, file.name, stem)) continue; const expected = try std.fmt.allocPrint(alloc, "/{d}.{d}/{s}.ui", .{ file.major, file.minor, file.name });
defer alloc.free(expected);
if (!std.mem.endsWith(u8, ui_file, expected)) continue;
try writer.print( try writer.print(
" <file compressed=\"true\" preprocess=\"xml-stripblanks\" alias=\"{d}.{d}/{s}.ui\">{s}</file>\n", " <file compressed=\"true\" preprocess=\"xml-stripblanks\" alias=\"{d}.{d}/{s}.ui\">{s}</file>\n",
.{ file.major, file.minor, file.name, ui_file }, .{ file.major, file.minor, file.name, ui_file },
@ -156,7 +144,7 @@ pub fn main() !void {
} }
pub const dependencies = deps: { pub const dependencies = deps: {
const total = css_files.len + icons.len + ui_files.len + blueprint_files.len; const total = css_files.len + icons.len + blueprint_files.len;
var deps: [total][]const u8 = undefined; var deps: [total][]const u8 = undefined;
var index: usize = 0; var index: usize = 0;
for (css_files) |css_file| { for (css_files) |css_file| {
@ -167,14 +155,6 @@ pub const dependencies = deps: {
deps[index] = std.fmt.comptimePrint("images/icons/icon_{s}.png", .{icon.source}); deps[index] = std.fmt.comptimePrint("images/icons/icon_{s}.png", .{icon.source});
index += 1; index += 1;
} }
for (ui_files) |ui_file| {
deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{d}.{d}/{s}.ui", .{
ui_file.major,
ui_file.minor,
ui_file.name,
});
index += 1;
}
for (blueprint_files) |blueprint_file| { for (blueprint_files) |blueprint_file| {
deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{d}.{d}/{s}.blp", .{ deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{d}.{d}/{s}.blp", .{
blueprint_file.major, blueprint_file.major,

View File

@ -87,10 +87,23 @@ pub inline fn runtimeAtLeast(
}) != .lt; }) != .lt;
} }
pub inline fn runtimeUntil(
comptime major: u16,
comptime minor: u16,
comptime micro: u16,
) bool {
const runtime_version = getRuntimeVersion();
return runtime_version.order(.{
.major = major,
.minor = minor,
.patch = micro,
}) == .lt;
}
test "atLeast" { test "atLeast" {
const testing = std.testing; const testing = std.testing;
const funs = &.{ atLeast, runtimeAtLeast }; const funs = &.{ atLeast, runtimeAtLeast, runtimeUntil };
inline for (funs) |fun| { inline for (funs) |fun| {
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION)); try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));

View File

@ -177,7 +177,7 @@ const Window = struct {
} }
/// "destroy" signal for the window /// "destroy" signal for the window
fn gtkDestroy(_: *gtk.ApplicationWindow, self: *Window) callconv(.C) void { fn gtkDestroy(_: *gtk.ApplicationWindow, self: *Window) callconv(.c) void {
log.debug("window destroy", .{}); log.debug("window destroy", .{});
self.deinit(); self.deinit();
} }

View File

@ -41,7 +41,7 @@ pub fn Menu(
else => unreachable, else => unreachable,
}; };
var builder = Builder.init("menu-" ++ object_type ++ "-" ++ menu_name, 1, 0, .blp); var builder = Builder.init("menu-" ++ object_type ++ "-" ++ menu_name, 1, 0);
defer builder.deinit(); defer builder.deinit();
const menu_model = builder.getObject(gio.MenuModel, "menu").?; const menu_model = builder.getObject(gio.MenuModel, "menu").?;
@ -130,7 +130,7 @@ pub fn Menu(
} }
/// Refocus tab that lost focus because of the popover menu /// Refocus tab that lost focus because of the popover menu
fn gtkRefocusTerm(_: *gtk.PopoverMenu, self: *Self) callconv(.C) void { fn gtkRefocusTerm(_: *gtk.PopoverMenu, self: *Self) callconv(.c) void {
const window: *Window = switch (T) { const window: *Window = switch (T) {
Window => self.parent, Window => self.parent,
Surface => self.parent.container.window() orelse return, Surface => self.parent.container.window() orelse return,

View File

@ -0,0 +1,25 @@
using Gtk 4.0;
menu menu {
section {
item {
label: _("Split Up");
action: "win.split-up";
}
item {
label: _("Split Down");
action: "win.split-down";
}
item {
label: _("Split Left");
action: "win.split-left";
}
item {
label: _("Split Right");
action: "win.split-right";
}
}
}

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface domain="com.mitchellh.ghostty">
<requires lib="gtk" version="4.0"/>
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
<property name="heading" translatable="true">Authorize Clipboard Access</property>
<property name="body" translatable="true">An application is attempting to read from the clipboard. The current clipboard contents are shown below.</property>
<responses>
<response id="cancel" translatable="true" appearance="suggested">Deny</response>
<response id="ok" translatable="true" appearance="destructive">Allow</response>
</responses>
<property name="default-response">cancel</property>
<property name="close-response">cancel</property>
<property name="extra-child">
<object class="GtkOverlay">
<style>
<class name="osd"/>
</style>
<child>
<object class="GtkScrolledWindow" id="text_view_scroll">
<property name="width-request">500</property>
<property name="height-request">250</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="cursor-visible">false</property>
<property name="editable">false</property>
<property name="monospace">true</property>
<property name="top-margin">8</property>
<property name="left-margin">8</property>
<property name="bottom-margin">8</property>
<property name="right-margin">8</property>
<style>
<class name="clipboard-content-view"/>
</style>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="reveal_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<child>
<object class="GtkImage">
<property name="icon-name">view-reveal-symbolic</property>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="hide_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<style>
<class name="opaque"/>
</style>
<child>
<object class="GtkImage">
<property name="icon-name">view-conceal-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</interface>

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface domain="com.mitchellh.ghostty">
<requires lib="gtk" version="4.0"/>
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
<property name="heading" translatable="true">Authorize Clipboard Access</property>
<property name="body" translatable="true">An application is attempting to write to the clipboard. The current clipboard contents are shown below.</property>
<responses>
<response id="cancel" translatable="true" appearance="suggested">Deny</response>
<response id="ok" translatable="true" appearance="destructive">Allow</response>
</responses>
<property name="default-response">cancel</property>
<property name="close-response">cancel</property>
<property name="extra-child">
<object class="GtkOverlay">
<style>
<class name="osd"/>
</style>
<child>
<object class="GtkScrolledWindow" id="text_view_scroll">
<property name="width-request">500</property>
<property name="height-request">250</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="cursor-visible">false</property>
<property name="editable">false</property>
<property name="monospace">true</property>
<property name="top-margin">8</property>
<property name="left-margin">8</property>
<property name="bottom-margin">8</property>
<property name="right-margin">8</property>
<style>
<class name="clipboard-content-view"/>
</style>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="reveal_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<child>
<object class="GtkImage">
<property name="icon-name">view-reveal-symbolic</property>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="hide_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<style>
<class name="opaque"/>
</style>
<child>
<object class="GtkImage">
<property name="icon-name">view-conceal-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</interface>

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface domain="com.mitchellh.ghostty">
<requires lib="gtk" version="4.0"/>
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
<property name="heading" translatable="true">Warning: Potentially Unsafe Paste</property>
<property name="body" translatable="true">Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.</property>
<responses>
<response id="cancel" translatable="true" appearance="suggested">Cancel</response>
<response id="ok" translatable="true" appearance="destructive">Paste</response>
</responses>
<property name="default-response">cancel</property>
<property name="close-response">cancel</property>
<property name="extra-child">
<object class="GtkOverlay">
<style>
<class name="osd"/>
</style>
<child>
<object class="GtkScrolledWindow" id="text_view_scroll">
<property name="width-request">500</property>
<property name="height-request">250</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="cursor-visible">false</property>
<property name="editable">false</property>
<property name="monospace">true</property>
<property name="top-margin">8</property>
<property name="left-margin">8</property>
<property name="bottom-margin">8</property>
<property name="right-margin">8</property>
<style>
<class name="clipboard-content-view"/>
</style>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="reveal_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<child>
<object class="GtkImage">
<property name="icon-name">view-reveal-symbolic</property>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkButton" id="hide_button">
<property name="visible">false</property>
<property name="halign">2</property>
<property name="valign">1</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<style>
<class name="opaque"/>
</style>
<child>
<object class="GtkImage">
<property name="icon-name">view-conceal-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</interface>

Some files were not shown because too many files have changed in this diff Show More