Compare commits
46 commits
pre-1.6-me
...
local/yoda
| Author | SHA1 | Date | |
|---|---|---|---|
| 81dc7d3eeb | |||
| 083e09f97e | |||
|
|
9129277bed | ||
|
|
78eaba9db1 | ||
|
|
d25c2108c0 | ||
|
|
120b4fdb12 | ||
|
|
4cd8f8d605 | ||
|
|
1d9e5784d2 | ||
|
|
327febcc92 | ||
| 99842bde03 | |||
| 5fc081e257 | |||
| b8fce5a272 | |||
|
|
4f0f0b6e4e | ||
|
|
7945b9ffc6 | ||
| 41203ab5f1 | |||
| f3f87e59da | |||
|
|
909a0d31aa | ||
|
|
7df9265243 | ||
|
|
dfa59f3ca4 | ||
| 78fb2be076 | |||
| eda2fb1d58 | |||
|
|
032a10796b | ||
|
|
f8ccd51d4a | ||
|
|
ad9a5bcc40 | ||
|
|
67b00d6392 | ||
|
|
c6ab857444 | ||
|
|
ba9c1aa69c | ||
|
|
5095059f90 | ||
|
|
69cdcbd1c1 | ||
|
|
7daf10e3b5 | ||
|
|
6bf0c65ca9 | ||
|
|
543cbb0cb8 | ||
|
|
33c3869c40 | ||
|
|
e28eebbfb2 | ||
|
|
17678baf55 | ||
|
|
5db18f3fac | ||
|
|
117644e9c1 | ||
|
|
01af42aff5 | ||
|
|
44d042f45d | ||
|
|
d05ed099b6 | ||
|
|
46f8b1a9cf | ||
|
|
1019e04b82 | ||
|
|
a43b5ae500 | ||
|
|
10ca3f1025 | ||
|
|
e3b1cda8ab | ||
|
|
6bd07a6363 |
42 changed files with 1683 additions and 1325 deletions
1701
Cargo.lock
generated
1701
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
13
Cargo.toml
13
Cargo.toml
|
|
@ -1,10 +1,10 @@
|
|||
[package]
|
||||
name = "cosmic-term"
|
||||
version = "1.3.0"
|
||||
version = "1.9.0"
|
||||
authors = ["Jeremy Soller <jeremy@system76.com>"]
|
||||
edition = "2024"
|
||||
license = "GPL-3.0-only"
|
||||
rust-version = "1.90"
|
||||
rust-version = "1.93"
|
||||
|
||||
[dependencies]
|
||||
alacritty_terminal = "0.25.1"
|
||||
|
|
@ -51,7 +51,14 @@ package = "libcosmic-yoda"
|
|||
path = "../libcosmic"
|
||||
default-features = false
|
||||
#TODO: a11y feature crashes file chooser dialog
|
||||
features = ["about", "autosize", "multi-window", "tokio", "winit", "surface-message"]
|
||||
features = [
|
||||
"about",
|
||||
"autosize",
|
||||
"multi-window",
|
||||
"tokio",
|
||||
"winit",
|
||||
"surface-message",
|
||||
]
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
fork = "0.4"
|
||||
|
|
|
|||
42
debian/changelog
vendored
42
debian/changelog
vendored
|
|
@ -1,3 +1,45 @@
|
|||
cosmic-term (1.9.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.9.0 version update
|
||||
|
||||
-- Michael Murphy <michael@mmurphy.dev> Mon, 14 Sep 2026 19:50:47 +0200
|
||||
|
||||
cosmic-term (1.8.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.8.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Wed, 02 Sep 2026 08:15:55 -0600
|
||||
|
||||
cosmic-term (1.7.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.7.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Tue, 25 Aug 2026 09:21:20 -0600
|
||||
|
||||
cosmic-term (1.6.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.6.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Tue, 18 Aug 2026 07:15:01 -0600
|
||||
|
||||
cosmic-term (1.5.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.5.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Tue, 28 Jul 2026 09:15:04 -0600
|
||||
|
||||
cosmic-term (1.4.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.4.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Mon, 20 Jul 2026 14:36:58 -0600
|
||||
|
||||
cosmic-term (1.3.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.3.0 version update
|
||||
|
||||
-- Jeremy Soller <jeremy@system76.com> Sun, 12 Jul 2026 13:22:28 -0600
|
||||
|
||||
cosmic-term (1.2.0) noble; urgency=medium
|
||||
|
||||
* Epoch 1.2.0 version update
|
||||
|
|
|
|||
6
debian/source/options
vendored
6
debian/source/options
vendored
|
|
@ -1,4 +1,6 @@
|
|||
tar-ignore=.github
|
||||
tar-ignore=.vscode
|
||||
tar-ignore=target/.rustc_info.json
|
||||
tar-ignore=target/CACHEDIR.TAG
|
||||
tar-ignore=target/debug
|
||||
tar-ignore=target/release
|
||||
tar-ignore=vendor
|
||||
tar-ignore=target
|
||||
|
|
@ -41,7 +41,7 @@ settings = الإعدادات
|
|||
### Appearance
|
||||
|
||||
appearance = المظهر
|
||||
theme = النسق
|
||||
theme = السمة
|
||||
match-desktop = طابق سطح المكتب
|
||||
dark = داكن
|
||||
light = فاتح
|
||||
|
|
@ -88,7 +88,7 @@ new-window = نافذة جديدة
|
|||
profile = ملف التعريف
|
||||
menu-profiles = ملفات التعريف...
|
||||
close-tab = أغلق اللسان
|
||||
quit = أنهِ
|
||||
quit = إنهِ
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
cancel = Cancel·lar
|
||||
settings = Configuració
|
||||
quit = Surt
|
||||
delete = Suprimeix
|
||||
rename = Canvia el nom
|
||||
name = Nom
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@ advanced-font-settings = Pokročilá nastavení písma
|
|||
default-font = Písmo
|
||||
default-font-size = Velikost písma
|
||||
default-font-stretch = Šířka písma
|
||||
default-font-weight = Normální tloušťka písma
|
||||
default-dim-font-weight = Tenká tloušťka písma
|
||||
default-bold-font-weight = Tučná tloušťka písma
|
||||
default-font-weight = Tloušťka normálního písma
|
||||
default-dim-font-weight = Tloušťka zeslabeného písma
|
||||
default-bold-font-weight = Tloušťka tučného písma
|
||||
use-bright-bold = Světlejší tučný text
|
||||
splits = Rozdělení
|
||||
focus-follow-mouse = Zaměření psaní sleduje myš
|
||||
advanced = Pokročilé
|
||||
show-headerbar = Zobrazit hlavičku
|
||||
show-header-description = Hlavičku je možné odkrýt z kontextového menu
|
||||
show-header-description = Hlavičku lze odkrýt z nabídky zobrazené po kliknutí pravým tlačítkem myši
|
||||
find-placeholder = Najít...
|
||||
find-previous = Najít předchozí
|
||||
find-next = Najít další
|
||||
|
|
@ -109,3 +109,4 @@ paste-primary = Vložit primární
|
|||
copy-link = Kopírovat odkaz
|
||||
tab-new-inherit-working-directory = Nové karty a okna používají aktuální adresář
|
||||
tab-new-inherit-working-directory-description = Otevírat nové karty a okna v pracovním adresáři aktivní karty
|
||||
show-pane-borders = Zobrazit ohraničení panelu
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
rename = Omdøb
|
||||
delete = Slet
|
||||
name = Navn
|
||||
cancel = Afbryd
|
||||
quit = Afslut
|
||||
find-next = Find næste
|
||||
select-all = Vælg alle
|
||||
new-window = Nyt vindue
|
||||
edit = Redigér
|
||||
copy = Kopiér
|
||||
theme = Tema
|
||||
appearance = Udseende
|
||||
light = Lyst
|
||||
repository = Pakkearkiv
|
||||
paste = Indsæt
|
||||
menu-settings = Indstillinger...
|
||||
view = Vis
|
||||
dark = Mørkt
|
||||
match-desktop = Følg skrivebordets indstillinger
|
||||
find-previous = Find forrige
|
||||
find-placeholder = Find...
|
||||
default-zoom-step = Zoom-trin
|
||||
file = Fil
|
||||
find = Find
|
||||
support = Support
|
||||
settings = Indstillinger
|
||||
keyboard-shortcuts = Tastaturgenveje
|
||||
menu-keyboard-shortcuts = Tastaturgenveje…
|
||||
replace = Erstat
|
||||
close-tab = Luk fane
|
||||
new-tab = Ny fane
|
||||
|
|
@ -69,7 +69,7 @@ advanced = Erweitert
|
|||
show-headerbar = Kopfzeile anzeigen
|
||||
show-header-description = Kopfzeile über das Rechtsklick-Menü aufzeigen
|
||||
# Suchen
|
||||
find-placeholder = Suchen...
|
||||
find-placeholder = Suchen ...
|
||||
find-previous = Vorherigen suchen
|
||||
find-next = Nächsten suchen
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ file = Datei
|
|||
new-tab = Neuer Tab
|
||||
new-window = Neues Fenster
|
||||
profile = Profil
|
||||
menu-profiles = Profile...
|
||||
menu-profiles = Profile ...
|
||||
close-tab = Tab schließen
|
||||
quit = Beenden
|
||||
|
||||
|
|
@ -106,14 +106,14 @@ previous-tab = Vorheriger Tab
|
|||
split-horizontal = Horizontal teilen
|
||||
split-vertical = Vertikal teilen
|
||||
pane-toggle-maximize = Maximierung umschalten
|
||||
menu-color-schemes = Farbschemen...
|
||||
menu-settings = Einstellungen...
|
||||
menu-about = Über COSMIC Terminal...
|
||||
repository = Repository
|
||||
menu-color-schemes = Farbschemen ...
|
||||
menu-settings = Einstellungen ...
|
||||
menu-about = Über COSMIC Terminal ...
|
||||
repository = Repositorium
|
||||
cancel = Abbrechen
|
||||
keyboard-shortcuts = Tastenkombinationen
|
||||
open-link = Link öffnen
|
||||
menu-password-manager = Passwörter...
|
||||
menu-password-manager = Passwörter ...
|
||||
passwords-title = Passwörter
|
||||
add-password = Passwort hinzufügen
|
||||
password-input = Passwort
|
||||
|
|
@ -124,7 +124,7 @@ focus-pane-down = Bereich unten fokussieren
|
|||
focus-pane-left = Bereich links fokussieren
|
||||
focus-pane-right = Bereich rechts fokussieren
|
||||
focus-pane-up = Bereich oben fokussieren
|
||||
menu-keyboard-shortcuts = Tastenkombinationen...
|
||||
menu-keyboard-shortcuts = Tastenkombinationen ...
|
||||
no-shortcuts = Keine Tastenkombinationen
|
||||
password-manager = Passwortmanager
|
||||
replace = Ersetzen
|
||||
|
|
@ -137,7 +137,7 @@ shortcut-group-window = Fenster
|
|||
shortcut-replace-title = Tastenkombination ersetzen?
|
||||
tab-activate = Tab { $number } aktivieren
|
||||
copy-link = Link kopieren
|
||||
type-to-search = Zum Suchen tippen...
|
||||
type-to-search = Zum Suchen tippen ...
|
||||
close-window = Fenster schließen
|
||||
copy-or-sigint = Kopieren oder SIGINT
|
||||
toggle-fullscreen = Vollbild umschalten
|
||||
|
|
@ -149,3 +149,4 @@ shortcut-replace-body = { $binding } ist bereits { $existing } zugeordnet. Durch
|
|||
keywords = Befehl;Shell;Terminal;CLI;
|
||||
tab-new-inherit-working-directory = Neue Tabs und Fenster verwenden das aktuelle Verzeichnis
|
||||
tab-new-inherit-working-directory-description = Neue Tabs und Fenster im Arbeitsverzeichnis des aktiven Tabs öffnen
|
||||
show-pane-borders = Bereichsrahmen anzeigen
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ new-window = Νέο παράθυρο
|
|||
profile = Προφίλ
|
||||
menu-profiles = Προφίλ...
|
||||
close-tab = Κλείσιμο καρτέλας
|
||||
quit = Έξοδος
|
||||
quit = Τερματισμός
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -152,3 +152,4 @@ shortcut-group-zoom = Ζουμ
|
|||
shortcut-replace-body = Ο συνδυασμός { $binding } έχει ήδη αντιστοιχιστεί στην ενέργεια «{ $existing }». Θέλετε να αντικατασταθεί με την ενέργεια «{ $new_action }»;
|
||||
tab-new-inherit-working-directory = Οι νέες καρτέλες και παράθυρα χρησιμοποιούν τον τρέχοντα κατάλογο
|
||||
tab-new-inherit-working-directory-description = Άνοιγμα νέων καρτελών και παραθύρων στον τρέχοντα κατάλογο της ενεργής καρτέλας
|
||||
show-pane-borders = Εμφάνιση περιγραμμάτων πλαισίων
|
||||
|
|
|
|||
|
|
@ -111,3 +111,7 @@ menu-settings = Settings...
|
|||
menu-about = About COSMIC Terminal...
|
||||
repository = Repository
|
||||
support = Support
|
||||
cancel = Cancel
|
||||
keyboard-shortcuts = Keyboard shortcuts
|
||||
replace = Replace
|
||||
menu-keyboard-shortcuts = Keyboard shortcuts...
|
||||
|
|
|
|||
|
|
@ -58,10 +58,12 @@ use-bright-bold = Make bold text brighter
|
|||
### Splits
|
||||
splits = Splits
|
||||
focus-follow-mouse = Typing focus follows mouse
|
||||
show-pane-borders = Show pane borders
|
||||
|
||||
### Advanced
|
||||
advanced = Advanced
|
||||
show-headerbar = Show header
|
||||
window-header = Window header
|
||||
show-header-description = Reveal the header from the right-click menu
|
||||
tab-new-inherit-working-directory = New tabs and windows use current directory
|
||||
tab-new-inherit-working-directory-description = Open new tabs and windows in the active tab's working directory
|
||||
|
|
@ -151,7 +153,7 @@ next-tab = Next tab
|
|||
previous-tab = Previous tab
|
||||
split-horizontal = Split horizontal
|
||||
split-vertical = Split vertical
|
||||
pane-toggle-maximize = Toggle maximized
|
||||
pane-toggle-maximize = Maximize or restore pane
|
||||
menu-color-schemes = Color schemes...
|
||||
menu-settings = Settings...
|
||||
menu-about = About COSMIC Terminal...
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
name = نام
|
||||
cancel = لغو
|
||||
quit = خروج
|
||||
rename = تغییر نام
|
||||
delete = حذف
|
||||
|
|
@ -38,7 +38,7 @@ settings = Asetukset
|
|||
|
||||
appearance = Ulkoasu
|
||||
theme = Teema
|
||||
match-desktop = Sovita työpöytään
|
||||
match-desktop = Sama kuin työpöytä
|
||||
dark = Tumma
|
||||
light = Vaalea
|
||||
syntax-dark = Tumma väriteema
|
||||
|
|
@ -151,3 +151,4 @@ toggle-fullscreen = Koko näyttö päällä tai pois
|
|||
shortcut-group-other = Muut
|
||||
tab-new-inherit-working-directory = Uudet välilehdet käyttävät nykyistä hakemistoa
|
||||
tab-new-inherit-working-directory-description = Avaa uudet välilehdet aktiivisen välilehden työskentelyhakemistossa
|
||||
show-pane-borders = Näytä paneelin rajat
|
||||
|
|
|
|||
0
i18n/fil/cosmic_term.ftl
Normal file
0
i18n/fil/cosmic_term.ftl
Normal file
|
|
@ -168,3 +168,4 @@ comment = Émulateur de terminal pour le bureau COSMIC
|
|||
keywords = Commande;Shell;Terminal;CLI;
|
||||
tab-new-inherit-working-directory = Les nouveaux onglets et fenêtres utilisent le répertoire actuel
|
||||
tab-new-inherit-working-directory-description = Ouvrir les nouveaux onglets et fenêtres dans le répertoire de travail de l'onglet actif
|
||||
show-pane-borders = Afficher les bordures des panneaux
|
||||
|
|
|
|||
|
|
@ -147,5 +147,5 @@ type-to-search = Clóscríobh le cuardach a dhéanamh...
|
|||
comment = Aithriseoir teirminéal don deasc COSMIC
|
||||
keywords = Ordú;Blaosc;Teirminéal;CLI;
|
||||
copy-link = Cóipeáil Nasc
|
||||
tab-new-inherit-working-directory = Úsáideann cluaisíní nua an eolaire reatha
|
||||
tab-new-inherit-working-directory-description = Oscail cluaisíní nua in eolaire oibre an chluaisín ghníomhaigh
|
||||
tab-new-inherit-working-directory = Úsáideann cluaisíní agus fuinneoga nua an t-eolaire reatha
|
||||
tab-new-inherit-working-directory-description = Oscail cluaisíní agus fuinneoga nua in eolaire oibre an chluaisín ghníomhaigh
|
||||
|
|
|
|||
112
i18n/gl/cosmic_term.ftl
Normal file
112
i18n/gl/cosmic_term.ftl
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
name = Nome
|
||||
cancel = Cancelar
|
||||
delete = Eliminar
|
||||
rename = Renomear
|
||||
repository = Repositorio
|
||||
support = Soporte
|
||||
settings = Axustes
|
||||
appearance = Apariencia
|
||||
theme = Tema
|
||||
match-desktop = Axustar ao escritorio
|
||||
dark = Escuro
|
||||
light = Claro
|
||||
default-zoom-step = Pasos do zoom
|
||||
keyboard-shortcuts = Atallos de teclado
|
||||
find-placeholder = Atopar…
|
||||
find-previous = Atopar antes
|
||||
find-next = Atopar seguinte
|
||||
replace = Remplazar
|
||||
file = Ficheiro
|
||||
new-window = Nova xanela
|
||||
quit = Pechar
|
||||
edit = Editar
|
||||
copy = Copiar
|
||||
paste = Pegar
|
||||
select-all = Seleccionar todo
|
||||
find = Atopar
|
||||
view = Ver
|
||||
menu-settings = Axustes...
|
||||
menu-keyboard-shortcuts = Atallos de teclado…
|
||||
new-tab = Nova lapela
|
||||
close-tab = Pechar lapela
|
||||
export = Exportar
|
||||
import = Importar
|
||||
reset-to-default = Restablecer aos valores predeterminados
|
||||
type-to-search = Escribe para buscar...
|
||||
add-another-keybinding = Engadir outro atallo de teclado
|
||||
cosmic-terminal = Terminal de COSMIC
|
||||
comment = Emulador de terminal para o escritorio COSMIC
|
||||
keywords = Orde; Shell; Terminal; CLI;
|
||||
new-terminal = Novo terminal
|
||||
color-schemes = Esquemas de cores
|
||||
import-errors = Importar erros
|
||||
profiles = Perfís
|
||||
command-line = Liña de comandos
|
||||
tab-title = Titulo da lapela
|
||||
tab-title-description = Substituír o título predeterminado da lapela
|
||||
add-profile = Engadir perfil
|
||||
new-profile = Novo perfil
|
||||
make-default = Facer predeterminado
|
||||
working-directory = Directorio de traballo
|
||||
hold = Manter
|
||||
remain-open = Permanecer aberto despois de que remate o proceso fillo.
|
||||
syntax-dark = Esquema de cores escuro
|
||||
syntax-light = Esquema de cores claras
|
||||
opacity = Opacidade do fondo
|
||||
font = Tipografía
|
||||
advanced-font-settings = Configuración avanzada da tipografía
|
||||
default-font = Tipografía
|
||||
default-font-size = Tamaño da tipografía
|
||||
default-font-stretch = Ancho da tipografía
|
||||
default-font-weight = Grosor da tipografía normal
|
||||
default-dim-font-weight = Grosor da tipografía fina
|
||||
default-bold-font-weight = Grosor da tipografía en negriña
|
||||
use-bright-bold = Facer máis brillante o texto en negriña
|
||||
splits = Divisións
|
||||
focus-follow-mouse = O foco de escritura segue o rato
|
||||
show-pane-borders = Mostrar os bordos dos paneis
|
||||
advanced = Avanzado
|
||||
show-headerbar = Mostrar a cabeceira
|
||||
show-header-description = Mostrar a cabeceira desde o menú contextual
|
||||
tab-new-inherit-working-directory = As novas lapelas e xanelas usan o directorio actual
|
||||
tab-new-inherit-working-directory-description = Abrir novas lapelas e xanelas no directorio de traballo da pestana activa
|
||||
close-window = Pechar xanela
|
||||
copy-or-sigint = Copiar ou SIGINT
|
||||
disable = Desactivar
|
||||
focus-pane-down = Poñer o foco no panel inferior
|
||||
focus-pane-left = Poñer o foco no panel esquerdo
|
||||
focus-pane-right = Poñer o foco no panel dereito
|
||||
focus-pane-up = Poñer o foco no panel superior
|
||||
no-shortcuts = Sen atallos de teclado
|
||||
password-manager = Xestor de contrasinais
|
||||
paste-primary = Pegar o contido primario
|
||||
shortcut-capture-hint = Preme a combinación de teclas
|
||||
shortcut-group-clipboard = Portapapeis
|
||||
shortcut-group-other = Outro
|
||||
shortcut-group-tabs = Lapelas
|
||||
shortcut-group-window = Xanela
|
||||
shortcut-group-zoom = Zoom
|
||||
shortcut-replace-body = { $binding } xa está asignado a { $existing }. Substituílo por { $new_action }?
|
||||
shortcut-replace-title = Remplazar atallo de teclado ?
|
||||
tab-activate = Activar a lapela { $number }
|
||||
toggle-fullscreen = Cambiar a pantalla completa
|
||||
profile = Perfil
|
||||
menu-profiles = Perfís...
|
||||
clear-scrollback = Limpar o historial de desprazamento
|
||||
open-link = Abrir enderezo
|
||||
copy-link = Copiar enderezo
|
||||
zoom-in = Texto máis grande
|
||||
zoom-reset = Tamaño de texto predeterminado
|
||||
zoom-out = Texto máis pequeno
|
||||
next-tab = Lapela seguinte
|
||||
previous-tab = Lapela previa
|
||||
split-horizontal = Dividir horizontalmente
|
||||
split-vertical = Dividir verticalmente
|
||||
pane-toggle-maximize = Alternar maximizado
|
||||
menu-color-schemes = Esquema de cores...
|
||||
menu-about = Sobre o Terminal de COSMIC...
|
||||
menu-password-manager = Contrasinais...
|
||||
passwords-title = Contrasinais
|
||||
add-password = Engadir contrasinal
|
||||
password-input = Contrasinal
|
||||
password-input-description = Descripción
|
||||
|
|
@ -29,18 +29,18 @@ remain-open = चाइल्ड प्रोसेस के निकलने
|
|||
|
||||
## Settings
|
||||
|
||||
settings = सेटिंग
|
||||
settings = सेटिंग्स
|
||||
|
||||
### Appearance
|
||||
|
||||
appearance = दिखावट
|
||||
theme = थीम
|
||||
match-desktop = डेस्कटॉप से मिलाएं
|
||||
appearance = रुप-रंग
|
||||
theme = प्रसंग
|
||||
match-desktop = डेस्कटॉप से मेल खाएँ
|
||||
dark = डार्क
|
||||
light = लाइट
|
||||
syntax-dark = रंग योजना डार्क
|
||||
syntax-light = रंग योजना लाइट
|
||||
default-zoom-step = ज़ूम स्तर
|
||||
default-zoom-step = ज़ूम चरण
|
||||
opacity = पृष्ठभूमि अपारदर्शिता
|
||||
|
||||
### Font
|
||||
|
|
@ -66,7 +66,7 @@ advanced = एडवांस
|
|||
show-headerbar = हैडर दिखाएं
|
||||
show-header-description = हैडर को राइट-क्लिक मेन्यू से दिखाएं।
|
||||
# Find
|
||||
find-placeholder = खोजें...
|
||||
find-placeholder = खोजें..।
|
||||
find-previous = पिछला खोजें
|
||||
find-next = अगला खोजें
|
||||
|
||||
|
|
@ -81,13 +81,13 @@ new-window = नई विंडो
|
|||
profile = प्रोफाइल
|
||||
menu-profiles = प्रोफाइल्स...
|
||||
close-tab = टैब बंद करें
|
||||
quit = बंद करें
|
||||
quit = बाहर जाएँ
|
||||
|
||||
### Edit
|
||||
|
||||
edit = संपादित करें
|
||||
edit = संपादन
|
||||
copy = कॉपी करें
|
||||
paste = पेस्ट करें
|
||||
paste = चिपकाएँ
|
||||
select-all = सभी चुनें
|
||||
find = खोजें
|
||||
clear-scrollback = स्क्रॉलबैक साफ़ करें
|
||||
|
|
@ -104,7 +104,11 @@ split-horizontal = क्षैतिज विभाजन
|
|||
split-vertical = लंबवत विभाजन
|
||||
pane-toggle-maximize = अधिकतम करें
|
||||
menu-color-schemes = रंग योजनाएँ...
|
||||
menu-settings = सेटिंग्स...
|
||||
menu-settings = सेटिंग्स..।
|
||||
menu-about = कॉस्मिक टर्मिनल के बारे में...
|
||||
repository = रिपॉजिटरी
|
||||
support = सहायता
|
||||
support = समर्थन
|
||||
cancel = रद्द करें
|
||||
keyboard-shortcuts = कीबोर्ड शॉर्टकट्स
|
||||
replace = बदलें
|
||||
menu-keyboard-shortcuts = कीबोर्ड शॉर्टकट्स..।
|
||||
|
|
|
|||
|
|
@ -149,3 +149,4 @@ type-to-search = Gépelj a kereséshez…
|
|||
copy-link = Hivatkozás másolása
|
||||
tab-new-inherit-working-directory = Az új lapok és ablakok az aktuális könyvtárat használják
|
||||
tab-new-inherit-working-directory-description = Az új lapok és ablakok az aktív lap munkakönyvtárában nyílnak meg
|
||||
show-pane-borders = Ablaktábla-szegélyek megjelenítése
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ repository = Repositori
|
|||
support = Dukungan
|
||||
color-schemes = Skema warna
|
||||
cosmic-terminal = Terminal COSMIC
|
||||
rename = Ganti nama
|
||||
rename = Ganti Nama
|
||||
export = Ekspor
|
||||
delete = Hapus
|
||||
import = Impor
|
||||
|
|
@ -23,7 +23,7 @@ remain-open = Tetap buka setelah proses anak berakhir.
|
|||
settings = Pengaturan
|
||||
appearance = Tampilan
|
||||
theme = Tema
|
||||
match-desktop = Cocokkan desktop
|
||||
match-desktop = Cocok desktop
|
||||
dark = Gelap
|
||||
light = Terang
|
||||
syntax-dark = Skema warna gelap
|
||||
|
|
@ -109,3 +109,4 @@ keywords = Perintah;Shell;Terminal;CLI;
|
|||
copy-link = Salin Tautan
|
||||
tab-new-inherit-working-directory = Tab dan jendela baru menggunakan direktori saat ini
|
||||
tab-new-inherit-working-directory-description = Buka tab dan jendela baru di direktori pekerjaan tab aktif
|
||||
show-pane-borders = Tampilkan batas panel
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ settings = Impostazioni
|
|||
|
||||
appearance = Aspetto
|
||||
theme = Tema
|
||||
match-desktop = Sistema
|
||||
match-desktop = Abbina al desktop
|
||||
dark = Scuro
|
||||
light = Chiaro
|
||||
syntax-dark = Schema colori scuro
|
||||
|
|
@ -115,3 +115,7 @@ menu-settings = Impostazioni...
|
|||
menu-about = Informazioni su COSMIC Terminal...
|
||||
support = Supporto
|
||||
repository = Repository
|
||||
cancel = Annulla
|
||||
keyboard-shortcuts = Scorciatoie da tastiera
|
||||
replace = Sostituisci
|
||||
menu-keyboard-shortcuts = Scorciatoie da tastiera...
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
cancel = Sefsex
|
||||
cancel = Semmet
|
||||
name = Isem
|
||||
delete = kkes
|
||||
rename = Snifel isem
|
||||
quit = Tuffɣa
|
||||
support = Tallalt
|
||||
quit = Ffeɣ
|
||||
support = Tallelt
|
||||
repository = Asarsay
|
||||
settings = Iɣewwaṛen
|
||||
appearance = Timeẓri
|
||||
|
|
@ -14,7 +14,7 @@ paste = Senteḍ
|
|||
select-all = Fren akk
|
||||
view = Wali
|
||||
menu-settings = Iɣewwaṛen…
|
||||
match-desktop = Amṣada d tnarit
|
||||
match-desktop = Semṣada akked tnarit
|
||||
file = Afaylu
|
||||
new-window = Asfaylu amaynut
|
||||
edit = Ẓreg
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ delete = Өшіру
|
|||
repository = Репозиторий
|
||||
support = Қолдау
|
||||
settings = Баптаулар
|
||||
appearance = Сыртқы түрі
|
||||
theme = Тақырып
|
||||
match-desktop = Жұмыс үстеліне сәйкес келу
|
||||
dark = Қараңғы
|
||||
light = Жарық
|
||||
appearance = Сыртқы көрініс
|
||||
theme = Тема
|
||||
match-desktop = Жұмыс үстеліне сәйкес болу
|
||||
dark = Қою
|
||||
light = Ашық
|
||||
file = Файл
|
||||
new-tab = Жаңа бет
|
||||
new-window = Жаңа терезе
|
||||
|
|
@ -107,5 +107,6 @@ type-to-search = Іздеу үшін теріңіз...
|
|||
comment = COSMIC жұмыс үстелі үшін терминал эмуляторы
|
||||
keywords = Command;Shell;Terminal;CLI;Команда;Қоршам;Терминал;
|
||||
copy-link = Сілтемені көшіру
|
||||
tab-new-inherit-working-directory = Жаңа беттерде ағымдағы буманы қолдану
|
||||
tab-new-inherit-working-directory-description = Жаңа беттерді белсенді беттің жұмыс бумасында ашу
|
||||
tab-new-inherit-working-directory = Жаңа беттерде және терезелерде ағымдағы буманы қолдану
|
||||
tab-new-inherit-working-directory-description = Жаңа беттерді және терезелерді белсенді беттің жұмыс бумасында ашу
|
||||
show-pane-borders = Панель жақтауларын көрсету
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ light = Ronî
|
|||
advanced = Pêşketî
|
||||
support = Piştgirî
|
||||
default-font = Cûrenivîs
|
||||
paste = Pêve bike
|
||||
paste = Pê ve bike
|
||||
menu-settings = Sazkarî...
|
||||
command-line = Rêza fermanê
|
||||
view = Dîtin
|
||||
dark = Tarî
|
||||
hold = Ragire
|
||||
match-desktop = Li gorî sermaseyê
|
||||
match-desktop = Bi sermaseyê re li hev bîne
|
||||
find-previous = Yê paş bibîne
|
||||
cosmic-terminal = Termînalê COSMIC
|
||||
find-placeholder = Bibîne...
|
||||
|
|
@ -62,7 +62,7 @@ shortcut-group-zoom = Nêzîkbûn
|
|||
repository = Embar
|
||||
find = Bibîne
|
||||
replace = Biguhêrîne
|
||||
syntax-light = Şêwaza rengê ronî
|
||||
syntax-light = Şêwaza rengan a ronî
|
||||
default-font-weight = Giraniya cûrenivîsê ya normal
|
||||
zoom-in = Nivîsa mezintir
|
||||
previous-tab = Rûgera paş
|
||||
|
|
@ -100,7 +100,7 @@ focus-pane-left = Balê bikişîne ser destgeha çepê
|
|||
focus-pane-right = Balê bikişîne ser destgeha rastê
|
||||
focus-pane-up = Balê bikişîne ser destgeha jorîn
|
||||
password-manager = Rêveberê borînpeyvê
|
||||
paste-primary = A sereke pêve bike
|
||||
paste-primary = A sereke pê ve bike
|
||||
reset-to-default = Vegere rewşa berdest
|
||||
shortcut-capture-hint = Kombînasyona kilîtan bitikîne
|
||||
shortcut-replace-body = { $binding } berê ji bo { $existing } hatiye destnîşankirin. Tu dixwazî bi { $new_action } re biguherînî?
|
||||
|
|
@ -109,3 +109,4 @@ tab-activate = Rûgera { $number } çalak bike
|
|||
toggle-fullscreen = Dîmendera tijî biguhêrîne
|
||||
type-to-search = Ji bo lêgerînê binivîse...
|
||||
copy-link = Girêdanê jê bigire
|
||||
show-pane-borders = Sînorên kilîtdankê nîşan bide
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name = Pavadinimas
|
||||
delete = Ištrinti
|
||||
cosmic-terminal = COSMIC Terminal
|
||||
cosmic-terminal = COSMIC Terminalas
|
||||
new-terminal = Naujas terminalas
|
||||
repository = Saugykla
|
||||
support = Palaikymas
|
||||
|
|
@ -19,7 +19,7 @@ make-default = Padaryti numatytu
|
|||
working-directory = Darbinis katalogas
|
||||
hold = Laikyti
|
||||
remain-open = Palikti atidarytą išsijungus vaikiniam procesui.
|
||||
settings = Nuostatos
|
||||
settings = Nuostatai
|
||||
appearance = Išvaizda
|
||||
theme = Stilius
|
||||
match-desktop = Pagal darbalaukio temą
|
||||
|
|
@ -47,7 +47,7 @@ new-window = Naujas langas
|
|||
profile = Profilis
|
||||
menu-profiles = Profiliai...
|
||||
close-tab = Uždaryti skirtuką
|
||||
quit = Išeiti
|
||||
quit = Išjungti
|
||||
edit = Redaguoti
|
||||
copy = Kopijuoti
|
||||
paste = Įdėti
|
||||
|
|
@ -65,7 +65,7 @@ split-horizontal = Skaidyti horizontaliai
|
|||
split-vertical = Skaidyti vertikaliai
|
||||
pane-toggle-maximize = Perjungti maksimalų padidinimą
|
||||
menu-color-schemes = Spalvų schemos...
|
||||
menu-settings = Nuostatos...
|
||||
menu-settings = Nuostatai...
|
||||
menu-about = Apie COSMIC Terminal...
|
||||
menu-password-manager = Slaptažodžiai...
|
||||
passwords-title = Slaptažodžiai
|
||||
|
|
|
|||
|
|
@ -1 +1,14 @@
|
|||
settings = Paramètres
|
||||
settings = Configuracion
|
||||
appearance = Aparéncia
|
||||
theme = Tèma
|
||||
match-desktop = Assortir al burèu
|
||||
dark = Escur
|
||||
light = Clar
|
||||
file = Fichièr
|
||||
name = Nom
|
||||
repository = Depaus
|
||||
cancel = Anullar
|
||||
menu-settings = Configuracion...
|
||||
quit = Quitar
|
||||
delete = Suprimir
|
||||
replace = Remplaçar
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ name = ਨਾਂ
|
|||
settings = ਸੈਟਿੰਗਾਂ
|
||||
appearance = ਦਿੱਖ
|
||||
theme = ਥੀਮ
|
||||
match-desktop = ਡੈਸਕਟਾਪ ਨਾਲ ਮਿਲਦਾ
|
||||
match-desktop = ਡੈਸਕਟਾਪ ਨਾਲ ਮਿਲਾਓ
|
||||
dark = ਗੂੜ੍ਹਾ
|
||||
light = ਹਲਕਾ
|
||||
light = ਫਿੱਕਾ
|
||||
default-zoom-step = ਜ਼ੂਮ ਸਟੈਪ
|
||||
quit = ਬਾਹਰ
|
||||
quit = ਸਮਾਪਤ
|
||||
edit = ਸੋਧੋ
|
||||
copy = ਕਾਪੀ ਕਰੋ
|
||||
paste = ਚੇਪੋ
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
cosmic-terminal = Terminal COSMIC
|
||||
comment = Emulator terminala dla pulpitu COSMIC
|
||||
comment = Emulator terminala dla środowiska COSMIC
|
||||
keywords = Cli;WierszPoleceń;Powłoka;Terminal;
|
||||
new-terminal = Nowy terminal
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ advanced = Zaawansowane
|
|||
show-headerbar = Pokaż pasek nagłówka
|
||||
show-header-description = Ukazuje pasek nagłówka z menu wybieranego prawym przyciskiem myszki
|
||||
# Find
|
||||
find-placeholder = Szukaj…
|
||||
find-placeholder = Wyszukaj…
|
||||
find-previous = Znajdź poprzedni
|
||||
find-next = Znajdź następny
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ new-window = Nowe okno
|
|||
profile = Profil
|
||||
menu-profiles = Profile...
|
||||
close-tab = Zamknij kartę
|
||||
quit = Zamknij
|
||||
quit = Zakończ
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ edit = Edytuj
|
|||
copy = Kopiuj
|
||||
paste = Wklej
|
||||
select-all = Zaznacz wszystko
|
||||
find = Szukaj
|
||||
find = Wyszukaj
|
||||
clear-scrollback = Wyczyść przewijanie
|
||||
|
||||
## View
|
||||
|
|
@ -149,3 +149,4 @@ focus-pane-up = Aktywuj panel wyżej
|
|||
copy-link = Skopiuj Odnośnik
|
||||
tab-new-inherit-working-directory = Nowe karty i okna użyją obecnego katalogu
|
||||
tab-new-inherit-working-directory-description = Otwieraj nowe karty i okna w katalogu roboczym aktywnej karty
|
||||
show-pane-borders = Pokaż obramowania paneli
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ new-window = Nova janela
|
|||
profile = Perfil
|
||||
menu-profiles = Perfis...
|
||||
close-tab = Fechar aba
|
||||
quit = Sair
|
||||
quit = Encerrar
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -149,3 +149,4 @@ type-to-search = Digite para pesquisar...
|
|||
copy-link = Copiar link
|
||||
tab-new-inherit-working-directory = Novas abas e janelas usam o diretório atual
|
||||
tab-new-inherit-working-directory-description = Abrir novas abas e janelas no diretório de trabalho da aba ativa
|
||||
show-pane-borders = Mostrar bordas do quadro
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
cosmic-terminal = Терминал
|
||||
comment = Эмулятор терминала для рабочей среды COSMIC
|
||||
comment = Эмулятор терминала для среды COSMIC
|
||||
keywords = Команда;Оболочка;Терминал;Консоль;
|
||||
new-terminal = Новый терминал
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ new-window = Новое окно
|
|||
profile = Профиль
|
||||
menu-profiles = Профили...
|
||||
close-tab = Закрыть вкладку
|
||||
quit = Выйти
|
||||
quit = Завершить
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -141,5 +141,6 @@ tab-activate = Активировать вкладку { $number }
|
|||
toggle-fullscreen = Вкл./выкл. полноэкранный режим
|
||||
type-to-search = Введите для поиска...
|
||||
copy-link = Копировать ссылку
|
||||
tab-new-inherit-working-directory = В новых вкладках исп. текущий каталог
|
||||
tab-new-inherit-working-directory-description = Открывать новые вкладки в рабочем каталоге активной вкладки
|
||||
tab-new-inherit-working-directory = Текущий каталог в новых вкладках и окнах
|
||||
tab-new-inherit-working-directory-description = Открывать новые вкладки и окна в рабочем каталоге активной вкладки
|
||||
show-pane-borders = Показывать границы панелей
|
||||
|
|
|
|||
2
i18n/sat/cosmic_term.ftl
Normal file
2
i18n/sat/cosmic_term.ftl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
cancel = ᱵᱟᱹᱛᱤᱞ
|
||||
name = ᱧᱩᱛᱩᱢ
|
||||
|
|
@ -113,7 +113,7 @@ split-vertical = Dela vertikalt
|
|||
pane-toggle-maximize = Växla maximerad
|
||||
clear-scrollback = Töm tillbakarullning
|
||||
menu-color-schemes = Färgscheman…
|
||||
menu-settings = Inställningar…
|
||||
menu-settings = Inställningar...
|
||||
menu-about = Om COSMIC Terminal…
|
||||
repository = Källkod
|
||||
support = Support
|
||||
|
|
@ -153,3 +153,4 @@ shortcut-group-zoom = Zooma
|
|||
copy-link = Kopiera länk
|
||||
tab-new-inherit-working-directory-description = Öppna nya flikar och fönster i den aktiva flikens arbetskatalog
|
||||
tab-new-inherit-working-directory = Nya flikar och fönster använder aktuell katalog
|
||||
show-pane-borders = Visa ram runt fält
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ settings = การตั้งค่า
|
|||
appearance = ลักษณะ
|
||||
theme = ธีม
|
||||
match-desktop = ใช้ตามธีมหน้าจอหลัก
|
||||
dark = ธีมมืด
|
||||
light = ธีมสว่าง
|
||||
dark = มืด
|
||||
light = สว่าง
|
||||
syntax-dark = โทนสีมืด
|
||||
syntax-light = โทนสีสว่าง
|
||||
default-zoom-step = ระยะซูม
|
||||
|
|
@ -109,3 +109,8 @@ pane-toggle-maximize = ขยายให้ใหญ่สุด
|
|||
menu-color-schemes = โทนสี...
|
||||
menu-settings = การตั้งค่า...
|
||||
menu-about = เกี่ยวกับ เทอร์มินัล COSMIC...
|
||||
cancel = ยกเลิก
|
||||
reset-to-default = รีเซ็ตเป็นค่าเริ่มต้น
|
||||
type-to-search = พิมพ์เพื่อค้นหา
|
||||
add-another-keybinding = เพิ่มคีย์ลัดเพิ่มเติม
|
||||
replace = แทนที่
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ new-window = Нове вікно
|
|||
profile = Профіль
|
||||
menu-profiles = Профілі...
|
||||
close-tab = Закрити вкладку
|
||||
quit = Вийти
|
||||
quit = Завершити
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -147,5 +147,6 @@ focus-pane-up = Фокус на верхню панель
|
|||
comment = Емулятор терміналу для середовища COSMIC
|
||||
keywords = Команда;Оболонка;Термінал;Інтерфейс;CLI;
|
||||
copy-link = Копіювати ланку
|
||||
tab-new-inherit-working-directory = У нових вкладках використовується поточний каталог
|
||||
tab-new-inherit-working-directory-description = Відкривати нові вкладки в робочому каталозі активної вкладки
|
||||
tab-new-inherit-working-directory = Нові вкладки та вікна відкривати в поточному каталозі
|
||||
tab-new-inherit-working-directory-description = Відкривати нові вкладки та вікна в робочому каталозі активної вкладки
|
||||
show-pane-borders = Показувати межі панелей
|
||||
|
|
|
|||
|
|
@ -149,3 +149,4 @@ keywords = 指令;外壳;终端;命令行界面;
|
|||
copy-link = 复制链接
|
||||
tab-new-inherit-working-directory = 新标签和窗口使用当前目录
|
||||
tab-new-inherit-working-directory-description = 在活动标签的工作目录中打开新标签和窗口
|
||||
show-pane-borders = 显示窗格边框
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ new-terminal = 新建終端機
|
|||
## Color schemes
|
||||
|
||||
color-schemes = 配色方案
|
||||
rename = 重命名
|
||||
rename = 重新命名
|
||||
export = 匯出
|
||||
delete = 刪除
|
||||
import = 匯入
|
||||
|
|
@ -24,7 +24,7 @@ command-line = 命令列
|
|||
tab-title = 分頁標題
|
||||
tab-title-description = 覆寫預設分頁標題
|
||||
add-profile = 新增設定檔
|
||||
new-profile = 新建設定檔
|
||||
new-profile = 新增設定檔
|
||||
make-default = 設為預設值
|
||||
working-directory = 工作目錄
|
||||
hold = 保留
|
||||
|
|
@ -79,12 +79,12 @@ find-next = 下一個
|
|||
## File
|
||||
|
||||
file = 檔案
|
||||
new-tab = 新建分頁
|
||||
new-window = 新建視窗
|
||||
new-tab = 新增分頁
|
||||
new-window = 新增視窗
|
||||
profile = 設定檔案
|
||||
menu-profiles = 設定檔案...
|
||||
close-tab = 關閉分頁
|
||||
quit = 退出
|
||||
quit = 結束
|
||||
|
||||
## Edit
|
||||
|
||||
|
|
@ -109,11 +109,11 @@ menu-color-schemes = 配色方案...
|
|||
menu-settings = 設定...
|
||||
menu-about = 關於 COSMIC 終端機…
|
||||
cancel = 取消
|
||||
repository = 軟體庫源
|
||||
repository = 軟體庫
|
||||
support = 支援
|
||||
keyboard-shortcuts = 鍵盤快速鍵
|
||||
keywords = 指令;殼層;終端;指令行介面CLI;
|
||||
add-another-keybinding = 添加另一個按鍵組合
|
||||
add-another-keybinding = 新增另一個鍵盤快速鍵
|
||||
close-window = 關閉視窗
|
||||
copy-or-sigint = 複製或 SIGINT
|
||||
disable = 停用
|
||||
|
|
@ -136,7 +136,7 @@ focus-pane-up = 聚焦上方窗格
|
|||
open-link = 開啟連結
|
||||
menu-password-manager = 密碼…
|
||||
passwords-title = 密碼
|
||||
add-password = 添增密碼
|
||||
add-password = 新增密碼
|
||||
password-input = 密碼
|
||||
password-input-description = 描述
|
||||
shortcut-replace-title = 取代快速鍵?
|
||||
|
|
@ -149,3 +149,4 @@ clear-scrollback = 清除捲動回朔
|
|||
comment = COSMIC 桌面終端機模擬器
|
||||
tab-new-inherit-working-directory = 新分頁和視窗使用目前目錄
|
||||
tab-new-inherit-working-directory-description = 在作用中分頁的工作目錄開啟新分頁和視窗
|
||||
show-pane-borders = 顯示窗格邊框
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ pub struct Config {
|
|||
pub opacity: u8,
|
||||
pub profiles: BTreeMap<ProfileId, Profile>,
|
||||
pub show_headerbar: bool,
|
||||
pub show_pane_borders: bool,
|
||||
pub use_bright_bold: bool,
|
||||
pub syntax_theme_dark: String,
|
||||
pub syntax_theme_light: String,
|
||||
|
|
@ -260,6 +261,7 @@ impl Default for Config {
|
|||
opacity: 100,
|
||||
profiles: BTreeMap::new(),
|
||||
show_headerbar: true,
|
||||
show_pane_borders: false,
|
||||
syntax_theme_dark: COSMIC_THEME_DARK.to_string(),
|
||||
syntax_theme_light: COSMIC_THEME_LIGHT.to_string(),
|
||||
use_bright_bold: false,
|
||||
|
|
|
|||
383
src/main.rs
383
src/main.rs
|
|
@ -566,11 +566,13 @@ pub enum Message {
|
|||
ReorderTab(Pane, ReorderEvent),
|
||||
SaveOutput(Option<segmented_button::Entity>),
|
||||
SaveOutputResult(pane_grid::Pane, segmented_button::Entity, DialogResult),
|
||||
Surface(surface::Action),
|
||||
Surface(surface::Action<Message>),
|
||||
SelectAll(Option<segmented_button::Entity>),
|
||||
ShowAdvancedFontSettings(bool),
|
||||
ShowHeaderBar(bool),
|
||||
SshConnect(usize),
|
||||
ShowPaneBorders(bool),
|
||||
|
||||
SyntaxTheme(ColorSchemeKind, usize),
|
||||
SystemThemeChange,
|
||||
TabNewInheritWorkingDirectory(bool),
|
||||
|
|
@ -602,7 +604,6 @@ pub enum Message {
|
|||
ZoomIn,
|
||||
ZoomOut,
|
||||
ZoomReset,
|
||||
ContextMenuPopupClosed(window::Id),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
|
@ -680,14 +681,6 @@ pub struct App {
|
|||
shortcut_search_regex: Option<regex::Regex>,
|
||||
shortcut_search_value: String,
|
||||
modifiers: Modifiers,
|
||||
context_menu_popup: Option<(
|
||||
window::Id,
|
||||
pane_grid::Pane,
|
||||
segmented_button::Entity,
|
||||
Option<String>,
|
||||
widget::Id,
|
||||
cosmic::iced::Point,
|
||||
)>,
|
||||
#[cfg(feature = "password_manager")]
|
||||
password_mgr: password_manager::PasswordManager,
|
||||
}
|
||||
|
|
@ -833,7 +826,7 @@ impl App {
|
|||
|
||||
// Update terminal window background color
|
||||
{
|
||||
let color = Color::from(theme.cosmic().background(false).base);
|
||||
let color = Color::from(theme.cosmic().background(theme.transparent).base);
|
||||
let bytes = color.into_rgba8();
|
||||
let data = u32::from(bytes[2])
|
||||
| (u32::from(bytes[1]) << 8)
|
||||
|
|
@ -1483,6 +1476,7 @@ impl App {
|
|||
}
|
||||
|
||||
fn settings(&self) -> Element<'_, Message> {
|
||||
let t = self.core().system_theme();
|
||||
let app_theme_selected = match self.config.app_theme {
|
||||
AppTheme::Dark => 1,
|
||||
AppTheme::Light => 2,
|
||||
|
|
@ -1566,13 +1560,13 @@ impl App {
|
|||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
.add_maybe((!t.transparent).then(|| {
|
||||
widget::settings::item::builder(fl!("opacity"))
|
||||
.description(format!("{}%", self.config.opacity))
|
||||
.control(widget::slider(0..=100, self.config.opacity, |opacity| {
|
||||
Message::Opacity(opacity)
|
||||
})),
|
||||
);
|
||||
}))
|
||||
}));
|
||||
|
||||
let mut font_section = widget::settings::section()
|
||||
.title(fl!("font"))
|
||||
|
|
@ -1658,10 +1652,16 @@ impl App {
|
|||
font_section = font_section.add(advanced_font_settings());
|
||||
}
|
||||
|
||||
let splits_section = widget::settings::section().title(fl!("splits")).add(
|
||||
widget::settings::item::builder(fl!("focus-follow-mouse"))
|
||||
.toggler(self.config.focus_follow_mouse, Message::FocusFollowMouse),
|
||||
);
|
||||
let splits_section = widget::settings::section()
|
||||
.title(fl!("splits"))
|
||||
.add(
|
||||
widget::settings::item::builder(fl!("focus-follow-mouse"))
|
||||
.toggler(self.config.focus_follow_mouse, Message::FocusFollowMouse),
|
||||
)
|
||||
.add(
|
||||
widget::settings::item::builder(fl!("show-pane-borders"))
|
||||
.toggler(self.config.show_pane_borders, Message::ShowPaneBorders),
|
||||
);
|
||||
|
||||
let advanced_section = widget::settings::section()
|
||||
.title(fl!("advanced"))
|
||||
|
|
@ -2204,7 +2204,6 @@ impl Application for App {
|
|||
shortcut_search_regex: None,
|
||||
shortcut_search_value: String::new(),
|
||||
modifiers: Modifiers::empty(),
|
||||
context_menu_popup: None,
|
||||
#[cfg(feature = "password_manager")]
|
||||
password_mgr: Default::default(),
|
||||
};
|
||||
|
|
@ -3045,7 +3044,8 @@ impl Application for App {
|
|||
}
|
||||
Message::PaneClicked(pane) => {
|
||||
self.pane_model.set_focus(pane);
|
||||
return self.update_title(Some(pane));
|
||||
let title_task = self.update_title(Some(pane));
|
||||
return Task::batch([self.update_focus(), title_task]);
|
||||
}
|
||||
Message::PaneSplit(axis) => {
|
||||
let result = self.pane_model.panes.split(
|
||||
|
|
@ -3295,6 +3295,11 @@ impl Application for App {
|
|||
tab_new_inherit_working_directory
|
||||
);
|
||||
}
|
||||
Message::ShowPaneBorders(show_pane_borders) => {
|
||||
if show_pane_borders != self.config.show_pane_borders {
|
||||
config_set!(show_pane_borders, show_pane_borders);
|
||||
}
|
||||
}
|
||||
Message::UseBrightBold(use_bright_bold) => {
|
||||
if use_bright_bold != self.config.use_bright_bold {
|
||||
config_set!(use_bright_bold, use_bright_bold);
|
||||
|
|
@ -3418,16 +3423,7 @@ impl Application for App {
|
|||
return self.update_title(None);
|
||||
}
|
||||
Message::TabContextAction(entity, action) => {
|
||||
// Close context menu popup
|
||||
let mut tasks = Vec::new();
|
||||
if let Some((_popup_id, _, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::destroy_popup(_popup_id),
|
||||
)));
|
||||
}
|
||||
}
|
||||
// Close terminal context menu state
|
||||
if let Some(tab_model) = self.pane_model.active()
|
||||
&& let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity)
|
||||
|
|
@ -3436,11 +3432,8 @@ impl Application for App {
|
|||
//Some actions need the menu_state,
|
||||
//so only clear the position for them.
|
||||
match action {
|
||||
Action::LaunchUrlByMenu | Action::CopyUrlByMenu => {
|
||||
if let Some(context_menu) = terminal.context_menu.as_mut() {
|
||||
context_menu.position = None;
|
||||
}
|
||||
}
|
||||
// these read the link from the menu state and clear it themselves
|
||||
Action::LaunchUrlByMenu | Action::CopyUrlByMenu => {}
|
||||
_ => {
|
||||
terminal.context_menu = None;
|
||||
}
|
||||
|
|
@ -3450,94 +3443,29 @@ impl Application for App {
|
|||
return cosmic::Task::batch(tasks);
|
||||
}
|
||||
Message::TabContextMenu(pane, menu_state) => {
|
||||
#[allow(unused_mut)]
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
// Close existing context menu popup if any
|
||||
if let Some((_popup_id, _, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::destroy_popup(_popup_id),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all terminal context_menu state
|
||||
for (_, tab_model) in self.pane_model.panes.iter() {
|
||||
for entity in tab_model.iter() {
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
let mut terminal = terminal.lock().unwrap();
|
||||
terminal.context_menu = None;
|
||||
if terminal.context_menu.take().is_some() {
|
||||
terminal.active_regex_match = None;
|
||||
terminal.needs_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(menu_state) = menu_state {
|
||||
if let Some(_position) = menu_state.position {
|
||||
let local_position = menu_state.local_position.unwrap_or(_position);
|
||||
if let Some(tab_model) = self.pane_model.panes.get(pane) {
|
||||
let entity = tab_model.active();
|
||||
let link = menu_state.link.clone();
|
||||
let popup_id = window::Id::unique();
|
||||
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
let mut terminal = terminal.lock().unwrap();
|
||||
terminal.context_menu = Some(menu_state);
|
||||
}
|
||||
|
||||
self.context_menu_popup = Some((
|
||||
popup_id,
|
||||
pane,
|
||||
entity,
|
||||
link,
|
||||
widget::Id::unique(),
|
||||
local_position,
|
||||
));
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
let main_window = self.core.main_window_id().unwrap();
|
||||
let pos_x = _position.x as i32;
|
||||
let pos_y = _position.y as i32;
|
||||
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::app_popup(
|
||||
|_: &Self| cosmic::surface::action::LiveSettings::default(),
|
||||
move |_app: &mut Self| {
|
||||
use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::{Anchor, Gravity};
|
||||
use cosmic::iced::runtime::platform_specific::wayland::popup::{SctkPopupSettings, SctkPositioner};
|
||||
|
||||
SctkPopupSettings {
|
||||
parent: main_window,
|
||||
id: popup_id,
|
||||
positioner: SctkPositioner {
|
||||
size: None,
|
||||
anchor_rect: cosmic::iced::Rectangle {
|
||||
x: pos_x,
|
||||
y: pos_y,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
anchor: Anchor::None,
|
||||
gravity: Gravity::BottomRight,
|
||||
reactive: true,
|
||||
..Default::default()
|
||||
},
|
||||
parent_size: None,
|
||||
grab: true,
|
||||
close_with_children: false,
|
||||
input_zone: None,
|
||||
}
|
||||
}, None),
|
||||
)));
|
||||
}
|
||||
}
|
||||
// A right press records what is under the cursor
|
||||
if let Some(menu_state) = menu_state
|
||||
&& let Some(tab_model) = self.pane_model.panes.get(pane)
|
||||
{
|
||||
let entity = tab_model.active();
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
terminal.lock().unwrap().context_menu = Some(menu_state);
|
||||
}
|
||||
self.pane_model.set_focus(pane);
|
||||
}
|
||||
|
||||
return cosmic::Task::batch(tasks);
|
||||
}
|
||||
Message::TabNew => {
|
||||
// The profile from `--profile` only applies to the first tab
|
||||
|
|
@ -3929,26 +3857,8 @@ impl Application for App {
|
|||
self.reset_active_pane_zoom();
|
||||
return self.update_config();
|
||||
}
|
||||
Message::ContextMenuPopupClosed(id) => {
|
||||
if let Some((popup_id, pane, entity, _, _, _)) = &self.context_menu_popup
|
||||
&& id == *popup_id
|
||||
{
|
||||
// Clear link underline on the terminal
|
||||
if let Some(tab_model) = self.pane_model.panes.get(*pane)
|
||||
&& let Some(terminal) = tab_model.data::<Mutex<Terminal>>(*entity)
|
||||
{
|
||||
let mut terminal = terminal.lock().unwrap();
|
||||
terminal.context_menu = None;
|
||||
terminal.active_regex_match = None;
|
||||
terminal.needs_update = true;
|
||||
}
|
||||
self.context_menu_popup = None;
|
||||
}
|
||||
}
|
||||
Message::Surface(a) => {
|
||||
return cosmic::task::message(cosmic::Action::Cosmic(
|
||||
cosmic::app::Action::Surface(a),
|
||||
));
|
||||
return cosmic::task::message(cosmic::Action::Surface(a));
|
||||
}
|
||||
Message::ReorderTab(
|
||||
pane,
|
||||
|
|
@ -4097,32 +4007,7 @@ impl Application for App {
|
|||
]
|
||||
}
|
||||
|
||||
fn on_close_requested(&self, id: window::Id) -> Option<Self::Message> {
|
||||
if let Some((popup_id, _, _, _, _, _)) = &self.context_menu_popup
|
||||
&& id == *popup_id
|
||||
{
|
||||
return Some(Message::ContextMenuPopupClosed(id));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn view_window(&self, window_id: window::Id) -> Element<'_, Message> {
|
||||
if let Some((popup_id, pane, entity, ref link, ref autosize_id, _)) =
|
||||
self.context_menu_popup
|
||||
&& window_id == popup_id
|
||||
{
|
||||
return widget::autosize::autosize(
|
||||
menu::context_menu(
|
||||
&self.config,
|
||||
&self.key_binds,
|
||||
entity,
|
||||
link.clone(),
|
||||
self.terminal_monitors(pane, entity),
|
||||
),
|
||||
autosize_id.clone(),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
match &self.dialog_opt {
|
||||
Some(dialog) => dialog.view(window_id),
|
||||
None => widget::text("Unknown window ID").into(),
|
||||
|
|
@ -4131,8 +4016,23 @@ impl Application for App {
|
|||
|
||||
/// Creates a view after each update.
|
||||
fn view(&self) -> Element<'_, Self::Message> {
|
||||
let cosmic_theme::Spacing { space_xxs, .. } = self.core().system_theme().cosmic().spacing;
|
||||
let t = self.core().system_theme();
|
||||
let cosmic = t.cosmic();
|
||||
let cosmic_theme::Spacing {
|
||||
space_xxxs,
|
||||
space_xxs,
|
||||
..
|
||||
} = cosmic.spacing;
|
||||
|
||||
let show_pane_borders =
|
||||
self.config.show_pane_borders && self.pane_model.panes.panes.len() > 1;
|
||||
let pane_corner_radius: iced::border::Radius = {
|
||||
let pad = f32::from(space_xxxs) / 2.0;
|
||||
cosmic
|
||||
.radius_s()
|
||||
.map(|r| if r > 0.0 { r + pad } else { 0.0 })
|
||||
.into()
|
||||
};
|
||||
let pane_grid = PaneGrid::new(&self.pane_model.panes, |pane, tab_model, _is_maximized| {
|
||||
let mut tab_column = widget::column::with_capacity(1);
|
||||
|
||||
|
|
@ -4181,60 +4081,51 @@ impl Application for App {
|
|||
.on_open_hyperlink(Some(Box::new(Message::LaunchUrl)))
|
||||
.on_window_focused(|| Message::WindowFocused)
|
||||
.on_window_unfocused(|| Message::WindowUnfocused)
|
||||
.opacity(self.config.opacity_ratio())
|
||||
.opacity(if t.transparent {
|
||||
t.cosmic().alpha_map.blurred_alpha(t.cosmic().frosted)
|
||||
} else {
|
||||
self.config.opacity_ratio()
|
||||
})
|
||||
.padding(space_xxs)
|
||||
.sharp_corners(self.core.window.sharp_corners)
|
||||
.show_headerbar(self.config.show_headerbar);
|
||||
.show_headerbar(self.config.show_headerbar)
|
||||
.pane_border_radius(show_pane_borders.then_some(pane_corner_radius))
|
||||
.border(pane_border(cosmic, t.transparent, show_pane_borders));
|
||||
|
||||
if self.config.focus_follow_mouse {
|
||||
terminal_box = terminal_box.on_mouse_enter(move || Message::MouseEnter(pane));
|
||||
}
|
||||
|
||||
// If a context menu popup is active for this pane, inform the
|
||||
// terminal_box so it will emit on_context_menu(None) on click
|
||||
// to dismiss the popup.
|
||||
if self.context_menu_popup.is_some() {
|
||||
terminal_box = terminal_box.context_menu(cosmic::iced::Point::ORIGIN);
|
||||
// The terminal records what was under the right press; the widget opens the
|
||||
// menu on release, so build it from that state
|
||||
let context_link = terminal
|
||||
.lock()
|
||||
.unwrap()
|
||||
.context_menu
|
||||
.as_ref()
|
||||
.map(|menu_state| menu_state.link.clone());
|
||||
if context_link.is_some() {
|
||||
terminal_box = terminal_box.context_menu_open(true);
|
||||
}
|
||||
|
||||
let use_wayland_popup = {
|
||||
#[cfg(feature = "wayland")]
|
||||
{
|
||||
is_wayland()
|
||||
}
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let tab_element: Element<'_, Message> = if !use_wayland_popup {
|
||||
// Fallback: render context menu as an inline popover
|
||||
if let Some((_, popup_pane, popup_entity, ref link, _, point)) =
|
||||
self.context_menu_popup
|
||||
{
|
||||
if pane == popup_pane {
|
||||
let mut popover = widget::popover(terminal_box.context_menu(point));
|
||||
popover = popover
|
||||
.popup(menu::context_menu(
|
||||
&self.config,
|
||||
&self.key_binds,
|
||||
popup_entity,
|
||||
link.clone(),
|
||||
self.terminal_monitors(popup_pane, popup_entity),
|
||||
))
|
||||
.position(widget::popover::Position::Point(point));
|
||||
popover.into()
|
||||
} else {
|
||||
terminal_box.into()
|
||||
}
|
||||
} else {
|
||||
terminal_box.into()
|
||||
}
|
||||
} else {
|
||||
terminal_box.into()
|
||||
};
|
||||
tab_column = tab_column.push(tab_element);
|
||||
let mut context_menu = widget::context_menu(
|
||||
terminal_box,
|
||||
context_link.map(|link| {
|
||||
menu::context_menu(
|
||||
&self.config,
|
||||
&self.key_binds,
|
||||
entity,
|
||||
link,
|
||||
self.terminal_monitors(pane, entity),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.item_width(widget::menu::ItemWidth::Uniform(360))
|
||||
.on_close(Message::TabContextMenu(pane, None))
|
||||
.on_surface_action(Message::Surface);
|
||||
if let Some(window_id) = self.core.main_window_id() {
|
||||
context_menu = context_menu.window_id(window_id);
|
||||
}
|
||||
tab_column = tab_column.push(context_menu);
|
||||
}
|
||||
|
||||
//Only draw find in the currently focused pane
|
||||
|
|
@ -4327,7 +4218,14 @@ impl Application for App {
|
|||
.on_drag(Message::PaneDragged);
|
||||
|
||||
//TODO: apply window border radius xs at bottom of window
|
||||
pane_grid.into()
|
||||
if show_pane_borders {
|
||||
// Each pane draws its own border stroke. Painting a filled
|
||||
// container behind the grid instead would stack its alpha with the
|
||||
// translucent panes and wash out the blurred backdrop.
|
||||
pane_grid.spacing(space_xxxs).into()
|
||||
} else {
|
||||
pane_grid.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn system_theme_update(
|
||||
|
|
@ -4408,10 +4306,79 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
fn is_wayland() -> bool {
|
||||
matches!(
|
||||
cosmic::app::cosmic::windowing_system(),
|
||||
Some(cosmic::app::cosmic::WindowingSystem::Wayland)
|
||||
)
|
||||
/// Divider color painted behind the pane grid to form pane borders.
|
||||
///
|
||||
/// When blur is active the transparent container must be used, otherwise the
|
||||
/// fill is opaque and hides the blurred desktop behind the window.
|
||||
fn pane_divider_color(
|
||||
cosmic: &cosmic_theme::Theme,
|
||||
transparent: bool,
|
||||
) -> cosmic::cosmic_theme::palette::Srgba {
|
||||
cosmic.background(transparent).divider
|
||||
}
|
||||
|
||||
/// Border stroke drawn around each terminal pane.
|
||||
///
|
||||
/// The stroke sits on the pane edge rather than behind it, so the pane
|
||||
/// interior keeps its own opacity and the blurred desktop stays visible.
|
||||
fn pane_border(cosmic: &cosmic_theme::Theme, transparent: bool, show: bool) -> iced::Border {
|
||||
if show {
|
||||
iced::Border {
|
||||
color: Color::from(pane_divider_color(cosmic, transparent)),
|
||||
width: 1.0,
|
||||
..Default::default()
|
||||
}
|
||||
} else {
|
||||
iced::Border::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{pane_border, pane_divider_color};
|
||||
|
||||
#[test]
|
||||
fn pane_border_is_drawn_only_when_enabled() {
|
||||
// With borders off the pane must render exactly as before, so the
|
||||
// stroke has to be zero width rather than a transparent hairline.
|
||||
let theme = cosmic::cosmic_theme::Theme::dark_default();
|
||||
assert_eq!(pane_border(&theme, true, false).width, 0.0);
|
||||
assert!(pane_border(&theme, true, true).width > 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pane_border_uses_the_divider_color() {
|
||||
// The stroke is the only thing marking the pane edge now that nothing
|
||||
// is painted behind the grid, so it must match the theme divider.
|
||||
let theme = cosmic::cosmic_theme::Theme::dark_default();
|
||||
let expected = cosmic::iced::Color::from(pane_divider_color(&theme, true));
|
||||
assert_eq!(pane_border(&theme, true, true).color, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pane_divider_is_translucent_when_blur_is_active() {
|
||||
// The divider is painted as a full-window container behind the pane
|
||||
// grid. With blur active it must keep alpha < 1 so the frosted
|
||||
// backdrop still shows through instead of a flat opaque fill.
|
||||
let theme = cosmic::cosmic_theme::Theme::dark_default();
|
||||
let color = pane_divider_color(&theme, true);
|
||||
assert!(
|
||||
color.alpha < 1.0,
|
||||
"expected translucent divider, got alpha {}",
|
||||
color.alpha
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pane_divider_is_opaque_without_blur() {
|
||||
// Without blur there is nothing to show through, so the divider keeps
|
||||
// the fully opaque background color.
|
||||
let theme = cosmic::cosmic_theme::Theme::dark_default();
|
||||
let color = pane_divider_color(&theme, false);
|
||||
assert!(
|
||||
(color.alpha - 1.0).abs() < f32::EPSILON,
|
||||
"expected opaque divider, got alpha {}",
|
||||
color.alpha
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
190
src/menu.rs
190
src/menu.rs
|
|
@ -1,17 +1,15 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic::iced::Point;
|
||||
use cosmic::widget::menu::action::MenuAction;
|
||||
use cosmic::widget::menu::key_bind::KeyBind;
|
||||
use cosmic::widget::menu::{Item as MenuItem, menu_button};
|
||||
use cosmic::widget::{Column, space};
|
||||
use cosmic::{
|
||||
Element,
|
||||
app::Core,
|
||||
iced::core::Border,
|
||||
iced::{Background, Length, advanced::widget::text::Style as TextStyle},
|
||||
theme,
|
||||
iced::{Background, Length},
|
||||
widget::{
|
||||
self, divider,
|
||||
self,
|
||||
menu::{ItemHeight, ItemWidth},
|
||||
responsive_menu_bar, segmented_button,
|
||||
},
|
||||
|
|
@ -23,147 +21,92 @@ use crate::{Action, ColorSchemeId, ColorSchemeKind, Config, Message, fl, termina
|
|||
static MENU_ID: LazyLock<cosmic::widget::Id> =
|
||||
LazyLock::new(|| cosmic::widget::Id::new("responsive-menu"));
|
||||
|
||||
/// What the terminal found under the right-click
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MenuState {
|
||||
pub position: Option<Point>,
|
||||
pub local_position: Option<Point>,
|
||||
pub link: Option<String>,
|
||||
}
|
||||
|
||||
pub fn context_menu<'a>(
|
||||
/// A context menu action dispatched to the tab the menu was opened on.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct TabAction(pub segmented_button::Entity, pub Action);
|
||||
|
||||
impl MenuAction for TabAction {
|
||||
type Message = Message;
|
||||
|
||||
fn message(&self) -> Message {
|
||||
Message::TabContextAction(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context_menu(
|
||||
config: &Config,
|
||||
key_binds: &HashMap<KeyBind, Action>,
|
||||
entity: segmented_button::Entity,
|
||||
link: Option<String>,
|
||||
monitors: (bool, bool, bool),
|
||||
) -> Element<'a, Message> {
|
||||
let find_key = |action: &Action| -> String {
|
||||
for (key_bind, key_action) in key_binds {
|
||||
if action == key_action {
|
||||
return key_bind.to_string();
|
||||
}
|
||||
}
|
||||
String::new()
|
||||
};
|
||||
fn key_style(theme: &cosmic::Theme) -> TextStyle {
|
||||
let mut color = theme.cosmic().background(false).component.on;
|
||||
color.alpha *= 0.75;
|
||||
TextStyle {
|
||||
color: Some(color.into()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
let menu_item = |label, action| {
|
||||
let key = find_key(&action);
|
||||
menu_button(vec![
|
||||
widget::text(label).into(),
|
||||
space::horizontal().into(),
|
||||
widget::text(key)
|
||||
.class(theme::Text::Custom(key_style))
|
||||
.into(),
|
||||
])
|
||||
.on_press(Message::TabContextAction(entity, action))
|
||||
) -> Vec<widget::menu::Tree<Message>> {
|
||||
let item =
|
||||
|label: String, action: Action| MenuItem::Button(label, None, TabAction(entity, action));
|
||||
let check = |label: String, value: bool, action: Action| {
|
||||
MenuItem::CheckBox(label, None, value, TabAction(entity, action))
|
||||
};
|
||||
|
||||
let menu_checkbox = |label, value, action| {
|
||||
menu_button(vec![
|
||||
widget::text(label).into(),
|
||||
widget::space::horizontal().into(),
|
||||
widget::toggler(value)
|
||||
.on_toggle(move |_| Message::TabContextAction(entity, action))
|
||||
.size(16.0)
|
||||
.into(),
|
||||
])
|
||||
.on_press(Message::TabContextAction(entity, action))
|
||||
};
|
||||
|
||||
let mut rows = vec![
|
||||
Element::from(menu_item(fl!("copy"), Action::Copy)),
|
||||
Element::from(menu_item(fl!("paste"), Action::Paste)),
|
||||
Element::from(menu_item(fl!("select-all"), Action::SelectAll)),
|
||||
Element::from(divider::horizontal::light()),
|
||||
Element::from(menu_item(fl!("clear-scrollback"), Action::ClearScrollback)),
|
||||
Element::from(menu_item(fl!("save-output"), Action::SaveOutput)),
|
||||
Element::from(divider::horizontal::light()),
|
||||
Element::from(menu_checkbox(
|
||||
let mut items = vec![
|
||||
item(fl!("new-tab"), Action::TabNew),
|
||||
item(fl!("rename-tab"), Action::TabRename),
|
||||
MenuItem::Divider,
|
||||
item(fl!("copy"), Action::Copy),
|
||||
item(fl!("paste"), Action::Paste),
|
||||
item(fl!("select-all"), Action::SelectAll),
|
||||
MenuItem::Divider,
|
||||
item(fl!("clear-scrollback"), Action::ClearScrollback),
|
||||
item(fl!("save-output"), Action::SaveOutput),
|
||||
MenuItem::Divider,
|
||||
check(
|
||||
fl!("monitor-activity"),
|
||||
monitors.0,
|
||||
Action::Monitor(MonitorKind::Activity),
|
||||
)),
|
||||
Element::from(menu_checkbox(
|
||||
),
|
||||
check(
|
||||
fl!("monitor-silence"),
|
||||
monitors.1,
|
||||
Action::Monitor(MonitorKind::Silence),
|
||||
)),
|
||||
Element::from(menu_checkbox(
|
||||
),
|
||||
check(
|
||||
fl!("monitor-process-finished"),
|
||||
monitors.2,
|
||||
Action::Monitor(MonitorKind::ProcessFinished),
|
||||
)),
|
||||
Element::from(divider::horizontal::light()),
|
||||
Element::from(menu_item(
|
||||
fl!("split-horizontal"),
|
||||
Action::PaneSplitHorizontal,
|
||||
)),
|
||||
Element::from(menu_item(fl!("split-vertical"), Action::PaneSplitVertical)),
|
||||
Element::from(menu_item(
|
||||
fl!("pane-toggle-maximize"),
|
||||
Action::PaneToggleMaximized,
|
||||
)),
|
||||
Element::from(divider::horizontal::light()),
|
||||
Element::from(menu_item(fl!("new-tab"), Action::TabNew)),
|
||||
Element::from(menu_item(fl!("rename-tab"), Action::TabRename)),
|
||||
Element::from(menu_item(fl!("menu-settings"), Action::Settings)),
|
||||
Element::from(menu_item(fl!("menu-about"), Action::About)),
|
||||
),
|
||||
MenuItem::Divider,
|
||||
item(fl!("split-horizontal"), Action::PaneSplitHorizontal),
|
||||
item(fl!("split-vertical"), Action::PaneSplitVertical),
|
||||
item(fl!("pane-toggle-maximize"), Action::PaneToggleMaximized),
|
||||
MenuItem::Divider,
|
||||
MenuItem::CheckBox(
|
||||
fl!("window-header"),
|
||||
None,
|
||||
config.show_headerbar,
|
||||
TabAction(entity, Action::ShowHeaderBar(!config.show_headerbar)),
|
||||
),
|
||||
MenuItem::Divider,
|
||||
];
|
||||
#[cfg(feature = "password_manager")]
|
||||
{
|
||||
rows.push(Element::from(menu_item(
|
||||
fl!("menu-password-manager"),
|
||||
Action::PasswordManager,
|
||||
)));
|
||||
}
|
||||
rows.push(Element::from(menu_checkbox(
|
||||
fl!("show-headerbar"),
|
||||
config.show_headerbar,
|
||||
Action::ShowHeaderBar(!config.show_headerbar),
|
||||
)));
|
||||
|
||||
//If we have a link
|
||||
//prepend the Open Link item
|
||||
items.push(item(fl!("menu-password-manager"), Action::PasswordManager));
|
||||
items.push(item(fl!("menu-settings"), Action::Settings));
|
||||
items.push(item(fl!("menu-about"), Action::About));
|
||||
// If we have a link, prepend the link items
|
||||
if link.is_some() {
|
||||
rows.insert(
|
||||
0,
|
||||
Element::from(menu_item(fl!("open-link"), Action::LaunchUrlByMenu)),
|
||||
);
|
||||
rows.insert(
|
||||
1,
|
||||
Element::from(menu_item(fl!("copy-link"), Action::CopyUrlByMenu)),
|
||||
);
|
||||
rows.insert(2, Element::from(divider::horizontal::light()));
|
||||
items.insert(0, item(fl!("open-link"), Action::LaunchUrlByMenu));
|
||||
items.insert(1, item(fl!("copy-link"), Action::CopyUrlByMenu));
|
||||
items.insert(2, MenuItem::Divider);
|
||||
}
|
||||
let content = Column::with_children(rows);
|
||||
widget::container(content)
|
||||
.padding(1)
|
||||
//TODO: move style to libcosmic
|
||||
.style(|theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let component = &cosmic.background(false).component;
|
||||
widget::container::Style {
|
||||
icon_color: Some(component.on.into()),
|
||||
text_color: Some(component.on.into()),
|
||||
background: Some(Background::Color(component.base.into())),
|
||||
border: Border {
|
||||
radius: cosmic.radius_s().map(|x| x + 1.0).into(),
|
||||
width: 1.0,
|
||||
color: component.divider.into(),
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.width(Length::Fixed(360.0))
|
||||
.into()
|
||||
|
||||
let key_binds: HashMap<KeyBind, TabAction> = key_binds
|
||||
.iter()
|
||||
.map(|(key_bind, action)| (key_bind.clone(), TabAction(entity, *action)))
|
||||
.collect();
|
||||
widget::menu::items(&key_binds, items)
|
||||
}
|
||||
|
||||
pub fn color_scheme_menu<'a>(
|
||||
|
|
@ -174,7 +117,8 @@ pub fn color_scheme_menu<'a>(
|
|||
let menu_item =
|
||||
|label, message| menu_button(vec![widget::text(label).into()]).on_press(message);
|
||||
|
||||
let mut column = widget::column::with_capacity(if id_opt.is_some() { 3 } else { 1 });
|
||||
let mut column =
|
||||
widget::menu::menu_column::MenuColumn::with_capacity(if id_opt.is_some() { 3 } else { 1 });
|
||||
if let Some(id) = id_opt {
|
||||
column = column.push(menu_item(
|
||||
fl!("rename"),
|
||||
|
|
@ -197,7 +141,7 @@ pub fn color_scheme_menu<'a>(
|
|||
//TODO: move style to libcosmic
|
||||
.style(|theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let component = &cosmic.background(false).component;
|
||||
let component = &cosmic.background(theme.transparent).component;
|
||||
widget::container::Style {
|
||||
icon_color: Some(component.on.into()),
|
||||
text_color: Some(component.on.into()),
|
||||
|
|
|
|||
148
src/terminal.rs
148
src/terminal.rs
|
|
@ -207,23 +207,28 @@ impl TerminalPaneGrid {
|
|||
}
|
||||
}
|
||||
pub fn unfocus_all_terminals(&self) {
|
||||
for (_pane, tab_model) in self.panes.panes.iter() {
|
||||
for entity in tab_model.iter() {
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
let mut terminal = terminal.lock().unwrap();
|
||||
terminal.set_focused(false);
|
||||
terminal.update();
|
||||
}
|
||||
for tab_model in self.panes.panes.values() {
|
||||
let entity = tab_model.active();
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
let mut terminal = terminal.lock().unwrap();
|
||||
terminal.set_focused(false);
|
||||
terminal.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Metadata {
|
||||
pub bg: cosmic_text::Color,
|
||||
pub underline_color: cosmic_text::Color,
|
||||
pub flags: Flags,
|
||||
/// Remplissage natif (élément de bloc Unicode) — voir [`BlockFill`].
|
||||
pub block: Option<BlockFill>,
|
||||
/// Couleur du remplissage natif. Hors bloc, sans effet ; participant à
|
||||
/// l'égalité pour que deux blocs adjacents de couleurs différentes ne
|
||||
/// fusionnent pas en un seul quad.
|
||||
pub block_color: cosmic_text::Color,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
|
|
@ -233,6 +238,8 @@ impl Metadata {
|
|||
bg,
|
||||
underline_color,
|
||||
flags,
|
||||
block: None,
|
||||
block_color: underline_color,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,6 +253,73 @@ impl Metadata {
|
|||
fn with_flags(self, flags: Flags) -> Self {
|
||||
Self { flags, ..self }
|
||||
}
|
||||
|
||||
fn with_block(mut self, block: Option<BlockFill>, color: cosmic_text::Color) -> Self {
|
||||
self.block = block;
|
||||
self.block_color = color;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Élément de bloc Unicode (U+2580–U+259F) rendu nativement.
|
||||
///
|
||||
/// Ces caractères ne passent PAS par le glyphe de la police : le `█` d'une
|
||||
/// police couvre à peine l'em (≈ 1× la taille de police) alors que la cellule
|
||||
/// fait `line_height` (≈ 1,4×) — d'où des trous entre les rangées et un rendu
|
||||
/// crénelé. À la place, chaque bloc est remplacé par une espace (le glyphe
|
||||
/// disparaît) et peint en quad GPU couvrant exactement la fraction voulue de
|
||||
/// la cellule : bords alignés sur la grille, jointif par construction, net à
|
||||
/// toute échelle. C'est l'approche de kitty/WezTerm.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum BlockFill {
|
||||
/// Un ou deux rectangles en huitièmes de cellule : `(x0, x1, y0, y1)`,
|
||||
/// abscisse et ordonnée depuis le coin haut-gauche. Un rectangle vide
|
||||
/// (`x0 >= x1` ou `y0 >= y1`) est ignoré au tracé — deux rectangles
|
||||
/// suffisent pour toute la famille des quadrants.
|
||||
Rects([(u8, u8, u8, u8); 2]),
|
||||
/// Trame (`░▒▓`) : rectangle plein, alpha en quarts (1–3).
|
||||
Shade(u8),
|
||||
}
|
||||
|
||||
/// Mappe un caractère vers son remplissage natif, s'il est un élément de bloc.
|
||||
pub fn block_fill(c: char) -> Option<BlockFill> {
|
||||
use BlockFill::{Rects, Shade};
|
||||
const NONE: (u8, u8, u8, u8) = (8, 8, 8, 8);
|
||||
match c {
|
||||
'▀' => Some(Rects([(0, 8, 0, 4), NONE])),
|
||||
'▁' => Some(Rects([(0, 8, 7, 8), NONE])),
|
||||
'▂' => Some(Rects([(0, 8, 6, 8), NONE])),
|
||||
'▃' => Some(Rects([(0, 8, 5, 8), NONE])),
|
||||
'▄' => Some(Rects([(0, 8, 4, 8), NONE])),
|
||||
'▅' => Some(Rects([(0, 8, 3, 8), NONE])),
|
||||
'▆' => Some(Rects([(0, 8, 2, 8), NONE])),
|
||||
'▇' => Some(Rects([(0, 8, 1, 8), NONE])),
|
||||
'█' => Some(Rects([(0, 8, 0, 8), NONE])),
|
||||
'▉' => Some(Rects([(0, 7, 0, 8), NONE])),
|
||||
'▊' => Some(Rects([(0, 6, 0, 8), NONE])),
|
||||
'▋' => Some(Rects([(0, 5, 0, 8), NONE])),
|
||||
'▌' => Some(Rects([(0, 4, 0, 8), NONE])),
|
||||
'▍' => Some(Rects([(0, 3, 0, 8), NONE])),
|
||||
'▎' => Some(Rects([(0, 2, 0, 8), NONE])),
|
||||
'▏' => Some(Rects([(0, 1, 0, 8), NONE])),
|
||||
'▐' => Some(Rects([(4, 8, 0, 8), NONE])),
|
||||
'░' => Some(Shade(1)),
|
||||
'▒' => Some(Shade(2)),
|
||||
'▓' => Some(Shade(3)),
|
||||
'▔' => Some(Rects([(0, 8, 0, 1), NONE])),
|
||||
'▕' => Some(Rects([(7, 8, 0, 8), NONE])),
|
||||
'▖' => Some(Rects([(0, 4, 4, 8), NONE])),
|
||||
'▗' => Some(Rects([(4, 8, 4, 8), NONE])),
|
||||
'▘' => Some(Rects([(0, 4, 0, 4), NONE])),
|
||||
'▝' => Some(Rects([(4, 8, 0, 4), NONE])),
|
||||
'▙' => Some(Rects([(0, 4, 0, 8), (4, 8, 4, 8)])),
|
||||
'▚' => Some(Rects([(0, 4, 0, 4), (4, 8, 4, 8)])),
|
||||
'▛' => Some(Rects([(0, 8, 0, 4), (0, 4, 4, 8)])),
|
||||
'▜' => Some(Rects([(0, 8, 0, 4), (4, 8, 4, 8)])),
|
||||
'▞' => Some(Rects([(4, 8, 0, 4), (0, 4, 4, 8)])),
|
||||
'▟' => Some(Rects([(0, 8, 4, 8), (4, 8, 0, 4)])),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Terminal {
|
||||
|
|
@ -906,9 +980,14 @@ impl Terminal {
|
|||
}
|
||||
|
||||
let start = text.len();
|
||||
// Tab skip/stop is handled by alacritty_terminal
|
||||
// Tab skip/stop is handled by alacritty_terminal.
|
||||
// Les éléments de bloc ne deviennent pas des glyphes : la
|
||||
// police ne couvre pas la cellule (trous d'interligne) ;
|
||||
// ils sont peints en quads natifs au tracé, via Metadata.
|
||||
let block = block_fill(indexed.cell.c);
|
||||
text.push(match indexed.cell.c {
|
||||
'\t' => ' ',
|
||||
c if block.is_some() => ' ',
|
||||
c => c,
|
||||
});
|
||||
if let Some(zerowidth) = indexed.cell.zerowidth() {
|
||||
|
|
@ -1026,6 +1105,7 @@ impl Terminal {
|
|||
}
|
||||
|
||||
let metadata = Metadata::new(bg, fg)
|
||||
.with_block(block, fg)
|
||||
.with_flags(flags)
|
||||
.with_underline_color(underline_color);
|
||||
let (meta_idx, _) = self.metadata_set.insert_full(metadata);
|
||||
|
|
@ -1345,3 +1425,53 @@ impl Drop for Terminal {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn block_fill_couvre_toute_la_plage_unicode() {
|
||||
// U+2580–U+259F : chaque élément de bloc a sa géométrie native.
|
||||
for code in 0x2580..=0x259F {
|
||||
let c = char::from_u32(code).unwrap();
|
||||
assert!(
|
||||
block_fill(c).is_some(),
|
||||
"{c} (U+{code:04X}) sans remplissage"
|
||||
);
|
||||
}
|
||||
// Hors de la plage : filets, espaces, lettres — pas de remplissage.
|
||||
for c in [' ', '─', '│', 'M', '●', '\u{25A0}'] {
|
||||
assert!(
|
||||
block_fill(c).is_none(),
|
||||
"{c} ne doit pas être un bloc natif"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_fill_geometry_toujours_valide() {
|
||||
// Fractions croissantes, bornées à la cellule — sinon le quad
|
||||
// déborderait sur la cellule voisine ou serait rejeté au tracé.
|
||||
for c in (char::from_u32(0x2580).unwrap()..=char::from_u32(0x259F).unwrap())
|
||||
.chain(['░', '▒', '▓'].iter().copied())
|
||||
{
|
||||
let Some(fill) = block_fill(c) else { continue };
|
||||
match fill {
|
||||
BlockFill::Rects(rects) => {
|
||||
for (x0, x1, y0, y1) in rects {
|
||||
// Rectangle vide (sentinelle) ou borné à la cellule.
|
||||
let empty = x0 >= x1 || y0 >= y1;
|
||||
assert!(
|
||||
empty || (x1 <= 8 && y1 <= 8),
|
||||
"{c}: géométrie déborde la cellule"
|
||||
);
|
||||
}
|
||||
}
|
||||
BlockFill::Shade(quarters) => {
|
||||
assert!((1..=3).contains(&quarters), "{c}: alpha de trame invalide")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use cosmic::{
|
|||
cosmic_theme::palette::{WithAlpha, blend::Compose},
|
||||
iced::core::{
|
||||
Border, Shell,
|
||||
border::Radius,
|
||||
clipboard::Clipboard,
|
||||
input_method::{self, InputMethod},
|
||||
keyboard::key::Named,
|
||||
|
|
@ -45,7 +46,11 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::{Action, Terminal, TerminalScroll, menu::MenuState, terminal::Metadata};
|
||||
use crate::{
|
||||
Action, Terminal, TerminalScroll,
|
||||
menu::MenuState,
|
||||
terminal::{BlockFill, Metadata},
|
||||
};
|
||||
|
||||
const AUTOSCROLL_INTERVAL: Duration = Duration::from_millis(100);
|
||||
|
||||
|
|
@ -109,8 +114,9 @@ pub struct TerminalBox<'a, Message> {
|
|||
border: Border,
|
||||
padding: Padding,
|
||||
show_headerbar: bool,
|
||||
pane_border_radius: Option<Radius>,
|
||||
click_timing: Duration,
|
||||
context_menu: Option<Point>,
|
||||
context_menu_open: bool,
|
||||
on_context_menu: Option<Box<dyn Fn(Option<MenuState>) -> Message + 'a>>,
|
||||
on_mouse_enter: Option<Box<dyn Fn() -> Message + 'a>>,
|
||||
opacity: Option<f32>,
|
||||
|
|
@ -135,8 +141,9 @@ where
|
|||
border: Border::default(),
|
||||
padding: Padding::new(0.0),
|
||||
show_headerbar: true,
|
||||
pane_border_radius: None,
|
||||
click_timing: Duration::from_millis(500),
|
||||
context_menu: None,
|
||||
context_menu_open: false,
|
||||
on_context_menu: None,
|
||||
on_mouse_enter: None,
|
||||
opacity: None,
|
||||
|
|
@ -171,13 +178,18 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
pub fn pane_border_radius(mut self, pane_border_radius: Option<Radius>) -> Self {
|
||||
self.pane_border_radius = pane_border_radius;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn click_timing(mut self, click_timing: Duration) -> Self {
|
||||
self.click_timing = click_timing;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn context_menu(mut self, position: Point) -> Self {
|
||||
self.context_menu = Some(position);
|
||||
pub fn context_menu_open(mut self, open: bool) -> Self {
|
||||
self.context_menu_open = open;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +253,7 @@ where
|
|||
if !state.is_focused {
|
||||
return InputMethod::Disabled;
|
||||
}
|
||||
if self.context_menu.is_some() {
|
||||
if self.context_menu_open {
|
||||
return InputMethod::Disabled;
|
||||
}
|
||||
|
||||
|
|
@ -409,13 +421,22 @@ where
|
|||
let state = tree.state.downcast_ref::<State>();
|
||||
|
||||
let cosmic_theme = theme.cosmic();
|
||||
// matches the corners to the window border
|
||||
let corner_radius = if self.sharp_corners {
|
||||
let corner_radius = if let Some(r) = self.pane_border_radius {
|
||||
r.into()
|
||||
} else if self.sharp_corners {
|
||||
// matches the corners to the window border
|
||||
cosmic_theme.radius_0()
|
||||
} else {
|
||||
cosmic_theme.radius_s()
|
||||
}
|
||||
.map(|x| if x < 4.0 { x - 1.0 } else { x + 3.0 });
|
||||
cosmic_theme
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x - 1.0 } else { x + 3.0 })
|
||||
};
|
||||
// When there's a headerbar and no pane border, only round the bottom corners
|
||||
let border_radius: Radius = if self.show_headerbar && self.pane_border_radius.is_none() {
|
||||
[0.0, 0.0, corner_radius[2], corner_radius[3]].into()
|
||||
} else {
|
||||
corner_radius.into()
|
||||
};
|
||||
let scrollbar_w = f32::from(cosmic_theme.spacing.space_xxs);
|
||||
|
||||
let view_position = layout.position() + [self.padding.left, self.padding.top].into();
|
||||
|
|
@ -429,16 +450,11 @@ where
|
|||
// Pane too small for content, but still fill background
|
||||
let terminal = self.terminal.lock().unwrap();
|
||||
let meta = &terminal.metadata_set[terminal.default_attrs().metadata];
|
||||
let background_color = shade(meta.bg, state.is_focused && !self.disabled);
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: layout.bounds(),
|
||||
border: Border {
|
||||
radius: if self.show_headerbar {
|
||||
[0.0, 0.0, corner_radius[2], corner_radius[3]].into()
|
||||
} else {
|
||||
corner_radius.into()
|
||||
},
|
||||
radius: border_radius,
|
||||
width: self.border.width,
|
||||
color: self.border.color,
|
||||
},
|
||||
|
|
@ -446,12 +462,12 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
Color::from_rgba(
|
||||
f32::from(background_color.r()) / 255.0,
|
||||
f32::from(background_color.g()) / 255.0,
|
||||
f32::from(background_color.b()) / 255.0,
|
||||
f32::from(meta.bg.r()) / 255.0,
|
||||
f32::from(meta.bg.g()) / 255.0,
|
||||
f32::from(meta.bg.b()) / 255.0,
|
||||
match self.opacity {
|
||||
Some(opacity) => opacity,
|
||||
None => f32::from(background_color.a()) / 255.0,
|
||||
None => f32::from(meta.bg.a()) / 255.0,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -472,17 +488,11 @@ where
|
|||
// Render default background
|
||||
{
|
||||
let meta = &terminal.metadata_set[terminal.default_attrs().metadata];
|
||||
let background_color = shade(meta.bg, state.is_focused && !self.disabled);
|
||||
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: layout.bounds(),
|
||||
border: Border {
|
||||
radius: if self.show_headerbar {
|
||||
[0.0, 0.0, corner_radius[2], corner_radius[3]].into()
|
||||
} else {
|
||||
corner_radius.into()
|
||||
},
|
||||
radius: border_radius,
|
||||
width: self.border.width,
|
||||
color: self.border.color,
|
||||
},
|
||||
|
|
@ -490,12 +500,12 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
Color::from_rgba(
|
||||
f32::from(background_color.r()) / 255.0,
|
||||
f32::from(background_color.g()) / 255.0,
|
||||
f32::from(background_color.b()) / 255.0,
|
||||
f32::from(meta.bg.r()) / 255.0,
|
||||
f32::from(meta.bg.g()) / 255.0,
|
||||
f32::from(meta.bg.b()) / 255.0,
|
||||
match self.opacity {
|
||||
Some(opacity) => opacity,
|
||||
None => f32::from(background_color.a()) / 255.0,
|
||||
None => f32::from(meta.bg.a()) / 255.0,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -537,7 +547,7 @@ where
|
|||
fn fill<Renderer: renderer::Renderer>(
|
||||
&mut self,
|
||||
renderer: &mut Renderer,
|
||||
is_focused: bool,
|
||||
_is_focused: bool,
|
||||
) {
|
||||
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
|
||||
Color::from_rgba(
|
||||
|
|
@ -551,7 +561,7 @@ where
|
|||
macro_rules! mk_pos_offset {
|
||||
($x_offset:expr, $bottom_offset:expr) => {
|
||||
Vector::new(
|
||||
self.start_x + $x_offset,
|
||||
(self.start_x + $x_offset).floor(),
|
||||
self.line_top + self.line_height - $bottom_offset,
|
||||
)
|
||||
};
|
||||
|
|
@ -568,19 +578,57 @@ where
|
|||
}
|
||||
};
|
||||
($pos_offset:expr, $style_line_height:expr) => {
|
||||
mk_quad!($pos_offset, $style_line_height, self.end_x - self.start_x)
|
||||
mk_quad!(
|
||||
$pos_offset,
|
||||
$style_line_height,
|
||||
(self.end_x - self.start_x).ceil()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
let metadata = &self.metadata_set[self.metadata];
|
||||
if metadata.bg != self.metadata_set[self.default_metadata].bg {
|
||||
let color = shade(metadata.bg, is_focused);
|
||||
renderer.fill_quad(
|
||||
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
|
||||
cosmic_text_to_iced_color(color),
|
||||
cosmic_text_to_iced_color(metadata.bg),
|
||||
);
|
||||
}
|
||||
|
||||
// Éléments de bloc peints nativement : fractions de la
|
||||
// cellule (ou de la course fusionnée, à géométrie
|
||||
// séparable), bords calés sur la grille — zéro glyphe,
|
||||
// zéro interligne.
|
||||
if let Some(block) = metadata.block {
|
||||
let span_w = self.end_x - self.start_x;
|
||||
let mut color = cosmic_text_to_iced_color(metadata.block_color);
|
||||
let rects = match block {
|
||||
BlockFill::Rects(rects) => rects,
|
||||
BlockFill::Shade(quarters) => {
|
||||
color.a *= f32::from(quarters) / 4.0;
|
||||
[(0, 8, 0, 8), (8, 8, 8, 8)]
|
||||
}
|
||||
};
|
||||
for (x0, x1, y0, y1) in rects {
|
||||
if x0 >= x1 || y0 >= y1 {
|
||||
continue;
|
||||
}
|
||||
let left = self.start_x + span_w * f32::from(x0) / 8.0;
|
||||
let right = self.start_x + span_w * f32::from(x1) / 8.0;
|
||||
let top = self.line_top + self.line_height * f32::from(y0) / 8.0;
|
||||
let bottom = self.line_top + self.line_height * f32::from(y1) / 8.0;
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: Rectangle::new(
|
||||
self.view_position + Vector::new(left.floor(), top),
|
||||
Size::new(right.ceil() - left.floor(), bottom - top),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !metadata.flags.is_empty() {
|
||||
let style_line_height = (self.glyph_font_size / 10.0).clamp(1.0, 16.0);
|
||||
|
||||
|
|
@ -756,7 +804,7 @@ where
|
|||
let scrollbar_color: Color = if pressed {
|
||||
// pressed_state_color, 0.5
|
||||
cosmic_theme
|
||||
.background(false)
|
||||
.background(theme.transparent)
|
||||
.component
|
||||
.pressed
|
||||
.without_alpha()
|
||||
|
|
@ -766,7 +814,7 @@ where
|
|||
} else if hover {
|
||||
// hover_state_color, 0.2
|
||||
cosmic_theme
|
||||
.background(false)
|
||||
.background(theme.transparent)
|
||||
.component
|
||||
.hover
|
||||
.without_alpha()
|
||||
|
|
@ -1344,11 +1392,11 @@ where
|
|||
}
|
||||
// Update context menu state
|
||||
if let Some(on_context_menu) = &self.on_context_menu {
|
||||
match self.context_menu {
|
||||
Some(_) => {
|
||||
match self.context_menu_open {
|
||||
true => {
|
||||
shell.publish(on_context_menu(None));
|
||||
}
|
||||
None => {
|
||||
false => {
|
||||
if *button == Button::Right {
|
||||
let x = p.x - self.padding.left;
|
||||
let y = p.y - self.padding.top;
|
||||
|
|
@ -1366,23 +1414,13 @@ where
|
|||
None,
|
||||
);
|
||||
let link = get_hyperlink(&terminal, location);
|
||||
let abs = cosmic::iced::Point::new(
|
||||
layout.bounds().x + p.x,
|
||||
layout.bounds().y + p.y,
|
||||
);
|
||||
shell.publish(on_context_menu(Some(MenuState {
|
||||
position: Some(abs),
|
||||
local_position: Some(p),
|
||||
link,
|
||||
})));
|
||||
shell.publish(on_context_menu(Some(MenuState { link })));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
shell.capture_event();
|
||||
}
|
||||
} else {
|
||||
state.is_focused = false;
|
||||
}
|
||||
}
|
||||
Event::Mouse(MouseEvent::ButtonReleased(Button::Left)) => {
|
||||
|
|
@ -1608,6 +1646,10 @@ where
|
|||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if terminal.needs_update {
|
||||
shell.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1754,20 +1796,6 @@ fn accumulate_wheel_lines(y: f32, accumulator: f32) -> (i32, f32) {
|
|||
(lines, total - lines as f32)
|
||||
}
|
||||
|
||||
fn shade(color: cosmic_text::Color, is_focused: bool) -> cosmic_text::Color {
|
||||
if is_focused {
|
||||
color
|
||||
} else {
|
||||
let shade = 0.92;
|
||||
cosmic_text::Color::rgba(
|
||||
(f32::from(color.r()) * shade) as u8,
|
||||
(f32::from(color.g()) * shade) as u8,
|
||||
(f32::from(color.b()) * shade) as u8,
|
||||
color.a(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message> From<TerminalBox<'a, Message>> for Element<'a, Message, cosmic::Theme, Renderer>
|
||||
where
|
||||
Message: Clone + 'a,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue