Compare commits

...

33 commits

Author SHA1 Message Date
b2126a9f2b fix: appeler refresh_volume_limits sur app, pas self
Some checks failed
Continuous Integration / formatting (push) Has been cancelled
Continuous Integration / linting (push) Has been cancelled
Le patch yoda 5b838a67 est conserve (il initialise les plafonds sink ET
source, contrairement au code inline amont) mais il est desormais dans
une closure recevant `app: &mut Self` : l appel sur `self` ne compilait
plus.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 22:18:37 +02:00
673547dc52 Merge remote-tracking branch 'upstream/master' into yoda-dock-magnification
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	cosmic-app-list/src/app.rs
#	cosmic-applet-audio/src/lib.rs
#	cosmic-applet-input-sources/Cargo.toml
#	cosmic-applet-input-sources/src/lib.rs
#	cosmic-applet-status-area/src/components/app.rs
#	cosmic-panel-button/src/lib.rs
2026-08-19 22:04:42 +02:00
Michael Aaron Murphy
73d727814c fix(audio): debounce volume updates by 128ms 2026-08-18 17:23:33 +02:00
Michael Murphy
a1d4be5d10
i18n: translation update from Hosted Weblate (#1511) 2026-08-18 14:06:42 +02:00
Hosted Weblate
4285090a44
i18n: translation updates from weblate
Co-authored-by: Andi Chandler <andi@gowling.com>
Co-authored-by: CodeBeats <nicholai67@hotmail.com>
Co-authored-by: David Carvalho <david.snt.carvalho@gmail.com>
Co-authored-by: Ettore Atalan <atalanttore@googlemail.com>
Co-authored-by: Feike Donia <feikedonia@proton.me>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hugo Carvalho <hugokarvalho@hotmail.com>
Co-authored-by: Jens Peter Nielsen <mail@jp-nielsen.dk>
Co-authored-by: Martin Meizoso <martinmeizoso@gmail.com>
Co-authored-by: Michael Millet <mikevlet@protonmail.com>
Co-authored-by: Prasanta-Hembram <Prasantahembram720@gmail.com>
Co-authored-by: Quentin PAGÈS <quentinantonin@free.fr>
Co-authored-by: Steen Rabol <steen@rabol.dev>
Co-authored-by: Walter William Beckerleg Bruckman <spayk.99@protonmail.com>
Co-authored-by: Wilbur Lindqvist <william@willmantrade.com>
Co-authored-by: lucamosca1 <luca.moscato@gmail.com>
Co-authored-by: sicKat <giuseppecatillo2003@gmail.com>
Co-authored-by: the-forest-watches <lucastronks@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/oc/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-notifications/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-power/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-tiling/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-tiling/nl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-time/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/nl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/oc/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/pt/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-input-sources-applet/da/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-input-sources-applet/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-workspaces-applet/gl/
Translation: Pop OS/COSMIC Accessibility Applet
Translation: Pop OS/COSMIC App List Applet
Translation: Pop OS/COSMIC Applets Desktop Entries
Translation: Pop OS/COSMIC Audio Applet
Translation: Pop OS/COSMIC Battery Applet
Translation: Pop OS/COSMIC Bluetooth Applet
Translation: Pop OS/COSMIC Input Sources Applet
Translation: Pop OS/COSMIC Network Applet
Translation: Pop OS/COSMIC Notifications Applet
Translation: Pop OS/COSMIC Power Applet
Translation: Pop OS/COSMIC Tiling Applet
Translation: Pop OS/COSMIC Time Applet
Translation: Pop OS/COSMIC Workspaces Applet
2026-08-18 07:51:49 +02:00
Rafael Kraut
63292ab74d fix(status-area): constrain menu icon-data to icon size
Menu items expose their icon as a themed `icon-name` or raw PNG `icon-data`. The named-icon branch renders at a fixed `.size(14)`, but the icon-data branch wrapped the pixmap in a bare `Image` with no size constraint, so it rendered at the PNG's native dimensions. Apps may send full-resolution pixmaps, which then render oversized in the menu.

Constrain icon-data to the same 14px box with ContentFit::Contain, matching how KDE (Qt small-icon size) and GNOME (St.Icon popup-menu-icon) render menu item icons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 21:28:12 +02:00
Michael Murphy
ec8ffdc85d
i18n: translation update from Hosted Weblate (#1446)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pop OS/COSMIC Audio
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/).


It also includes following components:

* [Pop OS/COSMIC Accessibility
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/)

* [Pop OS/COSMIC Power
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-power/)

* [Pop OS/COSMIC Time
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-time/)

* [Pop OS/COSMIC Network
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/)

* [Pop OS/COSMIC Input Sources
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-input-sources-applet/)

* [Pop OS/COSMIC Applets Desktop
Entries](https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/)

* [Pop OS/COSMIC App List
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-app-list/)

* [Pop OS/COSMIC Battery
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/)

* [Pop OS/COSMIC Bluetooth
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/)

* [Pop OS/COSMIC Workspaces
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-workspaces-applet/)

* [Pop OS/COSMIC Tiling
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-tiling/)

* [Pop OS/COSMIC Notifications
Applet](https://hosted.weblate.org/projects/pop-os/cosmic-applet-notifications/)



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pop-os/cosmic-applet-audio/horizontal-auto.svg)
2026-07-28 16:44:41 +02:00
Hosted Weblate
7ef0084a24
i18n: translation updates from weblate
Co-authored-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
Co-authored-by: Ahrakiel <christopherbatrier@gmail.com>
Co-authored-by: Aman Alam <aalam@users.noreply.hosted.weblate.org>
Co-authored-by: Aman Shaw <shaw4m4n@netc.fr>
Co-authored-by: Andi Chandler <andi@gowling.com>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: AriyA66Y <ariya66y@protonmail.com>
Co-authored-by: CYAXXX <85353920+CYAXXX@users.noreply.github.com>
Co-authored-by: Ettore Atalan <atalanttore@googlemail.com>
Co-authored-by: Fedorov Alexei <aleksejfedorov963@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Isaac Subirana <isaacsubiranac@gmail.com>
Co-authored-by: Jim Spentzos <jimspentzos2000@gmail.com>
Co-authored-by: Kartik Nayak <65574961+kodebarista@users.noreply.github.com>
Co-authored-by: Nara Díaz Viñolas <nara.diaz.vinolas@gmail.com>
Co-authored-by: Prasanta-Hembram <Prasantahembram720@gmail.com>
Co-authored-by: Saeed <s.zare.org.82@gmail.com>
Co-authored-by: Sproston <ojspr2007@gmail.com>
Co-authored-by: Tadas Misiūnas <tadujo@gmail.com>
Co-authored-by: VandaL <vandalhj@gmail.com>
Co-authored-by: Vilius Paliokas <viliuspaliokas@gmail.com>
Co-authored-by: Wilbur Lindqvist <william@willmantrade.com>
Co-authored-by: jonnysemon <jonnysemon@users.noreply.hosted.weblate.org>
Co-authored-by: lorduskordus <lorduskordus@gmail.com>
Co-authored-by: sicKat <giuseppecatillo2003@gmail.com>
Co-authored-by: taijuin Lee <taijuin@gmail.com>
Co-authored-by: therealmate <hellogaming91@gmail.com>
Co-authored-by: Димко <Dymkovych@proton.me>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/ar/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/cs/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/el/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/fa/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/hi/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/hu/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/lt/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/pa/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/pl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/ru/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/uk/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-app-list/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/fa/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/hi/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-a11y/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/lt/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-audio/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-battery/kmr/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/fa/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/hi/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-bluetooth/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/fr/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/sat/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-network/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-notifications/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-power/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-power/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-tiling/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-tiling/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-time/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applet-time/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/cs/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/en_GB/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/fa/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/hi/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/hu/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/it/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-applets-desktop-entries/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-input-sources-applet/ca/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-input-sources-applet/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-workspaces-applet/ca/
Translation: Pop OS/COSMIC Accessibility Applet
Translation: Pop OS/COSMIC App List Applet
Translation: Pop OS/COSMIC Applets Desktop Entries
Translation: Pop OS/COSMIC Audio Applet
Translation: Pop OS/COSMIC Battery Applet
Translation: Pop OS/COSMIC Bluetooth Applet
Translation: Pop OS/COSMIC Input Sources Applet
Translation: Pop OS/COSMIC Network Applet
Translation: Pop OS/COSMIC Notifications Applet
Translation: Pop OS/COSMIC Power Applet
Translation: Pop OS/COSMIC Tiling Applet
Translation: Pop OS/COSMIC Time Applet
Translation: Pop OS/COSMIC Workspaces Applet
2026-07-28 08:03:20 +00:00
Akrm Al-Hakimi
48c3633151 fix(network): re-register secret agent after NetworkManager restart 2026-07-17 16:59:55 +02:00
Hojjat
e544cb54c2 chore: update libcosmic to fix minimize applet crash 2026-07-13 17:17:24 -06:00
Ian Douglas Scott
d86c5631ed input-sources: Do not store full CosmicCompConfig
`update_xkb()` was previously never called before the subscription first
returns a config value, so not getting an initial value of `comp_config`
at start before the subscription does not change behavior.
2026-07-13 13:18:56 -07:00
Ian Douglas Scott
9acfd8d8c1 input-sources: Use cosmic-keyboard-layout-unstable-v1
https://github.com/pop-os/cosmic-protocols/pull/28

Continues to use `xkg_config` to get list of layouts, but the group is
now changed by modifying the group while leaving the config unchanged.
And changes to the group are now reflected in the applet.
2026-07-13 13:18:56 -07:00
Akrm Al-Hakimi
ba490e76af fix: normalize connections that match saved VPN profiles 2026-07-10 16:59:47 -06:00
Akrm Al-Hakimi
67415262d5 fix: show pending VPN state in applet
Track VPN activation and deactivation locally while nmrs operations are
running. This lets the applet show a spinner immediately, refresh state
while NetworkManager settles, and clear pending state on completion or
error.

Also use VPN-specific icons for VPN rows and prefer active or pending VPN
state for the panel icon.
2026-07-10 16:59:47 -06:00
Akrm Al-Hakimi
9025430cf2 fix: keep inactive known Wi-Fi rows visible
Only mark an nmrs Wi-Fi group as activated when the group itself is
active. Access points inherit device state, so inactive known networks on
a connected Wi-Fi device can otherwise appear activated and get skipped
from the known networks section while also being filtered out of visible
networks.
2026-07-10 16:59:47 -06:00
Akrm Al-Hakimi
829d66c44a fix: filter ssids by raw bytes to remove hidden network entries 2026-07-10 16:59:47 -06:00
akrm al-hakimi
74e2908987 chore: remove dead arm in DeviceState match 2026-07-10 16:59:47 -06:00
akrm al-hakimi
6fd8309cf7 chore: remove dead utils file 2026-07-10 16:59:47 -06:00
akrm al-hakimi
f69e943d91 fix(network): restore IPv4 display and wifi list ordering
- Strip the CIDR suffix (/24) from the shown IPv4 address
- Sort visible wireless networks by signal strength again
- Filter out empty-SSID "hidden network" entries from the list
2026-07-10 16:59:47 -06:00
Akrm Al-Hakimi
a3be51560f fix: dupe connection names; incorrect ipv6 labeling
Fixes a bug where we showed `Activated` networks after the current active
one.

Also ipv4/6 addresses were merged so this seperates them and only shows ipv4
for now until we decide the best way to show both, UI/UX wise.
2026-07-10 16:59:47 -06:00
Akrm Al-Hakimi
e318f0d412 cosmic-applet-network: migrate NetworkManager flow to nmrs 3.4 2026-07-10 16:59:47 -06:00
Hojjat
b282484463 chore: update libcosmic to fix minimize applet crash 2026-07-10 00:18:30 -06:00
Ashley Wulber
9621be48b3 chore: update libcosmic 2026-07-09 17:48:08 -06:00
Ashley Wulber
3f4d0f43a0
fix: update iced (#1468)
popup blur & corner cleanup
2026-07-09 09:42:22 -06:00
Jeremy Soller
0543dd7441
Theme v2 (#1455) 2026-07-06 07:12:26 -06:00
Ashley Wulber
69d358ec34 chore: cleanup and update deps 2026-07-01 23:26:15 -04:00
Ashley Wulber
1472f82061 chore: fix popup corners and doubled opacity 2026-06-30 13:17:39 -04:00
Ashley Wulber
7f4b1ab7be chore: update deps 2026-06-30 13:17:39 -04:00
Ashley Wulber
065551ed1b chore: update libcosmic 2026-06-30 13:17:39 -04:00
Ashley Wulber
74b6202686 fix: right click popup corners 2026-06-30 13:17:39 -04:00
Ashley Wulber
f0ca9e7aee chore: update libcosmic 2026-06-30 13:17:39 -04:00
Ashley Wulber
de1884e032 chore: update deps 2026-06-30 13:17:39 -04:00
Ashley Wulber
405fddda2d wip: blur 2026-06-30 13:17:37 -04:00
119 changed files with 2107 additions and 1222 deletions

1042
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -75,13 +75,9 @@ ignored = ["libcosmic"]
# cosmic-config = { path = "../libcosmic/cosmic-config" }
# libcosmic = { path = "../libcosmic" }
# iced_futures = { path = "../libcosmic/iced/futures" }
# cosmic-config = { git = "https://github.com/pop-os/libcosmic//" }
# libcosmic = { git = "https://github.com/pop-os/libcosmic//" }
# iced_futures = { git = "https://github.com/pop-os/libcosmic//" }
# [patch."https://github.com/pop-os/winit.git"]
# winit = { git = "https://github.com/rust-windowing/winit.git", rev = "241b7a80bba96c91fa3901729cd5dec66abb9be4" }
# winit = { path = "../winit" }
# cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
# libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
# iced_futures = { git = "https://github.com/pop-os/libcosmic//", branch = "theme-v2" }
[patch."https://github.com/pop-os/libcosmic"]
cosmic-config = { path = "/home/lionel/Projets/COSMIC/libcosmic/cosmic-config" }

View file

@ -1,6 +1,6 @@
cosmic-app-list = دُرج التطبيقات
pin = ثبِّت في درج التطبيقات
quit = أنهِ
quit = إنهِ
quit-all = أنهِ الكل
new-window = نافذة جديدة
run = شغِّل

View file

@ -1,5 +1,5 @@
cosmic-app-list = Panel aplikací
pin = Připnout do panelu aplikací
cosmic-app-list = Oblast aplikací
pin = Připnout do oblasti aplikací
quit = Ukončit
quit-all = Ukončit vše
new-window = Nové okno

View file

@ -0,0 +1,8 @@
run = Kør
run-on = Kør på { $gpu }
run-on-default = (Standard)
cosmic-app-list = Programbakke
new-window = Nyt Vindue
quit = Afslut
quit-all = Forlad Alle
pin = Fastgør til app-skuffe

View file

@ -1,5 +1,5 @@
new-window = Νέο παράθυρο
quit = Έξοδος
quit = Τερματισμός
cosmic-app-list = Περιοχή εφαρμογών
run = Εκτέλεση
run-on = Εκτέλεση με { $gpu }

View file

@ -0,0 +1,8 @@
cosmic-app-list = App Tray
new-window = New Window
quit = Quit
run = Run
run-on = Run on { $gpu }
quit-all = Quit All
run-on-default = (Default)
pin = Pin to app tray

View file

@ -1,8 +1,8 @@
cosmic-app-list = سینی برنامه‌ها
pin = سنجاق کردن به سینی برنامه‌ها
quit = بستن
quit-all = بستن همه
cosmic-app-list = نوار برنامه‌ها
pin = افزودن به نوار برنامه‌ها
quit = خروج
quit-all = خروج از همه
new-window = پنجره جدید
run = اجرا
run-on = اجرا روی {$gpu}
run-on-default = (پیش‌فرض)
run-on = اجرا با { $gpu }
run-on-default = (پیش‌فرض)

View file

@ -0,0 +1,8 @@
quit = Pechar
run = Executar
cosmic-app-list = Bandexa de aplicacións
pin = Fixar na bandexa de aplicacións
quit-all = Quitar todo
new-window = Nova Xanela
run-on = Executar en { $gpu }
run-on-default = (Por defecto)

View file

@ -1,8 +1,8 @@
cosmic-app-list = ऐप ट्रे
pin = ऐप ट्रे में पिन करें
quit = बंद करें
quit = बाहर जाएँ
quit-all = सभी बंद करें
new-window = नई विंडो
run = चलाएँ
run-on = {$gpu} पर चलाएँ
run-on = { $gpu } पर चलाएँ
run-on-default = (डिफ़ॉल्ट)

View file

@ -1,8 +1,8 @@
cosmic-app-list = Barra applicazioni
cosmic-app-list = Area applicazioni
pin = Fissa nella barra delle applicazioni
quit = Esci
quit-all = Chiudi tutto
new-window = Nuova finestra
run = Esegui
run-on = Esegui usando la GPU: { $gpu }
run-on-default = (default)
run-on = Esegui su { $gpu }
run-on-default = (Predefinito)

View file

@ -1,5 +1,5 @@
new-window = Naujas Langas
quit = Išeiti
quit = Išjungti
run = Paleisti
run-on = Paleisti naudojantis { $gpu }
run-on-default = (Numatytas)

View file

@ -0,0 +1 @@
cosmic-app-list = Cinta d’aplicacions

View file

@ -1,4 +1,4 @@
quit = ਬਾਹਰ
quit = ਸਮਾਪਤ
cosmic-app-list = ਐਪ ਟਰੇ
pin = ਐਪ ਟਰੇ ਵਿੱਚ ਟੰਗੋ
quit-all = ਸਭ ਵਿੱਚੋਂ ਬਾਹਰ

View file

@ -1,6 +1,6 @@
cosmic-app-list = Zasobnik aplikacji
pin = Przypnij do zasobnika aplikacji
quit = Zamknij
quit = Zakończ
quit-all = Zamknij wszystkie
new-window = Nowe okno
run = Uruchom

View file

@ -1,6 +1,6 @@
cosmic-app-list = Bandeja de aplicativos
pin = Fixar na bandeja de aplicativos
quit = Sair
quit = Encerrar
quit-all = Sair de Todos
new-window = Nova Janela
run = Executar

View file

@ -1,6 +1,6 @@
cosmic-app-list = Область приложений
pin = Закрепить на панели приложений
quit = Выйти
quit = Завершить
quit-all = Завершить все
new-window = Новое окно
run = Выполнить

View file

@ -0,0 +1,2 @@
run-on = { $gpu } ᱨᱮ ᱫᱟᱹᱲ ᱟᱭ
run-on-default = (ᱢᱩᱞ)

View file

@ -1,6 +1,6 @@
cosmic-app-list = Панель застосунків
pin = Закріпити
quit = Вийти
quit = Завершити
quit-all = Закрити всі
new-window = Нове вікно
run = Виконати

View file

@ -1,8 +1,8 @@
cosmic-app-list = 應用程式匣盤
pin = 釘選至應用程式匣盤
quit = 退出
cosmic-app-list = 應用程式托盤
pin = 釘選至應用程式托盤
quit = 結束
quit-all = 全部退出
new-window = 新建視窗
new-window = 新增視窗
run = 執行
run-on = 在 { $gpu } 上執行
run-on-default = (預設)

View file

@ -28,25 +28,28 @@ use cosmic::{
},
cosmic_config::{Config, CosmicConfigEntry},
desktop::IconSourceExt,
iced::runtime::{core::event, dnd::peek_dnd},
iced::{
self, Alignment, Background, Border, Length, Limits, Padding, Subscription,
advanced::text::{Ellipsize, EllipsizeHeightLimit},
clipboard::mime::{AllowedMimeTypes, AsMimeTypes},
event::listen_with,
platform_specific::shell::commands::popup::{destroy_popup, get_popup},
runtime::{core::event, dnd::peek_dnd, platform_specific::wayland::CornerRadius},
widget::{
Column, Row, column, mouse_area, row, rule::vertical as vertical_rule,
space::horizontal as horizontal_space, space::vertical as vertical_space, stack,
Column, Row, column, mouse_area, row,
rule::vertical as vertical_rule,
space::{horizontal as horizontal_space, vertical as vertical_space},
stack,
},
window,
},
surface,
surface::{self, action::LiveSettings},
theme::{self, Button, Container},
widget::{
DndDestination, Image, button, container, divider, dnd_source, grid,
icon::{self, from_name},
image::Handle,
menu,
rectangle_tracker::{RectangleTracker, RectangleUpdate, rectangle_tracker_subscription},
scrollable, svg, text, text_input,
},
@ -1249,44 +1252,54 @@ impl cosmic::Application for CosmicAppList {
.iter()
.chain(self.pinned_list.iter())
.find(|t| t.id == id)
.cloned()
{
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()) else {
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()).copied()
else {
tracing::error!("No rectangle found for toplevel group");
return Task::none();
};
let corners = self.core.system_theme().cosmic().corner_radii.radius_s;
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
move |_| LiveSettings::default(),
move |app: &mut Self| {
let new_id = window::Id::unique();
app.popup = Some(Popup {
parent: parent_window_id,
id: new_id,
dock_item: toplevel_group.clone(),
popup_type: PopupType::RightClickMenu,
});
let new_id = window::Id::unique();
self.popup = Some(Popup {
parent: parent_window_id,
id: new_id,
dock_item: toplevel_group.clone(),
popup_type: PopupType::RightClickMenu,
});
let mut popup_settings = self.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = *rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let mut popup_settings = app.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
popup_settings
},
None,
));
let gpu_update = Task::perform(try_get_gpus(), |gpus| {
cosmic::Action::App(Message::GpuRequest(gpus))
});
return Task::batch([gpu_update, get_popup(popup_settings)]);
return Task::batch([gpu_update, popup_task]);
}
}
Message::ToplevelListPopup(id, parent_window_id) => {
@ -1317,10 +1330,10 @@ impl cosmic::Application for CosmicAppList {
}
}
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()) else {
let Some(rectangle) = self.rectangles.get(&toplevel_group.id.into()).copied()
else {
return Task::none();
};
let new_id = window::Id::unique();
self.popup = Some(Popup {
parent: parent_window_id,
@ -1328,48 +1341,56 @@ impl cosmic::Application for CosmicAppList {
dock_item: toplevel_group.clone(),
popup_type: PopupType::ToplevelList,
});
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let max_windows = 7.0;
let window_spacing = 8.0;
popup_settings.positioner.size_limits = match app.core.applet.anchor
{
PanelAnchor::Right | PanelAnchor::Left => Limits::NONE
.min_width(100.0)
.min_height(30.0)
.max_width(window_spacing * 2.0 + TOPLEVEL_BUTTON_WIDTH)
.max_height(
TOPLEVEL_BUTTON_HEIGHT * max_windows
+ window_spacing * (max_windows + 1.0),
),
PanelAnchor::Bottom | PanelAnchor::Top => Limits::NONE
.min_width(30.0)
.min_height(100.0)
.max_width(
TOPLEVEL_BUTTON_WIDTH * max_windows
+ window_spacing * (max_windows + 1.0),
)
.max_height(window_spacing * 2.0 + TOPLEVEL_BUTTON_HEIGHT),
};
popup_settings
},
None,
));
let mut popup_settings = self.core.applet.get_popup_settings(
parent_window_id,
new_id,
None,
None,
None,
);
let iced::Rectangle {
x,
y,
width,
height,
} = *rectangle;
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let max_windows = 7.0;
let window_spacing = 8.0;
popup_settings.positioner.size_limits = match self.core.applet.anchor {
PanelAnchor::Right | PanelAnchor::Left => Limits::NONE
.min_width(100.0)
.min_height(30.0)
.max_width(window_spacing * 2.0 + TOPLEVEL_BUTTON_WIDTH)
.max_height(
TOPLEVEL_BUTTON_HEIGHT * max_windows
+ window_spacing * (max_windows + 1.0),
),
PanelAnchor::Bottom | PanelAnchor::Top => Limits::NONE
.min_width(30.0)
.min_height(100.0)
.max_width(
TOPLEVEL_BUTTON_WIDTH * max_windows
+ window_spacing * (max_windows + 1.0),
)
.max_height(window_spacing * 2.0 + TOPLEVEL_BUTTON_HEIGHT),
};
return get_popup(popup_settings);
return popup_task;
}
}
Message::ToplevelHoverChanged(handle, entering) => {
@ -2148,52 +2169,63 @@ impl cosmic::Application for CosmicAppList {
if create_new {
let new_id = window::Id::unique();
self.overflow_active_popup = Some(new_id);
let rectangle = self.rectangles.get(&DockItemId::ActiveOverflow);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
if let Some(iced::Rectangle {
let Some(iced::Rectangle {
x,
y,
width,
height,
}) = rectangle
{
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: *x as i32,
y: *y as i32,
width: *width as i32,
height: *height as i32,
};
}
let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).0;
let (_favorite_popup_cutoff, active_popup_cutoff) =
self.panel_overflow_lengths();
let popup_applet_count =
self.active_list.len().saturating_sub(
(active_popup_cutoff.unwrap_or_default()).saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32 * popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
}) = self.rectangles.get(&DockItemId::ActiveOverflow).copied()
else {
return Task::none();
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
cmds.push(get_popup(popup_settings));
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let applet_suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).0;
let (_favorite_popup_cutoff, active_popup_cutoff) =
app.panel_overflow_lengths();
let popup_applet_count = app.active_list.len().saturating_sub(
(active_popup_cutoff.unwrap_or_default()).saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32
* popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match app.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
popup_settings
},
None,
));
cmds.push(popup_task);
}
return Task::batch(cmds);
}
@ -2205,52 +2237,63 @@ impl cosmic::Application for CosmicAppList {
if create_new {
let new_id = window::Id::unique();
self.overflow_favorites_popup = Some(new_id);
let rectangle = self.rectangles.get(&DockItemId::FavoritesOverflow);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
if let Some(iced::Rectangle {
let Some(iced::Rectangle {
x,
y,
width,
height,
}) = rectangle
{
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: *x as i32,
y: *y as i32,
width: *width as i32,
height: *height as i32,
};
}
let applet_suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).0;
let (favorite_popup_cutoff, _active_popup_cutoff) =
self.panel_overflow_lengths();
let popup_applet_count =
self.pinned_list.len().saturating_sub(
favorite_popup_cutoff.unwrap_or_default().saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32 * popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
}) = self.rectangles.get(&DockItemId::FavoritesOverflow).copied()
else {
return Task::none();
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
cmds.push(get_popup(popup_settings));
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = iced::Rectangle::<i32> {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
};
let applet_suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).0;
let (favorite_popup_cutoff, _active_popup_cutoff) =
app.panel_overflow_lengths();
let popup_applet_count = app.pinned_list.len().saturating_sub(
favorite_popup_cutoff.unwrap_or_default().saturating_sub(1),
) as f32;
let popup_applet_size = applet_suggested_size as f32
* popup_applet_count
+ 4.0 * (popup_applet_count - 1.);
let (max_width, max_height) = match app.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => {
(popup_applet_size, applet_suggested_size as f32)
}
PanelAnchor::Left | PanelAnchor::Right => {
(applet_suggested_size as f32, popup_applet_size)
}
};
popup_settings.positioner.size_limits = Limits::NONE
.max_width(max_width)
.min_width(1.)
.max_height(max_height)
.min_height(1.);
popup_settings
},
None,
));
cmds.push(popup_task);
}
return Task::batch(cmds);
}
@ -2660,7 +2703,8 @@ impl cosmic::Application for CosmicAppList {
.width(Length::Fill)
}
let mut content = column![].align_x(Alignment::Center);
let mut content =
menu::menu_column::MenuColumn::with_capacity(4).align_x(Alignment::Center);
if let Some(exec) = desktop_info.exec() {
if !toplevels.is_empty() {
@ -2784,22 +2828,6 @@ impl cosmic::Application for CosmicAppList {
.popup_container(
container(content)
.padding(1)
//TODO: move style to libcosmic
.class(theme::Container::custom(|theme| {
let cosmic = theme.cosmic();
let component = &cosmic.background(false).component;
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().into(),
width: 1.0,
color: component.divider.into(),
},
..Default::default()
}
}))
.height(Length::Shrink)
.width(Length::Fill),
)

View file

@ -0,0 +1,6 @@
magnifier = Lupa
screen-reader = Narrador
invert-colors = Colors invertits
settings = Configuració d'accessibilitat...
filter-colors = Filtres de colors
high-contrast = Mode d'alt contrast

View file

@ -0,0 +1,6 @@
screen-reader = Skærmlæser
invert-colors = Invertér farver
high-contrast = Høj kontrast
filter-colors = Filtrér farver
settings = Tilgængelighedsindstillinger...
magnifier = Forstørrelsesglas

View file

@ -1,6 +1,6 @@
screen-reader = Bildschirmleser
magnifier = Vergrößerungsglas
invert-colors = Farben invertieren
settings = Barrierefreiheitseinstellungen…
settings = Barrierefreiheitseinstellungen ...
filter-colors = Farben filtern
high-contrast = Hoher Kontrast

View file

@ -0,0 +1,6 @@
screen-reader = Screen reader
invert-colors = Invert colours
high-contrast = High contrast
filter-colors = Filter colours
settings = Accessibility settings...
magnifier = Magnifier

View file

@ -1,6 +1,6 @@
screen-reader = صفحه‌خوان
magnifier = ذره‌بین
invert-colors = وارونه‌سازی رنگ‌ها
invert-colors = وارونه کردن رنگ‌ها
settings = تنظیمات دسترسی‌پذیری...
filter-colors = فیلتر رنگ‌ها
high-contrast = کنتراست بالا

View file

@ -0,0 +1,6 @@
screen-reader = Lector de pantalla
magnifier = Lupa
invert-colors = Invertir cores
settings = Configuración de accesibilidade...
filter-colors = Filtro de cores
high-contrast = Alto contraste

View file

@ -1,4 +1,6 @@
screen-reader = स्क्रीन रीडर
filter-colors = रंग फ़िल्टर
settings = सुलभता सेटिंग..।
magnifier = आवर्धक
filter-colors = रंग फ़िल्टर करें
settings = एक्सेसिबिलिटी सेटिंग्स..।
magnifier = मैग्नीफायर
high-contrast = उच्च कंट्रास्ट
invert-colors = रंग उल्टे करें

View file

@ -2,5 +2,5 @@ screen-reader = Lettore dello schermo
magnifier = Lente di ingrandimento
invert-colors = Inverti colori
settings = Impostazioni accessibilità...
filter-colors = Filtra colori
filter-colors = Filtri colore
high-contrast = Contrasto elevato

View file

@ -0,0 +1,2 @@
screen-reader = ᱥᱠᱨᱤᱱ ᱨᱤᱰᱟᱨ
invert-colors = ᱨᱚᱝ ᱩᱞᱴᱟᱹ ᱪᱷᱚ

View file

@ -133,20 +133,27 @@ impl cosmic::Application for CosmicA11yApplet {
}
Message::TogglePopup => {
if let Some(p) = self.popup.take() {
return destroy_popup(p);
return cosmic::surface::surface_task(cosmic::surface::action::destroy_popup(
p,
));
} else {
let new_id = window::Id::unique();
self.popup.replace(new_id);
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut CosmicA11yApplet| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
None,
None,
);
popup_settings
},
None,
None,
);
return get_popup(popup_settings);
));
}
}
Message::CloseRequested(id) => {

View file

@ -0,0 +1,7 @@
output = Sortida
show-media-controls = Mostra els controls multimèdia a la barra
disconnected = PulseAudio desconnectat
no-device = No s'ha seleccionat cap dispositiu
input = Entrada
unknown-artist = Desconegut
sound-settings = Configuració de so...

View file

@ -0,0 +1,7 @@
show-media-controls = Vis mediekontrol på panel
disconnected = PulseAudio Afbrudt
no-device = Ingen enhed valgt
input = Indgang
output = Udgang
unknown-artist = Ukendt
sound-settings = Lydindstillinger...

View file

@ -1,7 +1,7 @@
output = Ausgabe
input = Eingabe
show-media-controls = Mediensteuerung im Panel anzeigen
sound-settings = Klang-Einstellungen...
sound-settings = Klang-Einstellungen ...
disconnected = PulseAudio getrennt
no-device = Kein Gerät ausgewählt
unknown-artist = Unbekannt

View file

@ -0,0 +1,7 @@
show-media-controls = Show media controls on panel
disconnected = PulseAudio Disconnected
no-device = No device selected
input = Input
output = Output
unknown-artist = Unknown
sound-settings = Sound Settings...

View file

@ -0,0 +1,7 @@
output = Saída
input = Entrada
show-media-controls = Mostrar os controis multimedia no panel
sound-settings = Axustes do son...
disconnected = PulseAudio Desconectado
no-device = Ningún dipositivo seleccionado
unknown-artist = Descoñecido

View file

@ -4,4 +4,4 @@ show-media-controls = Mostra controlli multimediali nel pannello in alto
sound-settings = Impostazioni audio...
disconnected = PulseAudio Disconnesso
no-device = Nessun dispositivo selezionato
unknown-artist = Sconosciuto
unknown-artist = Sconosciuto

View file

@ -4,4 +4,4 @@ no-device = Nepasirinktas įrenginys
input = Įvestis
output = Išvestis
unknown-artist = Nežinomas atlikėjas
sound-settings = Garso Nustatymai...
sound-settings = Garso Nuostatos...

View file

@ -0,0 +1 @@
output = ᱟᱨᱡᱟᱣ

View file

@ -33,10 +33,15 @@ use cosmic::{
};
use cosmic_settings_audio_client::{self as audio_client, CosmicAudioProxy};
use futures::SinkExt;
use iced::platform_specific::shell::wayland::commands::popup::{destroy_popup, get_popup};
use mpris_subscription::{MprisRequest, MprisUpdate};
use mpris2_zbus::player::PlaybackStatus;
use std::{cell::RefCell, rc::Rc, sync::Arc};
use std::{
sync::{
Arc,
atomic::{self, AtomicU32},
},
time::Duration,
};
mod config;
mod mpris_subscription;
@ -58,11 +63,15 @@ pub struct Audio {
/// Track the applet's popup window.
popup: Option<window::Id>,
/// Varlink connection to `com.system76.CosmicSettings.Audio`.
audio_client: Option<Rc<RefCell<audio_client::Client>>>,
audio_client: Option<audio_client::Client>,
/// Known audio device state
model: model::Model,
/// Whether to expand the revealer of a source or sink device.
is_open: IsOpen,
/// Used to debounce sink volume updates.
applied_sink_volume: Arc<AtomicU32>,
/// Used to deboune source volume updates.
applied_source_volume: Arc<AtomicU32>,
/// Max slider volume for the sink device, as determined by the amplification property.
max_sink_volume: u32,
/// Max slider volume for the source device, as determined by the amplification property.
@ -140,26 +149,27 @@ enum IsOpen {
pub enum Message {
/// Connection to `com.system76.CosmicSettings`.
Client(Arc<audio_client::Client>),
Ignore,
SetSinkVolume(u32),
SetSourceVolume(u32),
ToggleSinkMute,
ToggleSourceMute,
SetDefaultSink(usize),
SetDefaultSource(usize),
OutputToggle,
InputToggle,
TogglePopup,
CloseRequested(window::Id),
ToggleMediaControlsInTopPanel(bool),
ConfigChanged(AudioAppletConfig),
Ignore,
InputToggle,
Mpris(mpris_subscription::MprisUpdate),
MprisRequest(MprisRequest),
Token(TokenUpdate),
OpenSettings,
OutputToggle,
ReattachClient(Arc<audio_client::Client>),
Rectangle(RectangleUpdate<u32>),
SetDefaultSink(usize),
SetDefaultSource(usize),
SetSinkVolume(u32),
SetSourceVolume(u32),
Subscription(audio_client::Event),
Surface(surface::Action),
Rectangle(RectangleUpdate<u32>),
ToggleMediaControlsInTopPanel(bool),
TogglePopup,
ToggleSinkMute,
ToggleSourceMute,
Token(TokenUpdate),
}
// TODO
@ -302,32 +312,45 @@ impl cosmic::Application for Audio {
self.rectangle_tracker.replace(tracker);
}
},
Message::ReattachClient(client) => {
if let Some(client) = Arc::into_inner(client) {
self.audio_client = Some(client);
}
}
Message::Ignore => {}
Message::TogglePopup => {
if let Some(p) = self.popup.take() {
return destroy_popup(p);
return cosmic::surface::surface_task(cosmic::surface::action::destroy_popup(
p,
));
} else {
let new_id = window::Id::unique();
self.popup.replace(new_id);
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
self.refresh_volume_limits();
app.refresh_volume_limits();
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
if let Some(r) = app.rectangle {
popup_settings.positioner.anchor_rect = Rectangle {
x: r.x as i32,
y: r.y as i32,
width: r.width as i32,
height: r.height as i32,
};
}
popup_settings
},
None,
None,
None,
);
if let Some(r) = self.rectangle {
popup_settings.positioner.anchor_rect = Rectangle {
x: r.x as i32,
y: r.y as i32,
width: r.width as i32,
height: r.height as i32,
};
}
return get_popup(popup_settings);
));
}
}
@ -355,7 +378,7 @@ impl cosmic::Application for Audio {
&& let Some(client) = self.audio_client.as_mut()
{
futures::executor::block_on(async {
_ = client.borrow_mut().conn.set_default(node_id, true).await;
_ = client.conn.set_default(node_id, true).await;
});
}
}
@ -366,7 +389,7 @@ impl cosmic::Application for Audio {
&& let Some(client) = self.audio_client.as_mut()
{
futures::executor::block_on(async {
_ = client.borrow_mut().conn.set_default(node_id, true).await;
_ = client.conn.set_default(node_id, true).await;
});
}
}
@ -374,7 +397,7 @@ impl cosmic::Application for Audio {
Message::ToggleSinkMute => {
if let Some(ref mut client) = self.audio_client {
futures::executor::block_on(async {
_ = client.borrow_mut().conn.sink_mute_toggle().await;
_ = client.conn.sink_mute_toggle().await;
});
}
}
@ -382,27 +405,43 @@ impl cosmic::Application for Audio {
Message::ToggleSourceMute => {
if let Some(ref mut client) = self.audio_client {
futures::executor::block_on(async {
_ = client.borrow_mut().conn.source_mute_toggle().await;
_ = client.conn.source_mute_toggle().await;
});
}
}
Message::SetSinkVolume(volume) => {
if let Some(ref mut client) = self.audio_client {
self.model.active_sink.volume = volume;
self.model.active_sink.volume_text = volume.to_string();
futures::executor::block_on(async {
_ = client.borrow_mut().conn.set_sink_volume(volume).await;
self.applied_sink_volume
.store(volume, atomic::Ordering::Relaxed);
self.model.active_sink.volume = volume;
self.model.active_sink.volume_text = volume.to_string();
if let Some(mut client) = self.audio_client.take() {
let volume = Arc::clone(&self.applied_sink_volume);
return cosmic::Task::future(async move {
tokio::time::sleep(Duration::from_millis(128)).await;
_ = client
.conn
.set_sink_volume(volume.load(atomic::Ordering::Relaxed))
.await;
Message::ReattachClient(Arc::new(client)).into()
});
}
}
Message::SetSourceVolume(volume) => {
if let Some(ref mut client) = self.audio_client {
self.model.active_source.volume = volume;
self.model.active_source.volume_text = volume.to_string();
futures::executor::block_on(async {
_ = client.borrow_mut().conn.set_source_volume(volume).await;
self.applied_source_volume
.store(volume, atomic::Ordering::Relaxed);
self.model.active_source.volume = volume;
self.model.active_source.volume_text = volume.to_string();
if let Some(mut client) = self.audio_client.take() {
let volume = Arc::clone(&self.applied_source_volume);
return cosmic::Task::future(async move {
tokio::time::sleep(Duration::from_millis(128)).await;
_ = client
.conn
.set_sink_volume(volume.load(atomic::Ordering::Relaxed))
.await;
Message::ReattachClient(Arc::new(client)).into()
});
}
}
@ -513,7 +552,7 @@ impl cosmic::Application for Audio {
}
Message::Client(client) => {
if let Some(client) = Arc::into_inner(client) {
self.audio_client = Some(Rc::new(RefCell::new(client)));
self.audio_client = Some(client);
self.model = model::Model::default();
}
}

View file

@ -0,0 +1,14 @@
power-settings = Strøm- og Batteriindstillinger...
hours = t
until-empty = indtil tom
battery-desc = Reduceret strømforbrug og ydeevne.
max-charge = Forøg dit batteris levetid, ved at angive en maksimal opladningsværdi på 80%
balanced = Balanceret
battery = Batteri
seconds = s
dgpu-running = Diskret GPU er aktiv og kan reducere batterilevetiden
performance = Høj Ydeevne
performance-desc = Høj ydeevne og strømforbrug.
minutes = m
balanced-desc = Standard ydeevne og batteriforbrug.
dgpu-applications = Applikationer som bruger { $gpu_name } diskret GPU

View file

@ -9,6 +9,6 @@ seconds = s
minutes = m
hours = h
until-empty = bis leer
power-settings = Energie- und Akkueinstellungen...
power-settings = Energie- und Akkueinstellungen ...
dgpu-running = Dedizierte GPU ist aktiv und kann die Akkulaufzeit reduzieren
dgpu-applications = Anwendungen, welche die dedizierte GPU { $gpu_name } nutzen

View file

@ -0,0 +1,14 @@
power-settings = Power & Battery settings...
hours = h
until-empty = until empty
battery-desc = Reduced power usage and performance.
max-charge = Increase the lifespan of your battery by setting a maximum charge value of 80%
balanced = Balanced
battery = Battery
seconds = s
dgpu-running = Discrete GPU is active and can reduce battery life
performance = High Performance
performance-desc = High performance and power usage.
minutes = m
balanced-desc = Standard performance and battery usage.
dgpu-applications = Applications using { $gpu_name } discrete GPU

View file

@ -0,0 +1,14 @@
battery = Batería
battery-desc = Reduce o consumo de enerxía e o rendemento.
balanced = Balanceado
balanced-desc = Rendemento e consumo de batería estándar.
performance = Alto rendemento
performance-desc = Alto rendemento e maior consumo de enerxía.
max-charge = Aumenta a vida útil da batería limitando a carga máxima ao 80 %
seconds = s
minutes = m
hours = h
until-empty = ata baleirar
power-settings = Axustes de enexía e batería...
dgpu-running = A GPU dedicada está activa e pode reducir a duración da batería
dgpu-applications = Aplicacións que están a usar a GPU dedicada { $gpu_name }

View file

@ -1,14 +1,14 @@
battery = Risparmio energetico
battery-desc = Consumi minimi, performance ridotta.
balanced = Bilanciato
balanced-desc = Consumi bilanciati, performance dinamica.
performance = Performance
performance-desc = Consumi alti, performance massima.
max-charge = Migliora la durata di vita della batteria caricandola fino all'80%
battery = Batteria
battery-desc = Prestazioni e consumo energetico ridotti.
balanced = Equilibrato
balanced-desc = Prestazioni e consumo energetico normali.
performance = Prestazioni elevate
performance-desc = Prestazioni elevate e consumo energetico.
max-charge = Aumenta la durata della batteria impostando un valore massimo di carica dell’80%
seconds = s
minutes = m
hours = h
until-empty = fino alla scarica
until-empty = finché non è vuoto
power-settings = Impostazioni energetiche...
dgpu-running = La GPU discreta è attiva e può ridurre la durata della batteria
dgpu-applications = Applicazioni che stanno usando la GPU discreta { $gpu_name }

View file

@ -2,7 +2,7 @@ battery = Betarî
seconds = ç
minutes = x
hours = d
until-empty = Heya vala dibe
until-empty = heya vala dibe
power-settings = Sazkariyên hêz û betariyê...
battery-desc = Bikaranîna hêzê kêmkirî û performans.
balanced = Hevseng

View file

@ -1,14 +1,14 @@
battery = Bateria
battery = Economia de energia
battery-desc = Uso reduzido de energia e desempenho limitado.
balanced = Balanceado
balanced-desc = Desempenho padrão e uso de bateria moderado.
performance = Alto Desempenho
performance = Alto desempenho
performance-desc = Máximo desempenho e alto uso de energia.
max-charge = Aumente a vida útil da sua bateria definindo um valor máximo de carga de 80%
seconds = s
minutes = m
hours = h
until-empty = até esvaziar
until-empty = até ficar descarregada
power-settings = Configurações de energia e bateria...
dgpu-running = GPU discreta está ativa e pode reduzir a vida útil da bateria
dgpu-applications = Aplicativos usando GPU discreta { $gpu_name }
dgpu-running = A GPU dedicada está ativa e pode reduzir a vida útil da bateria
dgpu-applications = Aplicativos usando a GPU dedicada { $gpu_name }

View file

@ -6,9 +6,9 @@ performance = 高效能
performance-desc = 高效能與高耗電量。
max-charge = 將電池充電上限設定為 80%,以延長電池使用壽命
seconds = 秒
minutes = 分
hours = 時
minutes = 分鍾
hours = 小時
until-empty = 直到電量耗盡
power-settings = 電源與電池設定…
dgpu-running = 獨立顯示卡已啟用,可能會縮短電池續航力
dgpu-applications = 使用 { $gpu_name } 獨立顯示卡的應用程式
dgpu-applications = 使用獨立顯示卡 { $gpu_name } 的應用程式

View file

@ -366,23 +366,31 @@ impl cosmic::Application for CosmicBatteryApplet {
let _ = tx.send(KeyboardBacklightRequest::Get);
}
let new_id = window::Id::unique();
self.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
None,
None,
);
if let Some(tx) = self.power_profile_sender.as_ref() {
let _ = tx.send(PowerProfileRequest::Get);
}
if let Some(tx) = self.update_trigger.as_ref() {
let _ = tx.send(());
}
let mut tasks = vec![get_popup(popup_settings)];
let mut tasks = vec![cosmic::surface::surface_task(
cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
None,
None,
);
popup_settings
},
None,
),
)];
if let Some(tx) = &self.settings_daemon_sender {
let _ = tx.send(settings_daemon::Request::GetDisplayBrightness);
let _ = tx.send(settings_daemon::Request::GetMaxDisplayBrightness);

View file

@ -0,0 +1,12 @@
cancel = Annuller
confirm-pin = Bekræft venligst, at følgende pinkode matcher den, der vises på { $deviceName }
bluetooth = Bluetooth
unsuccessful = Parring Mislykkedes
pairable = Parbare
try-again = Prøv Igen
check-device = Sørg for, at { $deviceName } er slået til, inden for rækkevidde og klar til parring.
other-devices = Andre Bluetooth-enheder
connected = Forbundet
confirm = Bekræft
settings = Bluetooth-indstillinger...
discoverable = Synlig

View file

@ -1,6 +1,6 @@
bluetooth = Bluetooth
other-devices = Andere Bluetooth-Geräte
settings = Bluetooth-Einstellungen...
settings = Bluetooth-Einstellungen ...
connected = Verbunden
confirm-pin = Bitte bestätige, dass die folgende PIN mit der auf { $deviceName } angezeigten PIN übereinstimmt
confirm = Bestätigen

View file

@ -0,0 +1,12 @@
cancel = Cancel
confirm-pin = Please confirm that the following PIN matches the one displayed on { $deviceName }
bluetooth = Bluetooth
unsuccessful = Pairing Unsuccessful
pairable = Pairable
try-again = Try Again
check-device = Make sure { $deviceName } is turned on, in range, and is ready to pair.
other-devices = Other Bluetooth devices
connected = Connected
confirm = Confirm
settings = Bluetooth settings...
discoverable = Discoverable

View file

@ -2,11 +2,11 @@ bluetooth = بلوتوث
other-devices = سایر دستگاه‌های بلوتوث
settings = تنظیمات بلوتوث...
connected = متصل
confirm-pin = لطفاً تأیید کنید که پین زیر با پین نمایش داده شده در {$deviceName} یکسان است.
confirm-pin = لطفاً تأیید کنید که پین زیر با پین نمایش داده شده در { $deviceName } یکسان است.
confirm = تأیید
cancel = لغو
unsuccessful = جفت‌سازی ناموفق بود
check-device = مطمئن شوید که {$deviceName} روشن، در محدوده و آماده جفت‌سازی است.
check-device = مطمئن شوید که { $deviceName } روشن، در محدوده و آماده جفت‌سازی است.
try-again = تلاش دوباره
discoverable = قابل شناسایی
pairable = قابل جفت‌سازی

View file

@ -0,0 +1,12 @@
cancel = Cancelar
bluetooth = Bluetooth
other-devices = Outros dispositivos Bluetooth
settings = Axustes Bluetooth…
connected = Conectado
confirm-pin = Por favor, confirme que o seguinte PIN coincide co que se mostra en{ $deviceName }
confirm = Confirmar
unsuccessful = Enparellamento non exitoso
check-device = Asegurate de que { $deviceName } está acendido, dentro do alcance e listo para emparellar.
try-again = Reintentar
discoverable = Atopable
pairable = Emparellable

View file

@ -2,11 +2,11 @@ bluetooth = ब्लूटूथ
other-devices = अन्य ब्लूटूथ उपकरण
settings = ब्लूटूथ सेटिंग्स...
connected = जुड़े हुए
confirm-pin = कृपया सुनिश्चित करें कि निम्नलिखित PIN {$deviceName} पर प्रदर्शित PIN से मेल खाता है
confirm-pin = कृपया सुनिश्चित करें कि निम्नलिखित PIN { $deviceName } पर प्रदर्शित PIN से मेल खाता है
confirm = पुष्टि करें
cancel = रद्द करें
unsuccessful = पेयरिंग असफल
check-device = सुनिश्चित करें कि {$deviceName} चालू है, रेंज में है, और पेयर करने के लिए तैयार है।
check-device = सुनिश्चित करें कि { $deviceName } चालू है, रेंज में है, और पेयर करने के लिए तैयार है।
try-again = फिर से प्रयास करें
discoverable = खोजने योग्य
pairable = पेयर करने योग्य

View file

@ -2,11 +2,11 @@ bluetooth = Bluetooth
other-devices = Altri dispositivi Bluetooth
settings = Impostazioni Bluetooth...
connected = Connesso
confirm-pin = Per favore conferma che il seguente PIN corrisponda a quello visualizzato nel dispositivo {$deviceName}
confirm-pin = Per favore conferma che il seguente PIN corrisponda a quello visualizzato nel dispositivo { $deviceName }
confirm = Conferma
cancel = Annulla
unsuccessful = Accoppiamento fallito
check-device = Assicurati che il dispositivo {$deviceName} sia acceso, a portata e pronto per l'accoppiamento.
check-device = Assicurati che il dispositivo { $deviceName } sia acceso, a portata e pronto per l'accoppiamento.
try-again = Riprova
discoverable = Visibile
pairable = Accoppiabile
pairable = Accoppiabile

View file

@ -0,0 +1 @@
cancel = ᱵᱟᱹᱛᱤᱞ

View file

@ -1,7 +1,7 @@
bluetooth = 藍牙
other-devices = 其他藍牙裝置
settings = 藍牙設定…
connected = 已經連線
connected = 已連線
confirm-pin = 請確認此 PIN 碼與 { $deviceName } 上顯示的是否相符
confirm = 確認
cancel = 取消

View file

@ -121,20 +121,25 @@ impl cosmic::Application for CosmicBluetoothApplet {
} else {
set_discovery(true);
// TODO request update of state maybe
let new_id = window::Id::unique();
self.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
let get_popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
)
},
None,
));
return Task::batch([
get_popup(popup_settings),
get_popup_task,
cosmic::task::future(set_tick(Duration::from_secs(3)))
.map(|()| cosmic::Action::App(Message::Ignore)),
]);

View file

@ -5,7 +5,9 @@ edition = "2024"
license = "GPL-3.0-only"
[dependencies]
cctk.workspace = true
cosmic-comp-config.workspace = true
futures.workspace = true
i18n-embed-fl.workspace = true
i18n-embed.workspace = true
cosmic.workspace = true

View file

@ -12,4 +12,5 @@ NoDisplay=true
X-CosmicApplet=true
X-CosmicShrinkable=true
X-CosmicHoverPopup=Auto
X-HostWaylandDisplay=true
X-OverflowPriority=10

View file

@ -0,0 +1,2 @@
show-keyboard-layout = Mostra la disposició de teclat...
keyboard-settings = Configuració de teclat...

View file

@ -0,0 +1,2 @@
show-keyboard-layout = Vis Tastaturopsætning...
keyboard-settings = Tastaturindstillinger...

View file

@ -1,2 +1,2 @@
show-keyboard-layout = Tastaturbelegung anzeigen...
keyboard-settings = Tastatureinstellungen...
show-keyboard-layout = Tastaturbelegung anzeigen ...
keyboard-settings = Tastatureinstellungen ...

View file

@ -0,0 +1,2 @@
show-keyboard-layout = Mostrar a disposición do teclado...
keyboard-settings = Axustes do teclado...

View file

@ -3,19 +3,23 @@
mod localize;
use cctk::{
cosmic_protocols::keyboard_layout::v1::client::zcosmic_keyboard_layout_v1::ZcosmicKeyboardLayoutV1,
wayland_client::{Connection, Proxy, backend::Backend},
};
use cosmic::{
app,
app::Core,
applet::{self},
cosmic_config::{self, ConfigSet, CosmicConfigEntry},
cosmic_theme::Spacing,
iced::Subscription,
iced::core::window,
iced::{
Rectangle, Task,
self, Rectangle, Task,
event::wayland::{Event as WaylandEvent, OutputEvent},
platform_specific::shell::commands::popup::{destroy_popup, get_popup},
window::Id,
},
iced::core::window,
prelude::*,
surface, theme,
widget::{
@ -23,14 +27,35 @@ use cosmic::{
rectangle_tracker::{RectangleTracker, RectangleUpdate, rectangle_tracker_subscription},
},
};
use cosmic_comp_config::CosmicCompConfig;
use std::sync::LazyLock;
use cosmic_comp_config::{CosmicCompConfig, XkbConfig};
use std::{
os::unix::{
io::{FromRawFd, RawFd},
net::UnixStream,
},
sync::LazyLock,
};
use xkb_data::KeyboardLayout;
mod wayland;
static AUTOSIZE_MAIN_ID: LazyLock<widget::Id> = LazyLock::new(|| widget::Id::new("autosize-main"));
pub const ID: &str = "com.system76.CosmicAppletInputSources";
pub fn run() -> cosmic::iced::Result {
let socket = std::env::var("X_PRIVILEGED_WAYLAND_SOCKET")
.ok()
.and_then(|fd| {
fd.parse::<RawFd>()
.ok()
.map(|fd| unsafe { UnixStream::from_raw_fd(fd) })
});
let wayland_connection = if let Some(socket) = socket {
Some(Connection::from_socket(socket).unwrap())
} else {
None
};
localize::localize();
let layouts = match xkb_data::all_keyboard_layouts() {
@ -41,27 +66,8 @@ pub fn run() -> cosmic::iced::Result {
}
};
let (comp_config_handler, comp_config) =
match cosmic_config::Config::new("com.system76.CosmicComp", CosmicCompConfig::VERSION) {
Ok(config_handler) => {
let config = match CosmicCompConfig::get_entry(&config_handler) {
Ok(ok) => ok,
Err((errs, config)) => {
tracing::error!("errors loading config: {:?}", errs);
config
}
};
(Some(config_handler), config)
}
Err(err) => {
tracing::error!("failed to create config handler: {}", err);
(None, CosmicCompConfig::default())
}
};
cosmic::applet::run::<Window>(Flags {
comp_config,
comp_config_handler,
wayland_connection,
layouts: layouts.layout_list.layout,
})
}
@ -76,12 +82,13 @@ pub struct ActiveLayout {
pub struct Window {
core: Core,
popup: Option<Id>,
comp_config: CosmicCompConfig,
comp_config_handler: Option<cosmic_config::Config>,
layouts: Vec<KeyboardLayout>,
active_layouts: Vec<ActiveLayout>,
rectangle_tracker: Option<RectangleTracker<u32>>,
rectangle: Rectangle,
wayland_connection: Option<Connection>,
keyboard_layout: Option<ZcosmicKeyboardLayoutV1>,
current_layout: usize,
}
#[derive(Clone, Debug)]
@ -93,12 +100,13 @@ pub enum Message {
KeyboardSettings,
Surface(surface::Action),
Rectangle(RectangleUpdate<u32>),
WaylandConnection(Backend),
Wayland(wayland::Event),
}
#[derive(Debug)]
pub struct Flags {
pub comp_config: CosmicCompConfig,
pub comp_config_handler: Option<cosmic_config::Config>,
wayland_connection: Option<Connection>,
pub layouts: Vec<KeyboardLayout>,
}
@ -119,14 +127,15 @@ impl cosmic::Application for Window {
fn init(core: Core, flags: Self::Flags) -> (Self, app::Task<Self::Message>) {
let window = Window {
comp_config_handler: flags.comp_config_handler,
layouts: flags.layouts,
core,
popup: None,
comp_config: flags.comp_config,
active_layouts: Vec::new(),
rectangle_tracker: None,
rectangle: Rectangle::default(),
wayland_connection: flags.wayland_connection,
keyboard_layout: None,
current_layout: 0,
};
(window, Task::none())
}
@ -139,19 +148,24 @@ impl cosmic::Application for Window {
match message {
Message::TogglePopup => {
return if let Some(p) = self.popup.take() {
destroy_popup(p)
return crate::surface::surface_task(crate::surface::action::destroy_popup(p));
} else {
let new_id = Id::unique();
self.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
return crate::surface::surface_task(crate::surface::action::app_popup(
|_| Default::default(),
|app: &mut Window| {
let new_id = Id::unique();
app.popup.replace(new_id);
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings
},
None,
None,
None,
);
get_popup(popup_settings)
));
};
}
Message::PopupClosed(id) => {
@ -160,8 +174,7 @@ impl cosmic::Application for Window {
}
}
Message::CompConfig(config) => {
self.comp_config = *config;
self.active_layouts = self.update_xkb();
self.active_layouts = self.update_xkb(&config.xkb_config);
}
Message::KeyboardSettings => {
let mut cmd = std::process::Command::new("cosmic-settings");
@ -169,31 +182,10 @@ impl cosmic::Application for Window {
tokio::spawn(cosmic::process::spawn(cmd));
}
Message::SetActiveLayout(pos) => {
if pos == 0 {
return Task::none();
}
self.active_layouts.swap(0, pos);
let mut new_layout = String::new();
let mut new_variant = String::new();
for layout in &self.active_layouts {
new_layout.push_str(&layout.layout);
new_layout.push(',');
new_variant.push_str(&layout.variant);
new_variant.push(',');
}
let _excess_comma = new_layout.pop();
let _excess_comma = new_variant.pop();
self.comp_config.xkb_config.layout = new_layout;
self.comp_config.xkb_config.variant = new_variant;
if let Some(comp_config_handler) = &self.comp_config_handler {
if let Err(err) =
comp_config_handler.set("xkb_config", &self.comp_config.xkb_config)
{
tracing::error!("Failed to set config 'xkb_config' {err}");
if let Some(keyboard_layout) = &self.keyboard_layout {
keyboard_layout.set_group(pos as u32);
if let Some(backend) = keyboard_layout.backend().upgrade() {
let _ = backend.flush();
}
}
}
@ -210,13 +202,26 @@ impl cosmic::Application for Window {
self.rectangle_tracker = Some(tracker);
}
},
Message::WaylandConnection(backend) => {
if self.wayland_connection.is_none() {
self.wayland_connection = Some(Connection::from_backend(backend));
}
}
Message::Wayland(w) => match w {
wayland::Event::KeyboardLayout(keyboard_layout) => {
self.keyboard_layout = Some(keyboard_layout);
}
wayland::Event::Group(group) => {
self.current_layout = group as usize;
}
},
}
Task::none()
}
fn view(&self) -> Element<'_, Self::Message> {
let applet_text = if let Some(l) = self.active_layouts.first() {
let applet_text = if let Some(l) = self.active_layouts.get(self.current_layout) {
if !l.variant.is_empty() {
format!("{} ({})", l.layout, l.variant)
} else {
@ -249,8 +254,13 @@ impl cosmic::Application for Window {
let mut content_list =
widget::column::with_capacity(4 + self.active_layouts.len()).padding([8, 0]);
for (id, layout) in self.active_layouts.iter().enumerate() {
let font = if id == self.current_layout {
cosmic::font::bold()
} else {
cosmic::font::default()
};
let group = widget::column::with_capacity(2)
.push(widget::text::body(layout.description.as_str()))
.push(widget::text::body(layout.description.as_str()).font(font))
.push(widget::text::caption(layout.layout.as_str()));
content_list = content_list
.push(applet::menu_button(group).on_press(Message::SetActiveLayout(id)));
@ -271,7 +281,7 @@ impl cosmic::Application for Window {
}
fn subscription(&self) -> Subscription<Self::Message> {
Subscription::batch(vec![
let mut subscriptions = vec![
rectangle_tracker_subscription(0).map(|e| Message::Rectangle(e.1)),
self.core
.watch_config("com.system76.CosmicComp")
@ -285,7 +295,23 @@ impl cosmic::Application for Window {
}
Message::CompConfig(Box::new(update.config))
}),
])
];
subscriptions.push(if let Some(connection) = &self.wayland_connection {
wayland::subscription(connection.clone()).map(Message::Wayland)
} else {
iced::event::listen_with(|evt, _, _| match evt {
iced::Event::PlatformSpecific(iced::event::PlatformSpecific::Wayland(evt)) => {
if let WaylandEvent::Output(OutputEvent::Created(_), output) = evt {
if let Some(backend) = output.backend().upgrade() {
return Some(Message::WaylandConnection(backend));
}
}
None
}
_ => None,
})
});
Subscription::batch(subscriptions)
}
fn style(&self) -> Option<cosmic::iced::theme::Style> {
@ -293,9 +319,8 @@ impl cosmic::Application for Window {
}
}
impl Window {
fn update_xkb(&self) -> Vec<ActiveLayout> {
fn update_xkb(&self, xkb: &XkbConfig) -> Vec<ActiveLayout> {
let mut active_layouts = Vec::new();
let xkb = &self.comp_config.xkb_config;
let layouts = xkb.layout.split_terminator(',');

View file

@ -0,0 +1,157 @@
use cctk::{
cosmic_protocols::keyboard_layout::v1::client::zcosmic_keyboard_layout_v1::ZcosmicKeyboardLayoutV1,
keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState},
sctk::{
self,
registry::{ProvidesRegistryState, RegistryState},
seat::{Capability, SeatHandler, SeatState},
},
wayland_client::{
Connection, QueueHandle, delegate_noop,
globals::registry_queue_init,
protocol::{wl_keyboard, wl_seat},
},
};
use cosmic::iced;
use futures::{SinkExt, channel::mpsc, executor::block_on};
use std::{hash::Hash, thread};
#[derive(Clone, Debug)]
pub enum Event {
KeyboardLayout(ZcosmicKeyboardLayoutV1),
Group(usize),
}
pub fn subscription(connection: Connection) -> iced::Subscription<Event> {
#[derive(Clone)]
struct WaylandSubscription(Connection);
impl Hash for WaylandSubscription {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.backend().display_id().hash(state);
}
}
iced::Subscription::run_with(
WaylandSubscription(connection),
|WaylandSubscription(connection)| {
let connection = connection.clone();
iced::stream::channel(8, move |sender| async move {
thread::spawn(move || thread(connection, sender));
})
},
)
}
struct Keyboard {
seat: wl_seat::WlSeat,
keyboard_layout: ZcosmicKeyboardLayoutV1,
}
impl Drop for Keyboard {
fn drop(&mut self) {
self.keyboard_layout.destroy();
}
}
struct AppData {
seat_state: SeatState,
registry_state: RegistryState,
keyboard_layout_state: KeyboardLayoutState,
keyboard: Option<Keyboard>,
sender: mpsc::Sender<Event>,
}
impl KeyboardLayoutHandler for AppData {
fn group(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &wl_keyboard::WlKeyboard,
_keyboard_layout: &ZcosmicKeyboardLayoutV1,
group: u32,
) {
let _ = block_on(self.sender.send(Event::Group(group as usize)));
}
}
impl ProvidesRegistryState for AppData {
fn registry(&mut self) -> &mut RegistryState {
&mut self.registry_state
}
sctk::registry_handlers![SeatState,];
}
impl SeatHandler for AppData {
fn seat_state(&mut self) -> &mut SeatState {
&mut self.seat_state
}
fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
fn new_capability(
&mut self,
_conn: &Connection,
qh: &QueueHandle<Self>,
seat: wl_seat::WlSeat,
capability: Capability,
) {
if capability == Capability::Keyboard && self.keyboard.is_none() {
let keyboard = seat.get_keyboard(qh, ());
let keyboard_layout = self
.keyboard_layout_state
.get_keyboard_layout(&keyboard, qh);
keyboard.release();
if let Some(keyboard_layout) = keyboard_layout {
let _ = block_on(
self.sender
.send(Event::KeyboardLayout(keyboard_layout.clone())),
);
self.keyboard = Some(Keyboard {
seat,
keyboard_layout,
});
} else {
keyboard.release();
}
}
}
fn remove_capability(
&mut self,
_conn: &Connection,
_: &QueueHandle<Self>,
seat: wl_seat::WlSeat,
_capability: Capability,
) {
self.keyboard.take_if(|x| x.seat == seat);
}
fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, seat: wl_seat::WlSeat) {
self.keyboard.take_if(|x| x.seat == seat);
}
}
fn thread(conn: Connection, sender: mpsc::Sender<Event>) {
let (globals, mut event_queue) = registry_queue_init(&conn).unwrap();
let qh = event_queue.handle();
let registry_state = RegistryState::new(&globals);
let seat_state = SeatState::new(&globals, &qh);
let keyboard_layout_state = KeyboardLayoutState::new(&registry_state, &qh);
let mut app_data = AppData {
seat_state,
registry_state,
keyboard_layout_state,
keyboard: None,
sender,
};
loop {
event_queue.blocking_dispatch(&mut app_data).unwrap();
}
}
sctk::delegate_registry!(AppData);
sctk::delegate_seat!(AppData);
cctk::delegate_keyboard_layout!(AppData);
delegate_noop!(AppData: ignore wl_keyboard::WlKeyboard);

View file

@ -248,40 +248,48 @@ impl cosmic::Application for Minimize {
}
Message::OpenOverflowPopup => {
if let Some(id) = self.overflow_popup.take() {
return destroy_popup(id);
return cosmic::surface::surface_task(cosmic::surface::action::destroy_popup(
id,
));
} else {
let new_id = window::Id::unique();
let pos = self.max_icon_count().unwrap_or_default();
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
let new_id = window::Id::unique();
let pos = app.max_icon_count().unwrap_or_default();
self.overflow_popup = Some(new_id);
let icon_size = self.core.applet.suggested_size(true).0 as u32
+ 2 * self.core.applet.suggested_padding(true).1 as u32;
let spacing = self.core.system_theme().cosmic().space_xxs() as u32;
let major_axis_len = (icon_size + spacing) * (pos.saturating_sub(1) as u32);
let rectangle = match self.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => iced::Rectangle {
x: major_axis_len as i32,
y: 0,
width: icon_size as i32,
height: icon_size as i32,
app.overflow_popup = Some(new_id);
let icon_size = app.core.applet.suggested_size(true).0 as u32
+ 2 * app.core.applet.suggested_padding(true).1 as u32;
let spacing = app.core.system_theme().cosmic().space_xxs() as u32;
let major_axis_len =
(icon_size + spacing) * (pos.saturating_sub(1) as u32);
let rectangle = match app.core.applet.anchor {
PanelAnchor::Top | PanelAnchor::Bottom => iced::Rectangle {
x: major_axis_len as i32,
y: 0,
width: icon_size as i32,
height: icon_size as i32,
},
PanelAnchor::Left | PanelAnchor::Right => iced::Rectangle {
x: 0,
y: major_axis_len as i32,
width: icon_size as i32,
height: icon_size as i32,
},
};
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = rectangle;
popup_settings
},
PanelAnchor::Left | PanelAnchor::Right => iced::Rectangle {
x: 0,
y: major_axis_len as i32,
width: icon_size as i32,
height: icon_size as i32,
},
};
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.anchor_rect = rectangle;
return get_popup(popup_settings);
));
}
}
Message::CloseOverflowPopup => todo!(),

View file

@ -0,0 +1,6 @@
cancel = Annuller
connected = Forbundet
connect = Opret forbindelse
wifi = Wi-Fi
identity = Identitet
network = Netværk

View file

@ -12,7 +12,7 @@ connected = Verbunden
connecting = Wird verbunden
connect = Verbinden
cancel = Abbrechen
settings = Netzwerkeinstellungen...
settings = Netzwerkeinstellungen ...
visible-wireless-networks = Sichtbare Drahtlosnetzwerke
enter-password = Gib das Passwort oder den Verschlüsselungsschlüssel ein
router-wps-button = Du kannst dich auch verbinden, indem du die Taste „WPS” am Router drückst

View file

@ -0,0 +1,2 @@
cancel = Cancel
connected = Connected

View file

@ -9,7 +9,7 @@ mac = MAC
megabits-per-second = Mbps
connected = Connecté
connecting = Connexion
connect = Connecter
connect = Se connecter
cancel = Annuler
settings = Paramètres réseaux...
visible-wireless-networks = Réseaux Wi-Fi disponibles

View file

@ -0,0 +1,24 @@
cancel = Cancelar
connected = Conectado
connect = Conectar
identity = Identidade
wifi = Wi-Fi
network = Rede
airplane-mode = Modo avión
airplane-mode-on = O modo avión está activo
turn-off-airplane-mode = Desactívao para activar a wifi, o Bluetooth e a banda larga móbil.
ipv4 = Dirección IPv4
ipv6 = Dirección IPv6
mac = MAC
megabits-per-second = Mbps
gigabits-per-second = Gbps
terabits-per-second = Tbps
connecting = Conectando
settings = Axustes da rede...
visible-wireless-networks = Redes sen fíos visibles
vpn-connections = Conexións VPN
enter-password = Introduce o contrasinal ou a chave de cifrado
router-wps-button = Tamén podes conectarte premendo o botón "WPS" do router
unable-to-connect = Non se puido conectar á rede
check-wifi-connection = Asegúrate de que a wifi está conectada a Internet e de que o contrasinal é correcto
reset = Restablecer

View file

@ -0,0 +1 @@
cancel = ᱵᱟᱹᱛᱤᱞ

View file

@ -8,7 +8,7 @@ ipv4 = IPv4 位址
ipv6 = IPv6 位址
mac = MAC
megabits-per-second = Mbps
connected = 已經連線
connected = 已連線
connecting = 連線中
connect = 連線
cancel = 取消

View file

@ -15,5 +15,5 @@ show-more = { $more } weitere anzeigen
clear-group = Gruppe leeren
clear-all = Alle Benachrichtigungen leeren
do-not-disturb = Nicht stören
notification-settings = Benachrichtigungseinstellungen...
notification-settings = Benachrichtigungseinstellungen ...
no-notifications = Keine Benachrichtigungen

View file

@ -0,0 +1,19 @@
hours-ago =
{ $duration ->
[0] Xusto agora
[one] Hai 1 hora
*[other] Hai { $duration } horas
}
minutes-ago =
{ $duration ->
[0] Xusto agora
[one] Hai 1 minuto
*[other] Hai { $duration } minutos
}
show-less = Mostrar menos
show-more = Mostrar { $more } máis
clear-group = Limpar grupo
clear-all = Limpar todas as notificacións
do-not-disturb = Non Molestar
notification-settings = Configuración das notificacións...
no-notifications = Sen notificacións

View file

@ -157,18 +157,23 @@ impl cosmic::Application for Notifications {
if let Some(p) = self.popup.take() {
return destroy_popup(p);
} else {
let new_id = window::Id::unique();
self.popup.replace(new_id);
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings
},
None,
None,
None,
);
return get_popup(popup_settings);
));
}
}
Message::DoNotDisturb(b) => {

View file

@ -2,3 +2,35 @@ cancel = Cancel·lar
confirm = Confirmar
restart = Reinicia
suspend = Suspèn
confirm-button =
{ $action ->
[restart] { restart }
[suspend] { suspend }
[shutdown] Apaga
[log-out] { log-out }
*[other] { confirm }
}
power = Energia
confirm-body =
{ $action ->
[restart] L'ordinador es reiniciarà
[suspend] L'ordinador se suspendrà
[shutdown] L'ordinador s'apagarà
[lock-screen] La pantalla es bloquejarà
[log-out] La sessió es tancarà
*[other] L'acció seleccionada es durà a terme
} automàticament d'aquí a { $countdown } segons.
lock-screen = Bloqueja la pantalla
shutdown = Apaga
log-out = Tanca la sessió
log-out-shortcut = Súper + Majús + Esc
settings = Configuració...
lock-screen-shortcut = Súper + Esc
confirm-title =
¿{ $action ->
[restart] { restart }
[suspend] { suspend }
[shutdown] { shutdown }
[log-out] Voleu tancar totes les aplicacions i tancar la sessió
*[other] Voleu dur a terme l'acció seleccionada
}?

View file

@ -1,5 +1,5 @@
power = Energie
settings = Einstellungen...
settings = Einstellungen ...
lock-screen = Sperrbildschirm
lock-screen-shortcut = Super + Esc
log-out = Abmelden

View file

@ -0,0 +1,36 @@
power = Enerxía
settings = Axustes...
lock-screen = Pantalla de Bloqueo
lock-screen-shortcut = Super + Esc
log-out = Pechar Sesión
log-out-shortcut = Super + Maiús + Esc
suspend = Suspender
restart = Reiniciar
shutdown = Apagar
confirm = Confirmar
cancel = Cancelar
confirm-button =
{ $action ->
[restart] { restart }
[suspend] { suspend }
[shutdown] Apagar
[log-out] { log-out }
*[other] { confirm }
}
confirm-title =
{ $action ->
[restart] { restart } agora?
[suspend] { suspend } agora?
[shutdown] { shutdown } agora?
[log-out] Pechar todas as aplicacións e pechar a sesión agora?
*[other] Aplicar a acción seleccionada agora
}
confirm-body =
O sistema { $action ->
[restart] reiniciarase
[suspend] suspenderase
[shutdown] apagarase
[lock-screen] bloqueará a pantalla
[log-out] pechará a sesión
*[other] aplicará a acción seleccionada
} automaticamente en { $countdown } segundos.

View file

@ -115,20 +115,27 @@ impl cosmic::Application for Power {
match message {
Message::TogglePopup => {
if let Some(p) = self.popup.take() {
return destroy_popup(p);
return cosmic::surface::surface_task(cosmic::surface::action::destroy_popup(
p,
));
} else {
let new_id = window::Id::unique();
self.popup.replace(new_id);
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Power| {
let new_id = window::Id::unique();
app.popup.replace(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings
},
None,
None,
None,
);
return get_popup(popup_settings);
));
}
}
Message::OpenSettings => {

View file

@ -246,38 +246,49 @@ impl cosmic::Application for App {
if let Some(popup_id) = self.popup.take() {
cmds.push(destroy_popup(popup_id));
}
let popup_id = self.next_popup_id();
let i = self.menus.keys().position(|&i| i == id).unwrap();
let (i, parent) = self
.overflow_index()
.and_then(|overflow_i| {
if overflow_i <= i {
Some(i - overflow_i).zip(self.overflow_popup)
} else {
Some((i, self.core.main_window_id().unwrap()))
}
})
.unwrap_or((i, self.core.main_window_id().unwrap()));
let mut popup_settings = self
.core
.applet
.get_popup_settings(parent, popup_id, None, None, None);
self.popup = Some(popup_id);
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let popup_id = app.next_popup_id();
let i = app.menus.keys().position(|&i| i == id).unwrap();
let (i, parent) = app
.overflow_index()
.and_then(|overflow_i| {
if overflow_i <= i {
Some(i - overflow_i).zip(app.overflow_popup)
} else {
Some((i, app.core.main_window_id().unwrap()))
}
})
.unwrap_or((i, app.core.main_window_id().unwrap()));
if matches!(
self.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else {
let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
}
cmds.push(get_popup(popup_settings));
let mut popup_settings = app
.core
.applet
.get_popup_settings(parent, popup_id, None, None, None);
app.popup = Some(popup_id);
if matches!(
app.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = app.core.applet.suggested_size(false).1
+ 2 * app.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y =
i as i32 * suggested_size as i32;
} else {
let suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x =
i as i32 * suggested_size as i32;
}
popup_settings
},
None,
));
cmds.push(popup_task);
return app::Task::batch(cmds);
} else if let Some(popup_id) = self.popup {
self.menus[&id].closed();
@ -339,39 +350,49 @@ impl cosmic::Application for App {
} else {
return Task::none();
}
let popup_id = self.next_popup_id();
let i = self.menus.keys().position(|&i| i == id).unwrap();
let popup_task = cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let popup_id = app.next_popup_id();
let i = app.menus.keys().position(|&i| i == id).unwrap();
let (i, parent) = self
.overflow_index()
.and_then(|overflow_i| {
if overflow_i <= i {
Some(i - overflow_i).zip(self.overflow_popup)
let (i, parent) = app
.overflow_index()
.and_then(|overflow_i| {
if overflow_i <= i {
Some(i - overflow_i).zip(app.overflow_popup)
} else {
Some((i, app.core.main_window_id().unwrap()))
}
})
.unwrap_or((i, app.core.main_window_id().unwrap()));
let mut popup_settings = app
.core
.applet
.get_popup_settings(parent, popup_id, None, None, None);
app.popup = Some(popup_id);
if matches!(
app.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = app.core.applet.suggested_size(true).1
+ 2 * app.core.applet.suggested_padding(true).1;
popup_settings.positioner.anchor_rect.y =
i as i32 * suggested_size as i32;
} else {
Some((i, self.core.main_window_id().unwrap()))
let suggested_size = app.core.applet.suggested_size(true).0
+ 2 * app.core.applet.suggested_padding(true).0;
popup_settings.positioner.anchor_rect.x =
i as i32 * suggested_size as i32;
}
})
.unwrap_or((i, self.core.main_window_id().unwrap()));
popup_settings
},
None,
));
cmds.push(popup_task);
let mut popup_settings = self
.core
.applet
.get_popup_settings(parent, popup_id, None, None, None);
self.popup = Some(popup_id);
if matches!(
self.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = self.core.applet.suggested_size(true).1
+ 2 * self.core.applet.suggested_padding(true).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else {
let suggested_size = self.core.applet.suggested_size(true).0
+ 2 * self.core.applet.suggested_padding(true).0;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
}
cmds.push(get_popup(popup_settings));
Task::batch(cmds)
}
Msg::WheelScrolled(delta) => {
@ -399,33 +420,41 @@ impl cosmic::Application for App {
return destroy_popup(popup_id);
} else if let Some(overflow_index) = self.overflow_index() {
// If we don't have an overflow, create it
let popup_id = self.next_popup_id();
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
popup_id,
None,
None,
None,
);
popup_settings.close_with_children = false;
let popup_task =
cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let popup_id = app.next_popup_id();
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
popup_id,
None,
None,
None,
);
popup_settings.close_with_children = false;
if matches!(
self.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = self.core.applet.suggested_size(true).1
+ 2 * self.core.applet.suggested_padding(true).1;
popup_settings.positioner.anchor_rect.y =
overflow_index as i32 * suggested_size as i32;
} else {
let suggested_size = self.core.applet.suggested_size(true).0
+ 2 * self.core.applet.suggested_padding(true).0;
popup_settings.positioner.anchor_rect.x =
overflow_index as i32 * suggested_size as i32;
}
if matches!(
app.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = app.core.applet.suggested_size(true).1
+ 2 * app.core.applet.suggested_padding(true).1;
popup_settings.positioner.anchor_rect.y =
overflow_index as i32 * suggested_size as i32;
} else {
let suggested_size = app.core.applet.suggested_size(true).0
+ 2 * app.core.applet.suggested_padding(true).0;
popup_settings.positioner.anchor_rect.x =
overflow_index as i32 * suggested_size as i32;
}
self.overflow_popup = Some(popup_id);
return get_popup(popup_settings);
app.overflow_popup = Some(popup_id);
popup_settings
},
None,
));
return popup_task;
} else {
return Task::none();
}
@ -444,34 +473,41 @@ impl cosmic::Application for App {
} else {
return Task::none();
}
let popup_id = self.next_popup_id();
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
popup_id,
None,
None,
None,
);
self.popup = Some(popup_id);
let Some(i) = self.overflow_index() else {
return Task::batch(cmds);
};
let popup_task = cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
move |app: &mut Self| {
let popup_id = app.next_popup_id();
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
popup_id,
None,
None,
None,
);
app.popup = Some(popup_id);
if matches!(
self.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = self.core.applet.suggested_size(false).1
+ 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y = i as i32 * suggested_size as i32;
} else {
let suggested_size = self.core.applet.suggested_size(false).0
+ 2 * self.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x = i as i32 * suggested_size as i32;
}
cmds.push(get_popup(popup_settings));
if matches!(
app.core.applet.anchor,
PanelAnchor::Left | PanelAnchor::Right
) {
let suggested_size = app.core.applet.suggested_size(false).1
+ 2 * app.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.y =
i as i32 * suggested_size as i32;
} else {
let suggested_size = app.core.applet.suggested_size(false).0
+ 2 * app.core.applet.suggested_padding(false).1;
popup_settings.positioner.anchor_rect.x =
i as i32 * suggested_size as i32;
}
popup_settings
},
None,
));
cmds.push(popup_task);
Task::batch(cmds)
}
}
@ -656,7 +692,7 @@ fn menu_icon_button<'a>(
.class(if symbolic {
cosmic::theme::Svg::Custom(std::rc::Rc::new(|theme| {
cosmic::iced::widget::svg::Style {
color: Some(theme.cosmic().background(false).on.into()),
color: Some(theme.cosmic().background(theme.transparent).on.into()),
}
}))
} else {

View file

@ -232,7 +232,11 @@ fn layout_view(layout: &Layout, expanded: Option<i32>) -> cosmic::Element<'_, Ms
}
if let Some(icon_data) = i.icon_data() {
let handle = iced::widget::image::Handle::from_bytes(icon_data.to_vec());
children.insert(0, iced::widget::Image::new(handle).into());
let icon = iced::widget::Image::new(handle)
.width(iced::Length::Fixed(14.0))
.height(iced::Length::Fixed(14.0))
.content_fit(iced::core::ContentFit::Contain);
children.insert(0, icon.into());
} else if let Some(icon_name) = i.icon_name() {
let icon = cosmic::widget::icon::from_name(icon_name)
.size(14)

View file

@ -0,0 +1,2 @@
tile-windows = Organitza les finestres en mosaic automàticament
shortcuts = Dreceres

View file

@ -4,11 +4,11 @@ shortcuts = Tastenkombinationen
navigate-windows = Fenster navigieren
move-window = Fenster verschieben
toggle-floating-window = Schwebendes Fenster umschalten
view-all-shortcuts = Alle Tastenkombinationen ansehen...
view-all-shortcuts = Alle Tastenkombinationen ansehen ...
active-hint = Aktiv-Hinweis
gaps = Lücken
floating-window-exceptions = Ausnahmen für schwebende Fenster...
window-management-settings = Einstellungen für die Fensterverwaltung...
floating-window-exceptions = Ausnahmen für schwebende Fenster ...
window-management-settings = Einstellungen für die Fensterverwaltung ...
all-workspaces = Alle Arbeitsflächen
per-workspace = Pro Arbeitsfläche
super = Super

View file

@ -0,0 +1,20 @@
tile-windows = Dispoñer as xanelas en mosaico automaticamente
tile-current = Dispoñer en mosaico o espazo de traballo actual
shortcuts = Atallos
navigate-windows = Navergar polas xanelas
move-window = Mover a xanela
toggle-floating-window = Alternar xanela flotante
view-all-shortcuts = Ver todos os atallos...
active-hint = Indicador de foco activo
gaps = Espazos
floating-window-exceptions = Excepcións de xanelas flotantes...
window-management-settings = Axustes da xestión de xanelas...
all-workspaces = Todos os espazos de traballo
per-workspace = Por espazo de traballo
super = Super
shift = Maiús
arrow-keys = frechas
tiled = En mosaico
floating = Flotante
autotile-behavior = Organizar as xanelas en mosaico nos espazos de traballo
new-workspace = Comportamento dos novos espazos de traballo

View file

@ -3,9 +3,9 @@ tile-current = Huidig werkblad tegelen
shortcuts = Sneltoetsen
navigate-windows = Tussen vensters schakelen
move-window = Venster verplaatsen
toggle-floating-window = Zet zwevende vensters aan/uit
toggle-floating-window = Zweven aan- of uitzetten voor venster
view-all-shortcuts = Alle sneltoetsen bekijken…
active-hint = Visuele hint actief venster
active-hint = Vensterfocus-aanduiding
gaps = Ruimte rond getegelde vensters
floating-window-exceptions = Uitzonderingen voor zwevende vensters…
window-management-settings = Instellingen voor vensterbeheer…

View file

@ -147,17 +147,22 @@ impl cosmic::Application for Window {
return if let Some(p) = self.popup.take() {
destroy_popup(p)
} else {
let new_id = Id::unique();
self.popup = Some(new_id);
let popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
let new_id = Id::unique();
app.popup = Some(new_id);
let popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
Some((1, 1)),
None,
None,
);
popup_settings
},
None,
None,
);
get_popup(popup_settings)
));
};
}
Message::PopupClosed(id) => {

View file

@ -0,0 +1 @@
datetime-settings = Configuració de data, hora i calendari...

View file

@ -1 +1 @@
datetime-settings = Datum, Uhrzeit und Kalendereinstellungen...
datetime-settings = Datum, Uhrzeit und Kalendereinstellungen ...

View file

@ -0,0 +1 @@
datetime-settings = Axustes de data, hora e calendario...

View file

@ -521,35 +521,40 @@ impl cosmic::Application for Window {
if let Some(p) = self.popup.take() {
destroy_popup(p)
} else {
self.date_today = self.now.date();
self.date_selected = self.date_today;
return cosmic::surface::surface_task(cosmic::surface::action::app_popup(
|_| Default::default(),
|app: &mut Self| {
app.date_today = app.now.date();
app.date_selected = app.date_today;
let new_id = window::Id::unique();
self.popup = Some(new_id);
let new_id = window::Id::unique();
app.popup = Some(new_id);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
let mut popup_settings = app.core.applet.get_popup_settings(
app.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
let Rectangle {
x,
y,
width,
height,
} = app.rectangle;
popup_settings.positioner.anchor_rect = Rectangle::<i32> {
x: x.max(1.) as i32,
y: y.max(1.) as i32,
width: width.max(1.) as i32,
height: height.max(1.) as i32,
};
popup_settings.positioner.size = None;
popup_settings
},
None,
None,
None,
);
let Rectangle {
x,
y,
width,
height,
} = self.rectangle;
popup_settings.positioner.anchor_rect = Rectangle::<i32> {
x: x.max(1.) as i32,
y: y.max(1.) as i32,
width: width.max(1.) as i32,
height: height.max(1.) as i32,
};
popup_settings.positioner.size = None;
get_popup(popup_settings)
));
}
}
Message::Tick => {

View file

@ -0,0 +1 @@
cosmic-applet-workspaces = Espais de treball del COSMIC

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